Closer/Engineering_Reference_Manua...

114 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Engineering Reference Manual Update Plan
**Status: ✅ COMPLETE — v0.2.1 phase (2026-06-28, 9 batches) + ✅ v0.2.x phase (2026-07-08, single comprehensive pass)**
Goal: bring `docs/Engineering_Reference_Manual.md` into alignment with the current
relationship-app codebase. Verify every claim, file path, function name,
collection name, and architectural fact. Never assume.
## Phase 2 (2026-07-08) — single comprehensive pass
Triggered by the 2026-07-08 Cloud Functions v2 deploy (B0B6d, Node 22 bump, 5 per-game part-finished triggers) + the R30 games/UX/seed round + the `b99a8338` RevenueCat↔Firebase-Auth identity link. Single comprehensive pass rather than the original 9-batch plan because the changes were concentrated in three areas (Cloud Functions, Billing, Daily question) and the manual had drifted in known directions.
### What changed (Phase 2)
- **Cloud Functions** — replaced the stale functions tree with the v2 layout (added `options.ts`, `log.ts`, the `push.ts`/`quietHours.ts`/`idempotency.ts`/`pruneTokens.ts`/`time.ts` shared infra, `releaseKey/`, `backup/`, `dates/onDate*`, `couples/aggregateOutcomes`, `notifications/sendStreakReminder` + `sendThinkingOfYouCallable`). Replaced `onGamePartFinished` (single) with the four per-game part-finished triggers (`onThisOrThatPartFinished`, `onWheelPartFinished`, `onHowWellPartFinished`, `onDesireSyncPartFinished`). Added the v2-migration deploy-failure pattern landmine (`FUNCTIONS-V2-DEPLOY`). Webhook reliability section now states the webhook is **not deployed** (RevenueCat project not yet created).
- **Daily question lifecycle** — replaced the "picks a random active free question" description with the server-authoritative, mode-aware, deterministic picker that mirrors the client's `DailyModeResolver`; added a new sub-section `### Server-authoritative mode-aware deterministic selection` with the frozen DOW → mode map; noted the picker is FROZEN against `daily_fun_mc` for HowWell/Desire Sync pool hygiene.
- **Billing** — added the `Purchases.logIn(firebaseAuth.currentUser!!.uid)` identity-link flow (commit `b99a8338`) and the `BillingException` typed error mapping; added a "Currently NOT deployed" callout on the webhook section that points to the Webhook reliability deploy steps.
- **iOS section** — corrected the Repository layout iOS `Crypto/` block (it is no longer empty; ships the R24 E2EE code) and the "pairing from iOS currently fails" claim (it does not, for the schemaVersion 2 path; schemaVersion 3 is still infrastructure-gated per `IOS_E2EE_STATUS.md`).
- **TOC + anchors** — added the new sub-anchors (`server-authoritative-mode-aware-deterministic-selection`, `webhook-reliability`, `schedule`, `server-verified-entitlements`, `webhook`, `premium-gated-features-and-gate-pattern`); fixed three pre-existing broken anchors (`#foreground-game-alert-banner-r10`, `#ios--android-sealed-answer-bridge-wrapreleasekeycallable`, `#recovery-phrase-change-desync--...`).
- **New landmines** — `BANNER-LIFE-001` (R30 game banner lifecycle) + `FUNCTIONS-V2-DEPLOY` (2nd-gen deploy / CPU-quota / Eventarc propagation pattern).
### What was NOT changed (Phase 2 — deliberately)
- The Android Gradle config drift (`versionCode = 1`, `versionName = "0.1.0"` in `app/build.gradle.kts` while HISTORY.md describes v0.2.1) is already flagged in the manual ("build config has drifted from HISTORY; do not ship a release until they're reconciled"). Bumping the version is a release-readiness task, not a docs task.
- The iOS E2EE section (sub-section "iOS E2EE gap (status as of current batch)") was already accurate after the R24 work; left unchanged.
- The "Files that must never be committed" gitignore + the iOS CryptoKit guidance section were both already correct.
## Approach
- **Batch-based.** Each batch covers one major section or a coherent set of
subsections. One agent/turn per batch.
- **Evidence-first.** For every factual claim in the manual, verify against the
repo (grep, read file, run build/test if needed).
- **Log everything.** Each batch updates this plan with findings and
changes made.
- **Ripley coordinates.** Ripley does not code unless necessary; Bishop or
subagents may verify builds/docs.
## Batches
### Batch 1 — Front matter + System overview + Repository layout
- Read: `## How to use this document` through `### Shared configuration`.
- Verify all directory paths under `app/src/main/java/app/closer/`,
`functions/src/`, `functions/dist/`, `res/drawable-*`.
- Flag missing or renamed directories/files.
- Update any stale paths or naming.
### Batch 2 — Authentication, pairing, couples model
- Read: `## Authentication and pairing flow` through `### Key Cloud Functions`.
- Verify auth files, pairing flow files, `couples` collection fields,
recovery phrase implementation.
- Cross-check `firestore.rules` for the rules described.
- Update if code diverges from doc.
### Batch 3 — E2EE model + Firestore data model
- Read: `## End-to-end encryption model` and `## Firestore data model`.
- Verify crypto files, encryption versions, collection schemas, field names.
- Check `firestore.rules` regex helpers and invariants.
- Update data model tables if collections/fields changed.
### Batch 4 — Daily question lifecycle + Cloud Functions module
- Read: `## Daily question lifecycle` and `## Cloud Functions`.
- Verify function triggers, handlers, schedules, module responsibilities.
- Cross-check `functions/src/` tree.
- Update if functions were added/removed/renamed.
### Batch 5 — Firestore security rules
- Read: `## Firestore security rules`.
- Line-by-line verify against `firestore.rules`.
- Note any rules in the file not documented, or documented rules not in file.
### Batch 6 — Billing + Notifications
- Read: `## Billing` and `## Notifications`.
- Verify RevenueCat integration files, entitlement checks, webhook handler.
- Verify notification classes, quiet hours, deep-link routing.
- Update for quiet-hours server-side suppression if doc still says local-only.
### Batch 7 — iOS-specific + Build and release
- Read: `## iOS-specific notes` and `## Build and release`.
- Verify iOS project state (is it still broken? still exists?).
- Verify build commands, secrets, ProGuard, Functions deploy commands.
- Update stale commands or iOS status.
### Batch 8 — Known landmines and recent fixes (cross-cutting)
- Read: `## Known landmines and recent fixes`.
- Verify each listed issue ID and fix matches git history and current code.
- Add any missing recent landmines (e.g., theme scanner, quiet hours server-side).
- Prune obsolete entries.
### Batch 9 — Final review, TOC update, formatting
- Update `## Table of Contents` if headings changed.
- Run markdown lint / build check if applicable.
- Final pass for consistency.
## Status tracking
| Batch | Status | Findings | Changes made |
|---|---|---|---|
| 1 | ✅ done | `core/feature/` note inaccurate (dir doesn't exist); `data/questions/` listed `QuestionDao` but it's in `data/local/` | Corrected `core/feature/` note; moved `QuestionDao` to `data/local/`; kept `QuestionJsonParser` in `data/questions/`; updated older-description note. |
| 2 | ✅ done | No anonymous sign-in or account linking in code; Android uses legacy Google Sign-In SDK (idToken), not Credential Manager; `encryptionMigrationUsers` field does not exist | Removed anonymous auth and account-linking claims; corrected Google Sign-In description; removed `encryptionMigrationUsers` from couples model and added note that `encryptionVersion` is always `2`. |
| 3 | ✅ done | `/users/{uid}` model missing `sex`, `partnerId`, `plan`, `lastActiveAt`, notification prefs, quiet-hours, `fcmToken`; `hasPremium` is not a real root field (premium lives in `/entitlements/premium`); `/couples/{coupleId}` listed non-existent `encryptionMigrationUsers`; date plan fields wrong; date plan preference fields wrong; bucket list fields wrong; missing `/answers/{userId}/secure/{doc}` for schemaVersion 2 | Updated `/users/{uid}` to full allowlist; removed `hasPremium` root field and added note about `/entitlements/premium`; removed `encryptionMigrationUsers`; corrected date plan, preference, and bucket list fields; added `secure` subdoc to daily-question model. |
| 4 | ✅ done | Handler table missing functions (`syncEntitlement`, `sendDailyQuestionProactiveReminder`, `sendReengagementReminder`, `sendChallengeDayReminders`, `unlockDueMemoryCapsules`, `sendGentleReminderCallable`, `onEntitlementChanged`, `onAnswerRevealed`, `onCoupleLeave`, `leaveCoupleCallable`, `submitOutcomeCallable`, `scheduledOutcomesReminder`, `onGamePartFinished`, `notifyOnDateMatch`); still listed removed `health` endpoint and old name `createDateMatchOnMutualLove`; webhook section said 200-ack-before-process (now process-before-ack); `scheduledOutcomesReminder` timezone wrong | Removed `health`; added all current functions and corrected `notifyOnDateMatch`; updated module responsibilities; corrected webhook to process-before-ack with 500-on-failure; fixed schedule timezones (only `assignDailyQuestion`, `sendDailyQuestionProactiveReminder`, `sendReengagementReminder` use `America/Chicago`). |
| 5 | ✅ done | `users/{uid}` section still described non-existent `hasPremium` root field; `couples/{coupleId}` section said all client writes denied (create is shape-restricted but possible); helper paragraph listed non-existent `isStartingEncryptionMigration`/`isCompletingOwnEncryptionMigration` | Updated `users/{uid}` to clarify `plan` is client-written and premium lives in `/entitlements/premium`; corrected couples create/update description; removed migration-helper references. |
| 6 | ✅ done | Billing Webhook flow still said "ack 200 then process" (process-before-ack was fixed in Batch 4 but Billing section had stale duplicate); missing `CouplePremiumChecker`; Notifications said quiet-hours server-side suppression not implemented (it is, via `recipientInQuietHours`); Notifications said `notification_queue` reads denied for clients (Android reads it for Together feed); `onEntitlementChanged` handler table description said it mirrors `plan` (it notifies partner instead) | Updated Billing webhook flow; added `CouplePremiumChecker` note; corrected quiet-hours to server-side-implemented; corrected `notification_queue` read claim; fixed `onEntitlementChanged` description. |
| 7 | ✅ done | iOS E2EE gap paragraph said iOS create invite writes an invite with null E2EE fields (server now rejects empty data, so no invite is created); ProGuard section claimed Tink reflection paths are kept (they are not in current rules) | Updated iOS create-invite consequence to "rejected by server"; clarified ProGuard does not currently keep Tink. |
| 8 | ✅ done | Theme landmine entry said C-ART-EDGE-002 still open (R13 fixed it); missing the mandatory `theme-scan.sh` Pass C pre-check | Updated theme landmine to mark C-ART-EDGE-002 closed and document `scripts/theme-scan.sh` as mandatory pre-check. |
| 9 | ✅ done | TOC incorrectly nested `Premium-gated features` under Notifications; broken anchor `[iOS E2EE gap](#ios-e2ee-gap)`; Repository layout still claimed iOS creates v0 couples | Removed misplaced TOC nesting; fixed broken anchor; corrected iOS Repository layout claim to "pairing fails". |
## Notes
- If a section is found to be mostly correct, still spot-check a few claims.
- If a section is wildly out of date, rewrite it and note the divergence.
- Commit after each batch (per Git Discipline Rules).