From f79b38c07c3d8af9331b82895c4e2a41cd539b74 Mon Sep 17 00:00:00 2001 From: null Date: Wed, 24 Jun 2026 23:15:23 -0500 Subject: [PATCH] qa(round2-B2): Memory Lane PASS (capsule create+seal, encrypted at rest enc:v1:, cross-device sealed view, no crash); D1 capsule ciphertext verified live --- ClaudeQACoverage.md | 2 +- ClaudeReport.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ClaudeQACoverage.md b/ClaudeQACoverage.md index 99e6e713..f683c996 100644 --- a/ClaudeQACoverage.md +++ b/ClaudeQACoverage.md @@ -28,7 +28,7 @@ superseded — redo every game cleanly. (Prior result for reference: This or Tha | 2. How Well Do You Know Me | pass | **pass (full, user-nav)** | **pass** | pass | **R2-B2: QA answered 5 (incl. a 1-5 scale Q5); Sam predicted via Play hub — 3 correct + 1 deliberate miss (Kind tone vs Specific examples) + scale match → results show 4/5 "You really know each other" with the wrong one marked ✗ on BOTH devices, scoring accurate, no crash ✅** | | 3. Desire Sync | pass | **pass (full, user-nav)** | **pass** | pass | **R2-B2: QA(free) entered w/o paywall (A-001 live ✅); both answered 5 Yes/No → exactly 3 mutual desires revealed, mismatches hidden (privacy correct), results match both, no crash ✅. Findings: B-003 (P3 confusing counts), C-DS-001 (P2 dark-mode low contrast on revealed list).** | | 4. Connection Challenges | pass | **pass (day-cycle, user-nav)** | **pass** | pass | **R2-B2: opened (D-001 rules hold ✅); started Gratitude Week → both completed Day 1 → day ✓, 🔥1 streak, advanced to Day 2 "Both of you showed up today", synced on both, no crash ✅. (7-day series is time-gated; full per-day cycle verified.) Finding: C-CC-001 (P2 duplicate header + double back). Minor: first partner's view shows next-day content + "waiting for partner" before the day is mutually done (self-resolves).** | -| 5. Memory Lane | todo | todo | todo | todo | todo (premium) | +| 5. Memory Lane | pass | **pass (create+seal, user-nav)** | **pass (sealed)** | pass | **R2-B2: loads clean (D-001 ✅, no hung heart); QA wrote a capsule (title+body), picked "1 month" → sealed "Opens in 29 days"; **encrypted at rest** (title+content `enc:v1:`, `unlockAt`=+30d, status=sealed); Sam sees the same sealed capsule cross-device; no crash / no PERMISSION_DENIED ✅. Unlock/reveal is future-dated (can't test w/o time-travel). Single header (no C-CC-001 here).** | | 6. Spin the Wheel | todo | todo | todo | todo | todo (premium) | | 7. Date Match | todo | todo | todo | todo | todo | diff --git a/ClaudeReport.md b/ClaudeReport.md index 883c5c2c..25911b2e 100644 --- a/ClaudeReport.md +++ b/ClaudeReport.md @@ -73,7 +73,7 @@ _Deep/stateful screens (answer reveal, wheel session/complete, date match/builde **Pass C requirement (added):** **navigation from every entry point** (each screen reached from all its links — e.g. conversation from inbox/Discuss/notification; game from Play/notification; paywall from each gate) + **back-stack / "double-back"** (system back AND in-app back return to the right place from each entry; no dead-ends, no exit-app surprise, **no screen needing two backs**/duplicate stack entries; deep-link/notification entries land with a sane back stack). Owed in Round 2. Wrong/double back or dead-end = P2 (P1 if it traps the user). ## Pass D — Security & Encryption ✅ clean (no P0/P1 found) -- **D1 at-rest:** all private content is ciphertext — message `text` + `lastMessagePreview` + thread messages = `enc:v1:`; daily answers `encryptedPayload` = `sealed:v1:`. Metadata (dates, types, commitmentHash, ids) plaintext as expected. Chat media bytes = Tink ciphertext (verified prior round + unchanged code path). **No plaintext content leak.** +- **D1 at-rest:** all private content is ciphertext — message `text` + `lastMessagePreview` + thread messages = `enc:v1:`; daily answers `encryptedPayload` = `sealed:v1:`; **Memory Lane capsules `title` + `content` = `enc:v1:`** (live-verified R2-B2: admin read the just-created capsule → both fields ciphertext, `status:sealed`, `unlockAt` set, only metadata plaintext). Metadata (dates, types, commitmentHash, ids) plaintext as expected. Chat media bytes = Tink ciphertext (verified prior round + unchanged code path). **No plaintext content leak.** - **D2 rules:** no catch-all `match /{document=**}`, no blanket `if true`; **`hasPremium` server-only** (client create/update blocked, rules L172/174); entitlements `write:false`; conversations/messages/typing/reactions + entitlement partner-read scoped to members. - **D4 key exchange:** pairing uses a **wrapped couple key** (`wrappedCoupleKey` + `kdfSalt`/`kdfParams` + `encryptedRecoveryPhrase`); invite code is the KDF seed, never stored raw; strict E2EE (invites without a wrapped key rejected) — confirmed in `acceptInviteCallable`. - **D5 App Check/secrets:** App Check enforced (`SecurityModule`, `PlayIntegrityChecker`, `FirebaseInitializer`); both service-account JSONs gitignored **and untracked**; `allowBackup=false`.