From eb78b920a4c83c6a2e1fc5242429b46cde9e115f Mon Sep 17 00:00:00 2001 From: null Date: Sun, 28 Jun 2026 11:12:15 -0500 Subject: [PATCH] =?UTF-8?q?docs(manual):=20Batch=207=20=E2=80=94=20correct?= =?UTF-8?q?=20iOS=20E2EE=20gap=20details=20and=20ProGuard=20description?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Engineering_Reference_Manual_Plan.md | 4 ++-- docs/Engineering_Reference_Manual.md | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Engineering_Reference_Manual_Plan.md b/Engineering_Reference_Manual_Plan.md index d482c501..478746da 100644 --- a/Engineering_Reference_Manual_Plan.md +++ b/Engineering_Reference_Manual_Plan.md @@ -80,8 +80,8 @@ collection name, and architectural fact. Never assume. | 3 | ✅ done | `/users/{uid}` model missing `sex`, `partnerId`, `plan`, `lastActiveAt`, notification prefs, quiet-hours, `fcmToken`; `hasPremium` is not a real root field (premium lives in `/entitlements/premium`); `/couples/{coupleId}` listed non-existent `encryptionMigrationUsers`; date plan fields wrong; date plan preference fields wrong; bucket list fields wrong; missing `/answers/{userId}/secure/{doc}` for schemaVersion 2 | Updated `/users/{uid}` to full allowlist; removed `hasPremium` root field and added note about `/entitlements/premium`; removed `encryptionMigrationUsers`; corrected date plan, preference, and bucket list fields; added `secure` subdoc to daily-question model. | | 4 | ✅ done | Handler table missing functions (`syncEntitlement`, `sendDailyQuestionProactiveReminder`, `sendReengagementReminder`, `sendChallengeDayReminders`, `unlockDueMemoryCapsules`, `sendGentleReminderCallable`, `onEntitlementChanged`, `onAnswerRevealed`, `onCoupleLeave`, `leaveCoupleCallable`, `submitOutcomeCallable`, `scheduledOutcomesReminder`, `onGamePartFinished`, `notifyOnDateMatch`); still listed removed `health` endpoint and old name `createDateMatchOnMutualLove`; webhook section said 200-ack-before-process (now process-before-ack); `scheduledOutcomesReminder` timezone wrong | Removed `health`; added all current functions and corrected `notifyOnDateMatch`; updated module responsibilities; corrected webhook to process-before-ack with 500-on-failure; fixed schedule timezones (only `assignDailyQuestion`, `sendDailyQuestionProactiveReminder`, `sendReengagementReminder` use `America/Chicago`). | | 5 | ✅ done | `users/{uid}` section still described non-existent `hasPremium` root field; `couples/{coupleId}` section said all client writes denied (create is shape-restricted but possible); helper paragraph listed non-existent `isStartingEncryptionMigration`/`isCompletingOwnEncryptionMigration` | Updated `users/{uid}` to clarify `plan` is client-written and premium lives in `/entitlements/premium`; corrected couples create/update description; removed migration-helper references. | -| 6 | in_progress | | | -| 7 | todo | | | +| 6 | ✅ done | Billing Webhook flow still said "ack 200 then process" (process-before-ack was fixed in Batch 4 but Billing section had stale duplicate); missing `CouplePremiumChecker`; Notifications said quiet-hours server-side suppression not implemented (it is, via `recipientInQuietHours`); Notifications said `notification_queue` reads denied for clients (Android reads it for Together feed); `onEntitlementChanged` handler table description said it mirrors `plan` (it notifies partner instead) | Updated Billing webhook flow; added `CouplePremiumChecker` note; corrected quiet-hours to server-side-implemented; corrected `notification_queue` read claim; fixed `onEntitlementChanged` description. | +| 7 | in_progress | | | | 8 | todo | | | | 9 | todo | | | diff --git a/docs/Engineering_Reference_Manual.md b/docs/Engineering_Reference_Manual.md index 69ff2435..25b700b4 100644 --- a/docs/Engineering_Reference_Manual.md +++ b/docs/Engineering_Reference_Manual.md @@ -994,14 +994,14 @@ xcodebuild -project iphone/Closer.xcodeproj \ The iOS port does not implement E2EE. **More importantly, this means iOS cannot complete pairing today:** -- `createInviteCallable` (iOS caller passes `[:]` as data) writes an invite with **no** `wrappedCoupleKey` / `kdfSalt` / `kdfParams` / `recoveryPhrase` fields. +- `createInviteCallable` (iOS caller passes `[:]` as data) is rejected by the server because the code and E2EE fields (`wrappedCoupleKey`, `kdfSalt`, `kdfParams`, `encryptedRecoveryPhrase`) are required. No invite is created. - `acceptInviteCallable` then **throws** `failed-precondition: "Invite is missing encryption material"` when an iOS user tries to accept any invite (Android or iOS) because those fields are required (`if (wrappedCoupleKey == null || kdfSalt == null || kdfParams == null) throw ...`). - The Firestore rules also reject any client-side attempt to write a couple with `encryptionVersion != 2` or without all four E2EE fields. So there is no fallback client-write path either. Concrete consequences if someone tries to pair from iOS: -- An iOS user trying to create an invite gets a code that nobody can accept (server rejects on accept). -- An iOS user trying to accept an Android invite gets `failed-precondition` from `acceptInviteCallable`. +- An iOS user trying to create an invite gets an `invalid-argument` error from `createInviteCallable`; no invite is created. +- An iOS user trying to accept an Android invite gets `failed-precondition` from `acceptInviteCallable` because the invite document is missing encryption material. - There is no v0 / PLAINTEXT couple creation path in the codebase. The `EncryptionVersion.kt` constants file defines only `STRICT = 2`. `acceptInviteCallable` hardcodes `encryptionVersion = 2`. Rules require `encryptionVersion == 2`. **State of iOS today**: the iOS app builds, signs in, and renders UI, but pairing is non-functional. Do not ship iOS to users until one of these is true: @@ -1062,7 +1062,7 @@ When implementing iOS E2EE parity: ### ProGuard -`app/proguard-rules.pro` keeps Tink reflection paths and other crypto classes. Release builds run `minifyEnabled = true` and `shrinkResources = true`. Always smoke-test a release build before publishing — ProGuard rules for new libraries are easy to forget. +`app/proguard-rules.pro` keeps Firebase, Hilt, Room, domain models, RevenueCat, Kotlin metadata, and BuildConfig. Release builds run `minifyEnabled = true` and `shrinkResources = true`. Tink is **not** explicitly kept in the current rules; add `-keep` rules if reflection-based Tink paths start breaking in release builds. Always smoke-test a release build before publishing — ProGuard rules for new libraries are easy to forget. ### Common commands