Skip to main content

Settings (Profile hub) — requirements

Epic. MVP-1 requirements breakdown for the settings hub (see the feature architecture). Each FR is sized to become one or a few user stories. The settings tiles are a navigation scaffold that routes members to secondary surfaces; they now live inside the Profile tab (the trailing IA slot that replaced the old More tab). Build cost is low; reachability value is high.

TypeFunctional
Layer (build approach)Frontend — nav scaffold + auto_route
RICER 8 × I 0.5 × C 100% / E 1 = 4.0 · Tier MVP-1
KPI (summary)Settings reachability; pending-item badge accuracy
Traces tofeature settings · C4 components · prioritization
Depends onAdmin · Account

Success criteria (definitive KPI)

Success = 100% of secondary surfaces reachable from Profile in ≤ 2 taps AND pending-item badge accuracy = 100% (badge count matches actual pending count) — both gates held from the first production build.

  • Metric A (reachability): each tile in the Profile hub routes to its target in exactly one tap; combined with the bottom-nav tap to reach Profile, no secondary surface requires > 2 taps from anywhere in the app. Target: 100%. Any broken route is a P1 regression (build gate, not a trend metric).
  • Metric B (badge accuracy): the pending-item badge on the Profile tab and on the Admin tile matches the live pending-approval / pending-invite count from the SDK at every render. Target: 100%. Staleness is a trust failure.
  • Baseline: no install base yet — both are structural invariants enforced at build and code-review time, not cohort thresholds. Instrument more_opened and settings_item_opened from day one to surface routing funnel drop-off.

Analytics — events to record

All events are INTERNAL BI — content-free, no child identity, never marketing (see COPPA and the consent-gated analytics substrate). isParental is a coarse session attribute of the adult account holder; it carries no child PII and is never used to target children.

EventWhenKey propertiesFeeds
more_openedProfile tab tapped (event key predates the More→Profile rename)isParental (bool, coarse)engagement denominator; nav-pattern analysis
settings_item_openedAny hub tile tappeditem (admin|appearance|accessibility|account|about|help|notifications), isParental (bool, coarse)reachability audit; feature-adoption signal

Both events ship with the surface — they are the minimum instrumentation needed to audit Metric A funnel drop-off. No child-linked properties present.

Scope

Settings are a navigation hub (not a functional surface) inside the Profile tab — the trailing IA slot that replaced the old More tab. It renders a list of secondary destinations: Admin (isParental-gated), Appearance, Accessibility, Account, About / legal, and Help & feedback; sign-out lives at the bottom of the Profile page (moved off the top header in the 2026-07-26 redesign). A pending-item badge on the Profile tab icon and on the Admin tile surfaces unactioned approvals and pending invites. Notification preferences are a stub in MVP-1; subscription / billing placement is an open decision.

Functional requirements

FR-SETTINGS-1 — Profile hub renders correct item list per persona

Priority: P1 · Status: 🔲 not built Statement. As any member, I open Profile and see a list of secondary surfaces appropriate to my role — Admin appears only when isParental = true. Acceptance

  • Given isParental = true When Profile renders Then the hub shows: Admin (badged), Appearance, Accessibility, Account, About, Help — in stable order.
  • Given isParental = false When Profile renders Then Admin is absent; all other tiles are present.
  • No tile flickers into or out of view on re-render or back-navigation.

FR-SETTINGS-2 — isParental gate on the Admin tile and route

Priority: P1 · Status: 🔲 not built (gate complements FR-ADMIN-1) Statement. As the app, I ensure a non-parental member cannot reach the Admin hub via the Profile tile or a direct deep-link route. Acceptance

  • Given isParental = false When the Admin route is attempted (tile or deep-link) Then the tile is absent and the auto_route guard redirects to Profile; no Admin content is rendered.
  • Given isParental = true When the Admin tile is tapped Then the guard passes and the Admin hub loads.
  • The guard reads isParental from MoreBloc state — no direct SDK import in the guard file.

FR-SETTINGS-3 — Pending-item badge (approval + invite count)

Priority: P1 · Status: 🔲 not built Statement. As a parental member, I see a live badge on the Profile tab and on the Admin tile showing the total count of pending approvals and pending invites. Acceptance

  • Given ≥ 1 pending chore-completion approval When Profile renders Then the badge displays the count and updates reactively as approvals are actioned.
  • Given ≥ 1 pending invite (sent, not yet accepted) When Profile renders Then the count includes pending invites; the Admin tile badge mirrors the same sum.
  • Given zero pending items When Profile renders Then no badge is shown (suppressed, not "0").
  • Given isParental = false When Profile renders Then no badge is rendered; non-parental members have no approval queue.
  • Badge data is stream-fed from MoreBloc → MoreRepository → SDK watchPendingBadgeCount(); no polling; zero stale renders guaranteed by the stream subscription lifecycle.

FR-SETTINGS-4 — Navigate to Appearance

Priority: P1 · Status: 🔲 not built Statement. As any member, I reach Appearance settings from Profile in one tap. Acceptance

  • Given I am on Profile When I tap Appearance Then I land on the Appearance page and settings_item_opened(item: 'appearance') fires.
  • Back-navigation returns to Profile without re-fetching the badge count from scratch.

FR-SETTINGS-5 — Navigate to Accessibility prefs

Priority: P1 · Status: 🔲 not built Statement. As any member, I reach Accessibility preferences from Profile in one tap. Acceptance

  • Given I am on Profile When I tap Accessibility Then I land on the Accessibility prefs page and settings_item_opened(item: 'accessibility') fires.
  • The Accessibility tile is always visible and never role-gated; preferences are per-member, not household-scoped.

FR-SETTINGS-6 — Navigate to Account; sign-out at Profile-page bottom

Priority: P1 · Status: 🔲 not built (sign-out delegates to FR-ACCOUNT-3) Statement. As an account holder, I reach Account settings from the Profile tab in one tap, and I find the sign-out action at the bottom of the Profile page. Acceptance

  • Given I am on the Profile tab When I tap Account Then I land on the Account page (display name, email) and settings_item_opened(item: 'account') fires.
  • Given I scroll to the bottom of the Profile page When I tap Sign out Then the FR-ACCOUNT-3 sign-out flow executes; sign_out fires and the app navigates to the sign-in screen.
  • Sign out is not surfaced in the top header (retired in the 2026-07-26 redesign); it lives at the very bottom of the Profile page.

Priority: P2 · Status: 🔲 not built Statement. As any member, I can reach app version info, Terms of Service, and Privacy Policy from Profile. Acceptance

  • Given I tap About When the page loads Then I see the app version string, a ToS link, and a Privacy Policy link; settings_item_opened(item: 'about') fires.
  • ToS and Privacy Policy open via the system browser or an in-app web view (see Open decisions).

FR-SETTINGS-8 — Help & feedback stub

Priority: P2 · Status: 🔲 not built Statement. As any member, I can tap Help from Profile and reach a support contact surface; a full help center is deferred. Acceptance

  • Given I tap Help When the page loads Then a support email link or web link is shown and settings_item_opened(item: 'help') fires.
  • The stub must not dead-end; a tappable contact mechanism is required even if minimal.

Architecture considerations

  • One data pathMoreBloc → MoreRepository → client_sdk facade; no page or widget imports drift or supabase directly. Appearance, Accessibility, and Account navigations are pure routing; no bloc data fetch is required beyond the persona check and badge stream.
  • auto_route nav scaffold — More is an auto_route stack; each destination is a named route in the app router. The isParental gate is an AutoRouteGuard that reads isParental from the active-session bloc. The guard fires on every Admin route attempt (tile or deep-link), not just on initial render. Widget- level tile omission is a UX guard; the route guard is the security layer — both are required.
  • Badge data sourcewatchPendingBadgeCount() on the SDK aggregates pending chore-completion approvals (CompletionService) and pending invite records (MemberService) into a single integer stream. MoreBloc subscribes on first render and cancels on dispose; no polling, no manual refresh needed.
  • PrivacyisParental is a session attribute of the adult account holder; it is never derived from child data. Both analytics events are INTERNAL BI only; no child PII crosses the analytics seam.

Design work (ahead of build)

  • Profile hub list IA — final item list, display order, grouping (flat list vs. labelled sections), and icon / label pairing for each row; document which items are always-visible vs. persona-gated.
  • Badge treatment — numeric badge on the Profile bottom-nav tab icon and on the Admin tile: max-display cap (e.g. "9+"), colour, and zero-state (hidden vs. persistent dot).
  • Admin tile visual distinction — the Admin row should read as configure, not act; consider a section divider, gear icon, or subtle background to separate it from personal-preference items (Appearance, Accessibility, Account).
  • Sign-out placementresolved (2026-07-26): a footer / destructive row at the bottom of the Profile page, removed from the top header entirely.

Decisions (resolved for MVP-1)

Resolved — see the MVP-1 decisions log for the canonical record, rationale, and status legend (✅ decided · ⚖️ counsel confirms · 🔜 MVP-1.x).

  • D-SETTINGS-1 — Sign-out placement.Bottom of the Profile page (2026-07-26 redesign; superseded the earlier "Account sub-page" ruling) — removed from the top header, avoids accidental taps.
  • D-SETTINGS-2 — Subscription tile. ✅ Owner-only "Subscription" row in Profile that deep-links to Admin → Billing (discoverable shortcut; Admin remains the config home). Reconciles with D-ADMIN-1.
  • D-SETTINGS-3 — About / legal link target.In-app web view for ToS / Privacy (contained; pins a versioned URL tied to consent records); system-browser fallback if the web view is unavailable.
  • D-SETTINGS-4 — Notifications tile. ✅ Ship the tile to a real (minimal) notifications-preferences route — local notifications are in MVP-1, so the tile is functional (quiet-hours + lead-time prefs live there), not a stub.

Out of scope (MVP-1)

  • Notification preferences — tile stubs only in MVP-1; functional surface deferred until the notifications feature track is built.
  • Subscription / billing entry on Profile — deferred pending FR-ADMIN-11 billing SDK readiness and placement open decision above.
  • Search within settings — the item list is short enough in MVP-1 to browse; search is deferred.
  • Full in-app help center / support chat — FR-SETTINGS-8 is a contact-link stub; a full help center is a later track.
  • Shared-device PIN-gated profile picker — deferred (see profile-switching feature). The active-member display-lens switcher itself shipped on the Profile page in the 2026-07-26 redesign.