Closer/ClaudeReport.md

4.9 KiB
Raw Blame 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).