Commit Graph

323 Commits

Author SHA1 Message Date
null 4e2c3fdf0d fix: rate limiter bump (20/day, 100/week), firestore rules for image messages, storage rules for chat_media, gitignore ClaudeReport
- NotificationRateLimiter: 20 partner/day, 100/week (was 2/4 — too tight for game activity)
- firestore.rules: messages create allows type=image with mediaUrl or type=text with ciphertext
- storage.rules: chat_media path with 15MB cap
- .gitignore: ClaudeReport.md, docs/img
2026-06-24 15:20:44 -05:00
null 608ddcfc5b feat(bubble): drag-to-dismiss zone, no auto-timeout, dismiss on conversation enter
- MessageBubbleOverlay: drag-to-dismiss target at bottom-center, no 12s auto-timeout (persists until read)
- MessageBubbleController: dismissFor clears bubble when its conversation is opened
- ActiveThreadMonitor: calls dismissFor on enter, clearing the bubble for that thread
2026-06-24 15:20:38 -05:00
null adb61715fe feat(home): partner photoUrl loaded and displayed in identity card
- PartnerHomeViewModel: loads partner photoUrl alongside name
- PartnerIdentityCard: shows AsyncImage when photoUrl available, fallback to initial letter
2026-06-24 15:20:32 -05:00
null a8fbbaa286 feat(notifications): deep link routing from FCM data extras, onMessageWritten includes author name + photo
- MainActivity: deepLinkRouteFromIntent resolves FCM data extras to navigation routes; pendingDeepLink state for onNewIntent
- AppNavigation: LaunchedEffect waits for HOME route before navigating deep link (fixes race with onboarding)
- onMessageWritten: includes author displayName + photoUrl in notification payload
2026-06-24 15:20:24 -05:00
null 06e4d609f2 feat(chat): image picker (gallery + camera), encrypted image rendering, messenger-style avatars on consecutive bubbles
- QuestionDiscussionThread: gallery picker via PickVisualMedia, camera capture via FileProvider, EncryptedChatImage composable decrypts + renders, MessageAvatar with partner photo
- QuestionThreadViewModel: sendImage, loadDecryptedMedia, dailyRevealed skip for already-revealed daily questions, partner photo loading
- QuestionThreadScreen: pass loadDecryptedMedia to discussion thread
- LocalQuestionContent: pass partnerPhotoUrl to discussion thread
- file_paths.xml: cache-path for camera capture
2026-06-24 15:20:18 -05:00
null c9aa5f1e12 feat(chat): encrypted image messages — Storage upload/download, Firestore send/load, domain model with type+mediaUrl 2026-06-24 15:20:11 -05:00
null 609ced4095 feat(notifications): FCM token registration on auth, Android 13 permission request, in-app chat bubble overlay, game results notification copy
- MainActivity: request POST_NOTIFICATIONS on TIRAMISU+, register FCM token when user signs in
- AppMessagingService: foreground chat messages show draggable bubble instead of OS notification
- MessageBubbleController/Overlay: new in-app chat-head that drifts over all screens, tap to open
- PartnerNotificationManager: GAME_RESULTS_READY type with proper copy, partner_finished_game maps to it
- onGameSessionUpdate: notify BOTH partners on completion (not just the non-starter), fix starter name in notification
2026-06-24 11:47:49 -05:00
null 0cb3d44f0d fix(reveal): partner option labels, release-key read rules, thread status uppercase, session id propagation, notification deep links, and re-open guard
- Firestore rules: partner can read user doc (name/photo), sender can read own release key
- QuestionThread: status stored UPPERCASE to match rules (lowercase broke discussion)
- GameSessionManager: propagate auto-generated session id (empty id crashed game start)
- AnswerReveal: decrypt partner's selectedOptionTexts from option IDs (showed raw ids)
- FirestoreAnswerDataSource: tolerate Timestamp/Date in updatedAt (serverTimestamp crash)
- FirestoreReleaseKeyDataSource: tolerate PERMISSION_DENIED on existence check (sender can't read)
- QuestionThreadRepository: runCatching status update (legacy lowercase status blocked submit)
- PartnerNotificationManager: suppress notification for active thread, deep link to thread
- ActiveThreadMonitor: new class tracks which thread user is reading (suppresses own notifs)
- DesireSync/HowWell/ThisOrThat: re-open guard skips INTRO if already answered; blank sessionId guard
- AppNavigation: deep link pattern for chat notification
2026-06-24 10:02:54 -05:00
null 77208ff1e6 fix(daily-question): deterministic per-day offset replaces RANDOM(); shared DailyQuestionResolver; auth profile fallback 2026-06-23 22:55:55 -05:00
null 6d74c6acec feat(brand): primaryMessage constant + rotator holds flagship slogan 3x longer 2026-06-23 22:39:31 -05:00
null 7923835861 docs(brand): update privacy slogan in CloserBrandCopy 2026-06-23 22:21:25 -05:00
null 9269a769be docs(readme): update privacy slogan 2026-06-23 22:17:42 -05:00
null 06e09da596 docs(readme): add privacy slogan to header 2026-06-23 22:14:36 -05:00
null e5c05abe90 fix(settings): partner card visual states — paired vs unpaired colors, border, avatar fallback 2026-06-23 19:35:35 -05:00
null 272c8997d0 refactor(ui): celebration overlay polish, activity screen layout, home screen streak dialog, pairing success cleanup 2026-06-23 19:26:41 -05:00
null 17d7489dd8 feat(engagement): streak milestones, celebration overlays, Together screen, avatar in notifications 2026-06-23 18:23:49 -05:00
null d4b20a9845 feat(e2ee): encrypt date plan content; live answer observation; own-thread-answer decrypt; strict rules 2026-06-23 17:47:07 -05:00
null 039752d691 refactor(e2ee): remove v0/v1 migration paths, fail-closed decrypt, strict-only rules 2026-06-23 17:06:23 -05:00
null 17c7ed60b9 fix(nav): tab-switch routing prevents stacking tabs; fix(crash): runCatching around getUser/getCoupleForUser across 6 screens 2026-06-23 14:35:01 -05:00
null fe1808b36c refactor(theme): full dark mode pass — CloserPalette, Theme, Color, and all surface screens 2026-06-23 13:56:27 -05:00
null 7d3b47b3ba fix(firestore): handle Timestamp type for lastAnsweredAt/createdAt in Android + Cloud Function 2026-06-23 12:40:00 -05:00
null 424ef0e4ab refactor(theme): replace hardcoded colors with Material3 theme-aware composables + adaptive iOS surface color 2026-06-23 12:31:59 -05:00
null e5c13b6b6d feat(app-check): stable debug token via BuildConfig; feat(firestore): indexes for questions + bucket_list 2026-06-23 12:17:17 -05:00
null 6977db7600 fix(wheel-reveal): error state with retry, null-safe uid/couple, close on snapshot error 2026-06-23 11:34:46 -05:00
null acaa8e635c fix(challenges): null-safe activeChallenge guard; feat(this-or-that): skip question button 2026-06-23 11:31:17 -05:00
null b854c0b391 feat(history): tappable challenge/capsule cards, deep-link to capsule detail, emoji per game type, dedicated error card; feat(nav): MEMORY_LANE_CAPSULE route 2026-06-23 11:19:14 -05:00
null 658ead38cd security: App Check enforcement on all callables, fail-closed device integrity, no raw code in logs; release signing config; iOS RevenueCat log level 2026-06-23 10:56:42 -05:00
null 015ac8eefe feat(challenges): abandon challenge flow; fix(play): premium lock on history; fix(memory-lane): null-safe detail state 2026-06-23 10:51:14 -05:00
null 58be8ed021 fix(game-history): disable replay on unsupported game types, clean up session title/route 2026-06-23 10:32:49 -05:00
null 755077c7ba feat(memory-lane): edit/delete capsules, custom unlock date picker, error snackbar 2026-06-23 10:11:25 -05:00
null 9710bbc438 fix(challenges): error state snackbar, CTA routing for BOTH_COMPLETED/CHALLENGE_COMPLETE, README prem tiers 2026-06-23 10:04:53 -05:00
null c97371a12e feat: challenge state machine, game screen updates, state machine tests 2026-06-22 22:02:39 -05:00
null c56dd53edd feat: capsule/challenge data sources, game screens, wheel history + viewmodel 2026-06-22 21:38:18 -05:00
null 17403b1a75 feat: challenges, desire sync, how well, memory lane, this or that screens 2026-06-22 21:24:02 -05:00
null 3f5d7a5cc1 feat: nav, capsule data source, challenges, desire sync, question category, wheel history + viewmodel 2026-06-22 21:19:19 -05:00
null 2108d48914 feat: challenges, desire sync, how well, memory lane, play hub + viewmodel, this or that, wheel history 2026-06-22 20:46:40 -05:00
null 7db075d195 feat: navigation, answer history screen + viewmodel, answer reveal, iOS navigation & question views 2026-06-22 19:44:44 -05:00
null 125a24eb85 feat: answer reveal, auth screens, challenges, onboarding, pairing, paywall, wheel, settings, components 2026-06-22 19:18:49 -05:00
null 42706b4dc6 feat: settings screen + iOS settings views 2026-06-22 18:14:55 -05:00
null 5d3ab8385d feat: daily questions, answer reveal, home screens, auth, analytics, DB, repositories 2026-06-22 17:45:51 -05:00
null 174e56c5a0 feat: local question content, question header, daily question illustration, iOS question/wheel views 2026-06-22 13:57:09 -05:00
null f350c91b55 feat: question pack library screen, pack art assets, iOS question views 2026-06-22 13:45:48 -05:00
null d96221c5c8 feat: home screen + iOS pairing views 2026-06-22 12:52:33 -05:00
null bb119b054b feat: home screen update, pairing views, activation illustrations 2026-06-22 11:25:21 -05:00
null d307904ff8 feat: home screen + viewmodel, iOS home & pairing views 2026-06-22 11:14:19 -05:00
null 7d5fc11366 feat: nav routes, play hub, spin wheel screen + viewmodel, firestore rules 2026-06-22 10:53:05 -05:00
null ecc41a77d2 feat: wheel screen, play hub, storage data source, iOS wheel/play views 2026-06-22 10:25:58 -05:00
null b29280ba87 feat: invite flow improvements, pairing success screen, iOS pairing updates 2026-06-22 09:06:40 -05:00
null 5e16177eb2 feat: code push -- notifications, cloud functions, iOS updates 2026-06-22 08:53:23 -05:00
null 9166721282 feat: notification improvements + daily question reminder cloud function 2026-06-22 08:34:15 -05:00
null 893c88d774 feat(auth): remove anonymous sign-in, add email verification flow (batch 0.3.0) 2026-06-21 21:18:30 -05:00
null 54fdaf831f docs(manual): fix placeholder notification function descriptions, add new collections, biometric flow, iOS gitignore note 2026-06-21 18:47:18 -05:00
null 8f47593cf5 fix: user repository cleanup, settings VM, iOS app init + settings parity 2026-06-21 17:44:56 -05:00
null 6b50e84f60 fix: onboarding flow, settings screen polish, iOS settings parity 2026-06-21 17:37:14 -05:00
null e2fd65f070 feat: security screen, theme polish, settings navigation, build config 2026-06-21 17:25:39 -05:00
null b720f0cf14 feat: pending invite store, iOS subscription illustration, settings theme polish 2026-06-21 17:04:40 -05:00
null b19fc0934c feat: paywall illustrations, subscription polish, recovery store, settings cleanup 2026-06-21 16:27:55 -05:00
null 720b52a33b chore: firebase config, gitignore updates, build tweaks 2026-06-21 16:07:19 -05:00
null af70280daa feat: E2EE recovery flow, iOS parity updates, onboarding + pairing polish 2026-06-21 11:20:48 -05:00
null 62d99505c9 feat: subscription screen with clear pricing, restore, cancel instructions 2026-06-21 09:54:59 -05:00
null dff86eb089 feat: settings polish, privacy strings, home partner state, proguard rules 2026-06-21 09:49:02 -05:00
null 26419ce08d feat: remove email invite screen, add accept-invite rate limiting, clean up iOS pairing (v0.2.2) 2026-06-21 08:55:43 -05:00
null a5aad4f0bf fix(outcomes): use AutoMirrored.TrendingUp to resolve icon import/type mismatch 2026-06-21 00:07:52 -05:00
null b70463274f fix(home): resolve OutcomeDay import for outcome dialogs 2026-06-21 00:03:02 -05:00
null 57a3e35359 feat(outcomes): add 30/60/90 day check-in flow with baseline + reminders 2026-06-20 23:59:24 -05:00
null 535c0ce668 feat(home): surface couple streak count on Home dashboard 2026-06-20 23:47:55 -05:00
null bc3317c65a feat(home): add "5-minute check-in" time budget framing to daily question card 2026-06-20 23:46:28 -05:00
null 2a1e5fad10 feat(functions): add createInviteCallable and tighten invite rules 2026-06-20 23:28:20 -05:00
null 8967fd23cd fix(crypto): define single source of truth for encryptionVersion and document v0/v2 drift risk
- Add EncryptionVersion.kt with constants PLAINTEXT(0), MIGRATING(1), STRICT(2)
- Route CoupleEncryptionManager through the new constants and add explicit v2 branch
- Comment acceptInviteCallable.ts:91 explaining the version and sync contract
- Add TODO in iOS FirestoreService.swift warning that iOS MVP creates v0 couples

Fixes Risk #2 from review.md.
2026-06-20 22:29:43 -05:00
null bdd2bf27c0 feat(settings): add appearance screen with theme picker, refactor settings nav 2026-06-20 18:45:44 -05:00
null 1f777e827d feat: add onMessageWritten cloud function, notification settings screen, user repo cleanup 2026-06-20 18:25:05 -05:00
null 4dad0e774e refactor: update crypto, invite flow, and account screen patterns 2026-06-20 18:09:46 -05:00
null 09a2480359 refactor(android): update question thread and answer mapping patterns 2026-06-20 18:02:21 -05:00
null 2a5cd28397 refactor(android): update question flow and navigation patterns (batch 6) 2026-06-20 17:17:51 -05:00
null 38aedab962 chore: update README, screenshots, answer data source cleanup (batch v1.0.21) 2026-06-20 02:01:42 -05:00
null 9c1fbf60a0 fix: reveal screen UX and rules hardening (batch v1.0.20) 2026-06-20 01:51:02 -05:00
null 737514d18f fix: sealed reveal flow fixes (batch v1.0.19) 2026-06-20 01:40:24 -05:00
null 8de5990230 fix: add Tink dependency, release key cleanup, rules hardening (batch v1.0.17) 2026-06-20 01:10:20 -05:00
null 84eab1825b feat: add thread sealed answers, release key cleanup, rules hardening (batch v1.0.16) 2026-06-20 00:41:48 -05:00
null a3993d08df feat: implement partner-proof sealed answers (batches 1-8)
- UserKeyManager: per-user keypair stored in Android Keystore
- SealedAnswerEncryptor: one-time answer key, sealed:v1 ciphertext
- PendingAnswerKeyStore: local EncryptedSharedPreferences storage
- ReleaseKeyEncryptor: keybox:v1 encrypted to recipient public key
- SealedRevealManager: full reveal flow with mutual key release
- AnswerCommitment: SHA-256 commitment hash over canonical payload
- FirestoreDeviceKeyDataSource: public key CRUD
- FirestoreReleaseKeyDataSource: release key CRUD
- FirestoreAnswerDataSource: sealed answer writes with schemaVersion=3
- FirestoreCollections: sealed answer and release key paths
- firestore.rules: ownership, immutability, timing, prefix enforcement
- HomeViewModel: sealed answer state integration
- AnswerRevealScreen/ViewModel: sealed reveal flow with UX states
- CloserApp: initialize UserKeyManager on startup
- LocalAnswer model: schemaVersion field
- Unit tests: SealedAnswerEncryptor, ReleaseKeyEncryptor, AnswerCommitment
- Crypto test vectors: docs/crypto/sealed-answer-test-vectors.json
- .gitignore: add partner-proof build plan
2026-06-20 00:23:58 -05:00
null 521989ec44 fix: remove duplicate comparison in StreakCalculator (batch v1.0.14) 2026-06-19 23:53:50 -05:00
null 195dfb5a0a refactor: replace PendingActionCard.action lambda with HomeActionTarget (batch v1.0.13)
- PendingActionCard now uses target enum instead of lambda
- HomeScreen routes pending actions through toActionHandler
- Remove onPendingAction callback, simplify HomeCallbacks
- Fix WeeklyRecapGenerator filter logic (remove always-true || true)
2026-06-19 23:51:47 -05:00
null 0e75b3b536 feat: add gentle reminder callable and wire into HomeViewModel (batch v1.0.12)
- GENTLE_REMINDER notification type with warm copy
- sendGentleReminderCallable Cloud Function
- HomeViewModel.sendGentleReminder() calls function, shows snackbar
- Snackbar event consumed after display
2026-06-19 23:47:01 -05:00
null 7dc14af627 feat: wire retention signals into HomeViewModel (batch v1.0.11)
- Replace TODO placeholders with real data source calls
- Add hasWaitingGame, hasActiveChallenge, hasUpcomingDatePlan, hasUnlockedCapsule, weeklyRecapReady
- Parallel async fetches in loadHome(), failures default to false
- FirestoreCapsuleDataSource.getCapsules() for capsule status checks
2026-06-19 23:42:54 -05:00
null 89213445b9 fix: add coEvery import and re-set settings flow in PartnerNotificationManagerTest (batch v1.0.10) 2026-06-19 22:52:27 -05:00
null fa501089f2 test: add unit tests for retention features (batch v1.0.10)
- PartnerNotificationManagerTest: notification creation, type mapping, deep links
- build.gradle.kts: enable Robolectric and default return values for unit tests
- AppRoute: fix NPE in asRouteArg when android.net.Uri is stubbed on test classpath
2026-06-19 22:51:08 -05:00
null 5698e5436a feat: add memory capsule generator for saving meaningful moments (batch v1.0.9) 2026-06-19 22:47:36 -05:00
null a500b86621 chore: update UI copy to match retention tone guidelines (batch v1.0.9) 2026-06-19 22:46:07 -05:00
null 3575af1b6f feat: add date suggestion engine for date planning loop (batch v1.0.8) 2026-06-19 22:44:33 -05:00
null 9db3c35f8d feat: add follow-up prompts after reveals (batch v1.0.7) 2026-06-19 22:43:40 -05:00
null 9040b97eb2 feat: add challenge loop state machine with 6 states and copy (batch v1.0.6)
- ChallengeState data model with 6 states: not started, started, waiting, both complete, missed, complete
- ChallengeStateMachine: pure Kotlin, configurable missed-day behavior
- 12 unit tests covering all states and edge cases
- Fix pre-existing missing import in AnswerRevealViewModel
2026-06-19 22:41:43 -05:00
null b1b35891c9 feat: add HomePriorityEngine and weekly recap generator (batch v1.0.5)
- HomePriorityEngine: 13-level priority system, primary + secondary CTA
- HomeScreen: add onNavigate to HomeContent, fix compile error
- WeeklyRecapGenerator: pure logic, counts, favorite category, suggested pack
- Privacy: hidden answers excluded from recap counts
- Unit tests for both engine and recap generator
2026-06-19 22:37:47 -05:00
null 935aee5ec5 feat: add partner-trigger notifications with rate limits and quiet hours (batch v1.0.4)
- PartnerNotificationManager: 6 notification types, static copy only
- NotificationRateLimiter: max 2 partner/day, 1 reminder/day, 4/week
- QuietHoursManager: default 10pm-8am, user-configurable
- NotificationChannelSetup: partner-actions channel (HIGH importance)
- PartnerNotificationScheduler: routes FCM events through manager
- AppMessagingService: safe static copy, drops unknown types
- Deep link navigation for all notification targets
- 3 test files covering quiet hours, rate limits, notification types
2026-06-19 22:34:42 -05:00
null 9828e73171 feat: add 'Waiting for you' unfinished business dashboard (batch v1.0.3)
- PendingActionCard data class with priority-ordered cards
- 6 card types: reveal ready, partner answered, game, challenge, date, capsule
- Max 3 cards, highest priority first, deep link to correct screen
- Placeholder guards for game/challenge/date/capsule (wired in later batches)
- Compact cards with purple/pink palette, no private text leaked
2026-06-19 22:31:11 -05:00
null c38e83b8ee feat: add streak calculator with couple/personal/weekly streaks and repair (batch v1.0.2)
- Streak data models: Couple, Personal, WeeklyRhythm streaks
- StreakCalculator: pure Kotlin, no Android deps, deterministic
- Milestone copy at 1/3/7/14/30 days
- Streak repair: 1 missed day per 7-day window, requires both partners
- 23 unit tests covering all streak types, milestones, repair, timezone
2026-06-19 22:25:47 -05:00
null 0b619ee7ba feat: improve daily question habit loop with 5 UI states (batch v1.0.1)
- Add DailyQuestionState enum to HomeViewModel with 5 states
- Real-time Firestore listener for partner's daily answer
- Home card shows correct copy/CTA per state
- CTAs: answer, gentle reminder (no-op), reveal, follow-up (placeholder)
- Cleanup listener on onCleared()
2026-06-19 22:23:24 -05:00
null aff1150295 feat: add retention events and analytics wrapper (batch v1.0.0)
- RetentionEvent sealed class with 19 event types (metadata only, no answer text)
- RetentionAnalytics interface + LogcatRetentionAnalytics (debug-only, hashed IDs)
- NoopRetentionAnalytics for tests/disabled state
- Hilt AnalyticsModule binding as singleton
- Couple IDs SHA-256 hashed before logging
2026-06-19 22:20:49 -05:00
null 700201bbd6 refactor: extract EncryptedSharedPreferences into SecurePreferencesFactory with auto-recovery (batch v0.2.21)
- New SecurePreferencesFactory handles EncryptedSharedPreferences creation
- Auto-resets and recreates on corruption (unreadable prefs)
- CoupleKeyStore and SharedPreferencesLocalAnswerRepository use the factory
- Removes duplicated EncryptedSharedPreferences boilerplate
2026-06-19 22:06:52 -05:00
null c31177d52b chore: remove dead invite code after Cloud Function migration (batch v0.2.19)
- Remove unused markAccepted from InviteRepository/Impl
- Remove unused loadedInvite field from InviteConfirmViewModel
- Fix deprecated getHttpsCallable result access
- Remove unused SetOptions import
2026-06-19 21:50:29 -05:00
null 39255c8733 fix: prevent invite code enumeration via Cloud Function (batch v0.2.18)
- Remove client-side read access to invites (only inviter can read own invite)
- Deny direct client update to invites (server-side only via Admin SDK)
- Add acceptInviteCallable Cloud Function: validates code, creates couple,
  updates user docs, marks invite accepted, returns wrapped key for local decryption
- Update Android client: FirestoreInviteDataSource calls callable function,
  InviteConfirmViewModel uses acceptInvite + unwrapAndStore flow
- Deprecate CoupleRepositoryImpl.createCouple (client-side path removed)
- Update Firestore rules tests: unpaired read now denied, direct update now denied
- 118/118 tests passing
2026-06-19 21:46:12 -05:00
null 2e2c79be3d fix: remove android.util.Base64 from RecoveryKeyManager for portability (batch v0.2.16)
- Replace android.util.Base64 with java.util.Base64 in RecoveryKeyManager
- Crypto layer now has zero Android SDK dependencies — portable to iOS/shared testing
2026-06-19 21:26:35 -05:00
null c1f7e6f7f9 feat: daily question date key uses local timezone instead of UTC (batch v0.2.15)
- Replace SimpleDateFormat/Calendar UTC date key with java.time LocalDate in device timezone
- FirestoreAnswerDataSource: todayLocalDateString() with injectable Clock, localDateString() helper
- DailyQuestionViewModel: pass date through submit flow so sync uses same date key
- AnswerRevealViewModel: use todayLocalDateString() for partner answer lookup
- Add FirestoreAnswerDataSourceTest: verifies timezone-aware date boundaries (Chicago vs Tokyo, LA vs London)
2026-06-19 21:24:53 -05:00
null 70bb0a346c fix: normalize crypto files to plain ASCII (batch v0.2.14)
- Replace smart quotes, em dash, prime, right arrow in comments with ASCII equivalents
- Affected: CoupleEncryptionManager.kt, FieldEncryptor.kt, RecoveryKeyManager.kt
2026-06-19 21:22:27 -05:00
null 85b4eb589b feat: add 3 stronger privacy slogans to BrandMessageRotator (batch v0.2.13)
- Add to CloserBrandCopy: 'Not even Closer can read your answers.', 'End to end encrypted private responses.', 'Built for trust, not tracking.'
- Update visual-identity.md: add new slogans to approved rotation, remove migration gating note (all legacy couples migrated)
2026-06-19 21:17:59 -05:00
null 55ca3dce27 fix: Firestore rules hardening, recovery phrase strength, test cleanup (batch v0.2.12)
- Firestore rules: add isCouplesMember(coupleId) to question thread answer writes (prevents outsider writes)
- Firestore rules: allow currentIndex increment on same-status session updates (fixes thread progression)
- RecoveryKeyManager: PHRASE_WORD_COUNT 6→10 (~80 bits entropy)
- build.gradle.kts: exclude META-INF/versions/9/OSGI-INF/MANIFEST.MF (packaging conflict)
- .gitignore: add firebase-debug.log, firestore-debug.log
- firestore-tests: configurable emulator port via FIRESTORE_EMULATOR_PORT env var
- firestore-tests: fix invite outsider test (seed with different coupleId), fix non-starter session test (active→completed allowed), remove redundant beforeEach(seedThread), add outsider-write-denied test for thread answers
- visual-identity.md: update encryption claim gating note
2026-06-19 21:08:55 -05:00
null 3233c54ab2 feat: strict E2EE — encryption migration, Firestore rules enforcement, version 2 protocol (batch v0.2.11)
- Add CoupleAnswerMigrationDataSource: one-time per-user rewrite of all historical answer-bearing fields (daily answers, thread answers/messages, ThisOrThat, DesireSync, HowWell, Wheel) to ciphertext
- Add EncryptionUpgradeScreen + ViewModel: handles version-0→1→2 migration, recovery phrase display, partner coordination
- Add FieldEncryptorTest: round-trip, cross-couple binding, null-key, plaintext-not-leaked
- CoupleEncryptionManager: STRICT_ENCRYPTION_VERSION=2, requireAead() throws on missing key, setupLegacyCouple, pendingRecoveryPhrase/acknowledge
- CoupleKeyStore: pending recovery phrase storage/clear
- FieldEncryptor: switch from android.util.Base64 to java.util.Base64
- All data sources: use requireAead() (throws instead of silent plaintext fallback), encrypt all answer-bearing writes
- FirestoreCoupleDataSource: beginEncryptionMigration (atomic version-0→1 claim), markEncryptionMigrationComplete (per-user + version-2 promotion)
- CoupleRepositoryImpl: require wrappedKey on invite acceptance (no more optional)
- HomeScreen/ViewModel: route to EncryptionUpgradeScreen for version-0 or unmigrated version-1 couples
- Firestore rules: isCiphertext validator, isEncryptedAnswerPayload, isStartingEncryptionMigration, isCompletingOwnEncryptionMigration, isUpdatingRecoveryWrap, isUpdatingCoupleRhythm; enforce ciphertext on all answer/message writes; game collection rules (this_or_that, desire_sync, how_well, wheel) with per-user answer ownership; couple doc update split into 4 mutually exclusive paths; invite doc requires createdAt + wrappedKey fields; isImmutable uses diff().hasAny() instead of field equality
- Firestore rules tests: encryption migration scenarios, plaintext rejection, per-user answer ownership, game collection ciphertext enforcement
- firebase.json: emulator port 8180
- .gitignore: firestore-tests/node_modules
2026-06-19 20:53:52 -05:00
null e7b45cc84f fix: profile photo temp dir, Firestore rules field-level lockdown (batch v0.2.10)
- Move temp profile photos to filesDir/photos/ subdirectory with mkdirs
- Update file_paths.xml to scope FileProvider to photos/ subdirectory
- Firestore rules: restrict couple doc updates to only mutable fields (streakCount, lastAnsweredAt, wrappedCoupleKey, kdfSalt, kdfParams, encryptionVersion) — prevents client from overwriting currentQuestionId, activePackId, id
2026-06-19 20:33:08 -05:00
null 9a0b2b6a3d feat: BrandMessageRotator — rotating privacy copy across screens (batch v0.2.9)
- Add CloserBrandCopy with 6 approved privacy messages
- Add BrandMessageRotator composable: animated fade rotation every 4.5s, reduced-motion support
- Integrate rotator into: OnboardingScreen (CTA + auth check), LoginScreen, LoadingState, AnswerRevealScreen (waiting card), WaitingForPartnerScreen, DesireSync/HowWell/ThisOrThat waiting screens
- Add CloserBrandCopyTest for uniqueness and length validation
- Update visual-identity.md with approved rotation and security-claim publishing rules
2026-06-19 20:24:50 -05:00
null 6828be72fc feat: Cloud Functions — leaveCoupleCallable, onUserDelete cascade (batch v0.2.8)
- Add leaveCoupleCallable: HTTPS callable that atomically unlinks couple via Admin SDK (clears both user coupleIds, recursiveDelete couple doc)
- Add onUserDelete: Auth deletion trigger that cascades cleanup — unpairs partner, sends FCM notification, deletes Storage objects, recursiveDelete user doc
- Replace client-side batch leaveCouple with callable invocation (Firestore rules prevent cross-user writes)
- Remove CoupleRepository/UserRepository from DeleteAccountViewModel — cleanup now handled by onUserDelete trigger
- Wire new functions into index.ts exports
2026-06-19 20:04:18 -05:00
null cbaa68ef2e feat: account deletion with re-authentication flow (batch v0.2.7)
- Add reauthenticateWithEmail to AuthRepository + FirebaseAuthDataSource
- DeleteAccountScreen: re-auth dialog for email users (password prompt), Google user guidance
- DeleteAccountViewModel: handle FirebaseAuthRecentLoginRequiredException, re-auth submission
- Reorder delete flow: auth account deleted first, then couple leave + user data cleanup
2026-06-19 19:57:07 -05:00
null 30fddcc2df feat: E2EE — Tink AEAD, Argon2id KDF, recovery phrase, encrypted Firestore fields (batch v0.2.6)
- Add crypto module: CoupleKeyStore (EncryptedSharedPreferences), RecoveryKeyManager (Argon2id + AES-256-GCM key wrap), FieldEncryptor (AEAD per-field), CoupleEncryptionManager (orchestration)
- Add Tink + Bouncy Castle dependencies to build.gradle.kts, register AeadConfig in CloserApp
- Encrypt answer fields (writtenText, selectedOptionIds, scaleValue) on write, decrypt on read
- Encrypt DesireSync, HowWell, WheelAnswer, QuestionThread fields via CoupleEncryptionManager
- Generate recovery phrase during invite creation, display in CreateInviteScreen
- Add recovery phrase input to InviteConfirmScreen for encrypted invites
- Add RecoveryScreen + RecoveryViewModel for post-pairing key recovery
- Update Couple model with encryptionVersion, wrappedCoupleKey, kdfSalt, kdfParams
- Update Firestore rules: allow couple doc creation by members, fcmTokens path, encryptionVersion monotonic check, invite doc extended fields
2026-06-19 19:52:35 -05:00
null 5caae523e7 feat: app icon redesign, store assets, brand identity docs (batch v0.2.5)
- Redraw adaptive icon layers (background + foreground) with Closer palette colors
- Add monochrome icon layer for Android 13+ themed icons
- Add mipmap-anydpi-v33 adaptive icon configs (round + standard)
- Add store assets: 512px app icon, 1024x500 feature graphic, source SVGs
- Add docs/brand/visual-identity.md with brand mark, color palette, store voice, asset rules
- Update store-assets.md checklist to reflect completed items
2026-06-19 19:10:03 -05:00
null 7256a71bdf feat: dark mode support — ThemeMode setting, dynamic colors, status bar sync (batch v0.2.4)
- Add ThemeMode enum (DEVICE/LIGHT/DARK) with DataStore persistence
- SettingsScreen: appearance section with radio buttons for Device/Light/Dark
- SettingsViewModel: observe and persist theme mode
- MainActivity: read theme setting, apply dark theme, sync status bar icons
- Replace hardcoded Color.White references with MaterialTheme.colorScheme.surface across auth, onboarding, settings, and theme
- Convert AuthVisuals, SettingsVisuals, CloserPalette brushes to @Composable getters using dynamic scheme colors
- Add values-night/themes.xml for dark theme manifest entry
- Add ThemeModeTest unit test for fromStorageValue parsing
2026-06-19 19:00:37 -05:00
null 7552c451db feat: notification copy, error messages, animations, reduced-motion support (batch v0.2.2)
- Rewrite all notification titles/bodies + channel descriptions to warmer, partner-centric tone
- Update error messages across all screens for clarity and consistency
- Add AnimatedVisibility + reduced-motion detection (Settings.Global.ANIMATOR_DURATION_SCALE) to AnswerRevealScreen and LocalQuestionContent
- Polish settings copy (quiet hours, partner activity labels, info footer)
- Update all game error states with actionable language ('Go back and try again')
- Refresh docs screenshots
2026-06-19 04:20:08 -05:00
null 79a63629f1 refactor: CloserPrimitives design system, PairPromptScreen, state component overhauls (batch v0.2.1)
- Add CloserPrimitives (CloserCard, CloserActionButton, CloserSpacing, CloserButtonStyle, SkeletonLine)
- Refactor EmptyState, ErrorState, LoadingState to use primitives with closer design tokens
- Add PairPromptScreen + nav route for post-signup partner invitation
- Update SignUpScreen onboarding copy to mention partner invite flow
- HomeScreen and PlayHubScreen layout/structure refinements
2026-06-19 04:04:52 -05:00
null 164e0e47ca feat: update AnswerHistory, BucketList, DateMatches, Onboarding, LocalQuestionContent, WheelHistory screens 2026-06-19 03:53:43 -05:00
null 803b681d06 feat: update PrivacyScreen, add Firestore test scripts, gitleaks audit artifacts 2026-06-19 03:45:53 -05:00
null 9e587a23dd feat: update question thread data source, repository, ViewModel, and Firestore security rules 2026-06-19 03:19:58 -05:00
null 927e930b79 feat: add SessionLength model, update game screens with session length awareness 2026-06-19 02:50:58 -05:00
null 0e0a33a6dd feat: add FCM game retention notification functions, messaging service updates, ThisOrThat screen fixes 2026-06-19 02:23:52 -05:00
null 70e7c66cd6 feat: add game history screen, shared session state, updated navigation + PlayHub 2026-06-19 01:43:06 -05:00
null 3ba6c659dd feat: add partner-waiting flow across all game screens with QuestionSession model updates 2026-06-19 01:14:04 -05:00
null 733c0967c2 fix: Q2 grammar quality pass on emotional_intimacy, parenting, stress questions + app.db rebuild 2026-06-19 00:50:23 -05:00
null a13167dc3e feat: Q1 question variety improvement across all categories, app.db rebuild 2026-06-19 00:35:00 -05:00
null 93813255fd chore: Q3 asset DB cleanup (remove 300 dead rows), Q5 grammar fix for depth-5 questions in emotional_intimacy + stress 2026-06-18 22:03:52 -05:00
null 5ad1456adb feat: update desire sync question bank, degender scripts, app.db rebuild 2026-06-18 21:41:14 -05:00
null 473feb78a9 feat: add DesireSync + HowWell Firestore data sources, update screens with cloud-backed answering 2026-06-18 20:47:18 -05:00
null 97cc334136 feat: add Firestore wheel answer data source, update wheel screens with logging + answer history 2026-06-18 20:10:08 -05:00
null 408a2f24ba feat: add ThisOrThat Firestore data source, updated screen with question answering flow 2026-06-18 19:53:17 -05:00
null af06cb2123 feat: add Time Capsule feature with Firestore data source, model, and MemoryLane UI screens 2026-06-18 04:14:12 -05:00
null 4e871f8e4f feat: add Connection Challenge system with game routing, Firestore data source, ChallengeGameScreen in PlayHub 2026-06-18 04:03:57 -05:00
null 574fed27f7 refactor: replace raw string game types with GameType constants, remove unused feature flag module 2026-06-18 03:51:12 -05:00
null debc6aed02 fix: handle partner_active_session error in SpinWheelViewModel, navigate to waiting screen 2026-06-18 03:46:34 -05:00
null 1b344e7220 fix: filter out empty-text/unknown-category questions from all DAO queries, regenerate app.db, handle deleted cloud question by falling back to random 2026-06-18 03:43:24 -05:00
null 606d724f12 feat: add answer history filter pills with reveal/private badges, DesireSync progress meter and reveal UI, HowWell ring progress and privacy tiles, Paywall feature scavenger hunt, category screen grid polish 2026-06-18 03:26:12 -05:00
null 15c1fbdda0 feat: replace PlaceholderScreen with FinishedEmptyStateScreen across PartnerHome, EmailInvite, QuestionComposer, Subscription 2026-06-18 03:20:13 -05:00
null 8b394ab40f fix: use UTC dates for daily question keys across all date consumers 2026-06-18 03:11:22 -05:00
null fb0e8fbaab refactor: extract startGameWithCouple, remove duplicate partner notification from leaveCouple 2026-06-18 03:08:48 -05:00
null 2521e91db4 fix: simplify hasPremium with first(), leave couple before deleting account 2026-06-18 02:56:34 -05:00
null dfd9974683 fix: use real-time session observation in WaitingForPartnerScreen, add credential type check in Google sign-in 2026-06-18 02:50:21 -05:00
null c894dd8c67 fix: simplify finishGame to not require userId — first caller wins 2026-06-18 02:47:57 -05:00
null 21df900bc7 fix: add contentDescription to icon buttons for accessibility 2026-06-18 02:46:10 -05:00
null df961e8d94 fix: enforce multi-choice maxSelections limit across all answer UIs, pass questionIds to startGame 2026-06-18 02:41:33 -05:00
null 4134c4570d fix: integrate game session lifecycle into DesireSync, HowWell, and ThisOrThat 2026-06-18 02:29:14 -05:00
null 2b8e05b29b fix: address Neo review — fix cloud function partnerName scope, WheelCompleteScreen session ID, polling isActive, navigateTo reset 2026-06-18 01:28:43 -05:00
null 7926289153 fix: clamp scale midpoint and handle edge case in wheel session answer UI 2026-06-18 01:17:47 -05:00
null c6df885e1e fix: add answer options to wheel session screen so partners can answer questions 2026-06-18 01:09:08 -05:00
null 7fb913db99 fix: add camera hardware feature flag, fix WaitingForPartnerScreen layout 2026-06-18 01:05:04 -05:00
null c58b1c6326 feat: enforce one active game per couple with partner notifications 2026-06-18 00:56:21 -05:00
null 2677e38514 fix: use sex column for Desire Sync question filtering instead of fragile ID pattern 2026-06-18 00:32:39 -05:00