Closer/ClaudeReport.md

49 lines
4.9 KiB
Markdown
Raw Normal View History

# Claude QA Report — Full-App QA (living report)
> **Verdict (2026-06-25): 0 open issues at every severity (P0P3). Security cornerstone fully clean. App is at the "flawless" bar.**
>
> This report shows **current state only**. Fixed issues live here for **one** confirmation round, then they're pruned
> to the archived-ID line below (full detail stays in git history). See **Report hygiene** in `ClaudeQAPlan.md`.
## Run-state (current)
`Round 7 (multi-angle deep dive) — COMPLETE | 0 open P0P3 | NEXT ACTION: Round 8 re-QA — confirm F-RACE-001, then prune it; run Passes I/J live.`
- **Build:** client HEAD `23dd6a7` (includes the F-RACE-001 fix, verified live), Cloud Functions deployed.
- **Devices / accounts:** emulator-5554 = QA (`Y05AKO2IlTPMa0JQW1BiNIM0uzK2`) · emulator-5556 = Sam (`imDjjO…`) · paired, coupleId `Xal3Kw3gjSdn0niERYKJ`, both free (baseline restored).
- **Docs:** Playbook `ClaudeQAPlan.md` · Coverage `ClaudeQACoverage.md` · Ideas `Future.md` `## QA` · Branding `ClaudeBrandingReview.md`.
## Severity board
| Severity | Open | Fixed (pending 1 confirm) |
|---|---|---|
| P0 | 0 | 0 |
| P1 | 0 | 1 (F-RACE-001) |
| P2 | 0 | 0 |
| P3 | 0 | 0 |
## Open issues
**None.**
## Fixed this round — pending one confirmation round (then prune)
| ID | Severity | Area | Description | Fix | Status |
|---|---|---|---|---|---|
| F-RACE-001 | P1 | Games / concurrency | Both partners starting the *same* game within ~1s created **2 divergent active sessions** (different question sets) → no shared reveal; core loop silently defeated. Non-transactional check-then-create in `GameSessionManager.startGameWithCouple`. | Atomic Firestore transaction on a per-couple pointer `couples/{cid}/sessions/_active` (`startSessionAtomically`): reads pointer → `AlreadyActive`→join, else atomically sets session + re-points lock. All 7 games funnel through it. Member-writable `sessions/_active` rule deployed. Files: `QuestionSessionRepository[Impl].kt`, `GameSessionManager.kt`, `firestore.rules`. | **Fixed + verified live (`23dd6a7`):** parallel-tap race → **1 session** (was 2); sequential 2nd start → joins; pointer self-heals on completion; 0 FATAL. **→ Round 8: re-confirm, then delete this row.** |
## Resolved & confirmed (archived — full detail in git history)
A-001 · A-003 · A-OBS · B-001 · B-002 · B-003 · B-004 · C-CC-001 · C-DS-001 · C-NAV-001 · D-001 · E-001 · E-002 · E-003 · E-OBS · F-OBS — all fixed and re-verified across Rounds 26 (commits cited in history). Pruned from the live report per the one-confirmation-round rule. (C-OBS / `outcomes` list / SubscriptionScreen per-user gate = investigated, **not bugs**.)
## Security cornerstone — clean (Pass D, deep dive, Round 7)
- **D1 at-rest:** chat text + `lastMessagePreview` + all 4 game-answer collections (ToT / How Well / Desire Sync / Wheel, both users) + Memory Lane capsules + date-swipe actions = `enc:v1:`. No plaintext content; only metadata in clear.
- **D2/D3 access:** non-member denied **all** reads/writes (raw Firestore REST → 403); real premium write `users/{uid}/entitlements/premium` denied (server-only → **no self-grant**); cross-couple denied.
- **D4 keys:** couple key phrase-wrapped (argon2id); recovery phrase server-blind; `encryptedRecoveryPhrase` wiped on acceptance; plaintext `inviteCode` not exploitable (invite readable only by inviter; no code-encrypted secret persisted).
- **Robustness:** malformed/abusive deep-link intents (unknown type, missing extras, injection/path-traversal) → 0 crash; killed-state cold-start chat deep-link → conversation loads.
## Round history (one line each)
- **R7** — multi-angle security/concurrency deep dive → cornerstone fully clean; F-RACE-001 found + fixed + verified. 0 new open.
- **R6** — branding drop + Future.md backlog regression (white-keyhole icons/loader/splash, inclusive gender, copy, rate-limit split, results-push suppression, paywall retry/offline) → 0 new open.
- **R5** — Cloud Functions deployed (E-OBS channel fix, E-003 results routing) + new Pass G (account creation / fake-account abuse) clean → 0 open.
- **R1R4** — baseline Passes AF report-only; every P0P2 found was fixed + verified (see archived IDs).
## Operational constants
- **Execution mode:** autonomous run-to-completion — don't stop; fix blockers inline; cycle fix→re-QA until flawless. Don't hand back when context fills — re-read this run-state + coverage after any compaction. Commit before interruptible work; recover stuck sessions via the session-start ritual.
- **Standing authorization (user, 2026-06-24):** may `firebase deploy --only firestore:rules` + has admin access (Firestore reads/writes/seeds + entitlement toggles) — run without pausing. Only the macOS requirement for iOS (Parts 2/3) is a hard stop.
- **Hardening backlog → Future.md:** App Check not enforced on Firestore; `users/{uid}` update rule allows arbitrary non-`hasPremium` fields (tighten to a field allowlist).