> Manual testing checklist for the internal MVP build. Covers every top-level flow in the app and notes known gaps discovered during the 2025-06 QA pass.
- [ ] Back navigation from auth screens returns to onboarding.
### 1.5 Known onboarding gaps (from code scan)
-`AccountScreen` shows "Local profile" and disables "Sign in or create account" and "Export your data" rows. These need real wiring before public release.
- Home header text changes based on `partnerName` presence; confirm both states render.
> `EmailInviteScreen` and the `EMAIL_INVITE` route have been deleted. Sharing is now handled entirely via the system share sheet in `CreateInviteScreen` / `CreateInviteView`. There is no separate email flow or backend email sending.
- [ ]**Android**: "Share" button on `CreateInviteScreen` opens system share sheet with invite message.
- [ ]**iOS**: "Share" button on `CreateInviteView` opens `UIActivityViewController` with the code.
- [ ] Share sheet offers SMS, email, Signal, WhatsApp, etc. — no Closer-specific channel required.
- [ ] All toggles reflect persisted `AppStorage` / DataStore state on load.
- [ ] Toggling "Partner answered" or "New chat message" writes `notifPartnerAnswered` / `notifChatMessage` to Firestore user doc (verify in Firebase console).
- [ ] Daily reminder and streak reminder toggles persist locally only (no Firestore write required).
- [ ] Dark theme colors defined but not wired to system dark mode (`isSystemInDarkTheme()` not used). Verify this is intentional for MVP.
- [ ] No stale Next.js / React Native references in resources or manifests.
### 12.4 Data / Offline
- [ ] App does not crash when offline (graceful error cards).
- [ ] Local answer repository persists data.
- [ ] Firebase calls fail cleanly and retry available where exposed.
---
## 13. Release Blockers Logged from This QA Pass
These findings came from the static review and should be fixed before public or store release. Do **not** block internal MVP on these unless explicitly required.
| 1 | Date builder | Date/time picker TODOs — fields are not interactive | High | **Not an issue** — `DatePickerDialog` and `TimeInput` are already implemented and wired |
| 2 | Special dates | Hardcoded names/dates in `SpecialDatesSection` | High | **Not an issue** — `SpecialDatesSection` is dead code, never rendered; home shows honest placeholder copy |
| 3 | Email invite | Placeholder screen with hardcoded `ABC123` code | Medium | **Fixed** — screen deleted; share sheet is the flow |
| 4 | Subscription | Placeholder screen, not real management | Medium | Open |
| 5 | Partner home | Placeholder screen only | Medium | **Fixed** — real `PartnerHomeViewModel` + screen with partner identity card, today activity status, send-nudge button, and navigation wired from HomeScreen streak card tap |
| 6 | Settings | Account rows disabled ("Auth coming soon", "Export coming soon") | Medium | **Not an issue** — `AccountScreen` no longer has those rows; only Delete account row present |
| 7 | External links | Support URL points to `couplesconnect.app/support` | Low | **Fixed** — updated to `https://closer.app/support` in `ExternalLinks.kt` |
| 8 | Strings | 100+ hardcoded display strings; should move to `strings.xml` for localization | Low | **Partial** — `strings.xml` built with 90+ entries; settings cluster (Appearance, Notifications, Account, Privacy) updated to use `stringResource()`; remaining screens (Home, Pairing, Daily Question, etc.) still hardcoded |
| 9 | Logging | `android.util.Log.e` used in `QuestionJsonParser` — confirm no verbose/debug logs in release builds | Low | **Fixed** — no sensitive data in any log; `Log.d`/`Log.v` stripped in release via `-assumenosideeffects` ProGuard rule |
| 10 | Pairing security | Direct Firestore fallback in `createInvite` bypassed server-side rules | High | **Fixed** — fallback removed; CF is the only path |
| 11 | Pairing security | No rate limiting on `acceptInviteCallable` — 6-char codes are enumerable | High | **Fixed** — 10 attempts/hour per user; `invite_attempts` TTL via Firestore field override |
| 12 | Pairing security | `recoveryPhrase` left in plaintext on invite doc post-accept | High | **Fixed** — wiped via `FieldValue.delete()` in accept batch |
| 13 | Pairing security | `encryptionVersion` hardcoded to 2 even when no E2EE fields present (iOS) | High | **Fixed** — derived from key presence: 2 if E2EE, 0 if plaintext |
| 14 | Notifications | No push sent when partner answers or sends a chat message | Medium | **Fixed** — `onAnswerWritten` gated on prefs; `onMessageWritten` CF added |
| 15 | Notifications | Notification prefs were local-only; server CFs had no way to respect them | Medium | **Fixed** — prefs synced to Firestore user doc on toggle (Android + iOS) |
| 16 | Functions | `invite_attempts` subcollection had no cleanup — would grow forever | Medium | **Fixed** — `expiresAt` TTL field added; `firestore.indexes.json` configures auto-delete |
| 17 | iOS deploy | `onMessageWritten` CF not yet deployed — iOS chat notifications not active until `firebase deploy --only functions` is run | Medium | Open — deploy required |