Skip to main content

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.

TypeFunctional
Layer (build approach)Cross — config hub over SDK services
RICER 7 × I 2 × C 80% / E 4 = 2.8 · Tier MVP-1
KPI (summary)Admin config-save events; % households finishing economy + catalog setup
Traces tofeature admin · C4 components · prioritization
Depends onPersonas / 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_saved events 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.

EventWhenKey propertiesFeeds
admin_config_savedAny admin config form savedarea (economy|catalog|buckets|flags|house|budget)primary KPI — setup completion + ongoing engagement
member_invitedMember added or invite sentrole (parental|member|helper), isChild (bool, coarse)household-growth funnel
catalog_item_createdChore / bounty / activity / reward createdkind (chore|bounty|activity|reward)catalog depth; setup KPI
default_bucket_setDefault-bucket template savedbucketCount (int), hasPermanent (bool)bucket-template adoption
family_budget_setFamily budget savedhasBudget (bool) — no amountbudget-feature adoption

admin_config_saved is 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 = false When Profile renders Then Admin tile is absent; direct route attempt redirects.
  • Given isParental = true When Admin route is visited Then the hub loads all sub-page tiles.
  • MemberRole.helper is 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 setMemberRole is called; access updates on their next session.
  • Given a member to remove When I confirm Then removeMember is 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.

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 addMember is 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 updateEconomyConfig is 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 setProductFeatureFlag is 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 updatePlace is called — SDK gap: this method must be implemented before FR-ADMIN-9 can ship.
  • Given a new zone When saved Then createPlace is 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 = true When Admin renders Then a Billing tile appears; absent for isOwner = 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: owner flag on member/account (SDK gap) + billing service (subscription-tiers track).

Architecture considerations

  • One data pathAdminBloc → Repository → client_sdk facade; no direct drift/supabase in 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.isOwner after 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); owner flag on member + billing surface (FR-ADMIN-11; may track with subscription-tiers).
  • COPPA invariant — VPC consent record must be persisted before addMember for 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 — updatePlace scope. ✅ 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).