Commit Graph

31 Commits

Author SHA1 Message Date
null 30eaa0cd61 build(functions): keep revenueCatWebhook out of the deploy until RevenueCat exists
RevenueCat isn't set up, so exporting revenueCatWebhook forced a Secret Manager entry:
defineSecret('REVENUECAT_SIGNING_KEY') runs at module load, and Firebase validates every
declared secret across the whole codebase at deploy time (even functions excluded via --only),
failing with "no latest version of the secret". Comment out the export so the file isn't loaded
during discovery — no secret, no validation. revenueCatWebhook.ts (already migrated to v2) is
untouched; re-enable by uncommenting the export, seeding the real key, and deploying it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 02:01:23 -05:00
null 4c077c4d7c refactor(functions): B6c split game part-finished trigger + reorder reads (#11)
Split the single broad onGamePartFinished (couples/{coupleId}/{gameType}/{sessionId}
wildcard, which fired a no-op invocation on every write to ANY couple subcollection) into
four narrow, explicitly-pathed triggers sharing one handler:
onThisOrThatPartFinished, onWheelPartFinished, onHowWellPartFinished, onDesireSyncPartFinished.
Behavior is identical for the four game collections; the spurious invocations for
messages/reactions/etc. are eliminated. (Background triggers have no client name dependency;
the old export is dropped and the four deploy fresh — the deploy runbook already accounts for
this.)

onGameSessionUpdate: move the `!change.after.exists` deletion guard ABOVE its four reads
(session/couple/userA/userB) so a delete/no-op event returns before doing any reads. The
delicate exactly-once claim-flag logic is otherwise untouched.

Build clean; 70 tests green. Discovery loads all four split triggers as v2 in us-central1
(36 functions total); old onGamePartFinished gone. dist rebuilt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 00:08:18 -05:00
null e0c2d67373 refactor(functions): B3 migrate 12 callables to v2 + harden
Migrate all callables off functions.https.onCall to firebase-functions/v2/https onCall:
createInvite, acceptInvite, leaveCouple, submitOutcome, sendGentleReminder,
sendThinkingOfYou, checkDeviceIntegrity, syncEntitlement, assignDailyQuestionCallable,
wrapReleaseKey. context.auth/app → request.auth/app, data arg → request.data. The 8
client-hardcoded callable names are preserved verbatim (verified via emulator discovery).
The manual `if (!request.app)` App Check check is a 1:1 port (no enforceAppCheck switch).

Hardening folded in:
- acceptInviteCallable: await the previously fire-and-forget partner_joined push (gen 2
  freezes the instance after the response) — still swallows push errors so a failed push
  never fails the accept.
- checkDeviceIntegrity: 10s timeout on the Play Integrity client.request so a hung upstream
  can't pin the instance (fail-closed catch already handles the throw); memory 512MiB.
- wrapReleaseKey: memory 512MiB (tink); HttpsError swapped to v2; lazy tink require + graceful
  failure preserved.
- Error mapping with `if (e instanceof HttpsError) throw e` re-throw guard around the risky
  DB sections in acceptInvite, leaveCouple, submitOutcome, sendGentleReminder,
  sendThinkingOfYou — raw errors map to a clean 'internal' without masking intentional codes
  (resource-exhausted rate limits, permission-denied, etc.). leaveCouple's best-effort
  recursiveDelete sweep now swallows errors (the transactional leave already succeeded).
- Adopt shared sendPushToUser()/logger; remove copied token readers + plaintext token logging.

Delete dead placeholder callables notifications/reminders.ts (sendDailyQuestionReminder,
sendPartnerAnsweredNotification) — no client caller; wrote sent:false rows nothing consumed.

Build clean; 70 tests green; discovery loads all callables as v2 in us-central1. dist rebuilt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:58:32 -05:00
null fbf4e7957c build(functions): B0 v2 foundation — global options, shared push helper, structured logging
Groundwork for the v1→v2 Cloud Functions migration; no function is migrated yet
(all 35 still load as v1, verified via emulator discovery).

- options.ts: setGlobalOptions({ region: 'us-central1', maxInstances: 20 }), imported
  first in index.ts so it applies before any v2 function is defined. Region pin is
  load-bearing — the Android client uses the default region.
- notifications/push.ts: single canonical getUserTokens() + sendPushToUser() that
  batches via messaging.sendEachForMulticast() and prunes dead tokens, to replace the
  ~10 copied token readers and ~19 copied send/prune blocks in later batches.
- log.ts: firebase-functions/logger re-export + redactToken() (FCM tokens are secrets).
- push.test.ts: 9 unit tests (token merge/dedupe, BatchResponse→dead-token mapping,
  send/prune/no-op/whole-batch-failure paths). 67 tests green.

firebase-functions stays at v5.1.1 for the migration (supports both the root v1 API and
the /v2 subpaths); bump to v6 is deferred to the final batch once nothing references the
root namespace, so the build stays green at every step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:36:16 -05:00
null eeac3c9383 build(functions): compile dist for outcome aggregation
Tracked dist output rebuilt to match src (aggregateOutcomeStats export +
aggregateOutcomes module), keeping the deployed bundle in sync with source.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 21:10:02 -05:00
null 896bf26b28 feat: date reflection reveal, UI upgrade plan, seed updates, ime-scan script 2026-07-01 04:12:58 -05:00
null 37815af781 chore: rebuild functions dist (add onRestoreRequested + onRestoreFulfilled exports) 2026-06-30 20:43:58 -05:00
null d4cedaf304 chore(date-memories): update compiled function index 2026-06-30 18:14:50 -05:00
null 6dddac4615 Revert "feat(date-memories): add onDateHistoryCreated + onDateReflectionWritten Cloud Functions (batch 5/8)"
This reverts commit 8829cffa7e.
2026-06-30 18:13:00 -05:00
null 8829cffa7e feat(date-memories): add onDateHistoryCreated + onDateReflectionWritten Cloud Functions (batch 5/8) 2026-06-30 16:51:59 -05:00
null d87603211a feat(activity): ActivityScreen timeline, HomeScreen activity feed, HomeViewModel wiring, PartnerNotificationManager, sendThinkingOfYouCallable Cloud Function 2026-06-30 03:54:01 -05:00
null 2a5c40508e feat(notifications): QuietHoursManager + NotificationSettingsScreen rewrite, Cloud Functions (streakReminder, quietHours, reengagement, gameRetention), UserRepository E2EE wiring, SettingsDataStore, firestore rules, wiring-scan 2026-06-30 00:38:06 -05:00
null f51a55743c feat(games): partner game-session push orchestration — in-app notification banner, Firestore rules, Cloud Function, QA docs 2026-06-28 22:24:46 -05:00
null 4eed0a8115 feat(premium): couple-shared unlock notification + reveal retry + users update allowlist + brand glyphs
- New Cloud Function: onEntitlementChanged (Firestore onWrite on entitlements/premium) — edge-triggered inactive→active, notifies the OTHER partner so couple-shared unlock isn't silent
- New notification type SUBSCRIPTION_CHANGED → routes to SUBSCRIPTION
- AnswerRevealViewModel: re-issue markRevealed if best-effort failed (offline/transient) so partner_opened_answer push eventually fires
- firestore.rules: harden users/{uid} update allowlist (defense-in-depth; no live hole)
- 18 new brand glyph vector drawables (drawable-nodpi/)
- SettingsScreen / PlayHubScreen / WaitingForPartnerScreen: swap Material icons for new brand glyphs
- ClaudeQA docs + Future.md updated
2026-06-27 16:35:41 -05:00
null 2cd0af65a8 chore: working tree changes — QA docs, app tweaks, Cloud Functions updates 2026-06-27 13:31:09 -05:00
null 8b4c5ba005 feat(notif): add onAnswerRevealed cloud function — notify partner when answers are opened 2026-06-26 12:40:36 -05:00
null 29beff1702 build(functions): rebuild dist from source — revenueCatWebhook ack-after-process, acceptInvite strict E2EE, onMessageWritten conversations path, onGameSessionUpdate both-partner notify 2026-06-24 16:15:30 -05:00
null 5e16177eb2 feat: code push -- notifications, cloud functions, iOS updates 2026-06-22 08:53:23 -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 1f777e827d feat: add onMessageWritten cloud function, notification settings screen, user repo cleanup 2026-06-20 18:25:05 -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 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 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 0e0a33a6dd feat: add FCM game retention notification functions, messaging service updates, ThisOrThat screen fixes 2026-06-19 02:23:52 -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 c0696cfb80 feat: partner leave notification, real-time couple state sync, in-app unpair alerts 2026-06-18 00:25:52 -05:00
null eaac8ffcc9 feat: couple-scoped daily question, answer sync, partner notifications, and answer review 2026-06-18 00:18:05 -05:00
null c816033e74 feat: cloud function for date match cleanup, ViewModel and repo improvements 2026-06-17 20:26:24 -05:00
null ec315c63e0 feat: add App Integrity + device attestation modules 2026-06-17 19:37:19 -05:00
null f3bad90ec6 feat(notifications): FCM token registration, quiet hours, notification permission helper, reminder Cloud Functions (batch 11) 2026-06-17 01:30:04 -05:00
null b9ad713ddb feat(billing): server-side entitlement sync — RevenueCat webhook handler, entitlement logic, Firestore EntitlementChecker, Hilt DI, callable sync function (batch 10) 2026-06-17 01:25:51 -05:00