Admin features — requirements
Epic. MVP-1 requirements breakdown for the Admin config hub (see the feature architecture). Each FR is sized to become one or a few user stories. Admin is the single
isParental-gated surface where household configuration lives; the rest of the app stays act/overview.
| Type | Functional |
| Layer (build approach) | Cross — config hub over SDK services |
| RICE | R 7 × I 2 × C 80% / E 4 = 2.8 · Tier MVP-1 |
| KPI (summary) | Admin config-save events; % households finishing economy + catalog setup |
| Traces to | feature admin · C4 components · prioritization |
| Depends on | Personas / authz (isParental, owner) · Money (default buckets, family budget) · Catalog |
Success criteria (definitive KPI)
Success = ≥ 70% of new households complete economy config + ≥ 1 catalog item
within 3 days of activation, AND ≥ 3 admin_config_saved events per active
household per week across weeks 1–4 post-activation.
- Metric 1 (setup completion): % of activated households with ≥ 1 economy config save AND ≥ 1 catalog item created within 72 hours of their first session.
- Target: ≥ 70% of new households cross both thresholds within 3 days.
- Metric 2 (ongoing engagement):
admin_config_savedevents per active household per week. - Target: ≥ 3 events / household / week in weeks 1–4 (setup is write-heavy; < 1/week by week 5 is expected — families configure then stabilize).
- Why this bar: without an economy config and at least one catalog item a household cannot complete a chore loop. Three saves/week captures active tuning without requiring perpetual engagement.
- Baseline: no install base yet — treat as the launch hypothesis; re-baseline from first-cohort week-1 data.
Analytics — events to record
All events are Internal BI — content-free, no child identity or PII. Marketing bucket receives plan type and parent-feature-active signals only; never child-derived. Emitted through the consent-gated analytics substrate.
| Event | When | Key properties | Feeds |
|---|---|---|---|
admin_config_saved | Any admin config form saved | area (economy|catalog|buckets|flags|house|budget) | primary KPI — setup completion + ongoing engagement |
member_invited | Member added or invite sent | role (parental|member|helper), isChild (bool, coarse) | household-growth funnel |
catalog_item_created | Chore / bounty / activity / reward created | kind (chore|bounty|activity|reward) | catalog depth; setup KPI |
default_bucket_set | Default-bucket template saved | bucketCount (int), hasPermanent (bool) | bucket-template adoption |
family_budget_set | Family budget saved | hasBudget (bool) — no amount | budget-feature adoption |
admin_config_savedis the KPI denominator and must ship with the first admin sub-page — not as a post-launch instrument.
Scope
Admin (Profile → Admin) is the single isParental-gated hub for all household configuration: Catalog CRUD, member Accounts, Economy, Default buckets, Feature flags, House/rooms/zones, Family budget, and (owner-only) Billing. Helper members can approve/deny completed jobs but have zero Admin access. The Household tab remains a read-only overview; Admin is where admins configure how things work.
Functional requirements
FR-ADMIN-1 — isParental gate on the Admin hub
Priority: P1 · Status: 🔲 not built Statement. As an admin, I can reach Profile → Admin; any non-parental member (member, helper, watch-only) sees no Admin tile and is blocked on direct route attempt. Acceptance
- Given
MemberKind.isParental = falseWhen Profile renders Then Admin tile is absent; direct route attempt redirects. - Given
isParental = trueWhen Admin route is visited Then the hub loads all sub-page tiles. MemberRole.helperis explicitly excluded: the helper gate widens chore-approval only — no Admin access regardless of any other flag.
FR-ADMIN-2 — Catalog CRUD
Priority: P1 · Status: 🔲 not built Statement. As an admin, I create, edit, and delete chores, bounties, activities, and rewards from Admin → Catalog so the household has a working catalog before leaving onboarding. Acceptance
- Given I create a chore with name + token value When saved Then it appears in the household catalog via the SDK facade and on Today for eligible members.
- Given an existing item When I delete it Then it is removed; household-scoped RLS prevents cross-household leakage.
catalog_item_created(kind)+admin_config_saved(area: 'catalog')fire on create.
FR-ADMIN-3 — Member management (add / edit / remove, role grants)
Priority: P1 · Status: 🔲 not built Statement. As an admin, I add adult members, change their display name or role, and remove them from the household via Admin → Accounts. Acceptance
- Given an existing member When I change their role Then
setMemberRoleis called; access updates on their next session. - Given a member to remove When I confirm Then
removeMemberis called; their wallet is frozen; chore history is retained for the ledger. member_invited(role, isChild: false)fires on add.
FR-ADMIN-4 — Adult account invite
Priority: P1 · Status: 🔲 not built Statement. As an admin, I invite an adult by email to join the household as a parental admin, helper, or member; they receive a deep-link and land in onboarding pre-joined. Acceptance
- Given a valid email When I send an invite Then an invite record is created (SP2 invite flow); the Accounts sub-page shows pending state.
- Invite expiry and re-send are handled by the invite service; the UI surfaces pending/expired states.
member_invited(role, isChild: false)fires on send.
FR-ADMIN-5 — Child member add (COPPA consent-gated VPC)
Priority: P1 · Status: 🔲 not built · COPPA-critical
Statement. As an admin, I add a child member; for any member under 13 the flow
requires verifiable parental consent (VPC) before addMember is called.
Acceptance
- Given the admin indicates the member is under 13 When the add-child flow runs Then a VPC consent step is presented; a consent record is persisted before any child data is stored.
- Given VPC is not completed When the admin attempts to finalize Then
addMemberis not called; no member record is created. member_invited(role: 'member', isChild: true)is the only analytics signal — content-free, no child identity. See COPPA.
FR-ADMIN-6 — Economy config
Priority: P1 · Status: 🔲 not built Statement. As an admin, I set the household currency name/emoji, default earn-allocation routing, and house name so the token economy fits the household. Acceptance
- Given a currency name and emoji When saved Then
updateEconomyConfigis called; token displays app-wide reflect the change. - Given a default-allocation config When a chore is approved Then tokens route to the configured buckets unless the member has a personal override (member allocation always wins per Money spec).
admin_config_saved(area: 'economy')fires on save.
FR-ADMIN-7 — Default buckets + permanent flag
Priority: P1 · Status: 🔲 not built Statement. As an admin, I define the household's starter-bucket template (e.g. Spend / Save / Give) and mark buckets permanent so members cannot delete them. Acceptance
- Given the admin marks a bucket permanent When a new member is added Then that bucket is in their starter wallet and they cannot delete it.
- Template changes apply to new members only; existing members' personal buckets are not retroactively removed (confirm — see Open decisions).
default_bucket_set(bucketCount, hasPermanent)+admin_config_saved(area: 'buckets')fire on save.
FR-ADMIN-8 — Feature flags
Priority: P2 · Status: 🔲 not built Statement. As an admin, I toggle household feature flags (tithe, stepBreakdown, activityGating, printableLists) to enable or disable capabilities household-wide. Acceptance
- Given a flag When the admin toggles it Then
setProductFeatureFlagis called; the change takes effect household-wide on the next session load. admin_config_saved(area: 'flags')fires on each toggle.
FR-ADMIN-9 — House, rooms, and zones
Priority: P2 · Status: 🔨 partial (updatePlace SDK gap) Statement. As an admin, I set house name/address and add, rename, or delete rooms and zones (Place + floor) so chores can be assigned by location. Acceptance
- Given I rename an existing room When saved Then
updatePlaceis called — SDK gap: this method must be implemented before FR-ADMIN-9 can ship. - Given a new zone When saved Then
createPlaceis called; the zone appears in the catalog's room-assignment picker. admin_config_saved(area: 'house')fires on any place or house-name save.
FR-ADMIN-10 — Family budget
Priority: P2 · Status: 🔨 partial (budget service partly stubbed) Statement. As an admin, I set the household family budget; it appears read-only on the Household tab so all members see the household envelope. Acceptance
- Given a budget value When saved Then the budget service records it; the Household tab read-only display updates.
- No member (including other admins) can edit the family budget except through this sub-page.
family_budget_set(hasBudget: true)+admin_config_saved(area: 'budget')fire on save.
FR-ADMIN-11 — Billing (owner-gated)
Priority: P2 · Status: ❓ open — SDK gap (owner flag + billing surface) Statement. As a household owner (distinct from admin), I see Admin → Billing and can manage subscription and payment; non-owners see no Billing tile even if they are admins. Acceptance
- Given
member.isOwner = trueWhen Admin renders Then a Billing tile appears; absent forisOwner = false. - Multiple owners are supported; any owner can access Billing.
- Plan type is a marketing-bucket signal (parent/account) — never child-derived, never child-linked.
- Blocked on:
ownerflag on member/account (SDK gap) + billing service (subscription-tiers track).
Architecture considerations
- One data path —
AdminBloc → Repository → client_sdkfacade; no directdrift/supabasein presentation. Sub-page blocs each delegate to their SDK service: ChoreService, RewardService, MemberService, EconomyConfigService, PlaceService, FeatureFlagService, BudgetService. - isParental gate — enforced at the auto_route guard level and re-verified in
each sub-page bloc on load. The SDK separately widens chore-approval to
isParental OR helper; the Admin gate is orthogonal and does not widen. - Owner gate for Billing — layered above the isParental check; the Billing
route checks
member.isOwnerafter the isParental guard passes. - Household-scoped RLS — all admin writes (catalog items, members, economy config, places, flags) are constrained by household RLS policies (SP3); no cross-household mutation is reachable from any admin path.
- SDK gaps to fill before build:
updatePlace(FR-ADMIN-9);ownerflag on member + billing surface (FR-ADMIN-11; may track with subscription-tiers). - COPPA invariant — VPC consent record must be persisted before
addMemberfor any under-13 child; this is a legal gate, not a UX preference. See COPPA. - Privacy model: OPERATIONAL (child PII → VPC only) · INTERNAL BI (no child identity, content-free) · MARKETING (plan type, parent-feature-active; never child-derived).
Design work (ahead of build)
- Admin hub landing page — IA with 6–7 sub-page tiles (Catalog, Accounts, Economy, Default Buckets, Feature Flags, House, [Billing for owners]); visual language that reads as configure, distinct from the act/overview surfaces.
- Catalog CRUD editor — tabbed or segmented by item kind; form design using DS atoms.
- Default bucket editor — bucket list with permanent-flag toggle; clear affordance distinguishing the household template from a member's personal buckets.
- Family budget editor — amount field + allocation preview; must coordinate with the Household tab read-only display (same data, two surfaces — design together).
- Consent-gated child invite flow — the VPC modal/interstitial is COPPA-critical; design with legal review before build begins.
- Billing tile + page (owner-only) — subscription state, tier label, payment method, upgrade/downgrade CTA; design deferred until billing SDK is ready.
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-ADMIN-1 — Billing placement. ✅ Admin → Billing is canonical (owner-only, the single config hub); the Profile hub surfaces an owner-only "Subscription" shortcut row that deep-links into it for discoverability. (Reconciles with D-SETTINGS-2.)
- D-ADMIN-2 —
updatePlacescope. ✅ Fill the SDK gap and ship room create / rename / delete in MVP-1 — a partial CRUD (no rename) is more confusing than the small added effort. - D-ADMIN-3 — Default-bucket template retroactivity (FR-ADMIN-7). ✅ New members only in MVP-1; adding a permanent bucket to the template does not retroactively touch existing members. A deliberate "apply to existing" admin action is 🔜 MVP-1.x.
Out of scope (MVP-1)
- Audit log for admin config actions → Later.
- Custom roles beyond the fixed set (parental / helper / member / owner) → deferred.
- Catalog import / export templates → Later.
- Multi-house membership (one account across households) → deferred.
- Subscription upsell, trial management, promo codes → MVP-2 (subscription-tiers track).
- Allowance automation from Admin → allowance-automation feature track (MVP-2).