Instruction file imported from FreeOnur/BallUp (
.cursor/rules/security.mdc). Copyright stays with the author.
Secrets
- Never commit Supabase URL/anon key, Google Maps keys, B2 keys, JWT secrets, or DB passwords
- Flutter: use
--dart-define=API_BASE_URL,SUPABASE_URL,SUPABASE_ANON_KEY— remove hardcoded values frommain.dart - Google Maps:
baller_app/android/.../AndroidManifest.xml·baller_app/ios/Runner/AppDelegate.swift— inject at build time - Backend:
backend/.envfrom.env.exampleonly;JWT_SECRETmin 32 random bytes in production - B2: only server-side in API env (
B2_KEY_ID,B2_APP_KEY) .cursor/mcp.json— rotate exposed tokens; use env-based auth locally
Auth (self-hosted API)
- Tokens in
flutter_secure_storageviaTokenStorage— neverSharedPreferences - Access JWT short-lived; refresh via
POST /auth/refresh - Legacy Supabase mode: migrate off before production; plan password reset for existing users
Auth (legacy Supabase)
auth_gate.dart—onAuthStateChange+profileslookup whenUSE_LEGACY_SUPABASE=true- Deprecate after cutover — see
auth-flowskill
Backend / Docker
- Postgres not exposed on public internet in production
- TLS via Coolify reverse proxy
- Rate-limit login endpoints in production (proxy or app layer)
Permissions
- iOS
Info.plist: location + photo library usage strings - Android
AndroidManifest.xml: location permissions as required by features