62 lines
5.1 KiB
Markdown
62 lines
5.1 KiB
Markdown
# Future — ideas & improvements backlog
|
|
|
|
Non-blocking ideas: things that work today but could be better, plus feature ideas. Actual bugs
|
|
(broken/incorrect behavior) live in `ClaudeReport.md`, not here.
|
|
|
|
## QA
|
|
|
|
Improvement & feature ideas surfaced while QA-testing as a consumer (each works today — none are defects).
|
|
|
|
- **Consistent brand glyphs across game cards + waiting/notification surfaces.** _(Blocked: needs the
|
|
generated G-set art — image generation is the user's step per `ClaudeBrandingReview.md`.)_ Game cards
|
|
(Play hub), the WaitingForPartner screen, and notifications mix Material icons with brand art. A small
|
|
custom glyph set (the C-heart-keyhole mark, paired/sealed card, daily card, capsule, date-card,
|
|
quiet-hours moon) used consistently would strengthen identity. Generate the G-set, drop the assets in,
|
|
then wire them in. *Prompted by:* Pass H branding review.
|
|
|
|
- **Notify the free partner when the couple gains premium.** When one partner subscribes, the other's app unlocks
|
|
(couple-shared premium) but they get **no notification** — they only find out next time they open a gated feature. A
|
|
`subscription_entitlement_changed` push ("You both have Premium now ✨") would close the loop. *Prompted by:* Pass E
|
|
(R8): the type isn't implemented; couple-shared unlock is silent for the non-subscriber.
|
|
- **Minor proactive-notification gaps (low priority).** No push when a partner *joins* your active game
|
|
(`partner_joined_game`) or *ends/abandons* one (`game_ended`/`game_abandoned`) — the other partner sees it
|
|
in-session / on WaitingForPartner, so nothing's broken, just less proactive. *Prompted by:* Pass E (R8) inventory —
|
|
these speculative types aren't implemented.
|
|
- **Retry the daily-reveal `isRevealed` write so the "partner opened" push is never silently lost.**
|
|
`performCoupleKeyReveal` sets local Room `markRevealed` *then* the Firestore `markRevealed` (best-effort,
|
|
`runCatching`). If that Firestore write fails (offline/transient), Room is already revealed → re-opening the reveal
|
|
takes `load()`'s auto-decrypt branch (which only runs when local `isRevealed==true`) and **never retries** the
|
|
Firestore write, so `onAnswerRevealed` never fires and the partner never gets the "opened your answers" push. Normal
|
|
online flow is fine (verified live). Fix: on reveal-screen load, if local says revealed but the server doc's
|
|
`isRevealed` is still false, re-issue `markRevealed`. *Prompted by:* daily-reveal QA (2026-06-26) — low severity
|
|
(content reveal unaffected; only the courtesy push on a write-failure edge).
|
|
|
|
- **Clarify Connection Challenges day-progress when partners are out of step.** If one partner catches up a *missed* day ("Pick it back up") while the other doesn't, the two devices show different **"Day N of 7"** (seen R10: QA Day 4 vs Sam Day 3) even though the 🔥 streak stays in sync on both. Not broken (plausibly individual-pace-through-the-series by design), but two people in the same shared challenge seeing different day numbers is confusing — consider a shared "you're on Day N together" framing or a clearer caught-up/ahead indicator. *Prompted by:* Pass B (R10) Connection Challenges playthrough.
|
|
|
|
### Security hardening (defense-in-depth — not vulnerabilities; rules already hold)
|
|
|
|
- **Enforce App Check on Firestore (currently OFF).** Round 7 raw-API test: an authenticated request with **no App
|
|
Check token** (raw Firestore REST) returned `200` for a member — so rules are the *sole* gate. Rules correctly deny
|
|
non-members/cross-couple (all `403`), so this is not a live hole, but enabling App Check enforcement on Firestore
|
|
would block non-app clients entirely (defense-in-depth). *Prompted by:* R7 D3 raw-API angle.
|
|
- **Tighten the `users/{uid}` update rule to a field allowlist.** The rule only blocks changing `hasPremium`; a user
|
|
can write arbitrary *other* fields to their own doc (e.g. a cosmetic `plan`/junk). No gate reads those (premium gates
|
|
on the server-only `users/{uid}/entitlements/premium` subcollection + `category.access`), so it grants nothing — but
|
|
restricting updates to a known field set is cleaner. *Prompted by:* R7 D3 (`plan` field writable, unused by gating).
|
|
|
|
> Artwork to generate (ChatGPT prompts, house-style-matched) lives in `ClaudeBrandingReview.md`, not here.
|
|
|
|
<!--
|
|
Completed (2026-06-25) and removed from the backlog:
|
|
- Inclusive sex/gender options in onboarding (Female/Male/Non-binary/Prefer not to say) + honest copy
|
|
(Desire Sync is already gender-neutral, so no tailoring fallback was needed).
|
|
- Turn-aware Home "waiting to play" copy ("Your turn to play.").
|
|
- Partner-action/results pushes exempt from the weekly promotional rate-limit ceiling.
|
|
- Suppress the redundant results / "partner finished" push when the recipient is already on that
|
|
game's screen (new ActiveGameSessionMonitor mirroring ActiveThreadMonitor).
|
|
- Friendlier paywall error state: retry-with-backoff, offline-aware message, Continue hidden until plans load.
|
|
- Wire iOS illustrations into Android empty states — already wired (history, invite, daily-question,
|
|
together-empty, partner-activation all show their illustration).
|
|
- Rotating privacy messages on sign-up + forgot-password (login already had it).
|
|
-->
|