2026-06-24 21:37:26 -05:00
|
|
|
|
# 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.
|
docs(qa): senior-QA review additions — Pass F, env/matrix, migration, iOS-native dims
- Pass F (cross-cutting): concurrency/realtime races, lifecycle/process-death, network
resilience, idempotency/rapid-input, time-dependent (daily rollover/streaks/capsules),
account/couple lifecycle, crash reporting.
- Methodology: prefer Firebase emulator/staging over prod; device/OS matrix; automate the
smoke; test-data hygiene.
- Pass D7: encryptionVersion 0->1->2 migration. Reporting/re-QA now A-F.
- iOS: iOS-native QA dims (Dynamic Type/VoiceOver/safe-area/edge-swipe-back/sizes),
real-device/sandbox needs (App Attest/APNs/StoreKit), crypto golden vectors.
- Logged D-OBS: PERMISSION_DENIED on outcomes/challenges/capsules to investigate in Round 2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 21:44:02 -05:00
|
|
|
|
- **Golden vectors** for the deterministic primitives (checked into both repos): `AnswerCommitment` SHA-256 and
|
|
|
|
|
|
`RecoveryKeyManager` Argon2id (fixed salt/params) must produce **identical bytes** on both platforms — assert in unit
|
|
|
|
|
|
tests on each side. AEAD/ECIES use random IVs so they can't be golden-matched; cover those with the **round-trip**
|
|
|
|
|
|
harness above. Generate the Android fixtures now (on Linux) so iOS has them ready.
|
2026-06-24 21:37:26 -05:00
|
|
|
|
|
|
|
|
|
|
### 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.
|
docs(qa): senior-QA review additions — Pass F, env/matrix, migration, iOS-native dims
- Pass F (cross-cutting): concurrency/realtime races, lifecycle/process-death, network
resilience, idempotency/rapid-input, time-dependent (daily rollover/streaks/capsules),
account/couple lifecycle, crash reporting.
- Methodology: prefer Firebase emulator/staging over prod; device/OS matrix; automate the
smoke; test-data hygiene.
- Pass D7: encryptionVersion 0->1->2 migration. Reporting/re-QA now A-F.
- iOS: iOS-native QA dims (Dynamic Type/VoiceOver/safe-area/edge-swipe-back/sizes),
real-device/sandbox needs (App Attest/APNs/StoreKit), crypto golden vectors.
- Logged D-OBS: PERMISSION_DENIED on outcomes/challenges/capsules to investigate in Round 2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 21:44:02 -05:00
|
|
|
|
- **iOS-native dimensions (add to the passes):** Dynamic Type (largest sizes), **VoiceOver**, safe-area / notch /
|
|
|
|
|
|
Dynamic Island, multiple device sizes (SE → Pro Max; iPad if supported), **edge-swipe-back gesture** + interactive
|
|
|
|
|
|
pop (the iOS "double-back"/nav-stack analog), `scenePhase` background/foreground, dark/light.
|
|
|
|
|
|
- **Real-device / sandbox needs:** **App Attest/DeviceCheck** and **APNs push** don't fully work on the Simulator —
|
|
|
|
|
|
use a real device (or `xcrun simctl push` with a payload for local notif routing); **RevenueCat IAP** needs a
|
|
|
|
|
|
StoreKit config file or a sandbox Apple ID. Plan Pass A/E around this.
|
2026-06-24 21:37:26 -05:00
|
|
|
|
|
|
|
|
|
|
## 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).
|