docs(manual): Batch 5 — correct Firestore rules per-collection notes (users premium, couples create/update shape, remove migration helpers)
This commit is contained in:
parent
d19f0f8eb8
commit
74e46761f2
|
|
@ -78,8 +78,8 @@ collection name, and architectural fact. Never assume.
|
|||
| 1 | ✅ done | `core/feature/` note inaccurate (dir doesn't exist); `data/questions/` listed `QuestionDao` but it's in `data/local/` | Corrected `core/feature/` note; moved `QuestionDao` to `data/local/`; kept `QuestionJsonParser` in `data/questions/`; updated older-description note. |
|
||||
| 2 | ✅ done | No anonymous sign-in or account linking in code; Android uses legacy Google Sign-In SDK (idToken), not Credential Manager; `encryptionMigrationUsers` field does not exist | Removed anonymous auth and account-linking claims; corrected Google Sign-In description; removed `encryptionMigrationUsers` from couples model and added note that `encryptionVersion` is always `2`. |
|
||||
| 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 | in progress | | |
|
||||
| 5 | todo | | |
|
||||
| 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 | in progress | | |
|
||||
| 6 | todo | | |
|
||||
| 7 | todo | | |
|
||||
| 8 | todo | | |
|
||||
|
|
|
|||
|
|
@ -715,13 +715,13 @@ isUpdatingCoupleRhythm() only streakCount/lastAnsweredAt
|
|||
|
||||
### Per-collection enforcement
|
||||
|
||||
**`users/{uid}`** — owner can read/create/update their own doc but `hasPremium` is server-only. `entitlements/`, `notification_queue/`, and `outcomes/` are server-only writes; `entitlements/` is also readable by the user's current couple partner (couple-shared premium; see [Couple-shared premium](#couple-shared-premium)), and `notification_queue/` is readable by the owner for the in-app activity feed (the owner can flip the `read` flag). `fcmTokens/` and `devices/` are owner-writable. The `devices/` public key is readable by the user's current couple partner only (to wrap release keys) — restricting it prevents speculative pre-encryption by non-partners.
|
||||
**`users/{uid}`** — owner can read/create/update their own doc. Root-level premium state is **not** stored here; the client-writable `plan` field is informational only, and authoritative premium state lives in the server-only `entitlements/premium` subdoc. `entitlements/`, `notification_queue/`, and `outcomes/` are server-only writes; `entitlements/` is also readable by the user's current couple partner (couple-shared premium; see [Couple-shared premium](#couple-shared-premium)), and `notification_queue/` is readable by the owner for the in-app activity feed (the owner can flip the `read` flag). `fcmTokens/` and `devices/` are owner-writable; the `devices/` public key is readable by the user's current couple partner only (to wrap release keys). Quiet-hours fields (`quietHoursEnabled`, `quietHoursStartMinutes`, `quietHoursEndMinutes`, `timezone`) and notification preferences (`notifPartnerAnswered`, `notifChatMessage`) are client-writable so Cloud Functions can honor them server-side.
|
||||
|
||||
**`date_ideas/`** — read-only for any signed-in user; writes are admin-only.
|
||||
|
||||
**`invites/{code}`** — reads are restricted to the inviter (`request.auth.uid == resource.data.inviterUserId`). All writes are denied for clients. This is the core defense against 6-character code enumeration: even legitimate create/update/delete must go through a Cloud Function, which can enforce rate limits, uniqueness, and key-material checks.
|
||||
|
||||
**`couples/{coupleId}`** — only the two members may read. Writes are denied for clients entirely; the rules restrict the shape of the doc and let Cloud Functions do all updates. Field-level immutability helpers (`isUpdatingCoupleRhythm`, `isUpdatingRecoveryWrap`, `isStartingEncryptionMigration`, `isCompletingOwnEncryptionMigration`) define what each update path is allowed to touch.
|
||||
**`couples/{coupleId}`** — only the two members may read. Direct client `create` is possible only if the document exactly matches the server-created shape (all required fields including `encryptionVersion == 2` and valid E2EE key material); in practice `acceptInviteCallable` creates the doc. `update` is limited to the rhythm/recovery-wrap field sets via `isUpdatingCoupleRhythm()` or `isUpdatingRecoveryWrap()`; everything else is server-only. `delete` is denied for clients. Field-level immutability helpers (`isUpdatingCoupleRhythm`, `isUpdatingRecoveryWrap`) define what each update path may touch. There is no encryption-migration path in the current rules.
|
||||
|
||||
**`couples/{coupleId}/daily_question/...`** — server-only writes. Daily-question assignment and answer-related subcollections are tightly constrained.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue