---
description: "Security standards for LegacyApp — ALWAYS APPLIED on every file write"
alwaysApply: true
---

# Security Standards — LegacyApp
> **Pillar 5**: Security is an always-on rule, not just a reactive agent.
> These rules apply to EVERY file write, regardless of feature or context.

## Credential & secret management
- **NEVER** hardcode API keys, tokens, or secrets in source code
- **NEVER** commit `.env` files — use `.gitignore` and document required vars in `.env.example`
- API keys belong in: flavored `--dart-define` build args, or a secrets manager (e.g. AWS Secrets)
- Use `flutter_secure_storage` for tokens/credentials — **NEVER** `SharedPreferences` for sensitive data
- Obfuscation: enable `--obfuscate --split-debug-info=build/debug-symbols/` for release builds

## Authentication & sessions
- JWT/session tokens: stored in `flutter_secure_storage`, never in `SharedPreferences` or local DB
- Implement token refresh with retry logic — never let a 401 show a raw error to the user
- Certificate pinning: required for production builds on JWT / REST Auth — use `dio_pinning_interceptor`
- Biometric re-auth: require for any transaction > defined threshold

## Data & privacy
- **NEVER** log PII (names, emails, phone numbers, addresses) to console or crash reporters
- Sanitize all user inputs before sending to backend
- Use `SensitiveWidget` wrapper to exclude screens from screenshots / app switcher thumbnails
- Comply with platform privacy requirements: iOS `NSPrivacyAccessedAPITypes`, Android permissions

## Network security
- All API calls use HTTPS — no http:// in production
- Validate SSL certificates — never bypass with `badCertificateCallback: (_,_,_) => true`
- Add a timeout to every HTTP call: `connectTimeout: Duration(seconds: 10)`
- Rate-limit sensitive endpoints: auth, OTP, password reset

## Dependency security
- Run `dart pub outdated` monthly — flag packages with known CVEs
- Never use a package with <100 pub points without explicit tech lead approval
- Pin critical security packages to exact versions in `pubspec.yaml`

## Secure coding patterns
```dart
// ✅ Correct: secure token storage
final storage = FlutterSecureStorage();
await storage.write(key: 'access_token', value: token);

// ❌ Wrong: SharedPreferences for sensitive data
final prefs = await SharedPreferences.getInstance();
prefs.setString('access_token', token); // NEVER do this

// ✅ Correct: PII-safe logging
logger.info('User authenticated: userId=${user.id}'); // ok — id, not email
logger.debug('Payment processed: orderId=$orderId');  // ok — no card data

// ❌ Wrong: PII in logs
logger.info('Login: email=${user.email}, phone=${user.phone}'); // NEVER

// ✅ Correct: --dart-define for secrets (build arg, not in code)
// flutter build apk --dart-define=API_KEY=$API_KEY
const apiKey = String.fromEnvironment('API_KEY'); // acceptable

// ✅ Correct: certificate pinning with Dio
(dio.httpClientAdapter as IOHttpClientAdapter).createHttpClient = () {
  final client = HttpClient();
  client.badCertificateCallback = (cert, host, port) => false; // strict
  return client;
};
```

## Deep linking & intent security
- Validate all incoming deep link parameters — never trust raw URL params
- Use `app_links` package for verified deep link handling
- Restrict URL schemes to known patterns — reject unknown schemes
- For OAuth callbacks: validate `state` parameter to prevent CSRF

## Storage security
- Encrypt locally cached sensitive data using `hive` with `HiveAesCipher`
- Clear sensitive data from memory after use (set to null, trigger GC)
- Do NOT cache auth tokens in network layer (no `dio_cache_interceptor` for auth endpoints)
- Use `SecureRandom` for nonce/token generation — never `Random()`

## Code obfuscation & binary protection
```yaml
# android/app/build.gradle — release config
buildTypes {
  release {
    minifyEnabled true
    shrinkResources true
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  }
}
```
```bash
# Flutter release build with obfuscation
flutter build apk --release --obfuscate --split-debug-info=build/debug-symbols/
flutter build ipa --release --obfuscate --split-debug-info=build/debug-symbols/
```

## Release checklist
Before every production release, verify:
- [ ] No hardcoded secrets (`grep -r "api_key\|secret\|password\|token" lib/`)
- [ ] Debug flags disabled (`kDebugMode` guards on all debug-only paths)
- [ ] Obfuscation enabled in release build config
- [ ] Certificate pinning active and tested on both platforms
- [ ] Crash reporter PII filters configured (Sentry `beforeSend`, Firebase `setConsentType`)
- [ ] `flutter_secure_storage` used for all tokens — no `SharedPreferences` for sensitive keys
- [ ] Network calls all HTTPS — scan for `http://` in lib/
- [ ] Dependencies audited: `dart pub outdated --json | jq '.packages[] | select(.isDiscontinued)'`
- [ ] Deep link parameters validated
- [ ] App transport security / network security config reviewed
