get to prod tasks

This commit is contained in:
2026-05-26 16:06:34 -04:00
parent 04e839640f
commit 5214412fff
105 changed files with 7447 additions and 38 deletions

View File

@@ -0,0 +1,83 @@
# 01. Play Store Listing Assets
meta:
id: android-production-01
feature: android-production
priority: P1
depends_on: []
tags: [play-store, marketing, production]
objective:
- Create and upload all required Google Play Store listing assets for Android app submission
deliverables:
- Screenshots for phone, tablet, and foldable devices
- App metadata (title, description, keywords)
- Play Store listing content
- Store listing experiments setup
steps:
1. Determine required screenshot sizes:
- Phone: 16:9 or 9:16 aspect ratio, min 320px, max 3840px
- Tablet: 16:9 or 9:16 aspect ratio
- Foldable: specific sizes if targeting
- 2-8 screenshots per form factor
2. Create screenshot content plan:
- Screenshot 1: Dashboard with threat score
- Screenshot 2: DarkWatch exposure monitoring
- Screenshot 3: VoicePrint enrollment
- Screenshot 4: SpamShield call filtering
- Screenshot 5: HomeTitle property list
- Screenshot 6: Settings and profile
- Screenshot 7: Alerts and notifications
3. Capture screenshots:
- Use Android Emulator for precise control
- Or use Firebase Test Lab screenshotting
- Ensure status bar shows clean state
- Use demo data (no real user info)
4. Write app metadata:
- Title: Kordant (50 chars max)
- Short description: 80 chars
- Full description: 4000 chars
- Keywords in description (Google indexes description text)
- Category: Tools or Lifestyle
- Content rating questionnaire
5. Prepare Play Console listing:
- Upload screenshots for each form factor
- Upload feature graphic (1024x500)
- Upload app icon (512x512 PNG)
- Set pricing (free with subscriptions)
- Configure countries/regions
6. Set up store listing experiments:
- A/B test different screenshots
- A/B test different descriptions
- Measure conversion rates
tests:
- Visual: Review screenshots for quality
- Content: Verify no placeholder data
- Compliance: Check content rating accuracy
acceptance_criteria:
- Screenshots for phone (2-8 images)
- Screenshots for tablet (2-8 images, if supporting)
- Feature graphic uploaded (1024x500)
- App icon uploaded (512x512)
- App metadata complete and within limits
- Screenshots show real app UI with clean demo data
- No beta/test labels visible
- Content rating accurate and complete
- Store listing experiments configured
- All assets uploaded to Play Console
validation:
- Play Console → all screenshot slots filled
- Screenshots reviewed by designer → approved
- Metadata spell-checked and reviewed
- Content rating questionnaire submitted
notes:
- Google Play allows more flexibility in screenshot sizes than App Store
- Feature graphic is very important for conversion
- Consider localized screenshots for major markets
- Store listing experiments help optimize conversion

View File

@@ -0,0 +1,79 @@
# 02. Feature Graphic & Promo Video
meta:
id: android-production-02
feature: android-production
priority: P2
depends_on: []
tags: [play-store, marketing, production]
objective:
- Create a compelling feature graphic and promotional video for the Google Play Store
deliverables:
- 1024x500 feature graphic
- 30-60 second promo video
- YouTube video link for Play Store
- Localized versions if applicable
steps:
1. Create feature graphic:
- Size: 1024x500 pixels (JPG or 24-bit PNG)
- Include app name and tagline
- Show app UI or brand imagery
- Use brand colors and typography
- Keep text minimal and readable
- Design for both light and dark Play Store themes
2. Plan promo video:
- 30-60 seconds showcasing core features
- Hook in first 5 seconds
- Show DarkWatch, VoicePrint, SpamShield, HomeTitle
- End with CTA "Download on Google Play"
- Background music (royalty-free)
3. Record and edit video:
- Use Android screen recorder or emulator
- Edit with DaVinci Resolve, Premiere, or CapCut
- Add smooth transitions
- Add text overlays for feature names
- Export in 1080p minimum
4. Upload to YouTube:
- Create unlisted or public video
- Add proper title, description, tags
- Add end screen with download link
- Copy video URL for Play Store
5. Upload to Play Console:
- Add feature graphic to store listing
- Add promo video URL
- Preview how it looks on Play Store
- Test on mobile and desktop Play Store
6. Create localized versions:
- Feature graphic text in Spanish, French (if targeting)
- Subtitles for promo video
tests:
- Visual: Review graphic and video quality
- Technical: Verify dimensions and format
- Content: Ensure no confidential data shown
acceptance_criteria:
- Feature graphic 1024x500 in correct format
- Promo video 30-60 seconds in 1080p
- Video uploaded to YouTube with proper metadata
- Feature graphic and video uploaded to Play Console
- Graphic readable on both light and dark themes
- Video showcases all core features
- CTA included at end of video
- No placeholder or test data visible
- Localized versions for supported markets
validation:
- Play Console preview → graphic and video display correctly
- YouTube video → plays correctly, good quality
- Mobile Play Store → graphic looks good on phone
- Team review → approved by 3+ members
notes:
- Feature graphic is the first thing users see on Play Store
- Video can significantly increase conversion rates
- Keep video under 60 seconds for best engagement
- Test video thumbnail for attractiveness

View File

@@ -0,0 +1,82 @@
# 03. Play Console Configuration
meta:
id: android-production-03
feature: android-production
priority: P1
depends_on: []
tags: [play-store, configuration, production]
objective:
- Complete all Google Play Console configuration for app submission and distribution
deliverables:
- App created in Play Console
- Signing key configured
- App bundles configured
- Pricing and distribution set
steps:
1. Create app in Play Console:
- App name: Kordant
- Default language: English
- App or game: App
- Free or paid: Free
2. Configure app signing:
- Generate upload key with keytool
- Upload public key certificate to Play Console
- Enable Google Play App Signing (recommended)
- Store keystore securely (password manager)
3. Set up internal testing:
- Create internal testing track
- Add test users by email
- Upload first internal build
- Verify testers can install
4. Configure store listing:
- Add screenshots, feature graphic, icon
- Write description and metadata
- Set category and contact details
- Add privacy policy URL
5. Set pricing and distribution:
- Price: Free
- Countries: All or selected
- Content rating: Everyone or Teen
- Complete content rating questionnaire
6. Configure in-app products (if applicable):
- Subscription products
- Managed products
- Promo codes for testing
7. Set up Play Integrity API:
- Enable for app attestation
- Configure server-side verification
- Add to backend API
tests:
- Build: Generate signed AAB (Android App Bundle)
- Upload: Upload to Play Console successfully
- Install: Testers can install from internal testing
acceptance_criteria:
- App created in Play Console
- App signing key generated and configured
- Google Play App Signing enabled
- Internal testing track created with testers
- Store listing complete with all assets
- Pricing set to free
- Distribution countries selected
- Content rating completed
- Play Integrity API enabled
- First build uploaded and processing
- Keystore backed up securely
validation:
- Generate signed AAB → successful
- Upload to Play Console → no errors
- Internal testers receive invite → can install
- Check Play Console → all sections green/complete
notes:
- Google Play App Signing is mandatory for new apps
- Keep keystore safe — losing it means losing ability to update app
- Internal testing is fastest way to distribute to team
- Play Integrity helps prevent tampered app usage

View File

@@ -0,0 +1,83 @@
# 04. Internal Testing Track
meta:
id: android-production-04
feature: android-production
priority: P1
depends_on: []
tags: [play-store, testing, production]
objective:
- Set up internal testing track with 20+ testers to validate app before public release
deliverables:
- Internal testing group with 20+ testers
- Testing feedback process
- Automated crash reporting
- Iteration cycle
steps:
1. Create internal testing track:
- In Play Console → Testing → Internal testing
- Add team members and trusted testers by email
- Target 20-100 testers
- Include various Android versions and devices
2. Upload first test build:
- Generate signed AAB
- Upload to internal testing track
- Add release notes
- Publish to internal testers
3. Prepare testing materials:
- Test invitation email template
- Testing checklist and focus areas
- Feedback collection form or channel
- Known issues list
4. Set up crash reporting:
- Integrate Firebase Crashlytics
- Enable NDK crash reporting if using native code
- Configure alerts for crash spikes
- Link crashes to specific builds
5. Collect and triage feedback:
- Review Play Console tester feedback
- Monitor Crashlytics for crashes
- Create issues from feedback
- Prioritize critical bugs
6. Iterate:
- Fix critical bugs within 1 week
- Upload new builds every 1-2 weeks
- Track tester retention and engagement
- Expand to closed testing after internal validation
7. Prepare for closed testing:
- Create closed testing track
- Plan external tester recruitment
- Prepare onboarding flow for new testers
tests:
- Distribution: Testers receive and install build
- Feedback: Feedback collection channel active
- Crash: Crash reporting receiving reports
acceptance_criteria:
- Internal testing track with 20+ testers
- First build uploaded and distributed
- Testers can install and run app
- Crash reporting active and receiving data
- Feedback collection process defined
- Known issues documented and shared
- New builds uploaded every 1-2 weeks
- Zero critical crashes in last 2 builds
- Closed testing track prepared
- Testers cover range of Android versions (10-14)
validation:
- Testers receive email invite → install app
- Run app → no immediate crashes
- Submit feedback → received by team
- Simulate crash → appears in Crashlytics
- Upload new build → testers receive update
notes:
- Internal testing is immediate (no review)
- Closed testing requires Google review (may take days)
- Use Firebase App Distribution for faster iteration if needed
- Test on physical devices, not just emulators

View File

@@ -0,0 +1,72 @@
# 05. Certificate Pinning & Network Security Config
meta:
id: android-production-05
feature: android-production
priority: P1
depends_on: []
tags: [security, networking, production]
objective:
- Implement certificate pinning and network security configuration to prevent man-in-the-middle attacks
deliverables:
- network_security_config.xml with certificate pinning
- OkHttp certificate pinner configuration
- TLS 1.3 enforcement
- Certificate rotation support
steps:
1. Create network security config:
- Add res/xml/network_security_config.xml
- Configure domain config with certificate pinning
- Include production certificate hashes
- Add debug overrides for development
2. Implement OkHttp certificate pinner:
- Modify NetworkModule.kt or OkHttp client builder
- Add CertificatePinner with pinned certificates
- Support multiple pins for rotation
- Log pinning failures for monitoring
3. Configure TLS settings:
- Enforce TLS 1.3 in OkHttp connection specs
- Disable weak cipher suites
- Enable certificate transparency
4. Add to manifest:
- Add android:networkSecurityConfig to AndroidManifest.xml
- Reference network_security_config.xml
5. Implement certificate rotation:
- Support old and new certificate hashes
- Grace period during rotation (30 days)
- Alert when certificate nearing expiry
6. Add tests:
- Test with correct certificate → connection succeeds
- Test with wrong certificate → connection fails
- Test certificate rotation → seamless transition
tests:
- Unit: Test certificate pinning with mock certificates
- Integration: Test against staging with pinned cert
- Security: Attempt MITM with proxy → blocked
acceptance_criteria:
- network_security_config.xml present in resources
- Certificate pinning active on all API requests
- TLS 1.3 enforced
- MITM attacks blocked (tested with proxy tools)
- Certificate rotation supported with grace period
- Pinning failures logged
- Debug config separate from production
- Unit tests covering pinning success and failure
- No hardcoded certificates in source (use hashes)
validation:
- Run app with correct cert → API calls succeed
- Run app with Charles Proxy MITM → API calls fail
- Check logs → pinning verification logged
- Inspect manifest → networkSecurityConfig referenced
notes:
- Use public key pinning (SHA-256 hash) rather than full certificate
- Include backup pin for certificate rotation
- OkHttp's CertificatePinner is easy to configure
- Test on physical device — emulator may behave differently

View File

@@ -0,0 +1,86 @@
# 06. Root Detection & Obfuscation (R8/ProGuard)
meta:
id: android-production-06
feature: android-production
priority: P1
depends_on: []
tags: [security, hardening, production]
objective:
- Enable code obfuscation with R8/ProGuard and implement root detection to protect the app on compromised devices
deliverables:
- R8/ProGuard enabled in release builds
- Root detection implementation
- Anti-tampering measures
- Code obfuscation rules
steps:
1. Enable R8/ProGuard:
- Set isMinifyEnabled = true in app/build.gradle.kts (currently false)
- Set isShrinkResources = true
- Add proguard-rules.pro with keep rules:
- Keep tRPC model classes (for serialization)
- Keep Retrofit interfaces
- Keep Compose navigation routes
- Keep Dagger/Hilt modules
2. Configure ProGuard rules:
- Keep all data model classes (User, Alert, Exposure, etc.)
- Keep Retrofit service interfaces
- Keep Hilt/Dagger components
- Keep Compose preview functions
- Keep enum values used in serialization
3. Implement root detection:
- Use RootBeer or similar library
- Check for common root indicators:
- su binary presence
- Busybox installation
- Test keys build
- Dangerous props
- Add custom checks for Magisk
4. Define root response:
- Degrade functionality (no biometric, no payments)
- Alert backend of root detection
- Allow basic monitoring features
5. Add anti-tampering:
- Verify app signature at runtime
- Check installer source (Google Play)
- Detect debug mode in release builds
- Detect emulator usage
6. Test obfuscation:
- Build release APK/AAB
- Verify classes obfuscated
- Test app functionality after obfuscation
- Verify no crashes from missing classes
tests:
- Build: Release build succeeds with R8 enabled
- Security: Root detection works on rooted device
- Functionality: App works correctly after obfuscation
acceptance_criteria:
- R8/ProGuard enabled (isMinifyEnabled = true)
- Resource shrinking enabled (isShrinkResources = true)
- ProGuard rules preserving all necessary classes
- Root detection active with multiple methods
- App degrades gracefully on rooted devices
- Backend alerted when root detected
- Code obfuscated in release builds
- Anti-tampering verifying app signature
- No crashes from obfuscation
- Release APK/AAB size reduced by >30%
validation:
- Build release → succeeds, no ProGuard warnings
- Decompile release APK → classes obfuscated
- Run on rooted device → degraded mode activated
- Run on non-rooted device → full functionality
- Check size → release build smaller than debug
notes:
- R8 is the modern replacement for ProGuard in Android
- isMinifyEnabled = false currently — this is a critical security gap
- Root detection can be bypassed — use as defense in depth
- Keep rules are critical — missing keeps cause runtime crashes
- Test thoroughly after enabling R8 — many issues only appear in release

View File

@@ -0,0 +1,80 @@
# 07. Encrypted SharedPreferences & DataStore Audit
meta:
id: android-production-07
feature: android-production
priority: P1
depends_on: []
tags: [security, data-protection, production]
objective:
- Audit and secure all local data storage using encrypted SharedPreferences and DataStore
deliverables:
- EncryptedSharedPreferences for sensitive data
- DataStore for preferences
- Secure data deletion
- Storage audit report
steps:
1. Audit current storage:
- Review all SharedPreferences usage
- Review DataStore usage
- Review CacheManager.kt
- Identify all sensitive data stored locally
2. Implement encrypted preferences:
- Use EncryptedSharedPreferences from androidx.security
- Store auth tokens, refresh tokens
- Store biometric preference
- Store user profile data
3. Configure DataStore:
- Use DataStore for non-sensitive preferences
- Theme, language, notification settings
- Migrate from SharedPreferences if needed
4. Secure CacheManager:
- Ensure no sensitive data in unencrypted cache
- Encrypt cached API responses containing PII
- Set cache size limits
- Implement secure eviction
5. Add secure deletion:
- Overwrite sensitive data before removal
- Clear all secure storage on logout
- Handle account deletion (GDPR)
6. Add backup exclusion:
- Exclude encrypted preferences from cloud backup
- Mark sensitive files with android:allowBackup="false"
- Document backup strategy
7. Test storage security:
- Verify data encrypted at rest
- Verify no plaintext sensitive data in files
- Test backup/restore behavior
tests:
- Unit: Test encrypted storage read/write
- Security: Verify no plaintext tokens in files
- Integration: Test logout clears all data
acceptance_criteria:
- All sensitive data in EncryptedSharedPreferences
- Auth tokens encrypted at rest
- Refresh tokens encrypted at rest
- Non-sensitive preferences in DataStore
- No sensitive data in unencrypted cache
- Secure deletion overwriting data
- Sensitive storage excluded from backup
- Logout clears all auth data
- Account deletion removes all local data
- No plaintext sensitive data discoverable in app files
validation:
- Inspect app files → no plaintext tokens
- Check EncryptedSharedPreferences → data encrypted
- Logout → all auth data cleared
- Backup app → sensitive data not included
- Account deletion → all data removed
notes:
- EncryptedSharedPreferences uses AES-256 encryption
- Master key stored in Android Keystore
- DataStore is modern replacement for SharedPreferences
- Consider using SQLCipher for database encryption if using Room

View File

@@ -0,0 +1,76 @@
# 08. OAuth & Social Login Integration
meta:
id: android-production-08
feature: android-production
priority: P1
depends_on: []
tags: [auth, security, production]
objective:
- Implement Google Sign-In and other OAuth providers, replacing any stubbed auth with real backend integration
deliverables:
- Google Sign-In integration
- Backend OAuth token exchange
- AuthRepository wired to real API
- Token refresh handling
steps:
1. Implement Google Sign-In:
- Configure Google Sign-In in Firebase Console
- Add google-services.json to project
- Integrate Google Sign-In SDK (com.google.android.gms:play-services-auth)
- Handle ID token and send to backend
2. Update backend for OAuth:
- Add OAuth endpoints to tRPC user router
- Verify Google ID token with Google certs
- Create/link user accounts from OAuth providers
- Return session token after OAuth login
3. Update AuthRepository:
- Modify AuthRepositoryImpl to use real API
- Implement login, signup, forgotPassword with real endpoints
- Handle OAuth token exchange
- Wire into AuthViewModel
4. Add token refresh:
- Implement refresh token rotation
- Silent token refresh on expiry
- Handle refresh failure (re-authenticate)
5. Add logout:
- Revoke OAuth tokens where possible
- Clear all local auth state
- Notify backend of logout
6. Handle errors:
- Map API errors to user-friendly messages
- Handle network errors gracefully
- Handle cancelled sign-in attempts
tests:
- Unit: Test OAuth token parsing
- Integration: Test Google Sign-In flow end-to-end
- Security: Verify token validation rejects invalid tokens
acceptance_criteria:
- Google Sign-In working with Firebase
- OAuth tokens verified server-side
- User accounts created or linked correctly
- AuthRepository uses real API in production
- Token refresh working silently
- Logout clears all auth state and revokes tokens
- Error handling for all auth scenarios
- Unit tests use mock repository
- Production builds use real repository
- No stubbed auth in production code
validation:
- Tap Google Sign-In → Google flow → authenticate → logged in
- Check backend → user created with Google provider
- Wait for token expiry → automatic refresh
- Logout → all tokens cleared, login screen shown
- Check build variant → debug uses staging, release uses production
notes:
- Google Sign-In is the most common OAuth on Android
- Consider adding Apple Sign-In for cross-platform consistency
- Backend must verify Google JWT with Google's public key
- Use Credential Manager for modern Android auth (API 34+)

View File

@@ -0,0 +1,75 @@
# 09. Image Caching & Coil Optimization
meta:
id: android-production-09
feature: android-production
priority: P2
depends_on: []
tags: [performance, caching, production]
objective:
- Optimize Coil image caching and loading for better performance and reduced network usage
deliverables:
- Coil cache configuration
- Image loading optimization
- Lazy loading for lists
- Memory and disk cache limits
steps:
1. Configure Coil:
- Set up ImageLoader in KordantApp.kt
- Configure memory cache (50MB)
- Configure disk cache (100MB)
- Set crossfade animation
- Configure placeholder and error drawables
2. Optimize image loading:
- Use appropriate image sizes (thumbnail vs full)
- Enable image transformations (circle crop for avatars)
- Use WebP format where supported
- Configure request priorities
3. Implement lazy loading:
- Use LazyColumn for all lists
- Implement pagination for long lists
- Add prefetching for adjacent items
- Show skeleton placeholders while loading
4. Add offline support:
- Cache images for offline viewing
- Show cached images when offline
- Handle network errors gracefully
5. Optimize memory usage:
- Clear memory cache on low memory
- Limit concurrent image loads
- Cancel loads for off-screen items
6. Add tests:
- Test cache hit/miss behavior
- Test scrolling performance with many images
tests:
- Unit: Test cache configuration
- Performance: Test scrolling with 1000 images
- Memory: Verify no memory leaks
acceptance_criteria:
- Coil ImageLoader configured with 50MB memory / 100MB disk cache
- Lazy loading on all lists with pagination
- Image placeholders while loading
- Error state for failed loads
- Cache cleared on low memory
- Offline image viewing working
- Smooth 60fps scrolling on image-heavy screens
- No memory leaks in image loading
- Crossfade animation on image load
- Appropriate image sizes requested from backend
validation:
- Scroll through alert list → smooth, no stuttering
- Turn on airplane mode → cached images still visible
- Monitor memory → stable during image browsing
- Check cache directory → images stored with correct expiration
notes:
- Coil is already included in dependencies (libs.coil.compose)
- Configuration happens in Application class
- Use rememberAsyncImagePainter for Compose integration
- Test on low-end devices for performance validation

View File

@@ -0,0 +1,77 @@
# 10. Pagination & List Performance
meta:
id: android-production-10
feature: android-production
priority: P2
depends_on: []
tags: [performance, lists, production]
objective:
- Implement pagination and optimize list performance to prevent ANRs and jank on large datasets
deliverables:
- Pagination for all list endpoints
- LazyColumn optimization
- DiffUtil or Compose lazy list optimization
- ANR prevention
steps:
1. Implement pagination:
- Add pagination to tRPC list endpoints (if not already)
- Use Paging 3 library for Jetpack Compose
- Configure page size (20-50 items)
- Add pagination parameters to API calls
2. Optimize LazyColumn:
- Use key parameter for item stability
- Use contentType for different item types
- Avoid unnecessary recompositions
- Use remember for expensive calculations
3. Add loading states:
- Skeleton placeholders while loading first page
- Load more indicator at bottom
- Empty state for no data
- Error state with retry
4. Optimize data flow:
- Use Flow/PagingData in ViewModels
- CollectAsStateWithLifecycle for Compose
- Avoid collecting flows in composables directly
5. Prevent ANRs:
- Move heavy calculations to background threads
- Use viewModelScope for coroutines
- Avoid blocking main thread
- Profile with Android Profiler
6. Add tests:
- Test pagination boundaries
- Test scroll performance
- Test memory usage with large lists
tests:
- Unit: Test pagination logic
- Performance: Scroll test with 1000+ items
- ANR: Profile main thread during list operations
acceptance_criteria:
- All lists paginated (20-50 items per page)
- Paging 3 library used for Compose integration
- LazyColumn with key and contentType optimization
- Skeleton placeholders on initial load
- Load more indicator on scroll
- Empty and error states handled
- No ANRs during list operations
- 60fps scrolling on lists >100 items
- Memory stable during list scrolling
- Unit tests for pagination logic
validation:
- Scroll through alert list → smooth 60fps
- Scroll to bottom → next page loads automatically
- Check Android Profiler → no main thread blocking
- Memory monitor → stable during scrolling
- Test with 1000 items → no ANR, no OOM
notes:
- Paging 3 is the modern standard for Android pagination
- ANRs on lists are often caused by blocking main thread
- Use LazyColumn, not Column, for long lists
- Test on low-end devices (Android 10, 2GB RAM)

View File

@@ -0,0 +1,82 @@
# 11. Background Sync & WorkManager Optimization
meta:
id: android-production-11
feature: android-production
priority: P2
depends_on: []
tags: [performance, background, production]
objective:
- Optimize background sync using WorkManager to keep data fresh without excessive battery drain
deliverables:
- WorkManager periodic sync workers
- Battery-efficient sync strategy
- Constraint-based scheduling
- Sync status indicators
steps:
1. Audit existing sync:
- Review android/app/.../data/sync/SyncManager.kt
- Review OfflineWorker.kt
- Identify sync frequency and triggers
2. Optimize sync workers:
- Use PeriodicWorkRequest for regular sync (15 min minimum)
- Use OneTimeWorkRequest for immediate sync
- Set constraints: requires network, battery not low
- Use expedited work for urgent syncs
3. Implement battery-efficient sync:
- Batch network requests
- Use delta sync (only changed data)
- Respect doze mode and app standby
- Use JobScheduler for API 21-22 (WorkManager uses internally)
4. Add sync types:
- Alert sync: high priority, frequent
- Exposure sync: medium priority
- Spam database update: low priority, daily
- Watchlist sync: on change
5. Add user controls:
- Settings toggle for background sync
- Sync frequency preference (if applicable)
- Manual sync button in settings
- Last sync timestamp display
6. Handle failures:
- Exponential backoff for failed syncs
- Max retry limit
- Alert user after repeated failures
- Queue syncs for when online
7. Add tests:
- Test worker execution
- Test constraint handling
- Test battery impact
tests:
- Unit: Test worker logic
- Integration: Test WorkManager scheduling
- Battery: Verify minimal battery impact
acceptance_criteria:
- WorkManager configured for periodic sync
- Sync constraints: network available, battery not low
- Delta sync reducing data transfer
- Background sync respects doze mode
- User can enable/disable background sync
- Manual sync button in settings
- Last sync timestamp visible
- Failed syncs retry with exponential backoff
- Battery impact <5% per day from background sync
- Unit tests for all worker classes
validation:
- Enable background sync → workers scheduled
- Turn on airplane mode → sync deferred
- Disable battery saver → sync resumes
- Check battery settings → Kordant background usage minimal
- Trigger manual sync → data updates immediately
notes:
- WorkManager is already included (libs.work.runtime.ktx)
- Minimum periodic work interval is 15 minutes
- Android 12+ has stricter background restrictions
- Use Foreground Service for urgent syncs if needed

View File

@@ -0,0 +1,77 @@
# 12. App Startup Time & ANR Prevention
meta:
id: android-production-12
feature: android-production
priority: P2
depends_on: []
tags: [performance, startup, production]
objective:
- Optimize app startup time and prevent ANRs to ensure smooth user experience
deliverables:
- Startup time measurement and baseline
- Lazy initialization of heavy components
- ANR prevention measures
- App Startup library integration
steps:
1. Measure current startup time:
- Use Android Studio Profiler
- Use Macrobenchmark library
- Measure cold start (first launch)
- Measure warm start (subsequent launches)
- Establish baseline metrics
2. Optimize Application.onCreate:
- Minimize work in KordantApp.onCreate
- Use App Startup library for initialization ordering
- Defer non-critical initialization
- Initialize on background threads where possible
3. Lazy load heavy components:
- Defer TRPCApiService initialization until needed
- Lazy load repository dependencies
- Defer analytics initialization
- Use Dagger/Hilt lazy injection
4. Optimize theme and layout:
- Use simple splash theme (windowBackground only)
- Avoid complex layouts in first screen
- Preload critical resources
5. Prevent ANRs:
- Move all IO operations to background threads
- Use coroutines with Dispatchers.IO
- Avoid blocking main thread in composables
- Profile with StrictMode in debug builds
6. Add tests:
- Macrobenchmark tests for startup time
- ANR detection in CI
- Memory usage during startup
tests:
- Performance: Startup time <1.5s on Pixel 6
- ANR: No ANRs during critical flows
- Memory: No memory spikes during startup
acceptance_criteria:
- Cold startup time <1.5 seconds on Pixel 6
- Warm startup time <1 second on Pixel 6
- Splash screen visible for <500ms
- No blocking operations on main thread during startup
- Heavy components loaded lazily
- ANR-free during all critical user flows
- Macrobenchmark tests for startup time
- Startup time tracked in CI
- No StrictMode violations in debug builds
validation:
- Android Profiler → cold start <1.5s
- Macrobenchmark → startup metrics within budget
- StrictMode → no disk/network on main thread
- Physical device test → feels instant
- ANR traces → none from Kordant
notes:
- Android Vitals tracks startup time and ANRs automatically
- ANR threshold is 5 seconds for input, 10 seconds for BroadcastReceiver
- App Startup library helps manage initialization order
- Test on low-end devices (Android 10, 2GB RAM)

View File

@@ -0,0 +1,86 @@
# 13. Call Screening Service Production Hardening
meta:
id: android-production-13
feature: android-production
priority: P1
depends_on: []
tags: [native-features, spamshield, production]
objective:
- Harden the CallScreeningService for production use with robust spam detection and minimal latency
deliverables:
- CallScreeningService production-ready
- Spam database local caching
- Real-time caller lookup
- Permission handling and user guidance
steps:
1. Audit existing service:
- Review android/app/.../service/CallScreeningService.kt
- Identify gaps in production readiness
- Test current functionality
2. Implement local spam database:
- Cache spam numbers locally (Room database)
- Sync with backend periodically
- Hash numbers for privacy
- Support pattern matching (wildcards)
3. Optimize lookup performance:
- Use indexed database queries
- Target <100ms lookup time
- Cache frequent lookups in memory
- Use Bloom filter for fast negative checks
4. Add caller identification:
- Display caller info for known contacts
- Show spam likelihood percentage
- Show spam category (telemarketer, scam, etc.)
5. Handle permissions:
- Request CALL_SCREENING role
- Guide user to Default Apps settings
- Handle permission denial gracefully
- Re-check permission on app launch
6. Add user controls:
- Toggle for call screening
- Toggle for call blocking
- Manage blocked numbers
- Report false positives/negatives
7. Add logging and analytics:
- Log screened calls (anonymized)
- Track block rate and accuracy
- Report metrics to backend
8. Test thoroughly:
- Test with simulated calls
- Test on physical devices
- Test with various carriers
tests:
- Unit: Test spam lookup logic
- Integration: Test CallScreeningService binding
- Device: Test with actual incoming calls
acceptance_criteria:
- CallScreeningService registered and active
- Local spam database synced daily
- Caller lookup <100ms
- Known spam calls blocked or flagged
- User can enable/disable screening
- Block list manageable from app
- Permission handling with user guidance
- False positive reporting mechanism
- No crashes during call handling
- Works on Android 10+ (API 29+)
- Battery impact minimal
validation:
- Enable call screening → incoming spam call blocked
- Check database → spam numbers cached locally
- Measure lookup time → <100ms
- Report false positive → number removed from block list
- Disable in app → screening stops
notes:
- CallScreeningService requires special role (not just permission)
- User must set app as default call screening app in Settings
- Different carriers may handle call screening differently
- Test thoroughly on physical devices with real SIM cards

View File

@@ -0,0 +1,89 @@
# 14. Notification Channels & Rich Notifications
meta:
id: android-production-14
feature: android-production
priority: P2
depends_on: []
tags: [native-features, notifications, production]
objective:
- Implement notification channels and rich notifications for Android 8+ with proper categorization and user controls
deliverables:
- Notification channels for all notification types
- Rich notifications with images and actions
- Notification permission handling (Android 13+)
- Deep linking from notifications
steps:
1. Create notification channels:
- Security Alerts (high importance, sound + vibration)
- Exposure Warnings (high importance)
- Scan Complete (default importance)
- Family Activity (default importance)
- Marketing/Promotions (low importance, no sound)
- System (low importance)
2. Configure channel properties:
- Importance levels appropriate per type
- Sound selection for alerts
- Vibration patterns
- LED color for alerts
- Lock screen visibility
3. Implement rich notifications:
- Large icon for user avatar or app icon
- BigPictureStyle for exposure screenshots
- BigTextStyle for alert descriptions
- MessagingStyle for family notifications
- Inline reply for quick actions
4. Add notification actions:
- Alert: "View Details", "Dismiss", "Mark Safe"
- Exposure: "View Exposure", "Start Removal"
- Scan Complete: "View Results", "Share"
5. Handle Android 13+ permissions:
- Request POST_NOTIFICATIONS permission
- Show rationale before system dialog
- Handle permission denial gracefully
- Guide users to Settings if denied
6. Add FCM integration:
- Review FCMService.kt
- Handle different message types
- Show notifications for data messages
- Handle notification tap actions
7. Test all scenarios:
- Foreground notification handling
- Background notification handling
- Killed app notification handling
- Notification action taps
tests:
- Unit: Test notification builder logic
- Integration: Test FCM message handling
- Device: Test on Android 10, 12, 13, 14
acceptance_criteria:
- Notification channels created for all types
- Channels have appropriate importance and settings
- Rich notifications with images and actions
- Notification permission requested on Android 13+
- Permission rationale shown before system dialog
- Deep links from notifications to correct screens
- Notification actions working
- FCM integration handling all message types
- Notifications grouped by channel
- No duplicate notifications
- Unit tests for notification builders
validation:
- Send test alert notification → displays with actions
- Send exposure notification → shows image
- Deny permission → app shows guidance to Settings
- Tap notification → opens correct screen
- Tap action button → correct action performed
- Check settings → notification channels visible
notes:
- Android 13 (API 33) requires runtime permission for notifications
- Notification channels cannot be changed programmatically after creation
- FCMService.kt already exists but may need enhancement
- Test on different OEM skins (Samsung, Xiaomi, Pixel)

View File

@@ -0,0 +1,84 @@
# 15. App Shortcuts & Widgets
meta:
id: android-production-15
feature: android-production
priority: P2
depends_on: []
tags: [native-features, widgets, production]
objective:
- Implement app shortcuts and home screen widgets to improve user engagement and accessibility
deliverables:
- Dynamic and static app shortcuts
- Home screen widget (threat score)
- Widget configuration
- Shortcut deep linking
steps:
1. Implement app shortcuts:
- Static shortcuts in shortcuts.xml:
- "View Dashboard" → opens dashboard
- "Check Alerts" → opens alerts
- "Run Scan" → starts DarkWatch scan
- Dynamic shortcuts:
- "Recent Alert" → opens latest alert
- "Quick Check" → runs quick threat assessment
2. Create home screen widget:
- GlanceAppWidget for modern Compose widgets
- Or traditional AppWidgetProvider
- Sizes: 2x1 (threat score), 3x2 (score + alerts)
- Update every 30 minutes (widget limit)
3. Design widget UI:
- Match app design system
- Show threat score with color coding
- Show number of unread alerts
- Show last update time
- Support dark/light themes
4. Implement widget updates:
- Update on app data refresh
- Schedule periodic updates
- Handle widget configuration changes
5. Add deep linking:
- Tap widget → open dashboard
- Tap alert count → open alerts list
- Tap threat score → open dashboard
6. Add preview:
- Widget preview image for picker
- Description for accessibility
7. Test:
- Add widget to home screen
- Verify updates work
- Test shortcuts
tests:
- Unit: Test widget provider
- Integration: Test shortcut deep links
- UI: Test widget rendering
acceptance_criteria:
- 3+ app shortcuts defined
- Static shortcuts working
- Dynamic shortcuts updated based on user activity
- Home screen widget showing threat score
- Widget updates every 30 minutes
- Widget supports dark and light themes
- Deep links from shortcuts and widgets work
- Widget preview in picker
- No crashes when widget data missing
- Widgets work on Android 8+ (API 26+)
validation:
- Long press app icon → shortcuts visible
- Tap shortcut → correct screen opens
- Add widget to home screen → threat score displayed
- Receive new alert → widget updates
- Tap widget → dashboard opens
- Check widget in dark mode → colors correct
notes:
- App shortcuts are great for power users
- Widgets use RemoteViews (limited UI capabilities)
- Glance is modern but requires additional dependency
- Test on different launchers (Pixel, Samsung, Nova)

View File

@@ -0,0 +1,78 @@
# 16. App Actions & Slices
meta:
id: android-production-16
feature: android-production
priority: P3
depends_on: []
tags: [native-features, assistant, production]
objective:
- Implement App Actions for Google Assistant integration, allowing users to interact with Kordant via voice commands
deliverables:
- App Actions XML definitions
- Fulfillment handlers for voice commands
- Built-in intents (BIIs) integration
- Test with Assistant
steps:
1. Define App Actions:
- Check threat score: "Hey Google, check my threat score on Kordant"
- Run security scan: "Hey Google, run a security scan on Kordant"
- Check alerts: "Hey Google, do I have security alerts on Kordant"
- Open dashboard: "Hey Google, open Kordant"
2. Create actions.xml:
- Define built-in intents (actions.intent.OPEN_APP_FEATURE)
- Map intents to app deep links
- Add parameter extraction
3. Implement fulfillment:
- Handle incoming intents in MainActivity
- Extract parameters from voice commands
- Navigate to correct screen
- Return results to Assistant (if applicable)
4. Add deep links:
- kordant://dashboard
- kordant://alerts
- kordant://scan
- kordant://settings
5. Test with Assistant:
- Use App Actions test tool
- Test on physical device with Assistant
- Verify voice commands work end-to-end
6. Add Slice (optional):
- Create SliceProvider for threat score
- Show in Google Search results
- Update periodically
7. Document:
- List of supported voice commands
- Example phrases for users
tests:
- Unit: Test intent handling
- Integration: Test with App Actions test tool
- Device: Test with Google Assistant
acceptance_criteria:
- App Actions defined in actions.xml
- 3+ voice commands working
- Built-in intents properly mapped
- Deep links handling all actions
- Assistant returns to app after command
- App Actions test tool passes all tests
- Voice commands tested on physical device
- Documentation of supported commands
- Slices implemented (optional)
- No crashes from malformed intents
validation:
- Say "Hey Google, check my threat score on Kordant" → app opens to dashboard
- Say "Hey Google, run a security scan on Kordant" → scan initiated
- App Actions test tool → all tests pass
- Check Google Assistant → Kordant listed in supported apps
notes:
- App Actions require Google Play Services
- Built-in intents are limited — custom intents not supported for third-party apps
- Slices are being deprecated in favor of Widgets
- Focus on most useful commands (check score, run scan)

View File

@@ -0,0 +1,86 @@
# 17. UI Test Suite (Compose Testing)
meta:
id: android-production-17
feature: android-production
priority: P1
depends_on: []
tags: [testing, ui-tests, quality]
objective:
- Implement comprehensive UI tests using Jetpack Compose Testing framework for all critical user journeys
deliverables:
- Compose UI tests for auth flows
- Compose UI tests for dashboard and services
- Compose UI tests for settings
- Test utilities and mocks
steps:
1. Set up Compose testing:
- Dependencies already in build.gradle.kts (androidx.compose.ui.test.junit4)
- Create test directory structure
- Add TestRule for ComposeTestRule
2. Create auth tests:
- Test onboarding flow
- Test login with valid credentials
- Test login with invalid credentials
- Test signup flow
- Test forgot password flow
- Test biometric prompt
3. Create dashboard tests:
- Test dashboard loads with widgets
- Test navigation to services
- Test alert list and detail
- Test threat score display
- Test pull-to-refresh
4. Create service tests:
- Test DarkWatch screen
- Test VoicePrint screen
- Test SpamShield screen
- Test HomeTitle screen
- Test RemoveBrokers screen
5. Create settings tests:
- Test settings screen loads
- Test profile update
- Test notification toggles
- Test logout
6. Add test utilities:
- Mock repository implementations
- Test data factories
- Navigation test helpers
- Hilt test configuration
7. Configure CI:
- Run UI tests on PR
- Test on multiple API levels (28, 30, 33, 34)
- Generate test reports
tests:
- UI: All critical paths covered
- CI: Tests run automatically
- Coverage: 80%+ of composables tested
acceptance_criteria:
- 20+ Compose UI test cases
- Auth flow fully tested
- All 5 services have UI tests
- Dashboard and alerts tested
- Settings and profile tested
- Tests run on API 28, 30, 33, 34
- Tests complete in <10 minutes
- Hilt injection working in tests
- Mock repositories for isolated tests
- CI runs UI tests on every PR
- Screenshots on failure
validation:
- Run UI tests → all pass
- Introduce UI bug → test fails
- Check test report → screenshots for failures
- CI pipeline → UI tests green
notes:
- Compose testing uses semantics and test tags
- Use createComposeRule() for Compose tests
- Hilt testing requires HiltTestApplication
- Test on emulators with different screen sizes

View File

@@ -0,0 +1,79 @@
# 18. Screenshot Testing (Paparazzi)
meta:
id: android-production-18
feature: android-production
priority: P2
depends_on: []
tags: [testing, screenshots, quality]
objective:
- Implement screenshot testing with Paparazzi to catch UI regressions across different screen sizes and themes
deliverables:
- Paparazzi integration
- Screenshot tests for key screens
- CI verification for screenshot changes
- Golden screenshot baseline
steps:
1. Add Paparazzi:
- Add plugin to build.gradle.kts
- Configure for library or application module
- Set up test directory
2. Create screenshot tests:
- Test LoginScreen in light and dark themes
- Test DashboardScreen with data
- Test AlertItem component
- Test ServiceRow component
- Test SettingsScreen
- Test empty states and error states
3. Generate golden screenshots:
- Run tests to generate baseline screenshots
- Review and commit baseline images
- Document generation process
4. Add CI integration:
- Run screenshot tests on PR
- Fail on unapproved changes
- Upload diff images for review
- Require approval for screenshot changes
5. Test multiple configurations:
- Light theme
- Dark theme
- Different screen widths (phone, tablet)
- Different font sizes
- RTL layout (if supporting)
6. Maintain screenshots:
- Update baseline when UI intentionally changes
- Document update process in README
- Review all screenshot changes in PR
tests:
- Visual: Screenshot tests pass with no changes
- Regression: UI change detected and flagged
- Coverage: All key screens have screenshot tests
acceptance_criteria:
- Paparazzi integrated and configured
- Screenshot tests for 10+ key screens/components
- Golden baseline screenshots generated
- Tests cover light and dark themes
- Tests cover phone and tablet sizes
- CI runs screenshot tests and flags changes
- Diff images uploaded for review
- Screenshot changes require explicit approval
- No false positives from font rendering differences
- Documentation for updating baselines
validation:
- Run screenshot tests → all pass (no changes)
- Change button color → test fails with diff image
- Review diff → clearly shows what changed
- Update baseline → tests pass again
- CI → screenshot check green or shows diff
notes:
- Paparazzi runs tests on JVM (fast, no emulator needed)
- Golden images must be committed to repository
- Be careful with font rendering differences across OS
- Consider using Roborazzi for Compose-specific screenshot testing

View File

@@ -0,0 +1,82 @@
# 19. Accessibility Audit (TalkBack)
meta:
id: android-production-19
feature: android-production
priority: P2
depends_on: []
tags: [testing, accessibility, compliance]
objective:
- Ensure the Android app is fully accessible with TalkBack and meets WCAG 2.1 AA mobile guidelines
deliverables:
- TalkBack audit report
- Accessibility labels on all elements
- Dynamic Type support
- Color contrast verification
steps:
1. Audit all screens with TalkBack:
- Enable TalkBack (Settings → Accessibility)
- Navigate every screen using swipe gestures
- Verify all interactive elements have labels
- Verify logical reading order
- Test with eyes closed
2. Add missing accessibility labels:
- Add contentDescription to all Image composables
- Add semantics { contentDescription = "..." } to icons
- Group related elements with mergeDescendants
- Add state descriptions for toggles
3. Test Dynamic Type:
- Enable largest font size in Settings
- Test all screens at largest text size
- Verify no truncation or overlap
- Use scrollable containers where needed
4. Verify color contrast:
- Test all text/background combinations
- Ensure 4.5:1 ratio for normal text
- Ensure 3:1 ratio for large text and UI components
- Test in both light and dark themes
5. Test Switch Access:
- Enable Switch Access
- Verify all actions reachable
- Test focus traversal order
6. Test keyboard navigation:
- Navigate with Bluetooth keyboard
- Verify Tab order logical
- Verify Enter/Space activation
7. Add automated tests:
- Use AccessibilityScanner for quick checks
- Add Compose semantics tests
- Test with uiautomator
tests:
- Manual: Full TalkBack navigation of all screens
- Automated: AccessibilityScanner results
- Visual: Color contrast verification
acceptance_criteria:
- All interactive elements have content descriptions
- TalkBack reads logical description for every element
- Dynamic Type supported at all sizes
- Color contrast ≥4.5:1 for all text
- Switch Access navigable
- Keyboard navigation works
- No accessibility warnings in lint
- Accessibility audit report completed
- Screenshots at largest font size showing no issues
- Compose semantics tests passing
validation:
- Turn on TalkBack → navigate entire app without visual
- Enable largest font size → all screens readable
- Check contrast → all combinations pass
- Run AccessibilityScanner → no suggestions
- Lint check → no accessibility warnings
notes:
- Compose has good accessibility by default but custom composables need attention
- Use Modifier.semantics { } for custom accessibility
- Test on physical device — emulator TalkBack is limited
- Consider hiring accessibility consultant for thorough audit

View File

@@ -0,0 +1,87 @@
# 20. Firebase Test Lab Integration
meta:
id: android-production-20
feature: android-production
priority: P2
depends_on: []
tags: [testing, device-farm, quality]
objective:
- Integrate Firebase Test Lab for automated testing on a wide range of physical Android devices
deliverables:
- Firebase Test Lab configuration
- Robo test configuration
- Instrumentation test execution
- Test results and reports
steps:
1. Set up Firebase Test Lab:
- Create Firebase project
- Link to Google Play Console
- Enable Blaze plan (pay-as-you-go)
- Install gcloud CLI
2. Configure test matrix:
- Select device models:
- Pixel 6 (API 33)
- Pixel 4 (API 30)
- Samsung Galaxy S21 (API 31)
- Xiaomi Redmi (API 29)
- Low-end device (API 28, 2GB RAM)
- Select orientations: portrait, landscape
- Select locales: en_US, es_ES
3. Run Robo tests:
- Upload APK/AAB
- Configure Robo crawl (timeout, login credentials)
- Run on device matrix
- Review crawl map and screenshots
4. Run instrumentation tests:
- Upload test APK
- Configure test runner
- Execute UI tests on device matrix
- Collect test results and videos
5. Integrate with CI:
- Add gcloud commands to GitHub Actions
- Run on release builds
- Block release on critical failures
- Upload results as artifacts
6. Analyze results:
- Review screenshots from all devices
- Watch test videos for failures
- Check performance metrics
- Document device-specific issues
7. Fix issues:
- Address failures on specific devices
- Fix OEM-specific bugs
- Optimize for low-end devices
tests:
- Device: All selected devices pass tests
- Regression: No new failures compared to previous run
- Performance: App responsive on all devices
acceptance_criteria:
- Firebase Test Lab project configured
- Test matrix with 5+ different devices
- Robo tests running on each release build
- Instrumentation tests running on device matrix
- CI integration for automated execution
- Test results archived
- Screenshots and videos from all test runs
- Device-specific issues identified and fixed
- No crashes on any tested device
- Performance acceptable on low-end device
validation:
- Run tests via gcloud → all devices complete
- Review results → screenshots show correct UI
- Watch videos → no ANRs or crashes
- Check performance metrics → within budget
- CI pipeline → Test Lab results green
notes:
- Firebase Test Lab is free for first 100 device-minutes/day (physical)
- Robo tests are great for exploratory testing without writing tests
- Physical devices are more reliable than virtual devices
- Test on low-end devices to catch performance issues

View File

@@ -0,0 +1,84 @@
# 21. Real API Client Verification & Wire-up
meta:
id: android-production-21
feature: android-production
priority: P1
depends_on: []
tags: [backend, api, production]
objective:
- Verify and complete the real API client integration, ensuring all endpoints are wired correctly to the production backend
deliverables:
- API endpoint verification report
- AuthRepository using real API
- Error handling and retry logic
- Environment-based configuration
steps:
1. Audit current API integration:
- Review android/app/.../data/remote/TRPCApiService.kt
- Review all repository implementations
- Check AuthRepositoryImpl
- Identify any stubbed or mock implementations
2. Verify all endpoints:
- Compare TRPCApiService methods with backend routers
- Ensure all mobile-needed endpoints are implemented
- Verify request/response models match backend schemas
- Test each endpoint against staging backend
3. Implement missing endpoints:
- Add any missing tRPC procedures
- Update request/response models
- Add error handling for new endpoints
4. Configure environment:
- Debug builds → staging API (10.0.2.2 or staging URL)
- Release builds → production API
- Use BuildConfig.API_BASE_URL correctly
- Add build variant configuration
5. Add error handling:
- Map tRPC error codes to user-friendly messages
- Handle network errors (timeout, no connection)
- Handle 401/403 authentication errors
- Handle 500 server errors
- Add retry logic with exponential backoff
6. Add logging:
- Log API requests in debug builds
- Log errors in all builds
- Sanitize logs (no tokens, no PII)
7. Test integration:
- Test auth flow end-to-end
- Test dashboard data loading
- Test all service screens
- Test offline behavior
tests:
- Unit: Test API service with MockWebServer
- Integration: Test against staging backend
- E2E: Complete critical flows on physical device
acceptance_criteria:
- All TRPC endpoints verified against backend
- AuthRepository using real API (no stubs)
- All repositories wired to real API service
- Debug builds use staging API
- Release builds use production API
- Error handling for all error types
- Retry logic with exponential backoff
- Request logging in debug builds
- No PII in logs
- Unit tests with MockWebServer
- Integration tests passing against staging
validation:
- Build debug → login to staging → success
- Build release → login to production → success
- Run unit tests → all pass with mocks
- Check logs → no sensitive data exposed
- Test all screens → data loads correctly
notes:
- TRPCApiService.kt exists but verify all endpoints are correct
- Some endpoints may have changed during development
- MockWebServer is already in test dependencies
- Coordinate with backend team on any API changes

View File

@@ -0,0 +1,78 @@
# 22. Token Refresh & Session Management
meta:
id: android-production-22
feature: android-production
priority: P1
depends_on: [android-production-21]
tags: [backend, auth, production]
objective:
- Implement automatic token refresh and robust session management to prevent unexpected logouts
deliverables:
- OkHttp authenticator for token refresh
- Token refresh interceptor
- Silent re-authentication flow
- Session expiry handling
steps:
1. Implement OkHttp authenticator:
- Add Authenticator to OkHttp client in NetworkModule.kt
- Detect 401 responses
- Attempt refresh with refresh token
- Retry original request with new token
2. Handle concurrent requests:
- Use Mutex or synchronized block to prevent duplicate refresh
- Queue requests while refresh in progress
- Use Kotlin coroutines for async coordination
3. Add token refresh endpoint:
- Ensure backend supports refresh token endpoint
- Implement refresh in AuthRepository
- Store new access and refresh tokens
4. Implement proactive refresh:
- Parse JWT expiry claim
- Refresh 5 minutes before expiry
- Schedule refresh on app foreground
5. Handle edge cases:
- Refresh token expired → logout user
- Network unavailable → queue and retry
- Refresh fails → prompt re-authentication
6. Update AuthViewModel:
- Expose session state
- Handle refresh failures gracefully
- Auto-logout on persistent auth failures
7. Add tests:
- Test token refresh logic
- Test concurrent request handling
- Test session expiry scenarios
tests:
- Unit: Test authenticator with MockWebServer
- Integration: Test refresh flow end-to-end
- E2E: Test session expiry behavior
acceptance_criteria:
- Token refresh automatic and transparent to user
- Concurrent requests queued during refresh
- Proactive refresh 5 minutes before expiry
- Biometric re-auth offered if refresh fails
- Session restored on app relaunch (if tokens valid)
- Graceful logout if all auth methods fail
- No duplicate refresh requests
- Background refresh on app foreground
- Unit tests covering all refresh scenarios
- MockWebServer tests for authenticator
validation:
- Wait for token expiry → app refreshes automatically
- Trigger 401 → refresh attempted, request retried
- Revoke refresh token → app prompts re-auth
- Background app → foreground → token refreshed if needed
- Check logs → no duplicate refresh requests
notes:
- OkHttp Authenticator is the standard way to handle 401s
- Use EncryptedSharedPreferences for token storage
- Consider using Credential Manager for modern auth (API 34+)
- Backend must support refresh token endpoint

View File

@@ -0,0 +1,84 @@
# 23. Offline Sync & Conflict Resolution
meta:
id: android-production-23
feature: android-production
priority: P2
depends_on: [android-production-21]
tags: [backend, offline, production]
objective:
- Implement robust offline mode with sync conflict resolution for all user actions
deliverables:
- Offline queue improvements
- Sync conflict resolution strategy
- Offline UI indicators
- Data consistency guarantees
steps:
1. Audit existing offline support:
- Review android/app/.../data/sync/SyncManager.kt
- Review OfflineWorker.kt
- Review PendingRequestQueue.kt
- Identify gaps in offline handling
2. Improve offline queue:
- Support all mutation types (add, update, delete)
- Add request deduplication
- Add request ordering (dependencies)
- Increase max retry count with exponential backoff
3. Implement conflict resolution:
- Define strategy per data type:
- Server wins for most data (alerts, exposures)
- Last write wins for user preferences
- Merge for watchlist items
- Add conflict detection (version numbers or timestamps)
- Show conflict UI for manual resolution (if needed)
4. Add offline UI:
- Offline indicator in status bar
- Disabled actions when offline
- "Sync pending" badges on modified items
- Pull-to-refresh with offline state
5. Implement data consistency:
- Optimistic updates (update UI immediately, sync in background)
- Rollback on sync failure
- Verify server state after sync
- Handle partial sync failures
6. Add background sync:
- Process queue on app foreground
- Process queue on network restoration
- Schedule periodic sync attempts
7. Test offline scenarios:
- Create watchlist item offline → syncs when online
- Delete exposure offline → syncs when online
- Modify settings offline → syncs when online
- Conflicting edits on multiple devices
tests:
- Unit: Test queue ordering and deduplication
- Integration: Test sync after offline period
- E2E: Test conflicting edits resolution
acceptance_criteria:
- All mutations queued when offline
- Queue processed automatically when online
- Optimistic updates show immediately
- Failed operations roll back UI changes
- Conflict resolution strategy defined per data type
- Offline indicator visible in UI
- Sync pending badges on modified items
- No data loss during sync failures
- Background sync on app foreground and network restore
- Unit tests for all offline scenarios
validation:
- Enable airplane mode → create watchlist item → badge shows
- Disable airplane mode → item syncs → badge clears
- Edit same item on web and Android → conflict resolved correctly
- Kill app during sync → queue persists, resumes on relaunch
notes:
- SyncManager.kt and OfflineWorker.kt already exist but may need enhancement
- Room database can help with offline queue persistence
- Simple server-wins strategy is acceptable for MVP
- Consider using WorkManager for reliable background sync

View File

@@ -0,0 +1,82 @@
# 24. FCM Push Notification Deep Linking
meta:
id: android-production-24
feature: android-production
priority: P2
depends_on: [android-production-21]
tags: [native-features, push-notifications, production]
objective:
- Ensure FCM push notifications correctly deep link to relevant screens with proper handling of app state
deliverables:
- Deep link routing for all notification types
- Cold start handling
- Background notification processing
- Notification analytics
steps:
1. Audit existing FCM handling:
- Review android/app/.../service/FCMService.kt
- Review NavGraph.kt for deep links
- Identify gaps in notification handling
2. Implement deep link routes:
- Alert notification → AlertDetail screen
- Exposure notification → DarkWatch screen
- Scan complete → Dashboard screen
- Family invite → Settings/Family
- Subscription renewal → Settings/Billing
- Marketing → Landing or specific feature
3. Handle app states:
- App closed (cold start): launch → process notification → navigate
- App background: wake → process → navigate
- App foreground: show in-app snackbar → navigate on tap
4. Add notification actions:
- Alert: "View Details", "Dismiss", "Mark Safe"
- Exposure: "View Exposure", "Start Removal"
- Scan Complete: "View Results", "Share"
5. Implement analytics:
- Track notification delivery
- Track notification open rates
- Track conversion from notification to action
- A/B test notification copy
6. Add notification preferences:
- Allow user to customize notification types
- Respect system notification settings
- Update backend preferences
7. Test all scenarios:
- Cold start from each notification type
- Background tap on notification
- Foreground notification handling
- Action button taps
tests:
- Unit: Test deep link route mapping
- Integration: Test FCM message handling
- Device: Send test notifications via Firebase Console
acceptance_criteria:
- All notification types deep link to correct screens
- Cold start from notification opens correct screen
- Background notification tap navigates correctly
- Foreground notifications show in-app snackbar
- Actionable notification buttons work
- Notification preferences respected
- Analytics tracking delivery and open rates
- Rich notifications with images render correctly
- No crashes from malformed notification payloads
- Unit tests for all deep link routes
validation:
- Send test alert notification → tap → AlertDetail opens
- Send exposure notification → app closed → DarkWatch opens
- Receive notification in foreground → snackbar shown
- Tap action button → correct action performed
- Check analytics → open rate tracked
notes:
- FCMService.kt already exists but may need enhancement
- Use NavDeepLinkBuilder for proper deep linking
- Test on different OEM skins (Samsung, Xiaomi)
- Coordinate with backend on notification payload format

View File

@@ -0,0 +1,97 @@
# 25. Privacy Policy & Data Safety Form
meta:
id: android-production-25
feature: android-production
priority: P1
depends_on: []
tags: [compliance, play-store, privacy, production]
objective:
- Complete the Google Play Data Safety form and ensure privacy policy compliance for Android app
deliverables:
- Data Safety form completed in Play Console
- Privacy policy page live
- Data collection audit
- Security practices documentation
steps:
1. Audit data collection:
- Review all data collected by app:
- Contact info (name, email)
- Voice recordings (VoicePrint)
- Phone numbers (SpamShield)
- Device info (for analytics)
- Location (if used)
- Review third-party SDK data collection:
- Firebase Analytics
- Firebase Crashlytics
- FCM
- Any other SDKs
2. Complete Data Safety form:
- Log into Play Console → App content → Data safety
- Answer all questions accurately:
- Does app collect/share data?
- Types of data collected
- Purposes of collection
- Whether data encrypted in transit
- Whether deletion requested
- Independent security review (if applicable)
3. Declare data types:
- Location (approximate or precise)
- Personal info (name, email, phone)
- Financial info (if in-app purchases)
- Health and fitness (not applicable)
- Messages (not applicable)
- Photos and videos (document scans)
- Audio files (voice recordings)
- Files and docs (not applicable)
- Calendar (not applicable)
- Contacts (not applicable)
- App activity (analytics)
- App info and performance (crash logs)
- Device IDs (for analytics)
4. Document security practices:
- Data encrypted in transit (TLS 1.3)
- Data encrypted at rest (EncryptedSharedPreferences)
- User can request deletion
- Independent security review (if available)
5. Link privacy policy:
- Ensure privacy policy URL is accessible
- Link from Play Store listing
- Link from app settings
6. Update for changes:
- Re-audit when adding new features
- Update Data Safety form for new data collection
- Update privacy policy
tests:
- Compliance: Data Safety form complete and accurate
- Legal: Privacy policy reviewed
- Technical: Data collection matches declaration
acceptance_criteria:
- Data Safety form 100% complete in Play Console
- All data types accurately declared
- Collection purposes clearly stated
- Encryption in transit declared
- Deletion mechanism declared
- Privacy policy URL live and accessible
- Privacy policy covers all data collection
- Third-party SDK data collection documented
- Security practices documented
- Form accurate and honest (no false claims)
validation:
- Play Console → Data Safety section complete
- Review answers → all accurate
- Check privacy policy → covers all declared data
- Test deletion request → process works
- Verify encryption → TLS 1.3 active
notes:
- Google strictly enforces Data Safety form accuracy
- False claims can lead to app suspension
- Update form whenever adding new data collection
- Privacy policy must be accessible without login

View File

@@ -0,0 +1,85 @@
# 26. Permissions Justification & Declarations
meta:
id: android-production-26
feature: android-production
priority: P1
depends_on: []
tags: [compliance, play-store, permissions, production]
objective:
- Justify all permissions used by the app and handle permission declarations for Play Store compliance
deliverables:
- Permissions audit report
- In-app permission rationale dialogs
- Play Console permission declarations
- Permission usage documentation
steps:
1. Audit all permissions:
- Review AndroidManifest.xml
- Review all uses-permission declarations
- List each permission and why it's needed:
- INTERNET: API communication
- CAMERA: Document scanning, VoicePrint enrollment
- RECORD_AUDIO: VoicePrint enrollment
- READ_PHONE_STATE: Call screening (if needed)
- READ_CALL_LOG: SpamShield (if needed)
- POST_NOTIFICATIONS: Android 13+ notifications
- USE_BIOMETRIC: Fingerprint/Face unlock
- FOREGROUND_SERVICE: Background sync
- RECEIVE_BOOT_COMPLETED: Schedule background sync
2. Remove unnecessary permissions:
- Remove any permissions not actually used
- Remove transitive permissions from old dependencies
- Use tools-manifest-merger to control merged permissions
3. Add in-app rationales:
- Show custom dialog before requesting each permission
- Explain why permission is needed
- Show feature benefit
- Add "Don't Allow" and "Allow" buttons
4. Handle permission denials:
- Degrade functionality gracefully
- Show guidance to Settings if permission denied
- Don't crash if permission unavailable
- Respect user's choice
5. Document in Play Console:
- Declare sensitive permissions
- Provide justification for each
- Explain why alternatives weren't used
6. Test permission flows:
- First request → rationale → system dialog
- Deny → feature degraded → Settings guidance
- Allow → feature fully functional
- Revoke in Settings → app handles gracefully
tests:
- Unit: Test permission state handling
- Integration: Test rationale dialog flow
- Device: Test all permissions on physical device
acceptance_criteria:
- All permissions justified with clear use cases
- No unnecessary permissions in manifest
- In-app rationale dialogs for all sensitive permissions
- Graceful degradation when permissions denied
- Settings guidance for denied permissions
- Play Console permission declarations complete
- Permission usage documented internally
- No crashes from missing permissions
- All permission flows tested on physical device
- App Review will approve permission usage
validation:
- Check manifest → only necessary permissions present
- Test camera permission → rationale dialog → system dialog
- Deny permission → app shows Settings guidance
- Check Play Console → permission declarations complete
- Review justifications → all accurate and reasonable
notes:
- Google Play requires justification for sensitive permissions
- READ_CALL_LOG and READ_SMS are especially scrutinized
- Call screening may not need READ_CALL_LOG if using CallScreeningService
- Be prepared to appeal if Play Store questions permissions

View File

@@ -0,0 +1,89 @@
# 27. Target API Level & Policy Compliance
meta:
id: android-production-27
feature: android-production
priority: P1
depends_on: []
tags: [compliance, play-store, policy, production]
objective:
- Ensure app targets the latest API level and complies with all Google Play policies
deliverables:
- Target API level 36 (or latest)
- No deprecated API usage
- Policy compliance verification
- Malware and abuse prevention
steps:
1. Verify target API level:
- Currently targeting API 36 (good)
- Ensure compileSdk is latest
- Check targetSdk in build.gradle.kts
- Update if needed before submission
2. Check for deprecated APIs:
- Run lint check for deprecated API usage
- Replace any deprecated methods
- Update to modern alternatives:
- Use BiometricPrompt instead of FingerprintManager
- Use WorkManager instead of JobScheduler directly
- Use NotificationChannel for notifications
- Use FileProvider for file sharing
3. Verify policy compliance:
- No malware, viruses, or deceptive behavior
- No unauthorized use of copyrighted content
- No impersonation of other apps
- No manipulation of ratings/reviews
- No excessive ads or disruptive monetization
4. Check for restricted content:
- No hate speech or harassment
- No dangerous products or services
- No illegal activities
- No sexually explicit content
5. Verify monetization compliance:
- In-app purchases properly configured (if applicable)
- No deceptive pricing
- No forced payments for basic functionality
- Subscription terms clear and fair
6. Test on latest Android version:
- Test on Android 14 (API 34)
- Test on Android 15 (API 35) if available
- Verify no compatibility issues
- Check for new permission requirements
7. Address pre-launch report issues:
- Run pre-launch report in Play Console
- Fix all crashes and ANRs
- Fix accessibility issues
- Fix security warnings
tests:
- Lint: No deprecated API warnings
- Policy: Internal review checklist
- Compatibility: Test on Android 14/15
acceptance_criteria:
- Target API level 36 (or latest available)
- Compile SDK latest stable version
- Zero deprecated API usage
- No lint warnings for deprecated APIs
- All Google Play policies complied with
- No restricted content
- Monetization compliant
- Pre-launch report issues resolved
- App works correctly on Android 14+
- No security warnings in Play Console
validation:
- Run lint → 0 deprecated API warnings
- Test on Android 14 → no issues
- Test on Android 15 → no issues
- Pre-launch report → all checks pass
- Play Console → no policy warnings
- Internal review → all policies checked
notes:
- Google requires targeting latest API level for new apps
- Pre-launch report catches many issues automatically
- Address all pre-launch report issues before submission
- Keep up with Google Play policy updates

View File

@@ -0,0 +1,88 @@
# 28. Content Rating & Regional Compliance
meta:
id: android-production-28
feature: android-production
priority: P1
depends_on: []
tags: [compliance, play-store, rating, production]
objective:
- Complete content rating questionnaire and ensure regional compliance for all target markets
deliverables:
- Content rating questionnaire completed
- Regional content compliance verified
- Age-appropriate content
- Local law compliance
steps:
1. Complete content rating:
- In Play Console → App content → Content rating
- Select category: Utilities or Lifestyle
- Answer all questions honestly:
- Violence: None
- Sexual content: None
- Language: None
- Drugs: None
- Gambling: None
- Fear: None (security alerts are informational)
- Receive rating: Everyone or Teen
2. Verify age-appropriate content:
- No explicit content in app
- No violence or gore
- No profanity
- No drug references
- Security alerts are factual, not graphic
3. Check regional compliance:
- South Korea: GRAC rating if required
- Brazil: ClassInd rating
- Other regions with specific requirements
- Verify no region-specific restrictions
4. Add parental controls (if Teen rating):
- Document any content that warrants Teen rating
- Consider if app is suitable for all ages
- Add parental guidance if needed
5. Verify data compliance by region:
- GDPR compliance for EU users
- CCPA compliance for California users
- LGPD compliance for Brazil users
- PIPEDA compliance for Canada users
6. Document content:
- Create internal content audit document
- List all user-facing content
- Verify appropriateness for declared rating
7. Handle user-generated content:
- If app allows UGC, implement moderation
- Document moderation process
- Add reporting mechanism
tests:
- Review: Content audit by team
- Compliance: Verify rating accuracy
- Regional: Check regional requirements
acceptance_criteria:
- Content rating questionnaire completed
- Rating accurate (Everyone or Teen)
- All content appropriate for declared rating
- Regional compliance verified for target markets
- Data protection compliance (GDPR, CCPA, etc.)
- No region-specific content restrictions
- Internal content audit completed
- User-generated content moderated (if applicable)
- Reporting mechanism for inappropriate content (if applicable)
- App suitable for all declared target audiences
validation:
- Play Console → content rating shows expected result
- Review all screens → no inappropriate content
- Check regional requirements → all met
- Verify data compliance → GDPR, CCPA handled
- Team review → content audit approved
notes:
- Content rating affects app visibility in some regions
- Be honest in questionnaire — false answers can lead to removal
- Security apps are typically "Everyone" or "Teen"
- Regional ratings may be required for some countries

View File

@@ -0,0 +1,90 @@
# Android Production Readiness
Objective: Prepare the Jetpack Compose Android application for Google Play Store submission with hardened security, optimized performance, comprehensive testing, and full native feature integration.
Status legend: [ ] todo, [~] in-progress, [x] done
## Tasks
### Play Store Preparation
- [ ] 01 — Play Store Listing Assets → `01-play-store-assets.md`
- [ ] 02 — Feature Graphic & Promo Video → `02-feature-graphic.md`
- [ ] 03 — Play Console Configuration → `03-play-console.md`
- [ ] 04 — Internal Testing Track → `04-internal-testing.md`
### Security Hardening
- [ ] 05 — Certificate Pinning & Network Security Config → `05-cert-pinning.md`
- [ ] 06 — Root Detection & Obfuscation (R8/ProGuard) → `06-root-detection.md`
- [ ] 07 — Encrypted SharedPreferences & DataStore Audit → `07-encrypted-storage.md`
- [ ] 08 — OAuth & Social Login Integration → `08-oauth-social-login.md`
### Performance Optimization
- [ ] 09 — Image Caching & Coil Optimization → `09-image-caching.md`
- [ ] 10 — Pagination & List Performance → `10-pagination-lists.md`
- [ ] 11 — Background Sync & WorkManager Optimization → `11-background-sync.md`
- [ ] 12 — App Startup Time & ANR Prevention → `12-startup-anr.md`
### Native Features
- [ ] 13 — Call Screening Service Production Hardening → `13-call-screening.md`
- [ ] 14 — Notification Channels & Rich Notifications → `14-notifications.md`
- [ ] 15 — App Shortcuts & Widgets → `15-shortcuts-widgets.md`
- [ ] 16 — App Actions & Slices → `16-app-actions.md`
### Testing & QA
- [ ] 17 — UI Test Suite (Compose Testing) → `17-ui-test-suite.md`
- [ ] 18 — Screenshot Testing (Paparazzi) → `18-screenshot-testing.md`
- [ ] 19 — Accessibility Audit (TalkBack) → `19-accessibility-audit.md`
- [ ] 20 — Firebase Test Lab Integration → `20-firebase-test-lab.md`
### Backend Integration
- [ ] 21 — Real API Client Verification & Wire-up → `21-api-verification.md`
- [ ] 22 — Token Refresh & Session Management → `22-token-refresh.md`
- [ ] 23 — Offline Sync & Conflict Resolution → `23-offline-sync.md`
- [ ] 24 — FCM Push Notification Deep Linking → `24-fcm-deep-links.md`
### Play Store Compliance
- [ ] 25 — Privacy Policy & Data Safety Form → `25-privacy-data-safety.md`
- [ ] 26 — Permissions Justification & Declarations → `26-permissions.md`
- [ ] 27 — Target API Level & Policy Compliance → `27-target-api-compliance.md`
- [ ] 28 — Content Rating & Regional Compliance → `28-content-rating.md`
## Dependencies
- 01, 02, 03, 04 can be done in parallel (Play Store prep)
- 05, 06, 07, 08 can be done in parallel (security)
- 09, 10, 11, 12 can be done in parallel (performance)
- 13, 14, 15, 16 can be done in parallel (native features)
- 17, 18, 19, 20 can be done in parallel (testing)
- 21 must be done before 22, 23, 24 (backend integration foundation)
- 22, 23, 24 depend on 21
- 25, 26, 27, 28 can be done in parallel (compliance)
- All groups can proceed independently
## Exit Criteria
- Play Store listing complete with screenshots for phone, tablet, and foldable
- Feature graphic and promo video uploaded
- Internal testing track active with 20+ testers
- Certificate pinning active with network_security_config.xml
- Root detection blocking app usage or degrading gracefully
- R8/ProGuard enabled with release build shrinking and obfuscation
- EncryptedSharedPreferences used for all sensitive data
- OAuth and social login working (Google Sign-In)
- Coil image cache configured with 100MB disk limit
- All lists paginated with lazy loading (no ANRs on large datasets)
- WorkManager syncing every 15 minutes with battery optimization
- Cold start under 1.5 seconds on Pixel 6
- Call screening service filtering calls with <100ms latency
- Notification channels configured for alerts, marketing, and system
- App shortcuts for dashboard, alerts, and new scan
- Home screen widget showing threat score
- UI tests covering auth flow, dashboard navigation, and service screens
- Screenshot tests catching UI regressions on PR
- TalkBack labels on all interactive elements
- Firebase Test Lab tests passing on Pixel, Samsung, and Xiaomi devices
- All TRPC endpoints verified against backend contract
- Token refresh working silently without user interruption
- Offline queue resolving sync conflicts with server-wins strategy
- FCM deep links routing to correct screens with cold start
- Data safety form accurately declaring all collected data types
- All permissions justified with in-app rationale dialogs
- Target API level 36 with no deprecated API usage
- Content rating questionnaire completed accurately

View File

@@ -0,0 +1,82 @@
# 01. App Store Screenshots & Metadata
meta:
id: ios-production-01
feature: ios-production
priority: P1
depends_on: []
tags: [app-store, marketing, production]
objective:
- Create and upload all required App Store screenshots and metadata for iOS app submission
deliverables:
- Screenshots for all required device sizes
- App metadata (name, subtitle, description, keywords)
- App Store listing content
- Promotional text and updates
steps:
1. Determine required screenshot sizes:
- iPhone 6.7" (iPhone 14 Pro Max, 15 Pro Max): 1290x2796
- iPhone 6.5" (iPhone 14 Plus, 13 Pro Max): 1284x2778
- iPhone 5.5" (iPhone 8 Plus, SE 3rd gen): 1242x2208
- iPad Pro 12.9" (6th gen): 2048x2732
- iPad Pro 11" (4th gen): 1668x2388
2. Create screenshot content plan:
- Screenshot 1: Dashboard with threat score and alerts
- Screenshot 2: DarkWatch exposure list
- Screenshot 3: VoicePrint enrollment screen
- Screenshot 4: SpamShield call log/filtering
- Screenshot 5: HomeTitle property monitoring
- Screenshot 6: Settings and profile
- Screenshot 7: Family plan management (if applicable)
- Screenshot 8: Push notification example
3. Capture or generate screenshots:
- Use iOS Simulator for precise sizing
- Or use Screenshotting library for programmatic capture
- Ensure status bar shows 9:41 and full battery
- Use clean data (no real user info)
4. Write app metadata:
- App Name: Kordant (30 chars max)
- Subtitle: AI Identity Protection (30 chars max)
- Description: 4000 chars highlighting features, benefits, use cases
- Keywords: identity protection, dark web, spam blocker, voice clone, privacy (100 chars max)
- Support URL, Marketing URL
- Copyright info
5. Prepare App Store listing:
- Primary category: Utilities or Lifestyle
- Secondary category: Productivity or Security
- Content rating: 4+ (no objectionable content)
- Age rating questionnaire completed
6. Upload to App Store Connect:
- Use Transporter app or Xcode upload
- Verify all screenshot sizes present
- Preview metadata in App Store Connect
tests:
- Visual: Review screenshots for quality and consistency
- Content: Verify no placeholder or test data visible
- Compliance: Check content rating accuracy
acceptance_criteria:
- Screenshots for all 5 required device sizes
- 5-8 screenshots per device size showing key features
- App metadata complete and within character limits
- Screenshots show real app UI with clean demo data
- Status bar shows 9:41 time and full battery
- No beta/test labels visible in screenshots
- Content rating accurate and complete
- All assets uploaded to App Store Connect
validation:
- App Store Connect → all screenshot slots filled
- Screenshots reviewed by designer → approved
- Metadata spell-checked and reviewed
- Content rating questionnaire submitted
notes:
- Use screenshot frames (iPhone bezel) for professional look
- Consider localized screenshots for major markets (EN, ES, FR)
- Screenshots are the #1 factor in app store conversion
- Update screenshots with each major UI release

View File

@@ -0,0 +1,79 @@
# 02. App Preview Video
meta:
id: ios-production-02
feature: ios-production
priority: P2
depends_on: []
tags: [app-store, marketing, production]
objective:
- Create a compelling App Preview video for the App Store to increase conversion rates
deliverables:
- 15-30 second App Preview video
- Video for required device sizes
- Captions or text overlays
- Professional quality and pacing
steps:
1. Plan the video narrative:
- 0-5s: Hook — identity threat scenario (notification)
- 5-15s: Solution — open app, see dashboard, run scan
- 15-25s: Features — DarkWatch, VoicePrint, SpamShield highlights
- 25-30s: CTA — "Protect your identity today"
2. Record screen capture:
- Use iOS Simulator screen recording (cmd+S)
- Or use QuickTime with connected device
- Record at native resolution (no scaling)
- Use clean demo account with realistic data
3. Edit the video:
- Use iMovie, Final Cut Pro, or CapCut
- Add smooth transitions between scenes
- Add text overlays for feature names
- Add background music (royalty-free, upbeat)
- Ensure pacing feels natural (not too fast)
4. Create required sizes:
- iPhone: 1080x1920 (portrait) or 1920x1080 (landscape)
- iPad: 1200x1600 (portrait) or 1600x1200 (landscape)
- Max file size: 500MB
- Format: MOV, M4V, or MP4 (H.264)
5. Add accessibility:
- Captions/subtitles for all spoken text
- Ensure color contrast for text overlays
- Avoid rapid flashing (photosensitive epilepsy)
6. Test and iterate:
- Show to team members for feedback
- A/B test different versions if possible
- Ensure video loops well (App Store autoplays)
7. Upload to App Store Connect:
- Upload preview video for each device size
- Verify autoplay and thumbnail
tests:
- Visual: Review video quality and pacing
- Technical: Verify format and size requirements
- Content: Ensure no confidential data shown
acceptance_criteria:
- 15-30 second video showcasing core app features
- Video for iPhone and iPad sizes
- Smooth transitions and professional pacing
- Text overlays for feature highlights
- Background music (royalty-free)
- Captions/subtitles included
- No placeholder or test data visible
- File size <500MB per video
- Uploaded to App Store Connect
validation:
- Play video → smooth, engaging, clear features
- Check technical specs → correct resolution, format, size
- Team review → approved by 3+ team members
- App Store Connect → video preview active
notes:
- App Preview videos auto-play muted in App Store
- First 5 seconds are critical for engagement
- Consider creating 3 shorter videos for different features
- Videos can significantly increase conversion rates

View File

@@ -0,0 +1,84 @@
# 03. App Store Connect Configuration
meta:
id: ios-production-03
feature: ios-production
priority: P1
depends_on: []
tags: [app-store, configuration, production]
objective:
- Complete all App Store Connect configuration for app submission and distribution
deliverables:
- App record created in App Store Connect
- Bundle ID registered and configured
- Signing certificates and provisioning profiles
- App Review information
- Pricing and availability
steps:
1. Create App Store Connect record:
- App name: Kordant
- Primary language: English
- Bundle ID: com.kordant.app (or existing)
- SKU: kordant-001
- User Access: Full access for team
2. Configure app capabilities:
- Push Notifications (entitlements configured)
- Background Modes (fetch, remote notifications)
- Camera (for document scanning)
- Microphone (for VoicePrint enrollment)
- Face ID / Touch ID (biometric auth)
- Associated Domains (universal links)
3. Set up signing:
- Apple Developer account ($99/year)
- Create Distribution certificate
- Create App Store provisioning profile
- Configure Xcode with correct team and signing
4. Configure pricing:
- Price tier: Free (subscription handled in-app or via web)
- If in-app purchases: configure in App Store Connect
- Subscription groups and tiers
- Introductory offers (free trial)
5. Set availability:
- All countries or selected markets
- Pre-order option (optional)
- Release strategy (manual or automatic)
6. Prepare App Review info:
- Contact information
- Demo account credentials (username/password for testing)
- Notes for reviewer (explain app functionality)
- Attachment: privacy policy, terms of service
7. Configure TestFlight:
- Internal testers (team members)
- External testers (beta group)
- Test information and feedback email
tests:
- Build: Archive and validate app in Xcode
- Upload: Upload build to App Store Connect
- Verification: Confirm build appears in TestFlight
acceptance_criteria:
- App record created in App Store Connect
- Bundle ID registered and matches Xcode project
- Distribution certificate and provisioning profile active
- All required capabilities enabled
- Pricing set (free with subscriptions)
- Availability configured for target markets
- App Review information complete with demo account
- TestFlight configured with internal testers
- Build successfully uploaded and processing
validation:
- Xcode → Product → Archive → Validate → no errors
- Upload build → appears in App Store Connect within 30 minutes
- TestFlight → build available for internal testing
- App Review info → all fields complete
notes:
- Ensure Apple Developer membership is active and paid
- Bundle ID must match exactly across all configs
- Demo account is critical for reviewer testing
- TestFlight builds must be signed with Distribution cert

View File

@@ -0,0 +1,80 @@
# 04. TestFlight Beta Distribution
meta:
id: ios-production-04
feature: ios-production
priority: P1
depends_on: []
tags: [app-store, testing, production]
objective:
- Set up TestFlight beta testing with internal and external testers to validate app before public release
deliverables:
- Internal testing group configured
- External testing group with 20+ testers
- Beta testing feedback process
- Crash reporting for beta builds
steps:
1. Configure internal testing:
- Add all team members to App Store Connect
- Create internal testing group
- Upload first beta build
- Verify team members can install via TestFlight app
2. Recruit external testers:
- Create external testing group "Kordant Beta"
- Invite 20-100 external testers via email or public link
- Target: mix of technical and non-technical users
- Include iPhone and iPad users
- Include different iOS versions (16, 17, 18)
3. Prepare beta testing materials:
- Beta app description and what to test
- Feedback email or link (TestFlight feedback)
- Known issues list
- Testing checklist for testers
4. Set up crash reporting:
- Enable TestFlight crash reporting in Xcode
- Integrate Firebase Crashlytics for detailed crashes
- Configure alerts for crash spikes
5. Distribute beta builds:
- Upload new build → auto-distribute to internal testers
- Submit for external testing review (first build only)
- Distribute to external testers after approval
6. Collect and triage feedback:
- Review TestFlight feedback daily
- Create issues from feedback in task tracker
- Respond to critical feedback within 24 hours
- Track bug reports and feature requests
7. Iterate based on feedback:
- Fix critical bugs within 1 week
- Address UI/UX issues before public release
- Update beta build every 1-2 weeks
tests:
- Distribution: Verify testers receive build notifications
- Feedback: Test feedback submission process
- Crash: Verify crash reports appear in Firebase
acceptance_criteria:
- Internal testing group with all team members
- External testing group with 20+ active testers
- First beta build distributed and installed successfully
- TestFlight feedback channel active
- Crash reporting receiving reports
- Beta testing checklist provided to testers
- Known issues documented and shared
- Iteration cycle: new build every 1-2 weeks
- Zero critical crashes in last 2 beta builds
validation:
- TestFlight app → build available for install
- External tester installs app → no issues
- Submit feedback → appears in App Store Connect
- Simulate crash → report appears in Firebase
notes:
- External testing requires App Review approval for first build
- Public link allows anyone to join without invitation
- Beta testing typically takes 2-4 weeks before release
- Use TestFlight groups to test different features

View File

@@ -0,0 +1,72 @@
# 05. Certificate Pinning & TLS Validation
meta:
id: ios-production-05
feature: ios-production
priority: P1
depends_on: []
tags: [security, networking, production]
objective:
- Implement certificate pinning and TLS validation to prevent man-in-the-middle attacks on API communications
deliverables:
- Certificate pinning implementation in APIClient
- TLS 1.3 enforcement
- Certificate expiration monitoring
- Fallback handling for certificate rotation
steps:
1. Obtain server certificates:
- Export production server certificate or public key
- Include intermediate certificates if needed
- Store certificate hash in app bundle
2. Implement certificate pinning:
- Modify iOS/Kordant/Services/APIClient.swift
- Use URLSessionDelegate with didReceiveChallenge
- Compare server certificate with pinned hash
- Support both certificate pinning and public key pinning
3. Configure TLS settings:
- Enforce TLS 1.3 minimum
- Disable weak cipher suites
- Enable certificate transparency checking
- Configure ATS (App Transport Security) in Info.plist
4. Add certificate rotation support:
- Support multiple pinned certificates (old + new)
- Grace period during rotation (30 days)
- Alert when certificate nearing expiry
5. Implement fallback strategy:
- If pinning fails, allow connection with additional verification
- Log pinning failures for monitoring
- Consider allowing override for enterprise users
6. Add tests:
- Test with correct certificate → connection succeeds
- Test with wrong certificate → connection fails
- Test certificate rotation → seamless transition
tests:
- Unit: Test pinning with mock certificates
- Integration: Test against staging with pinned cert
- Security: Attempt MITM with Charles Proxy → blocked
acceptance_criteria:
- Certificate pinning active on all API requests
- TLS 1.3 enforced for all connections
- MITM attacks blocked (tested with proxy tools)
- Certificate rotation supported with grace period
- Pinning failures logged for monitoring
- ATS configured in Info.plist
- Unit tests covering pinning success and failure
- No hardcoded certificates in source code (use hashes)
validation:
- Run app with correct cert → API calls succeed
- Run app with Charles Proxy MITM → API calls fail
- Check logs → pinning verification logged
- Inspect Info.plist → ATS settings correct
notes:
- Use public key pinning (more stable than full certificate)
- Include backup pin for certificate rotation
- TrustKit is a popular library for iOS certificate pinning
- Certificate expiry alerts prevent unexpected outages

View File

@@ -0,0 +1,74 @@
# 06. Jailbreak Detection & Runtime Security
meta:
id: ios-production-06
feature: ios-production
priority: P2
depends_on: []
tags: [security, hardening, production]
objective:
- Implement jailbreak detection and runtime security measures to protect the app on compromised devices
deliverables:
- Jailbreak detection implementation
- Runtime integrity checks
- Anti-tampering measures
- Secure enclave usage for sensitive operations
steps:
1. Implement jailbreak detection:
- Check for common jailbreak files (/Applications/Cydia.app, etc.)
- Check if app can write outside sandbox
- Check for suspicious dylibs
- Use multiple detection methods for robustness
- Add to APIClient or AppDelegate
2. Define jailbreak response:
- Option A: Block app usage with warning
- Option B: Degrade functionality (no biometric, no payments)
- Option C: Log and alert backend
- Recommended: Option B + alert backend
3. Implement runtime integrity checks:
- Verify code signature at runtime
- Detect debugger attachment
- Detect code injection attempts
- Verify method swizzling hasn't occurred
4. Use Secure Enclave:
- Store encryption keys in Secure Enclave
- Use biometrics via LocalAuthentication framework
- Protect keychain items with biometry constraint
5. Add anti-tampering:
- Obfuscate sensitive strings (API endpoints, keys)
- Verify bundle identifier hasn't changed
- Check for binary modification
6. Implement backend alerting:
- Send jailbreak detection event to backend
- Include device info (non-identifiable)
- Flag account for additional monitoring
tests:
- Unit: Test detection logic with mock jailbreak indicators
- Integration: Test on jailbroken device (if available)
- Security: Verify debugger detection works
acceptance_criteria:
- Jailbreak detection active with multiple methods
- App degrades gracefully on detected jailbreak
- Backend receives alert when jailbreak detected
- Secure Enclave used for key storage
- Debugger attachment detected and handled
- Runtime integrity checks active
- Sensitive strings obfuscated in binary
- No false positives on non-jailbroken devices
validation:
- Run on normal device → no jailbreak detected, full functionality
- Run on jailbroken device → degraded mode activated
- Attach debugger → app detects and responds
- Check backend logs → jailbreak events received
notes:
- Jailbreak detection is cat-and-mouse — don't rely on it exclusively
- Apple may reject apps that overly aggressively block jailbroken devices
- Degradation is safer than blocking (better user experience)
- Use Swift string obfuscation libraries for sensitive data

View File

@@ -0,0 +1,76 @@
# 07. Keychain & Data Protection Audit
meta:
id: ios-production-07
feature: ios-production
priority: P1
depends_on: []
tags: [security, data-protection, production]
objective:
- Audit and harden all keychain usage and data protection to ensure sensitive data is stored securely
deliverables:
- Keychain audit report
- Data protection class review
- Secure data deletion
- Encryption audit
steps:
1. Audit keychain usage:
- Review iOS/Kordant/Services/KeychainService.swift
- Verify all sensitive data stored in keychain (not UserDefaults)
- Check keychain accessibility levels:
- JWT tokens: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
- Refresh tokens: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
- Biometric flag: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
- Verify keychain items migrated to correct accessibility
2. Audit data storage:
- Review CacheManager.swift — should not store sensitive data
- Review UserDefaults usage — only non-sensitive preferences
- Verify no sensitive data in app sandbox documents
- Check Core Data or SQLite encryption if used
3. Implement secure deletion:
- Overwrite sensitive data before deletion
- Clear clipboard after password copy (if applicable)
- Auto-lock app after backgrounding (optional)
4. Review data protection classes:
- File protection: NSFileProtectionComplete for sensitive files
- Keychain: appropriate accessibility per item type
- Backup: exclude sensitive items from iCloud backup
5. Add encryption for local data:
- Encrypt cached API responses containing PII
- Use AES-256 with key from Secure Enclave
- Implement secure key rotation
6. Test data protection:
- Device locked → keychain items inaccessible
- Device backup → sensitive items excluded
- App deletion → all sensitive data removed
tests:
- Unit: Test keychain store/retrieve/delete
- Security: Verify data inaccessible when device locked
- Integration: Test backup exclusion
acceptance_criteria:
- All sensitive data (tokens, passwords) stored in keychain
- Keychain accessibility set to ThisDeviceOnly where possible
- No sensitive data in UserDefaults or app documents
- Cached data encrypted at rest
- Sensitive items excluded from iCloud backup
- Secure deletion overwriting data before removal
- Data inaccessible when device locked (if applicable)
- All keychain operations have error handling
validation:
- Inspect keychain → JWT stored with correct accessibility
- Check UserDefaults → no sensitive data found
- Lock device → keychain items inaccessible
- Backup device → sensitive items not in backup
- Delete app → reinstall → no previous data accessible
notes:
- Keychain persists across app reinstalls — consider this in design
- kSecAttrAccessibleWhenUnlockedThisDeviceOnly is most secure
- Use Data Protection API for file-level encryption
- Consider using CryptoKit for data encryption

View File

@@ -0,0 +1,79 @@
# 08. OAuth & Social Login Integration
meta:
id: ios-production-08
feature: ios-production
priority: P1
depends_on: []
tags: [auth, security, production]
objective:
- Implement OAuth and social login (Apple Sign-In, Google) to replace the stubbed auth client
deliverables:
- Apple Sign-In integration
- Google Sign-In integration
- Backend OAuth token exchange
- AuthService wired to real API client
steps:
1. Implement Apple Sign-In:
- Configure Sign in with Apple in Apple Developer portal
- Add com.apple.developer.applesignin.customauth entitlement
- Implement ASAuthorizationController in AuthService
- Handle authorization code and identity token
- Send Apple credentials to backend for verification
2. Implement Google Sign-In:
- Configure Google Sign-In in Firebase/Google Cloud Console
- Add URL scheme for Google callback
- Integrate GoogleSignIn SDK
- Handle ID token and send to backend
3. Update backend for OAuth:
- Add OAuth endpoints to tRPC user router
- Verify Apple ID token with Apple public keys
- Verify Google ID token with Google certs
- Create/link user accounts from OAuth providers
- Return session token after OAuth login
4. Replace StubAPIClient:
- Create real API client implementing AuthAPIClientProtocol
- Wire into AuthService initialization in KordantApp.swift
- Remove StubAPIClient from production builds
- Keep StubAPIClient for unit tests
5. Add token refresh:
- Implement refresh token rotation
- Silent token refresh on expiry
- Handle refresh failure (re-authenticate)
6. Add logout for OAuth:
- Revoke OAuth tokens where possible
- Clear all local auth state
- Notify backend of logout
tests:
- Unit: Test OAuth token parsing and validation
- Integration: Test Apple Sign-In flow end-to-end
- Integration: Test Google Sign-In flow end-to-end
- Security: Verify token validation rejects invalid tokens
acceptance_criteria:
- Apple Sign-In working on iOS 13+
- Google Sign-In working with Firebase
- OAuth tokens verified server-side
- User accounts created or linked correctly
- AuthService uses real API client in production
- Token refresh working silently
- Logout clears all auth state and revokes tokens
- Unit tests use mock client, production uses real client
- Error handling for cancelled sign-in attempts
validation:
- Tap Apple Sign-In → native sheet → authenticate → logged in
- Tap Google Sign-In → Google flow → authenticate → logged in
- Check backend → user created with correct provider
- Wait for token expiry → automatic refresh
- Logout → all tokens cleared, login screen shown
notes:
- Apple Sign-In is required if app uses other third-party sign-in
- Apple Sign-In must be primary button if multiple options
- Store Apple user ID for account linking
- Backend must verify Apple JWT with Apple's public key

View File

@@ -0,0 +1,74 @@
# 09. Image Caching & Lazy Loading
meta:
id: ios-production-09
feature: ios-production
priority: P2
depends_on: []
tags: [performance, caching, production]
objective:
- Implement efficient image caching and lazy loading to improve app performance and reduce network usage
deliverables:
- URLSession-based image caching
- Lazy loading for lists and grids
- Image optimization pipeline
- Memory and disk cache limits
steps:
1. Implement image caching:
- Use URLCache with memory (50MB) and disk (100MB) limits
- Or integrate Kingfisher or Nuke for advanced caching
- Configure cache expiration (7 days default)
- Add cache cleanup on low memory warnings
2. Add lazy loading:
- Use LazyVStack and LazyHGrid for lists
- Implement pagination for long lists (alerts, exposures)
- Add prefetching for adjacent items
- Show placeholder while loading
3. Optimize images:
- Request appropriate sizes from backend (thumbnail, full)
- Use WebP or HEIC format where supported
- Compress images before upload (VoicePrint, document scan)
- Implement progressive JPEG loading
4. Add loading states:
- Skeleton placeholders while images load
- Error state with retry button
- Fade-in animation when image loads
5. Implement memory management:
- Clear image cache on memory warning
- Limit concurrent image downloads (max 5)
- Cancel downloads for off-screen images
6. Add offline support:
- Cache images for offline viewing
- Show cached images when offline
- Queue uploads for when online
tests:
- Unit: Test cache hit/miss behavior
- Performance: Test scrolling with 1000 images
- Memory: Verify no memory leaks with image loading
acceptance_criteria:
- Images cached with 50MB memory / 100MB disk limits
- Lazy loading on all lists and grids
- Pagination for lists >50 items
- Image placeholders while loading
- Cache cleared on memory warning
- Offline image viewing working
- Progressive loading for large images
- No memory leaks in image loading pipeline
- Smooth 60fps scrolling on image-heavy screens
validation:
- Scroll through alert list → smooth, no stuttering
- Turn on airplane mode → cached images still visible
- Monitor memory → stable during image browsing
- Check cache directory → images stored with correct expiration
notes:
- Kingfisher is the most popular Swift image caching library
- Nuke is lighter and faster for advanced use cases
- Consider using SwiftUI AsyncImage for simple cases
- Always test on physical device, not just simulator

View File

@@ -0,0 +1,74 @@
# 10. Memory Management & Leak Audit
meta:
id: ios-production-10
feature: ios-production
priority: P2
depends_on: []
tags: [performance, memory, production]
objective:
- Audit and fix memory leaks and retain cycles to ensure stable app performance over long sessions
deliverables:
- Memory leak audit report
- Fixed retain cycles in ViewModels and Services
- Instruments leak check passing
- Memory usage optimization
steps:
1. Audit ViewModels for retain cycles:
- Review all ViewModels in iOS/Kordant/ViewModels/
- Check for strong references in closures
- Verify cancellables properly stored and cleaned up
- Check for delegate patterns causing cycles
2. Audit Services for leaks:
- Review APIClient, AuthService, CacheManager
- Check singleton patterns don't retain view controllers
- Verify notification observers removed on deinit
- Check timer/interval cleanup
3. Run Instruments leak check:
- Profile app with Leaks instrument
- Perform all critical user journeys
- Record and categorize all leaks
- Fix leaks in priority order (critical first)
4. Optimize memory usage:
- Reduce image cache size if needed
- Limit number of cached API responses
- Clear unused ViewModels from navigation stack
- Optimize large data structures
5. Add memory warnings handling:
- Clear caches on UIApplication.didReceiveMemoryWarningNotification
- Reduce quality of background operations
- Cancel non-essential network requests
6. Test long-running sessions:
- Leave app running for 24 hours
- Monitor memory growth
- Verify no crashes from memory pressure
tests:
- Instruments: Leaks instrument shows 0 leaks
- Performance: Memory stable after 1 hour of use
- Stress: No crashes after extended usage
acceptance_criteria:
- 0 memory leaks detected in Instruments
- No retain cycles in ViewModels or Services
- Memory usage stable over 1 hour session
- Memory warnings handled appropriately
- Caches cleared on low memory
- No strong reference cycles in closures
- Notification observers removed on deinit
- Long-running session (24h) without memory-related crashes
validation:
- Profile with Instruments → 0 leaks after full app navigation
- Monitor memory in Xcode → flat line during idle
- Trigger memory warning → caches cleared, app responsive
- Extended use test → no memory growth over time
notes:
- SwiftUI @StateObject and @ObservedObject can cause leaks if misused
- Use [weak self] in all async closures
- Combine subscribers must be stored in Set<AnyCancellable>
- Test on physical device — simulator behaves differently

View File

@@ -0,0 +1,76 @@
# 11. Background Fetch & Sync Optimization
meta:
id: ios-production-11
feature: ios-production
priority: P2
depends_on: []
tags: [performance, background, production]
objective:
- Optimize background fetch and data sync to keep app data fresh without draining battery
deliverables:
- Background fetch configuration
- Efficient sync strategy
- Battery usage optimization
- Background task handling
steps:
1. Configure background fetch:
- Enable Background Fetch in Signing & Capabilities
- Set minimum fetch interval (15 minutes)
- Implement application(_:performFetchWithCompletionHandler)
- Or use BGAppRefreshTask for iOS 13+
2. Optimize sync strategy:
- Sync only changed data (delta sync)
- Use If-Modified-Since or ETag headers
- Prioritize critical data (alerts, exposures)
- Defer non-critical sync (reports, historical data)
3. Implement background tasks:
- Use BGProcessingTask for heavy operations
- Schedule periodic dark web scans
- Schedule spam database updates
- Handle task expiration gracefully
4. Optimize battery usage:
- Batch network requests
- Use cellular data efficiently
- Defer sync until WiFi available (optional)
- Respect low power mode
5. Handle push notification sync:
- Silent push notifications for urgent updates
- Content-available: 1 for background processing
- Wake app for critical alerts
6. Add sync status indicators:
- Last sync timestamp in settings
- Sync progress for large operations
- Offline mode indicator
tests:
- Unit: Test background task scheduling
- Integration: Test fetch completion within 30 seconds
- Battery: Verify minimal battery impact over 24 hours
acceptance_criteria:
- Background fetch enabled and configured
- Data syncs every 15 minutes minimum
- Delta sync reducing data transfer by >50%
- Background tasks complete within 30 seconds
- Battery impact <5% per day from background activity
- Silent push notifications trigger data refresh
- Low power mode respected (reduced sync frequency)
- Sync status visible to user in settings
- No background task terminations due to timeouts
validation:
- Simulate background fetch → data refreshed
- Check battery settings → Kordant background activity minimal
- Receive silent push → app updates in background
- Enable low power mode → sync frequency reduced
- Monitor network usage → delta sync working
notes:
- iOS limits background fetch frequency based on app usage patterns
- BGAppRefreshTask is modern replacement for performFetch
- Always call completion handler or setTaskCompleted
- Background processing tasks require specific entitlements

View File

@@ -0,0 +1,79 @@
# 12. App Launch Time Optimization
meta:
id: ios-production-12
feature: ios-production
priority: P2
depends_on: []
tags: [performance, launch, production]
objective:
- Optimize app launch time to under 2 seconds for cold starts and under 1 second for warm starts
deliverables:
- Launch time measurement and baseline
- Optimized app initialization
- Lazy loading of heavy components
- Reduced binary size
steps:
1. Measure current launch time:
- Use Xcode Metrics Organizer
- Use os_signpost for custom timing
- Measure cold start (first launch after reboot)
- Measure warm start (subsequent launches)
- Establish baseline metrics
2. Optimize app delegate:
- Minimize work in application(_:didFinishLaunchingWithOptions)
- Defer non-critical initialization
- Move heavy setup to background threads
- Avoid blocking main thread
3. Lazy load heavy components:
- Defer VoicePrint model loading until needed
- Defer document scanner initialization
- Lazy load WebView components
- Load dashboard data after UI appears
4. Optimize storyboards/XIBs:
- Remove unused storyboards
- Minimize view controller initialization
- Use code-based UI where faster
5. Reduce binary size:
- Strip debug symbols from release builds
- Remove unused resources and assets
- Compress images in asset catalog
- Enable dead code stripping
6. Optimize framework loading:
- Link frameworks statically where possible
- Reduce dynamic framework count
- Prelink common frameworks
7. Add launch screen optimization:
- Simple, static launch screen
- Match first screen of app
- No animations or complex layouts
tests:
- Performance: Measure launch time on iPhone 12
- Stress: Launch app 100 times, average time <2s
- Memory: No memory spikes during launch
acceptance_criteria:
- Cold launch time <2 seconds on iPhone 12
- Warm launch time <1 second on iPhone 12
- Launch screen visible for <500ms
- No blocking operations on main thread during launch
- Binary size <100MB (App Store limit is much higher)
- Heavy components loaded lazily after launch
- Launch time measured and tracked in CI
- No crashes during launch under memory pressure
validation:
- Xcode Metrics → cold start <2s, warm <1s
- Instruments Time Profiler → no long blocking calls on main thread
- Physical device test → feels instant
- App Store Connect → binary size acceptable
notes:
- Launch time is critical for App Store review and user retention
- iOS may terminate apps with launch times >20 seconds
- Use pre-warmed launches for more accurate measurement
- Test on oldest supported device (iPhone SE 2nd gen or similar)

View File

@@ -0,0 +1,79 @@
# 13. CallKit Integration for SpamShield
meta:
id: ios-production-13
feature: ios-production
priority: P1
depends_on: []
tags: [native-features, spamshield, production]
objective:
- Integrate SpamShield with CallKit to identify and block spam calls at the system level
deliverables:
- CallKit extension for call identification
- Spam database sync
- Real-time caller lookup
- User-managed block list
steps:
1. Create CallKit extension:
- Add Call Directory Extension target in Xcode
- Implement CXCallDirectoryProvider
- Handle reloadExtensionRequests
- Add to app group for shared data
2. Implement caller identification:
- Lookup incoming numbers against spam database
- Display caller ID label ("Spam: Telemarketer")
- Use local cached database for speed
- Fall back to API lookup for unknown numbers
3. Implement call blocking:
- Block known spam numbers
- Block user-defined patterns
- Sync block list from app settings
- Handle block list updates
4. Sync spam database:
- Download updated spam numbers periodically
- Store in shared app group container
- Update Call Directory on sync
- Respect user privacy (hashed numbers where possible)
5. Add user controls:
- Settings toggle for call identification
- Settings toggle for call blocking
- Manage blocked numbers list
- Report false positives
6. Handle permissions:
- Request Call Directory extension enablement
- Guide user to Settings → Phone → Call Blocking
- Check extension status on app launch
tests:
- Unit: Test number lookup against spam database
- Integration: Test Call Directory update
- Device: Test with actual spam call (simulated)
acceptance_criteria:
- CallKit extension installed and enabled
- Incoming spam calls identified with label
- Known spam numbers automatically blocked
- Spam database synced daily
- User can enable/disable identification and blocking
- Block list manageable from app settings
- Extension updates without app restart
- False positive reporting mechanism
- Privacy: number lookups local where possible
- App guides users to enable extension in Settings
validation:
- Enable extension in Settings → calls identified
- Receive call from known spam number → blocked/identified
- Update spam database → Call Directory refreshed
- Disable in app → extension stops working
- Report false positive → number removed from block list
notes:
- Call Directory extensions have strict memory limits (17MB)
- Apple reviews CallKit extensions carefully
- Extension runs separately from main app
- Use app groups for sharing data between app and extension
- Users must manually enable extension in Settings

View File

@@ -0,0 +1,77 @@
# 14. Siri Shortcuts & Intents
meta:
id: ios-production-14
feature: ios-production
priority: P2
depends_on: []
tags: [native-features, siri, production]
objective:
- Implement Siri Shortcuts and custom intents for common Kordant actions
deliverables:
- Custom intents for Kordant actions
- Siri Shortcuts support
- Intent handling in app
- Suggested shortcuts
steps:
1. Define custom intents:
- CheckThreatScoreIntent: "What's my threat score?"
- RunSecurityScanIntent: "Run a security scan"
- CheckAlertsIntent: "Do I have any security alerts?"
- AddWatchlistItemIntent: "Add email to dark web watchlist"
- CheckSpamNumberIntent: "Is this number spam?"
2. Create intent definition file:
- Add SiriKit intent definition to project
- Define parameters for each intent
- Add response templates
- Localize for supported languages
3. Implement intent handling:
- Create IntentHandler extension
- Handle each custom intent
- Call TRPCBridge to fetch data
- Return formatted response to Siri
4. Add shortcuts support:
- Donate shortcuts after user performs actions
- Add NSUserActivity for eligible actions
- Support Add to Siri button in app
- Handle intent parameters from shortcuts app
5. Implement suggested shortcuts:
- Suggest "Check my threat score" on first launch
- Suggest "Run security scan" after onboarding
- Suggest "Check alerts" when new alert received
6. Add UI for shortcuts:
- Settings section for Siri Shortcuts
- List of available shortcuts
- Instructions for adding to Siri
tests:
- Unit: Test intent parameter parsing
- Integration: Test Siri response formatting
- Device: Test voice commands with Siri
acceptance_criteria:
- 5+ custom intents defined and working
- Siri can respond to "What's my threat score?"
- Siri can respond to "Run a security scan"
- Shortcuts app can create workflows with Kordant actions
- Intents donated after relevant user actions
- Suggested shortcuts appear in Siri suggestions
- Intent responses formatted naturally
- All intents work without opening app (where possible)
- Shortcuts settings UI in app
- Intents localized for English (expand to other languages later)
validation:
- Ask Siri "What's my threat score?" → responds with current score
- Say "Run a security scan" → scan initiated, confirmation spoken
- Create shortcut in Shortcuts app → Kordant actions available
- Check Siri suggestions → Kordant shortcuts suggested
notes:
- SiriKit intents require app to be in foreground for some actions
- Custom intents work best for read-only or simple actions
- Donate intents frequently so Siri learns user patterns
- Test on physical device — simulator Siri support is limited

View File

@@ -0,0 +1,77 @@
# 15. Home Screen Widgets
meta:
id: ios-production-15
feature: ios-production
priority: P2
depends_on: []
tags: [native-features, widgets, production]
objective:
- Implement home screen widgets to display threat score and recent alerts at a glance
deliverables:
- Widget extension target
- Small, medium, and large widget sizes
- Widget configuration intent
- Timelines with refresh strategy
steps:
1. Create widget extension:
- Add Widget Extension target in Xcode
- Configure app group for data sharing
- Set up widget bundle with multiple widgets
2. Design widgets:
- Small widget: Threat score gauge only
- Medium widget: Threat score + 2 recent alerts
- Large widget: Threat score + alert list + quick actions
- Use SwiftUI for widget UI
- Match app design system colors
3. Implement widget timeline:
- Create TimelineProvider
- Fetch data from shared UserDefaults or App Group
- Update every 15 minutes (widget limit)
- Handle placeholder, snapshot, and timeline entries
4. Add widget configuration:
- Intent for selecting widget type (if multiple variants)
- Intent for filtering alerts by severity
- Configuration UI in widget gallery
5. Share data with widget:
- Write threat score and alerts to shared container
- Update shared data when app refreshes
- Use WidgetCenter to reload timelines after app update
6. Add deep linking:
- Tap widget → open app to relevant screen
- Tap alert in widget → open alert detail
- Tap threat score → open dashboard
tests:
- Unit: Test timeline provider data formatting
- UI: Test widget rendering in all sizes
- Integration: Test data sharing between app and widget
acceptance_criteria:
- Widget extension building and running
- Small widget showing threat score
- Medium widget showing threat score + recent alerts
- Large widget showing full alert summary
- Widgets update every 15 minutes
- Data shared correctly between app and widget
- Deep links from widget to correct app screens
- Widgets match app design system
- Placeholder and snapshot states look good
- Widgets work in dark mode
- No crashes when widget data is missing
validation:
- Add widget to home screen → displays current threat score
- Receive new alert → widget updates within 15 minutes
- Tap widget → app opens to dashboard
- Tap specific alert in widget → alert detail opens
- Check widget in dark mode → colors correct
notes:
- Widgets cannot make network requests directly
- App must write data to shared container for widgets to read
- Widget memory limits are strict (especially for small widgets)
- Use WidgetCenter.reloadTimelines(ofKind:) to force updates

View File

@@ -0,0 +1,75 @@
# 16. App Clips
meta:
id: ios-production-16
feature: ios-production
priority: P3
depends_on: []
tags: [native-features, app-clips, production]
objective:
- Create an App Clip to allow users to preview Kordant functionality without downloading the full app
deliverables:
- App Clip target
- Lightweight onboarding flow
- Core feature preview (threat score check)
- App Clip invocation via QR code, NFC, or Safari
steps:
1. Create App Clip target:
- Add App Clip target in Xcode (max 15MB)
- Share code with main app where possible
- Configure associated domains for invocation
2. Design App Clip experience:
- Threat score check (no auth required, demo mode)
- Basic spam number check
- Signup prompt to unlock full features
- Clear CTA to download full app
3. Implement lightweight UI:
- Reuse SwiftUI components from main app
- Remove features requiring auth
- Simplify navigation (single screen or wizard)
- Fast load time (<2 seconds)
4. Configure invocation:
- Associated domain: appclips.kordant.com
- QR code generation for marketing
- Safari App Banner on website
- NFC tag support (optional)
5. Add App Clip card:
- Design card image (300x300 or 600x600)
- Configure in App Store Connect
- Include title, subtitle, action button
6. Handle App Clip to full app transition:
- Preserve state when user installs full app
- Transfer any entered data
- Deep link to relevant screen after install
tests:
- Size: Verify App Clip <15MB
- Performance: Launch time <2 seconds
- Invocation: Test QR code and Safari banner
acceptance_criteria:
- App Clip target building and <15MB
- App Clip shows threat score demo without auth
- App Clip includes spam number check
- Clear CTA to download full app
- Invocation via QR code, Safari banner, and associated domains
- App Clip card configured in App Store Connect
- Smooth transition to full app with state preserved
- App Clip loads in <2 seconds
- Works on iOS 14+
validation:
- Scan QR code → App Clip launches
- Check threat score → demo data displayed
- Tap "Get Full App" → App Store opens
- Install full app → previous state preserved
- Check size → binary <15MB
notes:
- App Clips are optional but great for user acquisition
- 15MB limit is strict — may need to strip features
- Focus on one compelling use case (threat score)
- App Clips cannot use Apple Sign-In or in-app purchases

View File

@@ -0,0 +1,88 @@
# 17. UI Test Suite Expansion
meta:
id: ios-production-17
feature: ios-production
priority: P1
depends_on: []
tags: [testing, ui-tests, quality]
objective:
- Expand UI test coverage to include all critical user journeys across the iOS app
deliverables:
- UI tests for auth flows
- UI tests for dashboard and services
- UI tests for settings
- Accessibility testing integration
steps:
1. Audit existing UI tests:
- Review iOS/KordantUITests/KordantUITests.swift
- Identify gaps in coverage
- Plan test scenarios
2. Create auth flow tests:
- Launch app → onboarding screen visible
- Sign up with valid credentials → dashboard
- Login with valid credentials → dashboard
- Login with invalid credentials → error shown
- Forgot password flow → confirmation shown
- Biometric prompt → enable/skip options
3. Create dashboard tests:
- Dashboard loads with widgets
- Pull to refresh updates data
- Tap alert → detail view opens
- Threat score updates correctly
4. Create service tests:
- Navigate to DarkWatch → watchlist loads
- Add watchlist item → appears in list
- Navigate to VoicePrint → enrollment screen
- Navigate to SpamShield → rules list
- Navigate to HomeTitle → property list
- Navigate to RemoveBrokers → listings shown
5. Create settings tests:
- Open settings → all options visible
- Toggle notifications → preference updated
- Update profile → changes saved
- Logout → returns to login screen
6. Add accessibility tests:
- Verify VoiceOver labels on all elements
- Test dynamic type support
- Test color contrast
7. Configure test data:
- Mock API responses for consistent tests
- Reset app state between tests
- Use test account credentials
8. Add CI integration:
- Run UI tests on pull requests
- Test on multiple simulators (iPhone SE, 14, 15 Pro Max)
- Upload test results and screenshots
tests:
- UI: All critical paths covered
- Accessibility: VoiceOver tests passing
- CI: Tests run automatically on PR
acceptance_criteria:
- 20+ UI test cases covering critical flows
- Auth flow fully tested (signup, login, forgot password)
- All 5 services have UI tests
- Settings and profile tested
- Tests run on iPhone SE, 14, and 15 Pro Max simulators
- Tests complete in <5 minutes
- Screenshots captured on failure
- Accessibility labels verified
- Mock API used for consistent test data
- CI runs UI tests on every PR
validation:
- Run UI tests → all pass
- Introduce UI bug → test fails
- Check test report → screenshots for all tests
- CI pipeline → UI tests green
notes:
- Use XCTest framework for UI tests
- Mock network layer for consistent, fast tests
- Tests should be independent (no shared state)
- Consider using Accessibility IDs for reliable element finding

View File

@@ -0,0 +1,76 @@
# 18. Performance Testing (XCTestMetric)
meta:
id: ios-production-18
feature: ios-production
priority: P2
depends_on: []
tags: [testing, performance, quality]
objective:
- Implement performance testing using XCTestMetric to ensure consistent 60fps and fast response times
deliverables:
- Performance tests for critical flows
- XCTMetric measurements
- Baseline performance documentation
- Performance regression detection in CI
steps:
1. Set up performance tests:
- Create XCTestCase with measure blocks
- Use XCTClockMetric for time measurements
- Use XCTCPUMetric for CPU usage
- Use XCTMemoryMetric for memory usage
2. Test critical flows:
- App launch time (cold and warm)
- Dashboard scroll performance (60fps)
- Alert list scroll performance
- Service screen transitions
- API response time (with mocked data)
- Image loading performance
3. Establish baselines:
- Run tests 10 times to establish baseline
- Document expected ranges for each metric
- Set performance budgets
4. Add regression detection:
- Configure XCTest to fail on 10% regression
- Add to CI pipeline
- Alert on performance degradation
5. Test on physical devices:
- iPhone SE (2nd gen) — minimum supported device
- iPhone 12 — mid-range target
- iPhone 15 Pro — high-end target
6. Document performance:
- Create docs/PERFORMANCE.md
- List all measured metrics and baselines
- Document optimization techniques used
tests:
- Performance: All metrics within budget
- Regression: 10% regression triggers failure
- Device: Tests pass on physical devices
acceptance_criteria:
- 10+ performance test cases
- App launch time measured and baselined
- Scroll performance tested (target 60fps)
- API response time measured
- Memory usage tracked during key flows
- Baselines established for iPhone SE, 12, and 15 Pro
- 10% regression threshold configured
- Performance tests run in CI
- Performance budget documented
- No performance regressions in release builds
validation:
- Run performance tests → all within budget
- Introduce slow animation → test fails
- Check CI → performance tests passing
- Review docs → baselines documented
notes:
- Performance tests should run on physical devices, not simulators
- Simulators don't reflect real-world performance accurately
- Use Xcode's Metrics tab to track performance over time
- Consider using Firebase Performance Monitoring for real-world data

View File

@@ -0,0 +1,80 @@
# 19. Accessibility Audit (VoiceOver)
meta:
id: ios-production-19
feature: ios-production
priority: P2
depends_on: []
tags: [testing, accessibility, compliance]
objective:
- Ensure the iOS app is fully accessible with VoiceOver and meets WCAG 2.1 AA mobile guidelines
deliverables:
- VoiceOver audit report
- Accessibility labels on all elements
- Dynamic Type support
- Color contrast verification
steps:
1. Audit all screens with VoiceOver:
- Turn on VoiceOver (Settings → Accessibility)
- Navigate every screen using swipe gestures
- Verify all interactive elements have labels
- Verify logical reading order
- Test with eyes closed
2. Add missing accessibility labels:
- Add .accessibilityLabel to all buttons
- Add .accessibilityHint where helpful
- Add .accessibilityValue for dynamic content
- Group related elements with .accessibilityElement(children:)
3. Test Dynamic Type:
- Enable Larger Text in Settings
- Test all screens at largest text size
- Verify no truncation or overlap
- Use ScrollView where content may overflow
4. Verify color contrast:
- Test all text/background color combinations
- Ensure 4.5:1 ratio for normal text
- Ensure 3:1 ratio for large text and UI components
- Test in both light and dark mode
5. Test Switch Control:
- Enable Switch Control
- Verify all actions reachable
- Test with external switch device if available
6. Test Reduce Motion:
- Enable Reduce Motion
- Verify app still functional without animations
- Respect prefersReducedMotion
7. Add accessibility tests:
- XCTest checks for accessibility labels
- Verify no unlabeled elements
- Test with accessibility inspector
tests:
- Manual: Full VoiceOver navigation of all screens
- Automated: XCTest accessibility label checks
- Visual: Color contrast verification
acceptance_criteria:
- All interactive elements have accessibility labels
- VoiceOver reads logical description for every element
- Dynamic Type supported at all sizes (AX5)
- Color contrast ≥4.5:1 for all text
- Reduce Motion respected
- Switch Control navigable
- No accessibility warnings in Xcode
- Accessibility audit report completed
- Screenshots at largest text size showing no layout issues
validation:
- Turn on VoiceOver → navigate entire app without visual
- Enable largest text size → all screens readable
- Check contrast → all combinations pass
- Xcode accessibility inspector → 0 warnings
notes:
- SwiftUI has good accessibility by default but custom views need attention
- Use .accessibilityElement(children: .combine) for complex views
- Test on physical device — simulator VoiceOver is limited
- Consider hiring accessibility consultant for thorough audit

View File

@@ -0,0 +1,85 @@
# 20. Device Farm Testing
meta:
id: ios-production-20
feature: ios-production
priority: P2
depends_on: []
tags: [testing, device-farm, quality]
objective:
- Test the iOS app on a diverse range of physical devices using a device farm service
deliverables:
- Device farm test configuration
- Tests running on multiple iOS versions and devices
- Test results and reports
- Bug fixes from device-specific issues
steps:
1. Choose device farm service:
- AWS Device Farm
- Firebase Test Lab (limited iOS support)
- BrowserStack App Live
- Sauce Labs
- Or manual testing on physical devices
2. Configure test suite:
- Upload IPA build
- Configure XCTest UI test bundle
- Select device matrix:
- iPhone SE (3rd gen) — iOS 17
- iPhone 12 — iOS 16
- iPhone 14 Pro — iOS 17
- iPhone 15 Pro Max — iOS 18
- iPad Pro 12.9" — iOS 18
- iPad mini — iOS 17
3. Define test scenarios:
- Install and launch
- Complete onboarding
- Login and dashboard navigation
- Run security scan
- View alerts and details
- Settings navigation
- Background/foreground transitions
4. Run tests and collect results:
- Execute automated test suite
- Collect screenshots and videos
- Gather performance metrics
- Document device-specific issues
5. Fix device-specific bugs:
- Notch/safe area issues on different models
- Dynamic Island interactions
- iPad multitasking support
- Performance on older devices
6. Add device farm to CI:
- Trigger tests on release builds
- Block release on critical failures
- Archive results for compliance
tests:
- Device: All selected devices pass core tests
- Regression: No new failures compared to previous run
- Performance: App responsive on all devices
acceptance_criteria:
- Tests run on 6+ different iOS devices
- Tests cover iOS 16, 17, and 18
- All critical flows pass on all devices
- Screenshots and videos from all test runs
- Device-specific issues identified and fixed
- Device farm integrated into release CI
- Test results archived for 1 year
- No crashes on any tested device
- Performance acceptable on oldest supported device
validation:
- Run device farm tests → all devices pass
- Review screenshots → UI looks correct on all sizes
- Check videos → no stuttering or crashes
- Compare with previous run → no regressions
notes:
- AWS Device Farm is most comprehensive for iOS
- Physical device testing is ideal but expensive
- Focus on edge cases: small screens, old iOS versions
- Test cellular vs WiFi behavior if possible

View File

@@ -0,0 +1,78 @@
# 21. Real API Client Wiring (Replace StubAPIClient)
meta:
id: ios-production-21
feature: ios-production
priority: P1
depends_on: []
tags: [backend, api, production]
objective:
- Replace the StubAPIClient with a real API client that connects to the production backend
deliverables:
- Real API client implementing AuthAPIClientProtocol
- Backend OAuth endpoints for iOS
- AuthService wired to real client in production
- Environment-based client selection
steps:
1. Create real API client:
- Create iOS/Kordant/Services/RealAPIClient.swift
- Implement AuthAPIClientProtocol methods:
- login(email:password:) → POST /api/trpc/user.login
- signup(name:email:password:) → POST /api/trpc/user.signup
- resetPassword(email:) → POST /api/trpc/user.forgotPassword
- Use existing APIClient for network layer
- Handle tRPC response format (batch input, result wrapper)
2. Add OAuth support:
- Apple Sign-In token exchange endpoint
- Google Sign-In token exchange endpoint
- Social account linking
3. Configure environment-based client:
- Debug builds: use RealAPIClient pointing to staging
- Release builds: use RealAPIClient pointing to production
- Unit tests: continue using StubAPIClient or MockAPIClient
4. Update AuthService initialization:
- Modify KordantApp.swift to inject RealAPIClient
- Keep dependency injection pattern
- Add build configuration for base URL
5. Add error handling:
- Map API errors to user-friendly messages
- Handle network errors gracefully
- Retry on transient failures
6. Test integration:
- Test login against staging backend
- Test signup flow
- Test token persistence
- Test session restoration
tests:
- Unit: Test RealAPIClient with mock URLSession
- Integration: Test against staging backend
- E2E: Complete auth flow on physical device
acceptance_criteria:
- RealAPIClient implements all AuthAPIClientProtocol methods
- Login works against production backend
- Signup creates user in production database
- Password reset sends email
- Apple Sign-In and Google Sign-In tokens exchanged correctly
- Auth token persisted in keychain
- Session restored on app relaunch
- Debug builds use staging, release builds use production
- Unit tests still use mock clients
- All auth errors mapped to user-friendly messages
validation:
- Build debug → login to staging → success
- Build release → login to production → success
- Run unit tests → all pass with mocks
- Check keychain → token stored after login
- Kill and relaunch app → still authenticated
notes:
- This is critical — currently StubAPIClient throws notImplemented for everything
- Must be done before any backend integration tasks
- Coordinate with backend team on OAuth endpoint contracts
- Use APIConfig.swift for base URL configuration

View File

@@ -0,0 +1,77 @@
# 22. Token Refresh & Session Management
meta:
id: ios-production-22
feature: ios-production
priority: P1
depends_on: [ios-production-21]
tags: [backend, auth, production]
objective:
- Implement automatic token refresh and robust session management to prevent unexpected logouts
deliverables:
- Token refresh interceptor in APIClient
- Silent re-authentication flow
- Session expiry handling
- Concurrent request queue during refresh
steps:
1. Implement token refresh:
- Add refresh token endpoint to backend if not exists
- Modify APIClient to detect 401 responses
- On 401, attempt token refresh with refresh token
- Retry original request with new token
2. Handle concurrent requests:
- Queue requests while refresh in progress
- Don't duplicate refresh requests
- Use Combine or async/await for coordination
3. Add silent re-authentication:
- If refresh fails, try biometric re-auth
- If biometric fails, prompt for password
- If all fail, logout user
4. Implement session expiry:
- Parse JWT expiry claim
- Proactively refresh before expiry (5 min buffer)
- Schedule background refresh
5. Add session monitoring:
- Track session age
- Alert user when session nearing expiry
- Auto-refresh on app foreground
6. Handle edge cases:
- Refresh token also expired → full re-auth
- Network unavailable during refresh → queue and retry
- Multiple tabs/apps refreshing simultaneously
7. Update AuthService:
- Expose session state
- Handle refresh failures gracefully
- Notify UI of re-authentication needs
tests:
- Unit: Test token refresh logic
- Integration: Test concurrent request handling
- E2E: Test session expiry and refresh
acceptance_criteria:
- Token refresh automatic and transparent to user
- Concurrent requests queued during refresh, not failed
- Proactive refresh 5 minutes before expiry
- Biometric re-auth offered if refresh fails
- Session restored on app relaunch (if tokens valid)
- Graceful logout if all auth methods fail
- No duplicate refresh requests
- Background refresh on app foreground
- Unit tests covering all refresh scenarios
validation:
- Wait for token expiry → app refreshes automatically
- Trigger 401 → refresh attempted, request retried
- Revoke refresh token → app prompts re-auth
- Background app → foreground → token refreshed if needed
- Check logs → no duplicate refresh requests
notes:
- Current APIClient has retry logic but no token refresh
- Backend must support refresh token endpoint
- Consider using OAuth 2.0 refresh token flow
- Store refresh token with higher security than access token

View File

@@ -0,0 +1,83 @@
# 23. Offline Mode & Sync Conflict Resolution
meta:
id: ios-production-23
feature: ios-production
priority: P2
depends_on: [ios-production-21]
tags: [backend, offline, production]
objective:
- Implement robust offline mode with sync conflict resolution for all user actions
deliverables:
- Offline queue improvements
- Sync conflict resolution strategy
- Offline UI indicators
- Data consistency guarantees
steps:
1. Audit existing offline support:
- Review iOS/Kordant/Services/OfflineQueue.swift
- Review CacheManager.swift
- Identify gaps in offline handling
2. Improve offline queue:
- Support all mutation types (add, update, delete)
- Add request deduplication
- Add request ordering (dependencies)
- Increase max retry count with exponential backoff
3. Implement conflict resolution:
- Define strategy per data type:
- Server wins for most data (alerts, exposures)
- Last write wins for user preferences
- Merge for watchlist items
- Add conflict detection (version numbers or timestamps)
- Show conflict UI for manual resolution (if needed)
4. Add offline UI:
- Offline indicator in status bar
- Disabled actions when offline
- "Sync pending" badges on modified items
- Pull-to-refresh with offline state
5. Implement data consistency:
- Optimistic updates (update UI immediately, sync in background)
- Rollback on sync failure
- Verify server state after sync
- Handle partial sync failures
6. Add background sync:
- Process queue on app foreground
- Process queue on network restoration
- Schedule periodic sync attempts
7. Test offline scenarios:
- Create watchlist item offline → syncs when online
- Delete exposure offline → syncs when online
- Modify settings offline → syncs when online
- Conflicting edits on multiple devices
tests:
- Unit: Test queue ordering and deduplication
- Integration: Test sync after offline period
- E2E: Test conflicting edits resolution
acceptance_criteria:
- All mutations queued when offline
- Queue processed automatically when online
- Optimistic updates show immediately
- Failed operations roll back UI changes
- Conflict resolution strategy defined per data type
- Offline indicator visible in UI
- Sync pending badges on modified items
- No data loss during sync failures
- Background sync on app foreground and network restore
- Unit tests for all offline scenarios
validation:
- Enable airplane mode → create watchlist item → badge shows
- Disable airplane mode → item syncs → badge clears
- Edit same item on web and iOS → conflict resolved correctly
- Kill app during sync → queue persists, resumes on relaunch
notes:
- Current OfflineQueue exists but may need enhancement
- CRDTs (Conflict-free Replicated Data Types) are ideal for sync
- Consider using Realm or Core Data with sync for complex cases
- Simple server-wins strategy is acceptable for MVP

View File

@@ -0,0 +1,82 @@
# 24. Push Notification Deep Linking
meta:
id: ios-production-24
feature: ios-production
priority: P2
depends_on: [ios-production-21]
tags: [native-features, push-notifications, production]
objective:
- Ensure push notifications correctly deep link to relevant screens with proper handling of app state
deliverables:
- Deep link routing for all notification types
- Cold start handling
- Background notification processing
- Notification analytics
steps:
1. Audit existing push handling:
- Review iOS/Kordant/Services/PushNotificationService.swift
- Review KordantApp.swift handleNotificationNavigation
- Identify gaps in deep linking
2. Implement deep link routes:
- Alert notification → AlertDetailView
- Exposure notification → DarkWatchView
- Scan complete notification → DashboardView
- Family invite → Settings/Family
- Subscription renewal → Settings/Billing
- Marketing → Landing or specific feature
3. Handle app states:
- App closed (cold start): launch → process notification → navigate
- App background: wake → process → navigate
- App foreground: show in-app toast → navigate on tap
4. Add notification categories:
- Actionable notifications (Resolve Alert, Dismiss)
- Rich notifications with images
- Grouped notifications by type
5. Implement analytics:
- Track notification delivery
- Track notification open rates
- Track conversion from notification to action
- A/B test notification copy
6. Add notification preferences:
- Allow user to customize notification types
- Respect system notification settings
- Update backend preferences
7. Test all scenarios:
- Cold start from each notification type
- Background tap on notification
- Foreground notification handling
- Action button taps
tests:
- Unit: Test deep link route mapping
- Integration: Test notification handling in all states
- Device: Send test notifications via Firebase Console
acceptance_criteria:
- All notification types deep link to correct screens
- Cold start from notification opens correct screen
- Background notification tap navigates correctly
- Foreground notifications show in-app toast
- Actionable notification buttons work
- Notification preferences respected
- Analytics tracking delivery and open rates
- Rich notifications with images render correctly
- No crashes from malformed notification payloads
- Unit tests for all deep link routes
validation:
- Send alert notification → tap → AlertDetailView opens
- Send exposure notification → app closed → DarkWatchView opens
- Receive notification in foreground → toast shown
- Tap action button → correct action performed
- Check analytics → open rate tracked
notes:
- Current KordantApp.swift has basic routing but needs expansion
- Use UNUserNotificationCenter for modern notification handling
- Test on physical device — simulator push notifications are limited
- Coordinate with backend on notification payload format

View File

@@ -0,0 +1,82 @@
# 25. Privacy Manifest & Nutrition Labels
meta:
id: ios-production-25
feature: ios-production
priority: P1
depends_on: []
tags: [compliance, app-store, privacy, production]
objective:
- Create and configure the required privacy manifest and App Privacy nutrition labels for App Store submission
deliverables:
- Privacy manifest file (PrivacyInfo.xcprivacy)
- App Privacy nutrition labels in App Store Connect
- Third-party SDK privacy manifests
- Data usage disclosure documentation
steps:
1. Create privacy manifest:
- Add PrivacyInfo.xcprivacy to project
- Declare all collected data types:
- Contact Info (name, email)
- User Content (voice recordings for VoicePrint)
- Identifiers (user ID, device ID)
- Usage Data (analytics)
- Diagnostics (crash logs)
- Declare required reason APIs:
- File timestamp APIs (if used)
- Disk space APIs (if used)
- System boot time APIs (if used)
- Active keyboard APIs (if used)
- User defaults APIs (used for preferences)
2. Configure App Privacy nutrition labels:
- Log into App Store Connect
- Navigate to App Privacy section
- Select all data types collected by app
- Mark each as linked to user identity or not
- Mark each as used for tracking or not
- Specify purposes (analytics, app functionality, etc.)
3. Audit third-party SDKs:
- Check Firebase SDK privacy manifest
- Check any analytics SDK privacy manifest
- Ensure all SDKs have updated manifests for iOS 17+
- Update SDKs if manifests missing
4. Document data usage:
- Create docs/IOS_PRIVACY.md
- List all data collection and purposes
- Explain user controls and opt-out options
- Document data retention periods
5. Test manifest validation:
- Build app in Xcode
- Check for privacy manifest warnings
- Validate with App Store Connect upload
tests:
- Build: No privacy manifest warnings in Xcode
- Upload: App Store Connect accepts privacy labels
- Review: Privacy labels match actual data collection
acceptance_criteria:
- PrivacyInfo.xcprivacy file in project
- All collected data types declared
- Required reason APIs documented
- App Privacy nutrition labels complete in App Store Connect
- All third-party SDKs have privacy manifests
- Privacy labels accurate and honest
- No Xcode warnings about missing privacy manifests
- Documentation of data usage available
- User-facing privacy policy linked
validation:
- Build app → no privacy manifest warnings
- Upload to App Store Connect → privacy section complete
- Review data types → all actual collection declared
- Check SDK versions → all include privacy manifests
notes:
- Apple requires privacy manifests for all apps starting 2024
- Nutrition labels must be accurate — false claims can lead to rejection
- Third-party SDKs without manifests may cause build warnings
- Update manifests when adding new data collection features

View File

@@ -0,0 +1,78 @@
# 26. App Tracking Transparency (ATT)
meta:
id: ios-production-26
feature: ios-production
priority: P1
depends_on: []
tags: [compliance, privacy, app-store, production]
objective:
- Implement App Tracking Transparency to comply with iOS privacy requirements for analytics and advertising
deliverables:
- ATT permission request
- Analytics gated behind ATT consent
- Tracking description in Info.plist
- Fallback for denied tracking
steps:
1. Add ATT framework:
- Import AppTrackingTransparency
- Add NSUserTrackingUsageDescription to Info.plist
- Description: "Your data will be used to improve app experience and measure marketing effectiveness"
2. Implement permission request:
- Request tracking authorization on first launch (after onboarding)
- Show explanation before system dialog
- Handle all authorization states:
- .notDetermined → request permission
- .restricted → disable tracking
- .denied → disable tracking
- .authorized → enable tracking
3. Gate analytics behind ATT:
- Check tracking status before initializing analytics
- If denied: use anonymous analytics only (no IDFA)
- If authorized: full analytics with IDFA
- Respect user's choice across app sessions
4. Update third-party SDKs:
- Configure Firebase Analytics to respect ATT
- Configure PostHog/Plausible to respect ATT
- Disable ad network tracking if denied
5. Handle state changes:
- Monitor for settings changes
- Update tracking status if user changes in Settings
- Re-initialize analytics accordingly
6. Add UI for tracking preferences:
- Settings toggle for analytics (if user previously denied)
- Explanation of what data is collected
- Link to system Settings for ATT changes
tests:
- Unit: Test ATT status handling
- Integration: Test analytics initialization gating
- Device: Test permission flow on physical device
acceptance_criteria:
- ATT permission requested after onboarding
- System dialog shows with accurate description
- Analytics initialize only after authorized or denied
- If denied: no IDFA collection, minimal anonymous analytics
- If authorized: full analytics collection
- Third-party SDKs configured to respect ATT
- Settings UI allows users to change preference
- App complies with Apple's ATT guidelines
- No tracking before permission granted
- Unit tests covering all authorization states
validation:
- Fresh install → onboarding → ATT dialog appears
- Deny tracking → analytics uses anonymous mode
- Authorize tracking → full analytics active
- Change in Settings → app respects new choice
- Check Info.plist → NSUserTrackingUsageDescription present
notes:
- ATT is required if app collects IDFA or shares data for tracking
- If only using first-party analytics, ATT may not be required
- Be honest in description — Apple reviews these carefully
- Consider making analytics fully anonymous to avoid ATT entirely

View File

@@ -0,0 +1,81 @@
# 27. Data Usage Descriptions
meta:
id: ios-production-27
feature: ios-production
priority: P1
depends_on: []
tags: [compliance, privacy, app-store, production]
objective:
- Add all required permission usage descriptions to Info.plist for camera, microphone, location, and other sensitive APIs
deliverables:
- Info.plist permission descriptions
- Localized descriptions for supported languages
- In-app permission rationale dialogs
- Permission handling in all features
steps:
1. Audit all permissions used:
- Camera (document scanning, VoicePrint enrollment)
- Microphone (VoicePrint enrollment)
- Photo Library (document upload)
- Push Notifications (alerts)
- Face ID / Touch ID (biometric auth)
- Location (not currently used — verify)
- Contacts (not currently used — verify)
2. Add Info.plist descriptions:
- NSCameraUsageDescription: "Camera is used to scan documents for identity verification"
- NSMicrophoneUsageDescription: "Microphone is used to enroll your voice for VoicePrint protection"
- NSPhotoLibraryUsageDescription: "Photo library access is used to upload identity documents"
- NSFaceIDUsageDescription: "Face ID is used to securely access your account"
- NSUserTrackingUsageDescription: (from task 26)
- UIBackgroundModes: fetch, remote-notification
3. Localize descriptions:
- Add translations for Spanish, French (if supporting)
- Create InfoPlist.strings for each language
- Keep descriptions concise but informative
4. Add in-app rationale dialogs:
- Show custom dialog before system permission request
- Explain why permission is needed
- Include example of feature benefit
- Add "Don't Allow" and "Allow" buttons
5. Handle permission denials:
- Show guidance to Settings if permission denied
- Degrade functionality gracefully
- Don't crash if permission unavailable
6. Test all permission flows:
- First request → rationale → system dialog
- Deny → feature degraded → Settings guidance
- Allow → feature fully functional
- Revoke in Settings → app handles gracefully
tests:
- Unit: Test permission state handling
- Integration: Test rationale dialog flow
- Device: Test all permissions on physical device
acceptance_criteria:
- All required Info.plist descriptions present
- Descriptions accurate and user-friendly
- Localized for all supported languages
- In-app rationale dialogs before system requests
- Graceful degradation when permissions denied
- Settings guidance for denied permissions
- No crashes from missing permissions
- All permission flows tested on physical device
- App Review will approve descriptions
validation:
- Check Info.plist → all NS*UsageDescription keys present
- Test camera permission → rationale dialog → system dialog
- Deny permission → app shows Settings guidance
- Check localization → descriptions in correct language
- App Review → no rejections for permission descriptions
notes:
- Apple rejects apps with generic permission descriptions
- Descriptions must explain specific feature usage
- Always show rationale before system dialog
- Test on physical device — simulator doesn't show permission dialogs realistically

View File

@@ -0,0 +1,88 @@
# 28. App Review Guidelines Compliance
meta:
id: ios-production-28
feature: ios-production
priority: P1
depends_on: []
tags: [compliance, app-store, production]
objective:
- Ensure the iOS app fully complies with Apple App Review Guidelines to pass review on first submission
deliverables:
- App Review Guidelines compliance checklist
- All guideline requirements met
- Reviewer demo account and notes
- Rejection risk mitigation
steps:
1. Review App Store Review Guidelines:
- Safety: no objectionable content, no physical harm
- Performance: complete app, no crashes, accurate metadata
- Business: no scams, proper IAP if digital goods
- Design: minimum functionality, proper use of system features
- Legal: privacy policy, data collection disclosure
2. Check specific requirements:
- App is complete and functional (no placeholders, no "coming soon")
- All buttons and features work
- No broken links
- No test data visible to users
- No beta/test labels
3. Verify business model:
- If subscriptions: use StoreKit or web billing (document choice)
- If digital goods: must use in-app purchase
- No external purchase links (unless reader apps exception)
- No misleading pricing
4. Check content guidelines:
- No spam, no excessive ads
- No misleading claims about security
- Accurate description of AI features
- No harassment or hate speech content
5. Verify technical requirements:
- App launches within reasonable time
- No excessive battery drain
- Proper use of background modes
- No private API usage
- No beta SDKs or frameworks
6. Prepare for review:
- Create demo account with realistic data
- Write detailed review notes
- Include video of app usage (optional but helpful)
- Document any complex features for reviewer
7. Handle common rejection reasons:
- Guideline 2.1 (App Completeness) → all features working
- Guideline 4.2 (Minimum Functionality) → not just a wrapper
- Guideline 5.1.1 (Data Collection) → proper disclosures
- Guideline 5.6 (Developer Code of Conduct) → no manipulation
tests:
- Review: Internal review using Apple guidelines checklist
- Functionality: All features tested end-to-end
- Content: Review all user-facing text for accuracy
acceptance_criteria:
- All App Store Review Guidelines requirements met
- App is complete with no placeholder content
- All features functional and tested
- Demo account created with realistic data
- Review notes prepared explaining app functionality
- Privacy policy and terms of service linked
- No test data, labels, or beta markings visible
- Business model compliant with IAP guidelines
- No private APIs or undocumented features
- App passes internal review checklist with 0 issues
validation:
- Internal review checklist → all items checked
- Test every button and flow → all work correctly
- Review all text → accurate, no typos, no placeholders
- Check for test data → none visible
- Verify no private APIs → scan with otool or similar
notes:
- Apple reviewers test on physical devices with various iOS versions
- First submission often takes 1-2 days for review
- Have a plan for addressing rejections quickly
- Consider using App Review acceleration for critical launches
- Document any complex authentication flows for reviewers

View File

@@ -0,0 +1,89 @@
# iOS Production Readiness
Objective: Prepare the SwiftUI iOS application for App Store submission with hardened security, optimized performance, comprehensive testing, and full native feature integration.
Status legend: [ ] todo, [~] in-progress, [x] done
## Tasks
### App Store Preparation
- [ ] 01 — App Store Screenshots & Metadata → `01-app-store-screenshots.md`
- [ ] 02 — App Preview Video → `02-app-preview-video.md`
- [ ] 03 — App Store Connect Configuration → `03-app-store-connect.md`
- [ ] 04 — TestFlight Beta Distribution → `04-testflight-beta.md`
### Security Hardening
- [ ] 05 — Certificate Pinning & TLS Validation → `05-certificate-pinning.md`
- [ ] 06 — Jailbreak Detection & Runtime Security → `06-jailbreak-detection.md`
- [ ] 07 — Keychain & Data Protection Audit → `07-keychain-data-protection.md`
- [ ] 08 — OAuth & Social Login Integration → `08-oauth-social-login.md`
### Performance Optimization
- [ ] 09 — Image Caching & Lazy Loading → `09-image-caching.md`
- [ ] 10 — Memory Management & Leak Audit → `10-memory-leak-audit.md`
- [ ] 11 — Background Fetch & Sync Optimization → `11-background-fetch.md`
- [ ] 12 — App Launch Time Optimization → `12-launch-time.md`
### Native Features
- [ ] 13 — CallKit Integration for SpamShield → `13-callkit-spamshield.md`
- [ ] 14 — Siri Shortcuts & Intents → `14-siri-shortcuts.md`
- [ ] 15 — Home Screen Widgets → `15-home-screen-widgets.md`
- [ ] 16 — App Clips → `16-app-clips.md`
### Testing & QA
- [ ] 17 — UI Test Suite Expansion → `17-ui-test-expansion.md`
- [ ] 18 — Performance Testing (XCTestMetric) → `18-performance-testing.md`
- [ ] 19 — Accessibility Audit (VoiceOver) → `19-accessibility-audit.md`
- [ ] 20 — Device Farm Testing → `20-device-farm-testing.md`
### Backend Integration
- [ ] 21 — Real API Client Wiring (Replace StubAPIClient) → `21-real-api-client.md`
- [ ] 22 — Token Refresh & Session Management → `22-token-refresh.md`
- [ ] 23 — Offline Mode & Sync Conflict Resolution → `23-offline-sync.md`
- [ ] 24 — Push Notification Deep Linking → `24-push-deep-links.md`
### App Store Compliance
- [ ] 25 — Privacy Manifest & Nutrition Labels → `25-privacy-manifest.md`
- [ ] 26 — App Tracking Transparency (ATT) → `26-app-tracking.md`
- [ ] 27 — Data Usage Descriptions → `27-data-usage-descriptions.md`
- [ ] 28 — App Review Guidelines Compliance → `28-review-compliance.md`
## Dependencies
- 01, 02, 03, 04 can be done in parallel (App Store prep)
- 05, 06, 07, 08 can be done in parallel (security)
- 09, 10, 11, 12 can be done in parallel (performance)
- 13, 14, 15, 16 can be done in parallel (native features)
- 17, 18, 19, 20 can be done in parallel (testing)
- 21 must be done before 22, 23, 24 (backend integration foundation)
- 22, 23, 24 depend on 21
- 25, 26, 27, 28 can be done in parallel (compliance)
- All groups can proceed independently
## Exit Criteria
- App Store listing complete with screenshots for all supported devices
- App preview video uploaded (15-30 seconds)
- TestFlight build distributed to internal testers
- Certificate pinning active on all API endpoints
- Jailbreak detection implemented with graceful degradation
- Keychain items secured with appropriate accessibility levels
- OAuth and social login flows working (Google, Apple Sign-In)
- Image caching with 50MB disk limit and LRU eviction
- Memory leaks resolved (0 leaks in Instruments leak check)
- Background fetch refreshing data every 15 minutes
- Cold launch time under 2 seconds on iPhone 12
- CallKit extension filtering spam calls in real-time
- Siri shortcuts for common actions (check alerts, run scan)
- Home screen widgets showing threat score and recent alerts
- App Clip allowing preview without full download
- UI tests covering all critical user flows
- Performance tests confirming 60fps scrolling on all lists
- VoiceOver labels on all interactive elements
- Device farm tests passing on iPhone SE, 12, 14 Pro, 15 Pro Max
- StubAPIClient fully replaced with real APIClient
- Token refresh automatic with silent re-authentication
- Offline queue syncing correctly with conflict resolution
- Push notifications deep linking to correct screens
- Privacy manifest accurately declaring all data collection
- ATT prompt shown before any analytics tracking
- All permission descriptions localized and accurate
- App passes App Review with no rejections on first submission

View File

@@ -0,0 +1,61 @@
# 01. Security Headers & CORS Configuration
meta:
id: web-production-01
feature: web-production
priority: P1
depends_on: []
tags: [security, infrastructure, production]
objective:
- Implement comprehensive security headers and CORS configuration to protect against common web vulnerabilities
deliverables:
- Security headers middleware in web/src/middleware.ts or Nitro config
- CORS configuration for API endpoints
- Content Security Policy (CSP) headers
- Remove X-Powered-By and other identifying headers
steps:
1. Add helmet-like security headers via Nitro hooks or Vite plugin:
- Strict-Transport-Security (HSTS)
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- X-XSS-Protection: 1; mode=block
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy for camera, microphone, geolocation
2. Implement CSP header allowing only necessary sources:
- script-src: 'self', stripe.com, clerk.dev
- style-src: 'self', 'unsafe-inline' (needed for Tailwind)
- img-src: 'self', data:, blob:, gravatar.com
- connect-src: 'self', api endpoints, websocket URL
- frame-src: 'self', stripe.com (for Checkout)
3. Configure CORS for /api/trpc endpoints:
- Allow origins: production domain, mobile app origins
- Allow methods: GET, POST
- Allow headers: Content-Type, Authorization, x-api-key
- Credentials: true
4. Remove server-identifying headers (X-Powered-By, Server)
5. Add tests verifying headers are present on all responses
tests:
- Unit: Test each header is present and correct value
- Integration: Test API endpoints return correct CORS headers
- Security scan: Use securityheaders.com or similar to verify A+ rating
acceptance_criteria:
- All 8 security headers present on every HTTP response
- CSP blocking inline scripts except nonce/hash approved
- CORS preflight requests handled correctly for API endpoints
- SecurityHeaders.com scan returns A+ rating
- No server version information leaked in headers
validation:
- Run `curl -I https://localhost:3000` and verify headers
- Run automated security header scanner
- Check browser dev tools Network tab for all response headers
notes:
- SolidStart/Nitro may require custom plugin for headers
- CSP 'unsafe-inline' for styles is acceptable with Tailwind v4 but document the trade-off
- Consider using nonce-based CSP once Tailwind supports it fully

View File

@@ -0,0 +1,58 @@
# 02. Rate Limiting & DDoS Protection
meta:
id: web-production-02
feature: web-production
priority: P1
depends_on: []
tags: [security, infrastructure, production]
objective:
- Implement robust rate limiting and DDoS protection beyond the basic in-memory tRPC middleware
deliverables:
- Redis-backed rate limiting for distributed deployment
- Per-endpoint rate limit tiers
- IP-based and user-based limiting
- DDoS protection via Cloudflare or similar
steps:
1. Replace in-memory rate limit map with Redis-backed solution:
- Use ioredis or @upstash/ratelimit for distributed rate limiting
- Create web/src/server/lib/ratelimit.ts with configurable tiers
2. Define rate limit tiers:
- Public endpoints (login, signup): 5 req/min per IP
- Authenticated API: 100 req/min per user
- Sensitive operations (password reset): 3 req/hour per email
- WebSocket connections: 1 per user, reconnect max 5/min
- Admin endpoints: 50 req/min per admin
3. Add IP-based rate limiting at edge/Nitro level for anonymous traffic
4. Configure Cloudflare (or alternative) for:
- DDoS protection
- Bot management
- Challenge pages for suspicious traffic
5. Add rate limit response headers (X-RateLimit-Remaining, X-RateLimit-Reset)
6. Implement sliding window algorithm for fairer limiting
tests:
- Unit: Test rate limiter correctly counts and resets
- Integration: Flood endpoint with requests, verify 429 responses
- Load: Use k6 or artillery to test limits under load
acceptance_criteria:
- Redis-backed rate limiting active on all endpoints
- 429 responses include Retry-After header
- Rate limits enforced per-IP, per-user, and per-endpoint
- DDoS protection layer active at edge
- No single IP can exceed 1000 req/min to any endpoint
- Rate limit headers present on all API responses
validation:
- `ab -n 1000 -c 10` against login endpoint → 429s after limit
- Verify Redis keys exist for rate limit counters
- Check Cloudflare dashboard for blocked threats
notes:
- Current in-memory rate limit in web/src/server/api/utils.ts will not work across multiple server instances
- Upstash Redis recommended for serverless deployments
- Consider implementing token bucket for burst tolerance

View File

@@ -0,0 +1,62 @@
# 03. Input Validation & XSS Prevention Audit
meta:
id: web-production-03
feature: web-production
priority: P1
depends_on: []
tags: [security, validation, production]
objective:
- Audit and harden all input validation to prevent XSS, injection attacks, and malformed data
deliverables:
- XSS prevention audit report
- Input sanitization layer
- HTML escaping on all user-generated content
- SQL injection protection verification
steps:
1. Audit all tRPC routers for input validation gaps:
- Check web/src/server/api/routers/*.ts for missing valibot schemas
- Ensure all user inputs have strict type validation
- Add maxLength constraints to all string inputs
2. Implement output escaping for user-generated content:
- Blog posts, user names, alert messages
- Use DOMPurify or similar on client-side rendering
- Escape HTML entities server-side before DB storage
3. Audit database queries for SQL injection:
- Verify all queries use Drizzle parameterized queries
- Check raw SQL usage in jobs and services
- Ensure no string concatenation in SQL
4. Add content validation for file uploads (if any):
- MIME type verification
- File size limits
- Scan for malware
5. Implement request body size limits:
- 1MB max for JSON payloads
- 10MB max for file uploads
6. Add tests for malformed input handling
tests:
- Unit: Test each router with XSS payloads, SQL injection attempts
- Integration: Submit malicious inputs via API, verify safe handling
- Security: Run OWASP ZAP or Burp Suite against app
acceptance_criteria:
- All tRPC inputs have strict valibot validation with bounds
- User-generated content escaped before rendering
- No SQL injection vectors in any query
- XSS payloads rendered as plain text, not executed
- Request body size limits enforced
- OWASP ZAP scan shows no high/critical vulnerabilities
validation:
- Submit `<script>alert('xss')</script>` in all text fields → rendered safely
- Submit SQL injection in search fields → no database errors
- Run `npm audit` and address all high severity issues
notes:
- Valibot schemas already in use — expand them with stricter bounds
- Consider using zod for more complex validation if valibot is limiting
- Sanitize inputs at API boundary, not just client-side

View File

@@ -0,0 +1,71 @@
# 04. Authentication & Session Security Hardening
meta:
id: web-production-04
feature: web-production
priority: P1
depends_on: []
tags: [security, auth, production]
objective:
- Harden authentication and session management to prevent session hijacking, fixation, and brute force attacks
deliverables:
- Secure session configuration
- JWT hardening
- Brute force protection
- Session invalidation on logout
- Multi-factor authentication foundation
steps:
1. Harden JWT implementation in web/src/server/auth/jwt.ts:
- Remove fallback secret (currently uses dev secret if env missing)
- Add JWT issuer and audience claims
- Implement token blacklisting for logout
- Add refresh token rotation
2. Harden session management in web/src/server/auth/session.ts:
- Use httpOnly, secure, sameSite=strict cookies
- Add session fingerprinting (user agent hash)
- Implement concurrent session limits (max 5 per user)
- Add automatic session expiry refresh on activity
3. Add brute force protection:
- Track failed login attempts per IP/email
- Progressive delays: 1s, 2s, 4s, 8s, 16s
- Lock account after 10 failed attempts (1 hour)
4. Implement secure logout:
- Invalidate session in database
- Clear all cookies
- Blacklist JWT token
- Revoke refresh token
5. Add MFA foundation:
- TOTP secret generation
- QR code for authenticator apps
- Backup codes
6. Audit Clerk integration for security:
- Verify webhook signature validation
- Check Clerk session sync with custom sessions
tests:
- Unit: Test JWT signing/verification with invalid tokens
- Integration: Test brute force lockout, session expiry
- Security: Test session hijacking resistance
acceptance_criteria:
- No hardcoded or fallback secrets in auth code
- All cookies have httpOnly, secure, sameSite=strict
- Brute force protection active on login endpoints
- Logout invalidates session completely
- JWT tokens include iss, aud, iat, exp claims
- Session fingerprinting prevents cookie theft reuse
- MFA TOTP generation working with Google Authenticator
validation:
- Attempt 10 failed logins → account locked
- Steal session cookie from one browser → invalid in another (fingerprinting)
- Logout → session token rejected on subsequent requests
- Check JWT with jwt.io → valid iss and aud claims
notes:
- Current JWT has fallback secret — this is critical to fix before production
- Clerk handles frontend auth but backend needs its own hardening
- Consider using Lucia Auth or NextAuth patterns for session management

View File

@@ -0,0 +1,61 @@
# 05. CDN & Asset Optimization
meta:
id: web-production-05
feature: web-production
priority: P2
depends_on: []
tags: [performance, infrastructure, production]
objective:
- Configure CDN for static assets and optimize frontend bundle delivery
deliverables:
- CDN configuration (Cloudflare, Vercel Edge, or AWS CloudFront)
- Asset optimization (images, fonts, JS/CSS)
- Brotli/Gzip compression
- Cache-Control headers for static assets
steps:
1. Configure CDN for static assets:
- Set up Cloudflare or Vercel Edge Network
- Point CDN to web/dist/client or .output/public
- Configure cache rules for static files
2. Optimize image delivery:
- Convert landing page SVGs to optimized formats where appropriate
- Add responsive image srcset for photos
- Implement lazy loading for below-fold images
3. Configure compression:
- Enable Brotli compression (better than gzip)
- Ensure Nitro/Vite build outputs compressed assets
4. Set Cache-Control headers:
- Immutable assets (hashed filenames): 1 year
- HTML pages: no-cache (for SSR)
- API responses: no-store or short cache
5. Implement resource hints:
- Preconnect to API domain, Stripe, Clerk
- Prefetch critical routes
6. Add tests verifying asset optimization
tests:
- Unit: Test asset hashing and cache headers
- Integration: Test CDN cache hit rates
- Performance: Lighthouse performance audit >90
acceptance_criteria:
- Static assets served from CDN with <50ms TTFB
- Brotli compression active on all text assets
- Cache-Control headers correct per asset type
- Image optimization reducing total page weight by >30%
- Lighthouse Performance score ≥ 90
- Preconnect hints present on critical pages
validation:
- `curl -I https://cdn.example.com/assets/main.js` → Cache-Control: public, max-age=31536000, immutable
- Lighthouse CI run shows Performance ≥ 90
- PageSpeed Insights shows <2s LCP on mobile
notes:
- SolidStart with Nitro should handle asset hashing automatically
- Vercel deployment may include CDN automatically
- Consider using @solidjs/start image optimization if available

View File

@@ -0,0 +1,62 @@
# 06. Database Connection Pooling & Query Optimization
meta:
id: web-production-06
feature: web-production
priority: P1
depends_on: []
tags: [performance, database, production]
objective:
- Optimize database connections and queries for production load
deliverables:
- Connection pooling configuration
- Query performance audit
- Index optimization
- Slow query logging
steps:
1. Configure connection pooling:
- If using PostgreSQL: configure PgBouncer or use @libsql/client pooling
- Set max connections based on server instances (e.g., 20 per instance)
- Add connection timeout and idle timeout settings
2. Audit all Drizzle queries for performance:
- Check web/src/server/db/schema/*.ts for missing indexes
- Review web/src/server/api/routers/*.ts for N+1 queries
- Add pagination to all list endpoints (default 50, max 100)
3. Add database indexes:
- createdAt indexes for time-range queries (alerts, exposures)
- Composite indexes for common filter combinations
- userId indexes on all user-scoped tables
4. Implement query result caching:
- Cache user profile lookups (5 min TTL)
- Cache subscription status (1 min TTL)
- Cache dashboard summary (30 sec TTL)
5. Add slow query logging:
- Log queries taking >500ms
- Alert on >1s queries
6. Set up database performance monitoring
tests:
- Unit: Test query execution plans for major endpoints
- Load: Run 1000 concurrent dashboard loads, verify <200ms p95
- Integration: Test pagination boundaries
acceptance_criteria:
- Database connection pool configured with max 20 connections
- No N+1 queries in any API endpoint
- All list endpoints paginated with cursor or offset
- Slow query logging active
- Dashboard load query <100ms p95
- Alert endpoint query <50ms p95
validation:
- EXPLAIN ANALYZE on major queries shows index usage
- Load test with k6: 1000 concurrent users, p95 < 200ms
- Database CPU <50% under normal load
notes:
- Current schema has some indexes but may need more for production scale
- Drizzle ORM doesn't automatically handle connection pooling — configure at driver level
- Consider read replicas if dashboard load is heavy

View File

@@ -0,0 +1,61 @@
# 07. Caching Strategy (Redis + HTTP Cache)
meta:
id: web-production-07
feature: web-production
priority: P2
depends_on: []
tags: [performance, caching, production]
objective:
- Implement multi-layer caching to reduce database load and improve response times
deliverables:
- Redis caching layer for API responses
- HTTP cache headers for client-side caching
- Cache invalidation strategy
- Stale-while-revalidate pattern
steps:
1. Implement Redis caching for API responses:
- Create web/src/server/lib/cache.ts with Redis-backed cache
- Cache user profile: key `user:{id}`, TTL 5 minutes
- Cache subscription: key `sub:{userId}`, TTL 1 minute
- Cache dashboard summary: key `dash:{userId}`, TTL 30 seconds
- Cache blog posts: key `blog:{slug}`, TTL 1 hour
2. Add cache decorators/procedures:
- Create cachedProcedure wrapper for tRPC
- Support cache tags for invalidation
3. Implement HTTP caching headers:
- Static assets: Cache-Control: public, max-age=31536000, immutable
- API responses: Cache-Control: private, max-age=30
- HTML pages: Cache-Control: no-cache (SSR)
4. Add cache invalidation:
- Invalidate user cache on profile update
- Invalidate subscription cache on billing event
- Invalidate blog cache on publish/edit
5. Implement stale-while-revalidate for dashboard data
6. Add cache hit/miss metrics
tests:
- Unit: Test cache set/get/delete operations
- Integration: Test cache invalidation on mutations
- Performance: Compare cached vs uncached response times
acceptance_criteria:
- Redis cache layer active on all read-heavy endpoints
- Cache hit rate >80% for user profile and subscription endpoints
- Cache invalidation working on all mutations
- HTTP cache headers correct per endpoint type
- Stale-while-revalidate pattern on dashboard widgets
- Cache metrics visible in monitoring dashboard
validation:
- Load test: cached endpoint p95 < 20ms
- Verify Redis keys created for cached data
- Update profile → cache invalidated, next request hits DB
notes:
- Redis already used for BullMQ jobs — share connection or use separate DB index
- Be careful caching authenticated data — always include userId in key
- Consider using Vercel KV or Upstash Redis for serverless

View File

@@ -0,0 +1,67 @@
# 08. Graceful Shutdown & Health Check Endpoints
meta:
id: web-production-08
feature: web-production
priority: P1
depends_on: []
tags: [reliability, infrastructure, production]
objective:
- Implement health checks and graceful shutdown to ensure zero-downtime deployments and reliable operations
deliverables:
- Health check endpoint (/health)
- Readiness probe endpoint (/ready)
- Graceful shutdown handler
- Dependency health checks (DB, Redis, Stripe)
steps:
1. Create health check endpoints:
- GET /health → basic liveness (HTTP 200 if process running)
- GET /ready → readiness check (DB, Redis, Stripe connectivity)
- GET /health/deep → comprehensive check with dependency status
2. Implement dependency health checks:
- Database: simple SELECT 1 query
- Redis: PING command
- Stripe: retrieve account info (cached)
- WebSocket server: connection count
3. Add graceful shutdown:
- Handle SIGTERM/SIGINT signals
- Stop accepting new connections
- Wait for active requests to complete (30s timeout)
- Close database connections
- Close Redis connections
- Exit process cleanly
4. Add startup probe:
- Delay readiness until all services initialized
- Retry logic for DB connection on startup
5. Add metrics endpoint (/metrics) for Prometheus:
- Request count and duration
- Error rates
- Active connections
- Dependency health status
tests:
- Unit: Test health check responses
- Integration: Test graceful shutdown with active requests
- Load: Verify zero failed requests during rolling restart
acceptance_criteria:
- /health returns 200 within 100ms
- /ready returns 200 only when all dependencies healthy
- /ready returns 503 with detailed error when dependency down
- Graceful shutdown completes within 30 seconds
- Zero failed requests during rolling deployment
- Prometheus metrics endpoint available
validation:
- `curl /health` → {"status":"ok"}
- `curl /ready` → {"status":"ok","dependencies":{"db":"ok","redis":"ok","stripe":"ok"}}
- Stop container with active requests → all complete before exit
- Block DB port → /ready returns 503
notes:
- Nitro/SolidStart may need custom server plugin for signal handling
- Use node-graceful-shutdown or similar library
- Kubernetes/Docker health checks rely on these endpoints

View File

@@ -0,0 +1,66 @@
# 09. Structured Logging & Log Aggregation
meta:
id: web-production-09
feature: web-production
priority: P2
depends_on: []
tags: [observability, logging, production]
objective:
- Replace ad-hoc logging with structured, aggregated logging for production debugging and auditing
deliverables:
- Structured logging library integration (Pino or Winston)
- Log aggregation pipeline (Datadog, Logtail, or CloudWatch)
- Request ID propagation across all logs
- Log rotation and retention policy
steps:
1. Add structured logging library:
- Install pino or winston in web/package.json
- Create web/src/server/lib/logger.ts with configured logger
- Replace all console.log/console.error with logger
2. Implement request context logging:
- Generate request ID for each incoming request
- Attach user ID, session ID to log context
- Propagate request ID through tRPC context
3. Configure log levels:
- ERROR: unhandled exceptions, auth failures, DB errors
- WARN: rate limit hits, slow queries, deprecated API usage
- INFO: requests, logins, signups, billing events
- DEBUG: query details, cache hits/misses (dev only)
4. Set up log aggregation:
- Configure log shipping to aggregation service
- Set up log parsing and indexing
- Create saved searches for common issues
5. Implement log rotation:
- 100MB max per file
- 7 days retention for production
- 30 days retention for audit logs
6. Add sensitive data redaction:
- Mask credit card numbers, SSNs, passwords in logs
- Redact JWT tokens (show only first 10 chars)
tests:
- Unit: Test logger outputs valid JSON
- Integration: Test request ID propagation
- Security: Verify no sensitive data in logs
acceptance_criteria:
- All logs output as structured JSON
- Request ID present on every log line for a given request
- Log aggregation service receiving logs in real-time
- Sensitive data redacted from all log output
- Log rotation preventing disk fill
- Searchable logs by user ID, request ID, endpoint
validation:
- Trigger error → log appears in aggregation with stack trace, request ID, user ID
- Search logs by request ID → all related logs returned
- Check log files → no credit card numbers, passwords, full JWTs
notes:
- Pino is fastest and recommended for Node.js
- Use pino-pretty for local development, JSON for production
- Consider OpenTelemetry for unified tracing + logging

View File

@@ -0,0 +1,69 @@
# 10. Error Tracking & Alerting (Sentry Integration)
meta:
id: web-production-10
feature: web-production
priority: P1
depends_on: []
tags: [observability, error-tracking, production]
objective:
- Implement comprehensive error tracking with Sentry to catch and alert on production errors in real-time
deliverables:
- Sentry integration for backend and frontend
- Error alerting rules
- Source maps upload for production builds
- Breadcrumbs for error context
steps:
1. Add Sentry SDK:
- Install @sentry/node for backend
- Install @sentry/solid or @sentry/browser for frontend
- Configure DSN from environment variable
2. Initialize Sentry in backend:
- Add to web/src/entry-server.tsx or Nitro plugin
- Capture unhandled exceptions
- Capture unhandled promise rejections
- Attach user context (ID, email) when available
3. Initialize Sentry in frontend:
- Add to web/src/entry-client.tsx
- Capture JavaScript errors
- Capture SolidJS component errors via ErrorBoundary
- Attach release version and environment
4. Configure error alerting:
- Slack/Discord/PagerDuty integration for P1 errors
- Email alerts for new error types
- Digest emails for recurring errors
- Alert thresholds: >10 errors/minute or >1 unhandled exception
5. Upload source maps:
- Configure Vite plugin for source map generation
- Upload maps to Sentry during build
- Verify error stack traces show original source
6. Add breadcrumbs:
- Log navigation changes
- Log API calls with response status
- Log user actions (clicks, form submissions)
tests:
- Unit: Test Sentry capture in error scenarios
- Integration: Trigger error, verify appears in Sentry
- Alert: Verify alert fires within 1 minute of error
acceptance_criteria:
- 100% of unhandled exceptions captured in Sentry
- All errors include user context, request URL, and environment
- Source maps working → stack traces show original TypeScript
- Alert fired within 60 seconds of first occurrence
- No duplicate alerts for same error (grouping working)
- Error rate dashboard showing trends over time
validation:
- Deploy with intentional bug → error appears in Sentry within 30s
- Check alert channel → notification received
- View error detail → correct file, line number, user context
notes:
- Sentry free tier: 5k errors/month — may need paid plan for scale
- Use Sentry releases to track which deploy introduced errors
- Consider integrating with GitHub for suspect commits

View File

@@ -0,0 +1,70 @@
# 11. Application Metrics & Dashboards
meta:
id: web-production-11
feature: web-production
priority: P2
depends_on: []
tags: [observability, metrics, production]
objective:
- Collect and visualize application metrics for performance monitoring and capacity planning
deliverables:
- Prometheus metrics endpoint
- Custom business metrics
- Grafana or Datadog dashboards
- Alerting on metric thresholds
steps:
1. Add metrics collection:
- Install prom-client for Node.js metrics
- Create web/src/server/lib/metrics.ts
- Expose /metrics endpoint for Prometheus scraping
2. Collect standard metrics:
- HTTP request duration (histogram)
- HTTP request count (counter, by status code, endpoint)
- Active connections (gauge)
- Memory usage (gauge)
- Event loop lag (gauge)
3. Collect business metrics:
- Signup rate (counter)
- Login success/failure rate (counter)
- Subscription conversions (counter)
- DarkWatch scan completions (counter)
- Alert generation rate (counter)
- Average threat score (gauge)
4. Set up dashboards:
- Grafana dashboard or Datadog dashboard
- Request latency percentiles (p50, p95, p99)
- Error rate over time
- Business funnel (landing → signup → subscribe)
- Infrastructure health (CPU, memory, DB connections)
5. Configure alerts:
- p99 latency > 500ms for 5 minutes
- Error rate > 1% for 2 minutes
- Memory usage > 80% for 10 minutes
- DB connection pool > 90% for 5 minutes
tests:
- Unit: Test metrics increment correctly
- Integration: Verify /metrics endpoint returns valid Prometheus format
- Dashboard: Confirm all panels show data
acceptance_criteria:
- /metrics endpoint serving valid Prometheus exposition format
- Request duration histogram with 0.1, 0.5, 1, 2, 5 second buckets
- Business metrics visible in dashboard
- Alert fires when p99 latency exceeds 500ms
- Dashboard refreshes every 10 seconds with live data
- Metrics retention for 30 days
validation:
- `curl /metrics` → valid Prometheus output
- Grafana dashboard shows request latency graph
- Trigger slow endpoint → alert fires within 5 minutes
notes:
- Prometheus + Grafana is open source and cost-effective
- Datadog is easier but more expensive
- Consider using Vercel Analytics if deployed on Vercel

View File

@@ -0,0 +1,69 @@
# 12. Uptime & Performance Monitoring
meta:
id: web-production-12
feature: web-production
priority: P2
depends_on: []
tags: [observability, uptime, production]
objective:
- Monitor application uptime and performance from external vantage points to ensure reliability
deliverables:
- External uptime monitoring (Pingdom, UptimeRobot, or Datadog Synthetics)
- Synthetic monitoring for critical user journeys
- Performance budget enforcement
- Status page for incident communication
steps:
1. Set up uptime monitoring:
- Configure checks for homepage, API health, dashboard
- Check from multiple regions (US East, US West, EU)
- 1-minute interval checks
- Alert on 2 consecutive failures
2. Implement synthetic monitoring:
- Signup flow: homepage → signup → verify email
- Login flow: login → dashboard → view alerts
- Billing flow: dashboard → pricing → checkout (test mode)
- DarkWatch flow: dashboard → darkwatch → add watchlist item
3. Set performance budgets:
- LCP (Largest Contentful Paint) < 2.5s mobile, < 1.5s desktop
- FID (First Input Delay) < 100ms
- CLS (Cumulative Layout Shift) < 0.1
- TTFB (Time to First Byte) < 200ms
- API response p95 < 200ms
4. Configure alerting:
- Downtime alert via Slack/SMS
- Performance degradation alert (LCP > 3s)
- SSL certificate expiry alert (30 days before)
- Domain expiry alert (30 days before)
5. Set up status page:
- Use statuspage.io or instatus.com
- Auto-update from monitoring checks
- Subscribe users for incident notifications
- Post incident updates and post-mortems
tests:
- Integration: Verify monitoring catches simulated outage
- Performance: Confirm synthetic tests complete successfully
- Alert: Test alert channels with deliberate failure
acceptance_criteria:
- Uptime monitoring checking every 60 seconds from 3+ regions
- 99.9% uptime SLA measured over 30 days
- Synthetic tests covering signup, login, and core flows
- Performance budget alerts for LCP > 2.5s
- Status page accessible and auto-updating
- SSL certificate expiry alert 30 days in advance
validation:
- Simulate outage → alert received within 2 minutes
- Check status page → shows incident with timeline
- Run synthetic test → completes in <30 seconds
- Lighthouse CI shows all metrics within budget
notes:
- UptimeRobot free tier: 50 monitors, 5-minute intervals
- Pingdom more reliable but paid
- Consider using Checkly for synthetic monitoring with JS

View File

@@ -0,0 +1,72 @@
# 13. GitHub Actions CI Pipeline
meta:
id: web-production-13
feature: web-production
priority: P1
depends_on: [web-production-17, web-production-18, web-production-19, web-production-20]
tags: [cicd, automation, production]
objective:
- Build a comprehensive CI pipeline that runs tests, linting, type checking, and security scans on every pull request
deliverables:
- GitHub Actions workflow files
- PR checks for web and browser-ext
- Test reporting and coverage
- Dependency vulnerability scanning
steps:
1. Create .github/workflows/ci.yml:
- Trigger on pull_request and push to main
- Set up Node.js 22 with pnpm
- Install dependencies with frozen lockfile
2. Add job: lint-and-typecheck:
- Run `pnpm lint` (tsc --noEmit)
- Run `pnpm lint:ext`
- Fail on any TypeScript errors
3. Add job: test:
- Run `pnpm test` (vitest for web)
- Run `pnpm test:ext` (vitest for browser-ext)
- Generate coverage reports with @vitest/coverage-v8
- Upload coverage to Codecov or similar
4. Add job: build:
- Run `pnpm build` for web
- Run `pnpm build:ext` for browser-ext
- Verify build artifacts exist
5. Add job: security-scan:
- Run `pnpm audit` with --audit-level=high
- Run `npm audit fix` suggestions as PR comment
- Add OWASP dependency check
6. Add job: docker-build:
- Build scheduler Dockerfile
- Verify Docker image builds successfully
7. Configure branch protection:
- Require all checks to pass before merge
- Require 1 reviewer approval
- Require up-to-date branch before merge
tests:
- Integration: Create test PR, verify all checks run
- Security: Introduce vulnerable dependency, verify scan catches it
- Build: Verify build artifacts are created
acceptance_criteria:
- All PRs trigger CI pipeline automatically
- Lint, typecheck, test, build, and security jobs run in parallel
- Tests failing blocks PR merge
- Coverage report uploaded for every PR
- Security vulnerabilities (high+) block PR merge
- Docker build verified on every PR
- Pipeline completes in <10 minutes
validation:
- Open test PR → all checks green
- Introduce TypeScript error → lint job fails
- Add vulnerable package → security scan fails
- Check Codecov → coverage diff visible in PR
notes:
- Use pnpm/action-setup for proper pnpm installation
- Cache node_modules between runs for speed
- Consider using GitHub Actions matrix for multiple Node versions

View File

@@ -0,0 +1,75 @@
# 14. Automated Deployment Pipeline
meta:
id: web-production-14
feature: web-production
priority: P1
depends_on: [web-production-13, web-production-15, web-production-16]
tags: [cicd, deployment, production]
objective:
- Build automated deployment pipelines for staging and production environments with rollback capability
deliverables:
- Staging deployment on merge to main
- Production deployment with manual approval
- Database migration automation
- Rollback strategy
steps:
1. Create .github/workflows/deploy-staging.yml:
- Trigger on push to main
- Build web application
- Run database migrations (drizzle-kit push)
- Deploy to staging environment (Vercel, Railway, or VPS)
- Run smoke tests against staging
2. Create .github/workflows/deploy-production.yml:
- Trigger on release published or manual dispatch
- Require manual approval from 1 team member
- Build and tag Docker image
- Run database migrations in dry-run first
- Deploy to production with blue-green or rolling strategy
- Run post-deploy smoke tests
3. Implement database migration safety:
- Migrations run before app deployment
- Backward-compatible migrations only (add columns, don't drop)
- Migration rollback script for each migration
- Database backup before production migration
4. Add deployment notifications:
- Slack notification on deploy start, success, failure
- Include commit SHA, author, and changelog
5. Implement rollback:
- One-click rollback to previous release
- Database migration rollback (if safe)
- CDN cache purge on rollback
6. Add smoke tests:
- Test homepage loads
- Test login API responds
- Test health endpoint
- Test critical user journey with Playwright
tests:
- Integration: Deploy to staging, verify app functional
- Rollback: Trigger rollback, verify previous version restored
- Migration: Test migration failure doesn't break deployment
acceptance_criteria:
- Every merge to main auto-deploys to staging
- Production deploy requires manual approval
- Database migrations run automatically before app start
- Rollback completes in <5 minutes
- Smoke tests pass before marking deploy successful
- Deployment notifications sent to Slack
- Zero-downtime deployment for web app
validation:
- Merge PR → staging deploys automatically within 5 minutes
- Trigger production deploy → approval gate shown
- Approve → production deploys, smoke tests pass
- Introduce bug → rollback to previous version in <5 minutes
notes:
- Vercel offers automatic preview deployments per PR
- For VPS deployment, use Docker Compose with rolling restart
- Consider using GitHub Environments for approval gates
- Database migrations should be additive-only in production

View File

@@ -0,0 +1,75 @@
# 15. Docker & Infrastructure Optimization
meta:
id: web-production-15
feature: web-production
priority: P2
depends_on: []
tags: [infrastructure, docker, production]
objective:
- Optimize Docker images and infrastructure for production deployment with security and efficiency
deliverables:
- Multi-stage optimized Dockerfile for web app
- Docker Compose for local production simulation
- Infrastructure as Code (Terraform or Pulumi)
- Security scanning for Docker images
steps:
1. Create optimized Dockerfile for web app:
- Multi-stage build (deps → build → runtime)
- Use node:22-alpine for minimal image size
- Run as non-root user
- Copy only necessary files to runtime stage
- Health check in Dockerfile
2. Optimize scheduler Dockerfile:
- Reduce image size (currently copies many files)
- Use .dockerignore to exclude unnecessary files
- Pin base image versions
3. Create docker-compose.prod.yml:
- Web app service with replicas
- Redis service with persistence
- PostgreSQL service (or external)
- Nginx reverse proxy with SSL termination
- Watchtower for automatic updates
4. Add security scanning:
- Trivy or Snyk scan in CI pipeline
- Fail build on CRITICAL vulnerabilities
- Weekly automated scan of production images
5. Implement Infrastructure as Code:
- Terraform configuration for AWS/GCP/Vultr
- VPC, subnets, security groups
- ECS/Fargate or Kubernetes deployment
- Load balancer with SSL
- RDS/Cloud SQL for PostgreSQL
- ElastiCache/Memorystore for Redis
6. Add environment-specific configs:
- Production nginx.conf with rate limiting
- SSL certificate management (Let's Encrypt)
- Firewall rules
tests:
- Integration: Build image, verify size <200MB
- Security: Trivy scan shows no CRITICAL vulnerabilities
- Deploy: Terraform apply creates infrastructure
acceptance_criteria:
- Web Docker image <200MB compressed
- Scheduler Docker image <150MB compressed
- No CRITICAL vulnerabilities in image scans
- docker-compose.prod.yml runs full stack locally
- Terraform creates reproducible infrastructure
- Nginx reverse proxy with SSL and rate limiting
- Non-root user running containers
validation:
- `docker images` → web image <200MB
- `trivy image kordant-web` → no CRITICAL
- `docker-compose -f docker-compose.prod.yml up` → full stack running
- `terraform plan` → no unexpected changes
notes:
- Current scheduler/Dockerfile copies many source files — optimize with .dockerignore
- Consider using distroless images for even smaller footprint
- Use AWS Fargate or Google Cloud Run for serverless containers

View File

@@ -0,0 +1,75 @@
# 16. Environment Management & Secrets Rotation
meta:
id: web-production-16
feature: web-production
priority: P1
depends_on: []
tags: [security, infrastructure, production]
objective:
- Implement secure environment variable management and automated secrets rotation
deliverables:
- Environment variable validation on startup
- Secrets manager integration (AWS Secrets Manager, Doppler, or 1Password)
- Automated secrets rotation
- Environment documentation
steps:
1. Create environment validation:
- Create web/src/server/lib/env.ts with Zod/Valibot schema
- Validate all required env vars on server startup
- Fail fast with clear error messages for missing vars
- Type-safe env access throughout codebase
2. Migrate to secrets manager:
- Set up Doppler or AWS Secrets Manager
- Move DATABASE_URL, JWT_SECRET, STRIPE_SECRET_KEY, CLERK_SECRET_KEY to secrets manager
- Remove secrets from .env files in production
- Use short-lived tokens where possible
3. Implement secrets rotation:
- JWT secret: rotate quarterly
- Database credentials: rotate monthly
- Stripe keys: rotate after any suspected leak
- API keys: rotate every 6 months
- Automated rotation scripts
4. Add environment documentation:
- Document all environment variables in docs/ENVIRONMENT.md
- Mark required vs optional
- Include examples and validation rules
- Document secrets rotation schedule
5. Secure local development:
- .env.example with dummy values
- .env.local in .gitignore
- Pre-commit hook to prevent secret commits
- Use 1Password CLI or Doppler CLI for local secrets
6. Audit existing secrets:
- Scan git history for leaked secrets (git-secrets, truffleHog)
- Rotate any potentially leaked secrets
- Enable GitHub secret scanning
tests:
- Unit: Test env validation catches missing vars
- Security: Verify no secrets in codebase with scanner
- Integration: Test secrets manager integration
acceptance_criteria:
- Server fails to start with clear error if required env var missing
- Zero secrets in codebase or git history
- All production secrets stored in secrets manager
- Rotation schedule documented and automated
- Environment documentation complete and accurate
- GitHub secret scanning enabled
- Pre-commit hooks preventing secret commits
validation:
- Remove DATABASE_URL → server exits with clear error
- Run truffleHog → no secrets found in history
- Check secrets manager → all production secrets stored
- Run rotation script → new JWT secret generated, app continues working
notes:
- Doppler is excellent for team secret management
- AWS Secrets Manager integrates well with ECS/Fargate
- Never commit .env files — use .env.example only
- Consider using sealed secrets for Kubernetes

View File

@@ -0,0 +1,73 @@
# 17. End-to-End Testing (Playwright)
meta:
id: web-production-17
feature: web-production
priority: P1
depends_on: []
tags: [testing, e2e, quality]
objective:
- Implement comprehensive end-to-end tests covering critical user journeys using Playwright
deliverables:
- Playwright test suite for critical flows
- Test database seeding and cleanup
- Visual regression testing setup
- CI integration for E2E tests
steps:
1. Install and configure Playwright:
- Install @playwright/test in web/package.json
- Create playwright.config.ts with project settings
- Configure test database (separate from dev)
2. Create test utilities:
- Test user creation helper
- Database reset between tests
- Authentication state management
- API mocking helpers
3. Write critical path tests:
- Landing page → Signup → Onboarding → Dashboard
- Login → Dashboard → DarkWatch → Add watchlist item
- Login → Settings → Update profile
- Login → Billing → View pricing → Checkout (test mode)
- Admin login → Blog → Create post → Publish
- Real-time alerts: WebSocket connection and alert display
4. Add visual regression tests:
- Screenshot comparison for landing page
- Screenshot comparison for dashboard
- Screenshot comparison for mobile responsive layout
5. Configure test data:
- Seed test database with known data
- Use test Stripe keys for billing tests
- Mock external APIs (Twilio, FCM) in tests
6. Add CI integration:
- Run E2E tests on PR (not blocking initially)
- Upload test artifacts (screenshots, videos)
- Parallel test execution across browsers
tests:
- E2E: All critical paths pass in CI
- Visual: Screenshot diffs reviewed and approved
- Cross-browser: Tests pass on Chromium, Firefox, WebKit
acceptance_criteria:
- 10+ E2E tests covering critical user journeys
- Tests run in <5 minutes with parallel execution
- Tests pass on Chromium, Firefox, and WebKit
- Visual regression catching UI changes
- Test artifacts (screenshots, videos) uploaded on failure
- Tests use isolated test database
- Mobile viewport tests included
validation:
- `npx playwright test` → all tests pass
- CI pipeline runs E2E tests on PR
- Change button color → visual regression test fails
- Check test report → screenshots and traces available
notes:
- Playwright is faster and more reliable than Cypress
- Use test database to avoid polluting dev data
- Start with 5 critical paths, expand over time
- Consider using MSW for API mocking in tests

View File

@@ -0,0 +1,78 @@
# 18. Load & Stress Testing
meta:
id: web-production-18
feature: web-production
priority: P2
depends_on: []
tags: [testing, performance, production]
objective:
- Validate application performance under production-like load and identify bottlenecks
deliverables:
- Load test suite with k6 or Artillery
- Performance baseline documentation
- Bottleneck identification report
- Scaling recommendations
steps:
1. Set up load testing tool:
- Install k6 or Artillery
- Create tests/ directory for load tests
- Configure test environment (staging)
2. Write load tests for critical endpoints:
- GET / (landing page)
- POST /api/trpc/user.login
- GET /api/trpc/user.me (authenticated)
- GET /api/trpc/darkwatch.getExposures
- GET /api/trpc/alerts.getAlerts
- WebSocket connection and alert subscription
3. Define load scenarios:
- Baseline: 100 concurrent users, 5 minutes
- Target: 1000 concurrent users, 10 minutes
- Stress: 5000 concurrent users, 5 minutes
- Spike: 0 to 2000 users in 10 seconds
4. Measure and record:
- Response time percentiles (p50, p95, p99)
- Error rate
- Requests per second (throughput)
- CPU and memory usage on server
- Database connection pool utilization
- Redis memory usage
5. Identify bottlenecks:
- Slow queries from database
- Memory leaks
- Connection pool exhaustion
- CPU-bound operations
6. Document scaling recommendations:
- Horizontal scaling (more instances)
- Vertical scaling (bigger instances)
- Caching improvements
- Query optimization
tests:
- Load: Baseline test passes with <200ms p95
- Stress: App remains functional under 5x normal load
- Spike: App recovers within 30 seconds after spike
acceptance_criteria:
- Baseline load (100 concurrent) → p95 < 200ms, 0% errors
- Target load (1000 concurrent) → p95 < 500ms, <1% errors
- Stress load (5000 concurrent) → no crashes, <5% errors
- Spike test → recovery within 30 seconds
- Performance baseline documented with metrics
- Bottleneck report with actionable recommendations
- Scaling plan documented
validation:
- Run k6 against staging → results within acceptable thresholds
- Check server metrics during test → CPU <80%, memory <80%
- Database connections → pool not exhausted
- Review report → identified 3+ bottlenecks with fixes
notes:
- Always test against staging, never production
- Schedule load tests during low-traffic periods
- Use k6 Cloud for distributed load testing if needed
- Consider using Vercel Analytics for real-user monitoring (RUM)

View File

@@ -0,0 +1,78 @@
# 19. Accessibility Audit & WCAG Compliance
meta:
id: web-production-19
feature: web-production
priority: P2
depends_on: []
tags: [testing, accessibility, compliance]
objective:
- Ensure the web application meets WCAG 2.1 AA standards and is usable by people with disabilities
deliverables:
- Automated accessibility testing with axe-core
- Manual keyboard navigation audit
- Screen reader testing
- Accessibility statement page
steps:
1. Set up automated accessibility testing:
- Install @axe-core/react or jest-axe
- Add accessibility tests to component test suite
- Integrate axe-core with Playwright E2E tests
- Fail build on critical accessibility violations
2. Run automated audit:
- Test all pages: landing, auth, dashboard, settings
- Check for: missing alt text, low contrast, missing labels, focus issues
- Generate report with violation severity
3. Manual keyboard navigation audit:
- Navigate entire app using only Tab, Enter, Space, Escape
- Verify focus indicators visible on all interactive elements
- Test skip links and logical tab order
- Verify no keyboard traps
4. Screen reader testing:
- Test with NVDA (Windows) or VoiceOver (macOS)
- Verify all interactive elements have accessible names
- Test live regions for dynamic content (alerts, toasts)
- Verify form error messages announced
5. Fix critical issues:
- Add missing aria-labels and aria-describedby
- Fix color contrast ratios (minimum 4.5:1 for normal text)
- Ensure all images have alt text
- Add proper heading hierarchy (h1 → h2 → h3)
6. Create accessibility statement:
- Page at /accessibility
- Commitment to WCAG 2.1 AA
- Known limitations
- Contact for accessibility feedback
7. Add accessibility CI check:
- Lighthouse accessibility audit >95
- axe-core scan in CI pipeline
tests:
- Automated: axe-core scan passes with 0 violations
- Manual: Keyboard navigation completes all flows
- Screen reader: All critical paths navigable
acceptance_criteria:
- WCAG 2.1 AA compliance on all pages
- Lighthouse accessibility score ≥ 95
- 0 critical or serious axe-core violations
- All interactive elements keyboard accessible
- Focus indicators visible and logical
- All images have descriptive alt text
- Color contrast ratios ≥ 4.5:1 for normal text
- Accessibility statement page live
validation:
- Run axe-core → 0 critical/serious violations
- Lighthouse CI → Accessibility score ≥ 95
- Navigate with keyboard only → complete signup flow
- Screen reader test → all elements announced correctly
notes:
- Current app has some accessibility features (skip link, aria-live) but needs audit
- SolidJS components need proper aria attributes
- Consider using Radix UI primitives for built-in accessibility
- Test with actual assistive technology, not just automated tools

View File

@@ -0,0 +1,71 @@
# 20. Dependency Vulnerability Scanning
meta:
id: web-production-20
feature: web-production
priority: P1
depends_on: []
tags: [security, dependencies, production]
objective:
- Implement continuous dependency vulnerability scanning and automated updates
deliverables:
- npm audit integration in CI
- Snyk or Dependabot monitoring
- Automated security patch PRs
- SBOM (Software Bill of Materials) generation
steps:
1. Set up automated scanning:
- Enable Dependabot alerts in GitHub repository settings
- Configure Dependabot version updates (weekly)
- Add Snyk integration for deeper analysis
- Configure Snyk to fail builds on high+ severity
2. Add CI scanning:
- `pnpm audit --audit-level=high` in GitHub Actions
- `snyk test` in CI pipeline
- Block PR merge on high/critical vulnerabilities
3. Implement automated patching:
- Dependabot auto-PR for patch updates
- Snyk auto-fix PRs for fixable vulnerabilities
- Manual review required for major version updates
4. Generate SBOM:
- Use cyclonedx or spdx-sbom-generator
- Generate on every release
- Store with release artifacts
5. Audit current dependencies:
- Run `pnpm audit` and fix all high/critical issues
- Check for unmaintained packages
- Review direct dependencies for necessity
- Remove unused dependencies
6. Set up alerting:
- Slack notification for new vulnerabilities
- Weekly vulnerability report
- Emergency alert for critical CVEs
tests:
- Security: Introduce vulnerable package → CI blocks merge
- Integration: Verify Dependabot creates PR for outdated package
- Audit: SBOM generated and contains all dependencies
acceptance_criteria:
- Zero high or critical vulnerabilities in dependencies
- Dependabot monitoring all dependencies
- CI fails on high+ severity vulnerabilities
- SBOM generated for every release
- Automated PRs for security patches within 24 hours
- Weekly dependency update report
- All unused dependencies removed
validation:
- `pnpm audit` → 0 high/critical findings
- Check GitHub Security tab → no open alerts
- Merge PR with vulnerable package → CI fails
- Create release → SBOM artifact attached
notes:
- Some vulnerabilities may be in devDependencies — these are lower priority
- Focus on production dependencies first
- Consider using pnpm overrides for emergency patches
- Review major version updates carefully for breaking changes

View File

@@ -0,0 +1,78 @@
# 21. Privacy Policy, TOS & Legal Pages
meta:
id: web-production-21
feature: web-production
priority: P2
depends_on: []
tags: [compliance, legal, production]
objective:
- Create and deploy all required legal pages for production operation
deliverables:
- Privacy Policy page (/privacy)
- Terms of Service page (/terms)
- Cookie Policy page (/cookies)
- Data Processing Agreement (DPA) page
- Legal pages linked in footer
steps:
1. Create Privacy Policy:
- Data collection practices (what, why, how long)
- Third-party services (Stripe, Clerk, Twilio, Firebase)
- User rights (access, rectification, deletion, portability)
- Contact information for privacy inquiries
- Last updated date
2. Create Terms of Service:
- Service description and limitations
- User responsibilities and prohibited conduct
- Subscription terms and billing
- Termination clauses
- Limitation of liability
- Dispute resolution
3. Create Cookie Policy:
- Types of cookies used (essential, analytics, marketing)
- Purpose of each cookie
- How to manage cookies
- Third-party cookies
4. Create Data Processing Agreement:
- Roles and responsibilities
- Data security measures
- Subprocessor list
- Breach notification procedures
5. Add legal pages to app:
- Create routes: /privacy, /terms, /cookies, /dpa
- Add links in Footer component
- Ensure pages are server-rendered for SEO
6. Review with legal counsel:
- Have privacy policy reviewed by attorney
- Ensure compliance with applicable jurisdictions
- Update based on feedback
tests:
- Unit: Test routes render correctly
- Integration: Verify links in footer navigate correctly
- Compliance: Review with legal counsel
acceptance_criteria:
- Privacy Policy live at /privacy
- Terms of Service live at /terms
- Cookie Policy live at /cookies
- DPA live at /dpa
- All pages linked in site footer
- Pages reviewed and approved by legal counsel
- Last updated date within 30 days of launch
- Contact email for privacy inquiries functional
validation:
- Navigate to /privacy → complete policy displayed
- Click footer links → correct pages load
- Legal counsel approval documented
- Email to privacy@kordant.com → received
notes:
- Consider using Termly or iubenda for generated policies
- Ensure policies cover all data processors (Stripe, Clerk, etc.)
- Update policies when adding new third-party services
- Keep records of user consent to terms

View File

@@ -0,0 +1,80 @@
# 22. Cookie Consent & GDPR Compliance
meta:
id: web-production-22
feature: web-production
priority: P2
depends_on: []
tags: [compliance, gdpr, cookies, production]
objective:
- Implement GDPR-compliant cookie consent with granular controls and data processing transparency
deliverables:
- Cookie consent banner component
- Granular cookie preference management
- Consent storage and enforcement
- GDPR compliance verification
steps:
1. Create cookie consent banner:
- Banner appears on first visit
- Accept all, reject non-essential, customize options
- Links to cookie policy
- Dismissible but persistent until choice made
- Mobile-responsive design
2. Implement granular controls:
- Essential cookies (always on): auth, security
- Analytics cookies (opt-in): PostHog, Plausible
- Marketing cookies (opt-in): retargeting, ads
- Preference cookies (opt-in): theme, language
3. Create preference modal:
- Toggle switches for each category
- Description of each cookie type
- Save preferences button
- Re-openable from footer link
4. Implement consent enforcement:
- Store consent in cookie/localStorage
- Block analytics scripts until consent given
- Block marketing scripts until consent given
- Respect "Do Not Track" browser setting
5. Add GDPR-specific features:
- Data processing notice in signup flow
- Right to access data (export tool)
- Right to erasure (delete account)
- Right to portability (data export)
- Data retention periods documented
6. Add consent logging:
- Log consent choices with timestamp
- Store for compliance audit trail
- Allow users to view their consent history
tests:
- Unit: Test consent banner rendering and interaction
- Integration: Test analytics blocked until consent
- Compliance: Verify DNT respected
acceptance_criteria:
- Cookie banner appears on first visit to all users
- Users can accept, reject, or customize cookie preferences
- Analytics scripts load only after opt-in consent
- Marketing scripts load only after opt-in consent
- Essential cookies function without consent
- Consent preferences persist across sessions
- "Do Not Track" browser setting respected
- Consent choice logged with timestamp
- GDPR rights accessible from settings page
- Cookie policy linked from banner and footer
validation:
- Clear cookies → visit site → banner appears
- Click "Reject" → analytics network requests blocked
- Click "Customize" → toggle analytics on → requests allowed
- Enable DNT in browser → banner shows "DNT detected"
- Check localStorage → consent object stored
notes:
- Use CookieConsent by Orestbida or build custom with SolidJS
- Must comply with both GDPR (EU) and CCPA (California)
- Analytics must be completely blocked, not just paused
- Document consent choices for 2 years (regulatory requirement)

View File

@@ -0,0 +1,76 @@
# 23. Data Export & Deletion Tools
meta:
id: web-production-23
feature: web-production
priority: P2
depends_on: []
tags: [compliance, gdpr, privacy, production]
objective:
- Implement user-facing data export and account deletion tools to comply with GDPR and CCPA requirements
deliverables:
- Data export API and UI (/settings/data-export)
- Account deletion API and UI (/settings/delete-account)
- Data retention policy enforcement
- Deletion confirmation and grace period
steps:
1. Create data export functionality:
- API endpoint: POST /api/trpc/user.exportData
- Collect all user data: profile, alerts, exposures, subscriptions, family members
- Format as JSON or machine-readable format
- Include metadata: export date, data categories
- Email download link or provide direct download
- Complete within 30 days (GDPR requirement)
2. Create account deletion:
- UI in settings page with warning and confirmation
- Require password re-entry for confirmation
- API endpoint: POST /api/trpc/user.delete
- Soft delete first (mark deletedAt, anonymize)
- Hard delete after 30-day grace period
- Cancel active subscriptions via Stripe
- Remove from email lists
3. Implement family data handling:
- If family group owner: transfer ownership or delete group
- If family member: remove from group
- Notify family members of account deletion
4. Add data retention policy:
- Define retention periods per data type
- Automated cleanup of deleted accounts after 30 days
- Audit logs retained for 1 year
- Backup deletion after retention period
5. Add admin tools:
- Admin endpoint to fulfill data export requests
- Admin endpoint to process deletion requests
- Audit log of all export/deletion actions
tests:
- Unit: Test export includes all user data
- Integration: Test deletion flow end-to-end
- Compliance: Verify grace period and hard delete
acceptance_criteria:
- Users can export all personal data from settings
- Export includes: profile, alerts, exposures, watchlist, subscriptions, family data
- Export delivered within 30 seconds (async for large data)
- Account deletion requires password confirmation
- Deleted accounts soft-deleted immediately, hard-deleted after 30 days
- Active subscriptions cancelled on deletion
- Family group handled correctly (ownership transfer)
- Deletion audit log maintained
- Data retention policy documented and enforced
validation:
- Export data → JSON file contains all user data
- Delete account → user marked deleted, can login to restore within 30 days
- After 30 days → user data completely removed from DB
- Check Stripe → subscription cancelled
- Check audit log → deletion action recorded
notes:
- Soft delete preserves referential integrity for family groups
- Hard delete must cascade through all related tables
- Consider GDPR Article 17 exceptions (legal obligations)
- Backup restoration may temporarily restore deleted data

View File

@@ -0,0 +1,79 @@
# 24. Security.txt & Responsible Disclosure
meta:
id: web-production-24
feature: web-production
priority: P2
depends_on: []
tags: [security, compliance, production]
objective:
- Implement security.txt and responsible disclosure process for security researchers
deliverables:
- security.txt file at /.well-known/security.txt
- security@kordant.com email address
- Responsible disclosure policy page
- Bug bounty program foundation
steps:
1. Create security.txt:
- Contact: mailto:security@kordant.com
- Expires: date 1 year in future
- Encryption: link to PGP key (optional)
- Acknowledgments: link to hall of fame page
- Policy: link to disclosure policy
- Hiring: link to security jobs (if applicable)
2. Create responsible disclosure policy:
- Page at /security/disclosure
- Scope of testing (what's in scope, what's out)
- Rules of engagement (no DDoS, no data exfiltration)
- Safe harbor promise (won't prosecute good faith research)
- Reporting process and expected response time
- Reward/recognition program details
3. Set up security email:
- Create security@kordant.com alias
- Forward to engineering team
- Set up auto-responder with acknowledgment
- Create internal triage process
4. Create vulnerability response process:
- Internal SLA: acknowledge within 48 hours
- Triage within 72 hours
- Fix critical vulnerabilities within 7 days
- Fix high severity within 30 days
- Public disclosure after fix deployed
5. Add hall of fame page:
- Page at /security/hall-of-fame
- List researchers who reported valid vulnerabilities
- Include date, severity, and researcher name (with permission)
6. Add security page to footer:
- Link to disclosure policy
- Link to security.txt
- Link to hall of fame
tests:
- Integration: Verify security.txt accessible
- Process: Test email auto-responder
- Content: Review policy with security team
acceptance_criteria:
- security.txt accessible at /.well-known/security.txt
- Disclosure policy live at /security/disclosure
- security@kordant.com email active with auto-responder
- Hall of fame page live at /security/hall-of-fame
- Safe harbor promise clearly stated
- Response SLA documented and followed
- Security links in site footer
- PGP key available for encrypted communication (optional)
validation:
- `curl https://kordant.com/.well-known/security.txt` → valid security.txt
- Email security@kordant.com → auto-responder received
- Navigate to /security/disclosure → complete policy visible
- Check footer → security links present
notes:
- security.txt standard defined by RFC 9116
- Safe harbor is critical for encouraging responsible disclosure
- Consider joining HackerOne or Bugcrowd for managed bug bounty
- Document vulnerability severity classification (CVSS)

View File

@@ -0,0 +1,83 @@
# 25. Sitemap, Robots.txt & Open Graph
meta:
id: web-production-25
feature: web-production
priority: P2
depends_on: []
tags: [seo, marketing, production]
objective:
- Implement SEO fundamentals including sitemap, robots.txt, and Open Graph meta tags for all pages
deliverables:
- Dynamic sitemap.xml generation
- robots.txt configuration
- Open Graph meta tags on all pages
- Twitter Card meta tags
- Canonical URLs
steps:
1. Create dynamic sitemap:
- Route: /sitemap.xml
- Include all public pages: /, /about, /features, /pricing, /blog/*
- Include auth pages: /login, /signup
- Exclude admin pages and user-specific pages
- Set priorities and change frequencies
- Auto-update when blog posts published
2. Create robots.txt:
- Allow: all public pages
- Disallow: /(admin)/*, /api/*, /billing/*, /auth/*
- Sitemap reference
- Crawl-delay for respectful crawling
3. Add Open Graph tags to all pages:
- og:title matching page title
- og:description from meta description
- og:image with branded preview image (1200x630)
- og:url with canonical URL
- og:type (website, article for blog)
- og:site_name: Kordant
4. Add Twitter Card tags:
- twitter:card: summary_large_image
- twitter:title, twitter:description, twitter:image
5. Add canonical URLs:
- Prevent duplicate content issues
- Use absolute URLs with https
- Handle query parameters correctly
6. Create branded OG image:
- Design 1200x630px image with Kordant branding
- Include logo, tagline, and shield icon
- Generate dynamically for blog posts (optional)
7. Add structured data:
- Organization schema on homepage
- WebSite schema with SearchAction
- Article schema for blog posts
- SoftwareApplication schema for app
tests:
- Unit: Test sitemap XML generation
- Integration: Verify meta tags on all pages
- SEO: Test with Facebook Sharing Debugger and Twitter Card Validator
acceptance_criteria:
- Sitemap accessible at /sitemap.xml with all public pages
- robots.txt accessible at /robots.txt with correct directives
- Open Graph tags present on all public pages
- Twitter Card tags present on all public pages
- Canonical URL on every page
- Branded OG image displaying correctly in social shares
- Structured data valid per schema.org (test with Google Rich Results)
- Blog posts have Article schema
validation:
- `curl /sitemap.xml` → valid XML with all routes
- `curl /robots.txt` → correct allow/disallow directives
- Facebook Sharing Debugger → OG image and title display correctly
- Google Rich Results Test → structured data valid
- View page source → all meta tags present
notes:
- SolidJS MetaProvider already in use — extend with OG tags
- Use @solidjs/meta for dynamic meta tags per route
- Consider using @vercel/og or similar for dynamic OG images
- Blog sitemap should update automatically on publish

View File

@@ -0,0 +1,83 @@
# 26. Analytics Integration (Plausible/PostHog)
meta:
id: web-production-26
feature: web-production
priority: P2
depends_on: []
tags: [analytics, marketing, production]
objective:
- Implement privacy-respecting analytics to understand user behavior and measure conversion funnels
deliverables:
- Analytics tracking setup
- Custom event tracking for key actions
- Conversion funnel measurement
- Dashboard for key metrics
steps:
1. Set up analytics platform:
- Choose: Plausible (privacy-first, simple) or PostHog (powerful, self-hostable)
- Create account and add tracking script
- Configure domain and goals
2. Add tracking to app:
- Add script to web/src/entry-client.tsx or layout
- Respect cookie consent (load only after opt-in)
- Respect Do Not Track
- Exclude admin traffic
3. Track page views:
- All public pages
- Dashboard pages (anonymized)
- Blog post reads
4. Track custom events:
- signup_started, signup_completed
- login, logout
- subscription_started, subscription_completed
- darkwatch_scan_initiated
- alert_viewed, alert_resolved
- feature_page_viewed (voiceprint, spamshield, etc.)
5. Create conversion funnels:
- Landing → Signup → Onboarding → Dashboard
- Dashboard → Pricing → Checkout → Subscription
- Blog → Signup (content marketing ROI)
6. Set up dashboards:
- Daily/weekly active users
- Signup conversion rate
- Subscription conversion rate
- Feature adoption (DarkWatch, VoicePrint, etc.)
- Churn rate
- Revenue metrics (via Stripe integration)
7. Add A/B testing foundation:
- PostHog feature flags or Split.io
- Test landing page variants
- Test pricing page variants
tests:
- Integration: Verify events fire correctly
- Privacy: Confirm no PII in analytics payload
- Consent: Test analytics blocked until cookie consent
acceptance_criteria:
- Analytics tracking active on all public pages
- Custom events firing for signup, login, subscription, key features
- Conversion funnels visible in dashboard
- No PII (names, emails, IDs) sent to analytics
- Analytics loads only after cookie consent (if required)
- Admin pages excluded from tracking
- Daily active users metric available
- Subscription conversion rate tracked
- A/B testing framework ready for use
validation:
- Visit landing page → pageview event in analytics
- Sign up → signup_completed event with funnel progression
- Check analytics dashboard → conversion rates visible
- Inspect network tab → no email addresses in payload
- Reject cookies → analytics script not loaded
notes:
- Plausible is GDPR-compliant without cookie consent banner
- PostHog offers more features but requires consent in EU
- Consider self-hosting Plausible for complete data control
- Stripe can send revenue data to analytics automatically

View File

@@ -0,0 +1,82 @@
# 27. Structured Data & Rich Snippets
meta:
id: web-production-27
feature: web-production
priority: P2
depends_on: []
tags: [seo, marketing, production]
objective:
- Implement schema.org structured data to enable rich snippets in search results and improve SEO
deliverables:
- JSON-LD structured data on all relevant pages
- Organization schema
- WebSite schema with search
- Article schema for blog posts
- SoftwareApplication schema
- BreadcrumbList schema
steps:
1. Add Organization schema to homepage:
- @type: Organization
- name: Kordant
- url: https://kordant.com
- logo: URL to logo image
- sameAs: social media profiles
- description: AI-powered identity protection
2. Add WebSite schema:
- @type: WebSite
- url: https://kordant.com
- potentialAction: SearchAction with search URL template
3. Add SoftwareApplication schema:
- @type: SoftwareApplication
- name: Kordant
- applicationCategory: SecurityApplication
- operatingSystem: Web, iOS, Android
- offers: Free tier, Plus ($12/mo), Premium ($29/mo)
- aggregateRating (once reviews collected)
- featureList: DarkWatch, VoicePrint, SpamShield, HomeTitle, RemoveBrokers
4. Add Article schema for blog posts:
- @type: Article
- headline, author, datePublished, dateModified
- image, articleBody, keywords
- publisher (Organization reference)
5. Add BreadcrumbList schema:
- Dynamic breadcrumbs based on current route
- Include in all non-home pages
6. Add FAQPage schema (optional):
- For /about or /features pages
- Common questions and answers
7. Validate all structured data:
- Test with Google Rich Results Test
- Test with Schema Markup Validator
- Fix any warnings or errors
tests:
- Unit: Test JSON-LD generation for each schema type
- Integration: Verify schema present in page source
- SEO: Validate with Google's tools
acceptance_criteria:
- Organization schema on homepage
- WebSite schema with SearchAction on homepage
- SoftwareApplication schema with pricing and features
- Article schema on all blog posts
- BreadcrumbList on all non-home pages
- All schemas pass Google Rich Results Test
- No errors or warnings in Schema Markup Validator
- Schemas dynamically generated based on page data
validation:
- View homepage source → Organization and WebSite JSON-LD present
- View blog post source → Article JSON-LD with correct dates
- Google Rich Results Test → all schemas valid
- Search console → rich results reported
notes:
- Use @solidjs/meta or script tags in JSX for JSON-LD
- Keep JSON-LD in <head> for optimal crawler discovery
- Update SoftwareApplication schema when pricing changes
- Consider adding Review schema once user reviews available

View File

@@ -0,0 +1,73 @@
# 28. API Versioning & Deprecation Strategy
meta:
id: web-production-28
feature: web-production
priority: P2
depends_on: []
tags: [api, stability, mobile]
objective:
- Establish API versioning and deprecation strategy to support mobile app updates without breaking existing clients
deliverables:
- API versioning scheme
- Deprecation policy documentation
- Backward compatibility testing
- Mobile client version tracking
steps:
1. Implement API versioning:
- Current: tRPC v10 (consider upgrade to v11)
- Add version header or URL prefix for breaking changes
- Version format: v1, v2, etc.
- Mobile apps send X-API-Version header
2. Create deprecation policy:
- Document in docs/API_VERSIONING.md
- Breaking changes only in major versions
- Support previous version for minimum 6 months
- Announce deprecations 3 months in advance
- Sunset dates for old versions
3. Add version negotiation:
- Backend supports multiple tRPC router versions
- Route to correct router based on version header
- Default to latest for web clients
4. Track client versions:
- Log app version from User-Agent or X-Client-Version
- Dashboard showing active client versions
- Alert when old versions still in use near sunset
5. Add compatibility tests:
- Test all mobile app versions against current API
- Automated compatibility matrix
- Breaking change detection in CI
6. Document API changes:
- Changelog for all API modifications
- Migration guides for major versions
- Breaking vs non-breaking classification
tests:
- Unit: Test version routing
- Integration: Test old client with new API
- Compatibility: Verify mobile app versions work
acceptance_criteria:
- API versioning scheme documented and implemented
- Mobile apps send version header in all requests
- Backend supports at least 2 API versions simultaneously
- Deprecation policy published and followed
- 6-month support window for old versions
- Client version tracking dashboard active
- Compatibility tests passing for all supported versions
- Changelog maintained for all API changes
validation:
- Mobile app sends X-API-Version: 1 → receives v1 responses
- Deploy v2 changes → v1 clients continue working
- Check dashboard → active client versions visible
- Review changelog → all changes documented
notes:
- tRPC v10 to v11 is a breaking change — plan migration carefully
- Mobile apps may take weeks to update — long support windows needed
- Consider using feature flags instead of versioning for minor changes
- Track iOS and Android app versions separately

View File

@@ -0,0 +1,82 @@
# 29. API Documentation (OpenAPI/tRPC Docs)
meta:
id: web-production-29
feature: web-production
priority: P2
depends_on: []
tags: [api, documentation, production]
objective:
- Generate and publish comprehensive API documentation for internal and external developers
deliverables:
- Auto-generated API documentation
- Interactive API explorer
- Authentication documentation
- Error code reference
steps:
1. Set up tRPC documentation generation:
- Use trpc-openapi or @trpc/openapi-v3 to generate OpenAPI spec
- Or use trpc-docs or @trpc/doc-generator
- Export spec as JSON/YAML
2. Create documentation site:
- Use Swagger UI or Scalar for interactive docs
- Host at /api/docs or separate docs subdomain
- Include request/response examples
- Include authentication requirements
3. Document all routers:
- User router: login, signup, profile, family
- Billing router: subscription, checkout, webhooks
- DarkWatch router: watchlist, exposures, scan
- VoicePrint router: enrollments, analysis
- SpamShield router: rules, phone check
- HomeTitle router: properties, monitoring
- RemoveBrokers router: listings, removals
- Alerts router: list, resolve, correlation
- Admin router: user management, blog
4. Add authentication docs:
- Session cookie authentication
- JWT bearer token authentication
- API key authentication (for extensions)
- Clerk webhook handling
5. Add error documentation:
- Standard error codes (400, 401, 403, 404, 429, 500)
- tRPC error codes and meanings
- Rate limit headers explanation
6. Add webhook documentation:
- Stripe webhook events
- Clerk webhook events
- Payload schemas and verification
7. Keep docs in sync:
- Auto-generate on build
- CI check for doc changes
- Version docs with API versions
tests:
- Unit: Test OpenAPI spec generation
- Integration: Verify docs site loads and examples work
- Review: Team review for accuracy
acceptance_criteria:
- API docs accessible at /api/docs
- All tRPC routers documented with input/output schemas
- Interactive explorer allowing test requests
- Authentication methods documented with examples
- All error codes explained with examples
- Webhook payloads documented with verification steps
- Docs auto-generated from code (single source of truth)
- Examples use realistic test data
validation:
- Navigate to /api/docs → interactive explorer loads
- Try user.me endpoint → returns example response
- Check auth section → all methods documented
- Review webhook docs → verification steps clear
notes:
- trpc-openapi requires adding meta tags to procedures
- Consider using Scalar (modern alternative to Swagger UI)
- Docs should be public but sensitive endpoints marked as auth-required
- Keep examples updated when schemas change

View File

@@ -0,0 +1,82 @@
# 30. WebSocket Production Hardening
meta:
id: web-production-30
feature: web-production
priority: P1
depends_on: []
tags: [security, websockets, production]
objective:
- Harden WebSocket server for production with authentication, rate limiting, and connection management
deliverables:
- Authenticated WebSocket connections
- Connection rate limiting
- Connection cleanup on logout
- Horizontal scaling support (Redis adapter)
steps:
1. Harden WebSocket authentication:
- Validate JWT token in connection query param
- Reject unauthenticated connections immediately
- Re-authenticate periodically (every 15 minutes)
- Close connection on token expiry
2. Implement connection rate limiting:
- Max 1 WebSocket connection per user
- Max 5 reconnection attempts per minute
- IP-based connection limits (100 per IP)
3. Add connection management:
- Track active connections per user
- Close duplicate connections
- Heartbeat with timeout (current implementation good)
- Graceful close on server shutdown
4. Implement horizontal scaling:
- Use Redis adapter for ws (socket.io-redis or @socket.io/redis-adapter)
- Or use Redis pub/sub for broadcast across instances
- Ensure alerts reach all connected clients regardless of instance
5. Add message validation:
- Validate all incoming message schemas
- Reject malformed messages
- Limit message size (max 10KB)
- Sanitize message content
6. Add monitoring:
- Track active connection count
- Track messages per second
- Track connection duration
- Alert on connection spikes (possible DDoS)
7. Secure WebSocket server:
- Run on separate port or path
- TLS encryption (wss://)
- No mixed content (ws on https page)
tests:
- Unit: Test authentication rejection
- Integration: Test duplicate connection handling
- Load: Test 1000 concurrent WebSocket connections
- Security: Test unauthenticated connection rejection
acceptance_criteria:
- All WebSocket connections authenticated with valid JWT
- Unauthenticated connections rejected immediately
- Max 1 connection per user (duplicates closed)
- Heartbeat/ping-pong working with 30s interval
- Redis adapter active for multi-instance deployment
- Message size limited to 10KB
- TLS encryption (wss://) in production
- Connection metrics visible in monitoring
- Graceful shutdown closes all connections cleanly
validation:
- Connect without token → connection rejected
- Connect with valid token → connection accepted
- Open second connection → first connection closed
- Send 20KB message → connection closed with error
- Scale to 2 server instances → alerts broadcast to all clients
- Check metrics → active connections, message rate visible
notes:
- Current WebSocket in web/src/lib/websocket.ts and web/src/server/websocket.ts
- ws library supports Redis adapter for scaling
- Consider using Socket.io for more robust connection management
- WebSocket auth via query params is common but consider cookie-based for security

View File

@@ -0,0 +1,77 @@
# 31. Backup Strategy & Point-in-Time Recovery
meta:
id: web-production-31
feature: web-production
priority: P1
depends_on: []
tags: [database, reliability, production]
objective:
- Implement automated database backups with point-in-time recovery capability
deliverables:
- Automated daily backups
- Point-in-time recovery setup
- Backup testing and verification
- Retention policy
steps:
1. Set up automated backups:
- If PostgreSQL: configure pg_dump cron job or managed backups (RDS, Cloud SQL)
- If SQLite/Turso: configure Turso database branching/backups
- Daily full backups at off-peak hours (3 AM UTC)
- Hourly incremental backups (WAL archiving for Postgres)
2. Configure backup storage:
- Store in separate region/cloud provider (S3, GCS, R2)
- Encrypt backups at rest
- Versioning enabled (protect against deletion)
3. Implement point-in-time recovery:
- WAL archiving for PostgreSQL
- Transaction log backups every 15 minutes
- Test recovery to specific timestamp
4. Add backup monitoring:
- Alert on backup failure
- Track backup size and duration
- Verify backup integrity (checksum)
5. Test restore procedures:
- Monthly restore test to staging environment
- Document step-by-step restore process
- Measure RTO (Recovery Time Objective) and RPO (Recovery Point Objective)
- Target: RTO < 1 hour, RPO < 15 minutes
6. Document retention:
- Daily backups: 7 days
- Weekly backups: 4 weeks
- Monthly backups: 12 months
- Annual backups: 7 years (compliance)
7. Add Redis backup:
- RDB snapshots every 6 hours
- AOF persistence for point-in-time
- Backup to S3/GCS
tests:
- Integration: Test backup creation
- Recovery: Test restore to staging
- Monitoring: Verify backup alerts
acceptance_criteria:
- Daily automated backups running successfully
- Backups stored in separate region with encryption
- Point-in-time recovery tested and working
- Backup failures trigger alerts within 5 minutes
- Monthly restore test completed and documented
- RTO < 1 hour, RPO < 15 minutes
- Retention policy enforced automatically
- Redis backups included in strategy
validation:
- Check backup storage → daily backups present
- Trigger restore test → staging database restored successfully
- Simulate backup failure → alert received
- Check retention → old backups purged per policy
notes:
- Turso offers automatic backups for SQLite — verify configuration
- RDS automated backups are easiest for PostgreSQL
- Test restores are critical — untested backups are useless
- Document restore process for on-call engineers

View File

@@ -0,0 +1,79 @@
# 32. Migration Safety & Rollback Procedures
meta:
id: web-production-32
feature: web-production
priority: P1
depends_on: []
tags: [database, reliability, production]
objective:
- Ensure database migrations are safe, reversible, and won't cause downtime or data loss in production
deliverables:
- Migration safety guidelines
- Backward-compatible migration policy
- Rollback scripts for each migration
- Migration testing in staging
steps:
1. Create migration safety guidelines:
- Document in docs/MIGRATIONS.md
- Additive changes only in production (add columns, create tables)
- No destructive changes during deployment (no DROP COLUMN)
- Two-phase migrations for destructive changes:
- Phase 1: Add new column/table, deploy code to use it
- Phase 2: Remove old column/table after code stable
2. Audit existing migrations:
- Review all drizzle migrations in web/src/server/db/
- Check for any destructive operations
- Add rollback scripts where missing
3. Implement migration testing:
- Run migrations against staging database copy
- Verify app works after migration
- Test rollback script
- Measure migration duration (must be <30 seconds)
4. Add migration safety checks:
- CI check: verify no destructive migrations in PR
- Pre-deploy: dry-run migration in production
- Post-deploy: verify migration applied successfully
5. Document rollback procedures:
- Step-by-step rollback for each migration
- Database backup before migration
- Code rollback procedure
- Data recovery steps if needed
6. Add migration monitoring:
- Log migration start, duration, success/failure
- Alert on migration failure
- Track migration duration trends
7. Set up migration automation:
- GitHub Action to run migrations on staging deploy
- Manual approval for production migrations
- Automated rollback on migration failure
tests:
- Unit: Test migration scripts in isolation
- Integration: Test migration on staging database
- Rollback: Test rollback procedure
acceptance_criteria:
- All production migrations are additive-only
- Two-phase migration process documented for destructive changes
- Rollback script exists for every migration
- Migrations tested on staging before production
- Migration duration <30 seconds
- Automated CI check preventing destructive migrations
- Backup taken before every production migration
- Migration failure triggers automatic alert and rollback
validation:
- Review migration history → no destructive changes in production
- Test rollback → database restored to previous state
- Run destructive migration in PR → CI blocks merge
- Check migration logs → all migrations completed successfully
notes:
- Drizzle migrations are generally safe but review generated SQL
- Use drizzle-kit generate with --custom for complex migrations
- Consider using gh-ost or pt-online-schema-change for large tables
- Always have a database backup before running production migrations

View File

@@ -0,0 +1,93 @@
# Web Production Readiness
Objective: Harden, optimize, and operationalize the SolidStart web application for production deployment with enterprise-grade security, performance, monitoring, and compliance.
Status legend: [ ] todo, [~] in-progress, [x] done
## Tasks
### Security & Hardening
- [ ] 01 — Security Headers & CORS Configuration → `01-security-headers-cors.md`
- [ ] 02 — Rate Limiting & DDoS Protection → `02-rate-limiting-ddos.md`
- [ ] 03 — Input Validation & XSS Prevention Audit → `03-input-validation-xss.md`
- [ ] 04 — Authentication & Session Security Hardening → `04-auth-session-hardening.md`
### Performance & Reliability
- [ ] 05 — CDN & Asset Optimization → `05-cdn-asset-optimization.md`
- [ ] 06 — Database Connection Pooling & Query Optimization → `06-db-connection-pooling.md`
- [ ] 07 — Caching Strategy (Redis + HTTP Cache) → `07-caching-strategy.md`
- [ ] 08 — Graceful Shutdown & Health Check Endpoints → `08-health-checks-shutdown.md`
### Monitoring & Observability
- [ ] 09 — Structured Logging & Log Aggregation → `09-structured-logging.md`
- [ ] 10 — Error Tracking & Alerting (Sentry Integration) → `10-error-tracking.md`
- [ ] 11 — Application Metrics & Dashboards → `11-metrics-dashboards.md`
- [ ] 12 — Uptime & Performance Monitoring → `12-uptime-monitoring.md`
### CI/CD & DevOps
- [ ] 13 — GitHub Actions CI Pipeline → `13-github-actions-ci.md`
- [ ] 14 — Automated Deployment Pipeline → `14-deployment-pipeline.md`
- [ ] 15 — Docker & Infrastructure Optimization → `15-docker-infra.md`
- [ ] 16 — Environment Management & Secrets Rotation → `16-env-secrets.md`
### Testing & Quality Assurance
- [ ] 17 — End-to-End Testing (Playwright) → `17-e2e-testing.md`
- [ ] 18 — Load & Stress Testing → `18-load-testing.md`
- [ ] 19 — Accessibility Audit & WCAG Compliance → `19-accessibility-audit.md`
- [ ] 20 — Dependency Vulnerability Scanning → `20-dependency-scanning.md`
### Compliance & Legal
- [ ] 21 — Privacy Policy, TOS & Legal Pages → `21-legal-pages.md`
- [ ] 22 — Cookie Consent & GDPR Compliance → `22-cookie-gdpr.md`
- [ ] 23 — Data Export & Deletion Tools → `23-data-export-deletion.md`
- [ ] 24 — Security.txt & Responsible Disclosure → `24-security-txt.md`
### SEO & Marketing
- [ ] 25 — Sitemap, Robots.txt & Open Graph → `25-seo-meta.md`
- [ ] 26 — Analytics Integration (Plausible/PostHog) → `26-analytics.md`
- [ ] 27 — Structured Data & Rich Snippets → `27-structured-data.md`
### API & Backend Stability
- [ ] 28 — API Versioning & Deprecation Strategy → `28-api-versioning.md`
- [ ] 29 — API Documentation (OpenAPI/tRPC Docs) → `29-api-documentation.md`
- [ ] 30 — WebSocket Production Hardening → `30-websocket-production.md`
### Database Production Readiness
- [ ] 31 — Backup Strategy & Point-in-Time Recovery → `31-db-backup.md`
- [ ] 32 — Migration Safety & Rollback Procedures → `32-migration-safety.md`
## Dependencies
- 01, 02, 03, 04 can be done in parallel (security foundation)
- 05, 06, 07, 08 can be done in parallel (performance foundation)
- 09, 10, 11, 12 can be done in parallel (observability)
- 13 depends on 17, 18, 19, 20 (tests must pass before CI)
- 14 depends on 13, 15, 16 (CI + infra + env)
- 21, 22, 23, 24 can be done in parallel (compliance)
- 25, 26, 27 can be done in parallel (SEO)
- 28, 29, 30 can be done in parallel (API stability)
- 31, 32 can be done in parallel (DB ops)
- All groups can proceed independently
## Exit Criteria
- All security headers present and scoring A+ on Security Headers scan
- Rate limiting active on all public endpoints (100 req/min)
- Database queries optimized with connection pooling (PgBouncer or equivalent)
- Redis caching layer active for hot paths
- Health check endpoint responding with 200 and dependency status
- Structured logging shipping to aggregation service
- Error tracking capturing 100% of unhandled exceptions
- CI pipeline running tests, lint, typecheck, and build on every PR
- Automated deployment to staging on merge to main
- E2E tests covering critical user journeys (signup → dashboard → billing)
- Load tests confirming 1000 concurrent users with <200ms p95 latency
- Accessibility audit passing WCAG 2.1 AA
- All production dependencies vulnerability-free
- Legal pages live and linked in footer
- Cookie consent banner functional with granular controls
- GDPR data export and deletion APIs operational
- SEO meta tags, sitemap, and robots.txt serving correctly
- Analytics tracking page views and conversion events
- API documentation publicly accessible and up-to-date
- WebSocket connections stable with reconnection logic tested
- Database backups automated with 7-day retention
- Migration rollback tested and documented

View File

@@ -1,7 +1 @@
export { ColorWaveBackground } from "./ColorWaveBackground";
export { default as HeroSection } from "./HeroSection";
export { default as HowItWorksSection } from "./HowItWorksSection";
export { default as FeaturesGridSection } from "./FeaturesGridSection";
export { default as ForUsersSection } from "./ForUsersSection";
export { default as WhyKordantSection } from "./WhyKordantSection";
export { default as CTABannerSection } from "./CTABannerSection";

View File

@@ -1,14 +1,15 @@
import { createResource } from "solid-js";
import { createResource, createMemo } from "solid-js";
import { api } from "~/lib/api";
const FEATURE_TIERS: Record<string, string> = {
voiceprint: "plus",
hometitle: "plus",
removebrokers: "plus",
darkwatch_realtime: "premium",
voiceprint_batch: "plus",
hometitle_scan: "plus",
removebrokers_unlimited: "premium",
};
const TIER_ORDER = ["free", "basic", "plus", "premium"];
const TIER_ORDER = { free: -1, basic: 0, plus: 1, premium: 2 };
export function useSubscription() {
const [subscription] = createResource(() =>
@@ -16,17 +17,38 @@ export function useSubscription() {
);
const tier = () => subscription()?.tier ?? "free";
const effectiveTier = () => subscription()?.effectiveTier ?? "free";
const isTrialing = () => subscription()?.isTrialing ?? false;
const trials = () => subscription()?.trials ?? [];
const hasFeature = (feature: string) => {
const requiredTier = FEATURE_TIERS[feature];
if (!requiredTier) return true;
return TIER_ORDER.indexOf(tier()) >= TIER_ORDER.indexOf(requiredTier);
const currentLevel = TIER_ORDER[effectiveTier() as keyof typeof TIER_ORDER] ?? TIER_ORDER.free;
const requiredLevel = TIER_ORDER[requiredTier as keyof typeof TIER_ORDER] ?? 0;
if (currentLevel >= requiredLevel) return true;
const now = new Date();
return trials().some(
(t: { feature: string; status: string; expiresAt: string | Date }) =>
t.feature === feature && t.status === "active" && new Date(t.expiresAt) > now,
);
};
const requestFeatureTrial = api.billing.requestFeatureTrial.mutate;
const upgradeFromTrial = api.billing.upgradeFromTrial.mutate;
return {
subscription,
tier,
effectiveTier,
isTrialing,
trials,
isLoading: subscription.loading,
hasFeature,
requestFeatureTrial,
upgradeFromTrial,
};
}

View File

@@ -1,8 +1,8 @@
import { For, Show, onMount } from "solid-js";
import { For, onMount } from "solid-js";
import { Title } from "@solidjs/meta";
import { A } from "@solidjs/router";
import { cn } from "~/lib/utils";
import { Button, Badge, Card } from "~/components/ui";
import { Button, Card } from "~/components/ui";
import { Typewriter } from "~/components/ui/Typewriter";
import { ColorWaveBackground } from "~/components/landing/ColorWaveBackground";
import PageContainer from "~/components/layout/PageContainer";

View File

@@ -87,7 +87,7 @@ const faqs: FAQ[] = [
},
{
q: "What happens after my free trial?",
a: "Your trial includes full access to your selected plan for 14 days. You can cancel anytime before the trial ends with no charge.",
a: "Your trial includes Basic features for 14 days. Upgrade anytime during your trial to unlock Plus or Premium features immediately. If you don't upgrade, your account will remain active with Basic features.",
},
{
q: "Can I remove my data from brokers?",
@@ -220,10 +220,10 @@ export default function PricingPage() {
Protection That Fits{" "}
<span class="text-gradient-primary">Your Budget</span>
</h1>
<p class="text-xl text-text-secondary mb-8 max-w-2xl mx-auto">
Start with a 14-day free trial. No credit card required. Cancel
anytime.
</p>
<p class="text-xl text-text-secondary mb-8 max-w-2xl mx-auto">
Start with a 14-day free trial of Basic features. No credit card
required. Upgrade anytime to unlock Plus or Premium.
</p>
<div class="flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm text-text-tertiary">
<span class="flex items-center gap-1.5">
<CheckIcon />

View File

@@ -8,6 +8,8 @@ import {
CancelSubscriptionSchema,
ReactivateSubscriptionSchema,
ListInvoicesSchema,
RequestFeatureTrialSchema,
UpgradeFromTrialSchema,
} from "../schemas/billing";
import {
getOrCreateCustomer,
@@ -16,18 +18,86 @@ import {
cancelSubscription,
reactivateSubscription,
listInvoices,
mapStripeProductToTier,
} from "~/server/services/billing.service";
import { db } from "~/server/db";
import { subscriptions } from "~/server/db/schema/subscription";
import { stripe } from "~/server/stripe";
import {
getEffectiveTier,
getActiveTrials,
createFeatureTrial,
} from "~/server/lib/tier";
export const billingRouter = createTRPCRouter({
getSubscription: protectedProcedure.query(async ({ ctx }) => {
const sub = await db.query.subscriptions.findFirst({
where: eq(subscriptions.userId, ctx.user.id),
});
return sub ?? null;
if (!sub) return null;
const trials = await getActiveTrials(ctx.user.id);
return {
...sub,
effectiveTier: getEffectiveTier(sub.tier as "basic" | "plus" | "premium", sub.status as "active" | "trialing"),
isTrialing: sub.status === "trialing",
trials,
};
}),
requestFeatureTrial: protectedProcedure
.input(wrap(RequestFeatureTrialSchema))
.mutation(async ({ ctx, input }) => {
const sub = await db.query.subscriptions.findFirst({
where: eq(subscriptions.userId, ctx.user.id),
});
if (!sub || sub.status !== "active" || sub.tier !== "basic") {
throw new TRPCError({
code: "FORBIDDEN",
message: "Feature trials are available for active Basic subscribers",
});
}
const trial = await createFeatureTrial(ctx.user.id, input.feature, 7);
return { trial };
}),
upgradeFromTrial: protectedProcedure
.input(wrap(UpgradeFromTrialSchema))
.mutation(async ({ ctx, input }) => {
const sub = await db.query.subscriptions.findFirst({
where: eq(subscriptions.userId, ctx.user.id),
});
if (!sub || sub.status !== "trialing") {
throw new TRPCError({
code: "FORBIDDEN",
message: "No active trial to upgrade from",
});
}
const priceMap: Record<string, string | undefined> = {
basic: process.env.STRIPE_PRICE_BASIC,
plus: process.env.STRIPE_PRICE_PLUS,
premium: process.env.STRIPE_PRICE_PREMIUM,
};
const priceId = priceMap[input.plan];
if (!priceId) {
throw new TRPCError({ code: "BAD_REQUEST", message: "Invalid plan" });
}
// Cancel current trial subscription
await stripe.subscriptions.cancel(sub.stripeId!);
return createCheckoutSession(
ctx.user.id,
ctx.user.email,
priceId,
input.returnUrl,
);
}),
createCheckoutSession: protectedProcedure
.input(wrap(CreateCheckoutSessionSchema))
.mutation(async ({ ctx, input }) => {

View File

@@ -21,3 +21,12 @@ export const ListInvoicesSchema = object({
limit: optional(string(), "10"),
startingAfter: optional(string()),
});
export const RequestFeatureTrialSchema = object({
feature: picklist(["voiceprint", "hometitle", "removebrokers"]),
});
export const UpgradeFromTrialSchema = object({
plan: picklist(["basic", "plus", "premium"]),
returnUrl: string([url()]),
});

View File

@@ -44,3 +44,15 @@ export const subscriptions = sqliteTable("subscriptions", {
stripeIdIdx: index("subscriptions_stripe_id_idx").on(table.stripeId),
tierIdx: index("subscriptions_tier_idx").on(table.tier),
}));
export const featureTrials = sqliteTable("feature_trials", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
feature: text("feature").notNull(),
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
status: text("status").default("active").notNull(),
createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(),
}, (table) => ({
userIdFeatureIdx: index("feature_trials_user_feature_idx").on(table.userId, table.feature),
expiresAtIdx: index("feature_trials_expires_at_idx").on(table.expiresAt),
}));

View File

@@ -1,9 +1,10 @@
import cron from "node-cron";
import { eq, and } from "drizzle-orm";
import { eq, and, inArray } from "drizzle-orm";
import { db } from "~/server/db";
import { subscriptions } from "~/server/db/schema";
import { getQueue } from "./queue";
import type { JobType } from "./queue";
import { getEffectiveTier } from "~/server/lib/tier";
const TIER_SCHEDULES: Record<string, Array<{ type: JobType; cron: string }>> = {
basic: [
@@ -65,10 +66,17 @@ export async function registerSchedules(): Promise<void> {
const activeSubs = await db
.select()
.from(subscriptions)
.where(and(eq(subscriptions.status, "active")));
.where(and(
inArray(subscriptions.status, ["active", "trialing"]),
));
for (const sub of activeSubs) {
const schedules = TIER_SCHEDULES[sub.tier];
// Trial users always get basic-tier schedule
const effectiveTier = getEffectiveTier(
sub.tier as "basic" | "plus" | "premium",
sub.status as "active" | "trialing",
);
const schedules = TIER_SCHEDULES[effectiveTier];
if (!schedules) continue;
for (const schedule of schedules) {

View File

@@ -0,0 +1,89 @@
import { db } from "~/server/db";
import { featureTrials } from "~/server/db/schema/subscription";
import { and, eq, gte } from "drizzle-orm";
export type Tier = "basic" | "plus" | "premium";
export type SubscriptionStatus = "active" | "past_due" | "canceled" | "unpaid" | "trialing";
export const TIER_ORDER: Record<Tier, number> = { basic: 0, plus: 1, premium: 2 };
export const FEATURE_TIERS: Record<string, Tier> = {
voiceprint: "plus",
hometitle: "plus",
removebrokers: "plus",
darkwatch_realtime: "premium",
removebrokers_unlimited: "premium",
};
export interface FeatureTrial {
id: string;
feature: string;
expiresAt: Date;
status: string;
}
export interface SubWithEffectiveTier {
id: string;
userId: string;
tier: Tier;
status: SubscriptionStatus;
effectiveTier: Tier;
isTrialing: boolean;
trials: FeatureTrial[];
}
export function getEffectiveTier(tier: Tier, status: SubscriptionStatus): Tier {
if (status === "trialing") return "basic";
return tier;
}
export function isTrialing(status: SubscriptionStatus): boolean {
return status === "trialing";
}
export function hasFeatureAccess(sub: SubWithEffectiveTier, feature: string): boolean {
const requiredTier = FEATURE_TIERS[feature];
if (!requiredTier) return true;
const subTierLevel = TIER_ORDER[sub.effectiveTier] ?? 0;
const requiredLevel = TIER_ORDER[requiredTier] ?? 0;
if (subTierLevel >= requiredLevel) return true;
const now = new Date();
return sub.trials.some(
(t) => t.feature === feature && t.status === "active" && t.expiresAt > now,
);
}
export async function getActiveTrials(userId: string): Promise<FeatureTrial[]> {
const now = new Date();
return db
.select()
.from(featureTrials)
.where(and(
eq(featureTrials.userId, userId),
gte(featureTrials.expiresAt, now),
eq(featureTrials.status, "active"),
));
}
export async function createFeatureTrial(
userId: string,
feature: string,
days: number = 7,
): Promise<FeatureTrial> {
const expiresAt = new Date(Date.now() + days * 24 * 60 * 60 * 1000);
const [trial] = await db
.insert(featureTrials)
.values({
userId,
feature,
expiresAt,
status: "active",
})
.returning();
return trial;
}

Some files were not shown because too many files have changed in this diff Show More