From e907453f3f67dffc22ced18733bbf16c05bb1793 Mon Sep 17 00:00:00 2001 From: null Date: Wed, 24 Jun 2026 21:37:26 -0500 Subject: [PATCH] =?UTF-8?q?docs(plan):=20add=20Part=202=20(build=20iOS=20t?= =?UTF-8?q?o=20parity)=20+=20Part=203=20(iOS=20QA)=20=E2=80=94=20ClaudeiOS?= =?UTF-8?q?Plan.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Program now Part1 Android QA -> Part2 iOS build -> Part3 iOS QA + cross-platform. iOS = native SwiftUI (iphone/ scaffold, audit stale at v0.2.0). Decisions: full Tink-compatible E2EE (Android<->iOS decrypt), working-parity build (no App Store). Hard constraint: iOS build/run/QA needs macOS (not this Linux box) — Linux = author Swift + refresh audit only; compile/run/QA deferred to a Mac. Co-Authored-By: Claude Opus 4.8 --- ClaudeQAPlan.md | 4 ++ ClaudeiOSPlan.md | 103 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 ClaudeiOSPlan.md diff --git a/ClaudeQAPlan.md b/ClaudeQAPlan.md index ab2ea170..a063c3af 100644 --- a/ClaudeQAPlan.md +++ b/ClaudeQAPlan.md @@ -3,6 +3,10 @@ > Reusable QA plan for the Closer app. Run report-only first, fix everything, then re-QA until a clean round. > Progress/state is tracked in **ClaudeReport.md** (issues) + **ClaudeQACoverage.md** (coverage matrix), which are > the authoritative source of truth. See the Continuity section before resuming. +> +> **Program roadmap:** **Part 1** = Android QA (this doc) → **Part 2** = build the iOS app to Android's current +> parity → **Part 3** = run these same passes on iOS + a cross-platform (Android↔iOS) pass. **Parts 2 & 3 live in +> `ClaudeiOSPlan.md`** (note: iOS build/run/QA requires macOS — not possible from this Linux box). ## Context Drive the real app on both emulators, verify each thing live, report, fix, re-verify. Five QA dimensions: diff --git a/ClaudeiOSPlan.md b/ClaudeiOSPlan.md new file mode 100644 index 00000000..351b0c5c --- /dev/null +++ b/ClaudeiOSPlan.md @@ -0,0 +1,103 @@ +# Claude iOS Plan — Part 2 (build to parity) + Part 3 (iOS QA) + +> Program: **Part 1** = Android QA (`ClaudeQAPlan.md`, in progress) → **Part 2** = build the iOS app to Android's +> CURRENT state → **Part 3** = run the same QA passes on iOS. This doc covers Parts 2 & 3. + +## Decisions (locked) +- **Approach:** native **SwiftUI** + Firebase iOS SDK (the `iphone/` scaffold already chose this: SwiftPM + XcodeGen, + feature dirs mirroring Android, `ARCHITECTURE_AUDIT.md`). Do NOT switch to KMP/Compose-MP. +- **E2EE:** **full Tink-compatible** crypto — iOS must byte-match Android's wire formats so an **iOS↔Android couple + decrypts each other**. (Overrides the audit's "skip E2EE for MVP" note — encryption is the cornerstone.) +- **Scope:** **working parity build** (Simulator + real device, TestFlight optional). **No App Store submission.** + +## ⚠️ Hard constraint — macOS required (we are on Linux) +iOS build/run/QA needs **macOS + Xcode + iOS Simulator**; there is **no adb-equivalent from Linux**. Therefore: +- **On this Linux box** I can only: author/refresh Swift source, refresh the audit, write the plan/specs, and reason + about the code. **I cannot compile, run the Simulator, or do interactive/visual QA here.** +- **Everything that requires building or running is deferred to a Mac** (a Mac, cloud-Mac, or macOS CI runner). +- Part 2 done-on-Linux = "code authored + self-reviewed"; Part 2 *truly* done = builds green in Xcode and runs on + Simulator + device (on a Mac). **Part 3 (iOS QA) is entirely macOS-gated.** + +## Current iOS state (as found) +`iphone/` = scaffold only: ~19 stub Swift files, `Crypto/` **empty**, most feature dirs empty, one `FirestoreService`. +`ARCHITECTURE_AUDIT.md` is thorough but generated from Android **v0.2.0** — it **predates** Messages/conversations, +chat media (photo/GIF/sticker/voice), reactions/typing/read-receipts/pagination, and couple-shared premium (A-001). +So this is a near-full build, not a top-up. + +--- + +## Part 2 — Build iOS to current Android parity + +### 2.0 Refresh the audit to CURRENT Android (do first) +Update `iphone/ARCHITECTURE_AUDIT.md` from the live Android code: add the **Messages** tab (conversations inbox + +conversation chat: text/photo/GIF/sticker/voice, reactions, delete/tombstone, typing, read-receipts, pagination, +chat-head bubble), the conversations Firestore model, the new notification types, and **couple-shared premium** +(`CouplePremiumChecker` — either partner premium unlocks all features for both). Re-tally screens/models/functions. + +### 2.1 Project + dependencies (Mac) +XcodeGen/`project.yml`; SPM: Firebase Auth/Firestore/Functions/Messaging/Storage, RevenueCat (`purchases-ios`), +GoogleSignIn; `GoogleService-Info.plist`; entitlements (push, keychain); **App Check** via DeviceCheck/App Attest +(Android uses Play Integrity); APNs setup for FCM. + +### 2.2 Core infrastructure +`AppDependencies` (manual DI), `AuthService` + `AuthRateLimiter` (mirror Android limits), `FirestoreService` + +per-domain services (User/Couple/Invite/Question/Answer/Game/Date/Conversation), `NotificationService` +(APNs+FCM + deep-link routing mirroring `PartnerNotificationType`), navigation (TabView + NavigationStack per tab, +`AppRoute` mirror, deep-link handler), `CloserTheme` (light+dark), reusable components. + +### 2.3 E2EE — full Tink-compatible crypto (HIGHEST RISK; cornerstone) +Implement byte-compatible Swift crypto for every Android wire format: +- `SealedAnswerEncryptor` (AES-256-GCM, 96-bit IV, AAD `"{coupleId}|{questionId}|{userId}"`, `sealed:v1:`), + `FieldEncryptor` (`enc:v1:`, AAD=coupleId) — used by messages/previews/dates, + `AnswerCommitment` (SHA-256, `sha256:`), `UserKeyManager` (ECIES P-256 HKDF-HMAC-SHA256 AES128-CTR-HMAC, keypair in + Keychain, `pub:v1:`), `ReleaseKeyEncryptor` (`keybox:v1:`), `RecoveryKeyManager` (**Argon2id m=46MiB, t=3, p=1**, + BIP39-style wordlist), `CoupleEncryptionManager`, Keychain-backed key stores. +- **Interop test harness (the acceptance gate):** (a) decrypt Android-produced fixtures (`sealed:v1:`/`enc:v1:`/ + `keybox:v1:`) on iOS; (b) have Android decrypt iOS-produced ciphertext; (c) verify an Android-generated recovery + phrase unlocks on iOS and vice versa. Wire formats must match byte-for-byte. If a format can't be matched with + CryptoKit, use a vetted Swift lib (e.g. swift-sodium/SwiftArgon2) — never a non-interoperable shortcut. + +### 2.4 Screens & features to parity (~48 + new messaging) +All routes from the refreshed audit's screen map, **including the NEW Messages experience** (inbox + conversation +with full media/reactions/typing/read-receipts/pagination) and the games (full, not stubs), dates, wheel, settings, +paywall. Mirror the Android UX + the couple-shared premium gating (route gated features through the iOS +`EntitlementChecker` couple-shared equivalent). + +### 2.5 Build & smoke (Mac) +Xcode build green; run on Simulator + a real device; smoke each major flow (auth → pair → home/today/play/messages/ +settings) with no crashes. **This step + 2.1/2.5 runs on a Mac.** + +--- + +## Part 3 — iOS QA (reuse `ClaudeQAPlan.md` passes A–E on iOS) +Same methodology, severity scale (P0–P3), report-only→fix→re-QA-until-flawless loop, continuity (use +`ClaudeReport-iOS.md` + `ClaudeQACoverage-iOS.md` + run-state header), and **autonomous run-to-completion** mode. +**macOS-gated.** Tooling adaptation from Android: + +| Android (Part 1) | iOS (Part 3) | +|---|---| +| `adb` install/tap/screencap | `xcrun simctl` install/io screenshot; XCUITest or `idb` to drive taps | +| 2 emulators (5554/5556) | 2 iOS Simulators (or Simulator + device) for the two partners | +| `adb logcat` FATAL/ANR | `xcrun simctl spawn booted log stream` / Console crash logs | +| `cmd uimode night` for theme | Simulator Appearance (light/dark) per device | +| premium toggle via `set_premium.js` | same admin script (server-side) | + +Run all passes on iOS: +- **A** couple-shared premium (gates + paywall), **B** each game one full playthrough on both, **C** visual + light+dark all screens + navigation-from-every-entry + back-stack/double-back, **D** security/encryption, **E** + notifications (APNs/FCM delivery + tap-to-open every type). +- **NEW — cross-platform pass (X):** a **mixed couple (Android + iOS)** — messaging, answers, dates, premium, and + notifications work cross-platform, and **E2EE decrypts both ways** (the Part 2 interop gate, verified live on real + paired devices). This is the make-or-break for the cornerstone. + +## Definition of done +- **Part 2:** iOS builds green + runs on Simulator + device at feature parity with current Android; E2EE interop + harness passes (Android↔iOS decrypt both ways). +- **Part 3:** an iOS QA round is flawless (zero P0–P2, D+E clean, every game fully played, nav/back verified) AND the + cross-platform pass X is clean. + +## What can proceed now (Linux) vs needs a Mac +- **Now (Linux):** 2.0 audit refresh; author Swift for models/services/crypto/screens; write iOS QA tooling scripts; + prepare Android-produced crypto fixtures for the interop harness. +- **Needs a Mac:** 2.1 project/deps, all compiling, 2.5 build+run, and **all of Part 3**. Surface this as the blocker + when execution reaches it (per the autonomous-mode rule: do all non-gated work first, then flag the Mac requirement).