Household — feature architecture
DRAFT — IA decided 2026-06-25. The Household tab is the people surface (read-only member tiles + Family Goals); budget/summaries live on Dashboards and all configuration in Admin. This is the source of truth that flow tests, unit tests, and implementation derive from (same contract as Member Profile).
Purpose & scope
The Household tab (HouseholdPage, in the adult nav set Home · Earn · Rewards ·
Household · Profile) is the family + house at a glance: a read-only overview of
every member (tap → Member Profile) plus the family-level
shared things. It is deliberately not where you manage accounts/roles, nor
where you configure the economy or catalog. Per-member detail lives in the member
profile; member management lives in Profile → Account; economy/budget/flags are
settings.
Current state vs intent (important)
- Today (as-built): the tab renders only a members
ListView+ an add-member button + a member-editor bottom sheet (MembersBloc). That is the T5 state — a member roster, not the restructured Household. - T7 (restructure) is specced but NOT built (every plan checkbox unchecked). T7's locked decisions: Household = read-only member-profile tiles + Family Goals card + house config; member management (add/edit/remove/roles/invite) moves to Profile → Account → Members.
- The POC's Household page also carried economy, budget, rooms, giving-destination, and catalog-management tiles. This doc argues most of those do not belong on the Household tab — see the IA assessment.
IA — where everything lives (DECIDED 2026-06-25)
The split is act / glance / browse / people / configure. The Household tab is the people surface — nothing else lives there.
| Surface | Role | Household-related content |
|---|---|---|
| Home (Today) | act | do chores, approvals |
| Dashboards | glance | family budget (1st widget) + budget/goal summaries + today + member glance; lean-back TV/desktop ambient — see Dashboards |
| Catalog | browse | chore/reward browse + redeem |
| Household | people | read-only member tiles (→ Profile) + the Family Goals card. That is the whole tab. |
| Profile → Admin | configure (parental) | catalog CRUD · accounts/invites · economy · feature flags · house (name/emoji/address + rooms/zones) · default buckets · Billing (owner-only) — see Admin features |
| Member Profile | personal (sub-page) | wallet/envelopes · goals · own budget/buckets · "Manage account" → Admin |
Decisions
- Household tab = the people surface: read-only member tiles (→ Profile) + Family Goals. The budget + summaries live on Dashboards; all config lives in Admin.
- Admin lives under Profile — a single hub,
MemberKind.isParental-gated. It holds every CRUD surface (catalog, accounts/invites, economy, flags, house/rooms/zones, default buckets) + Billing (owner-only; multiple owners). - Helper gets NO admin access.
MemberRole.helper(think babysitter) can only approve / deny completed jobs — nothing else. Admin/config isisParentalonly. - Move funds: the member themselves (their own envelopes) and an admin (any member's wallet) can move funds — see Money & Envelopes.
- Member management → Admin → Accounts; the Member Profile links to it via "Manage account". Household tiles stay read-only.
- Rooms = "zones" via
Place.floor(no new entity): restoreemoji+floor, add the missingupdatePlace. Managed in Admin → House. - House
address→ an optional field onHousehold(not on a room — see ERD). - Family budget shows on the Dashboard: a non-admin can recommend a
change (admin reviews — mirrors goal
request → approve); an admin gets an "Edit" link into Admin → Family budget. - Base envelopes = Spend + Save (fixed base) + a Give bucket the
admin can remove / rename / re-icon. Members CRUD their own buckets
(except admin-
permanentones). See Money & Envelopes.
Feature set (target)
Status: ✅ built · 🔨 to build (SDK-ready) · 📍 lives off-tab (Admin / Dashboards).
| Feature | Status | SDK surface | Notes |
|---|---|---|---|
| Member roster (read-only tiles → Profile) | 🔨 (today: editable list) | watchMembers() + walletOf + getGoals(memberId) | restructure to a read-only tile w/ wallet glance + 🎯 goal chip |
| Family Goals card | 🔨 | getGoals(memberId:null) + createGoal(scope:family) + lifecycle | reuse the goal components from member-profile |
| Member management | 📍 Admin → Accounts | addMember/updateMember/removeMember/setMemberRole | off the tab; profile links via "Manage account" |
| Budget + summaries | 📍 Dashboards | budget + goalProgress aggregation | the dashboard's first widget |
| House config · economy · flags · default buckets · billing | 📍 Admin | see Admin features | configure, not overview. SDK gaps: updatePlace, Household.address |
ERD
Notes: there is no giveDestinationName on Household (POC had it) and no
updatePlace anywhere — both are SDK gaps. Family-goal progress
(goalProgress) sums all members' save balances.
Multi-household (DEFERRED — forward-compatible model)
A family may eventually span multiple houses (co-parents across two homes; a kid whose identity is present in both). The feature (a house picker, switching, cross-house views) is deferred — but the model is shaped now so we can evolve into it without a migration that splits identity or money:
- Account ↔ households = many-to-many. An auth account (
authUserId) may be associated with more than one household (e.g. a parent managing two homes). - Member ↔ households = many-to-many via a membership/identity link. A person can be present in multiple households (aligns with the post-MVP "continuous kid identity" / divorce-clone note).
- Wallet + goals belong to the MEMBER, not the house. They are member-scoped envelopes (see Money & Envelopes), so they travel with the member across houses — multi-house never fragments a member's money or goals.
- House-scoped (one per house): chores, rooms/zones, family goals, economy config, default allocation, address.
- Roles + the
ownerflag are per-membership. A person'sMemberRoles andownerflag live on theHouseholdMemberrecord, so they are scoped to that household — admin-in-A / member-in-B is supported. One subscription is per account (an account may manage N homes); the zero-admin and zero-owner guards are enforced per household (service + schema trigger). See Personas and Roles & permissions.
Build implication now: keep wallet/goals keyed by memberId (member
identity), not householdId; don't hard-code "one household per account/member"
in ways a future membership join would have to undo.
State machines
Household tab (members) bloc
(The member editor state machine — open/save/saveFailure — relocates to the Profile → Account Members-management page; it leaves the Household tab.)
Family Goal lifecycle
Identical to the member goal lifecycle (see
Member Profile → State machines): active → requested → active (approve, parental) → complete, → archived → active. The only
difference is scope == family (memberId == null), so a family goal is
proposed/approved at the household level, not for one member.
Data flow
The members-management surface (Profile → Account) reuses HouseholdRepository
(add/update/remove/role) — the CRUD logic relocates, it is not duplicated.
SDK surface (+ gaps)
Have: watchMembers/getMembers/addMember/updateMember/removeMember/setMemberRole/ setMemberHomePlace/setMemberTraits/setMemberColorKey/assignableMembers,
walletOf, getGoals/createGoal/updateGoal/archiveGoal/restoreGoal/requestGoal/ approveGoal/completeGoal/goalProgress, setHouseholdName, updateEconomyConfig,
getPlaces/createPlace/deletePlace, getFeatureFlags/setProductFeatureFlag.
Gaps to fill before the relevant build:
updatePlace— absent at every layer (facade/service/StoragePort/adapter). Needed to rename a room (today = delete + recreate). Required only if Rooms management lands.Household.giveDestinationName— model field + setter absent. Required only if giving-destination lands.watchGoals(...)stream — absent; family + member goals are one-shotgetGoalstoday. A nicety for live family-goal updates (T7 P1).
Test plan (anchors)
Unit / bloc: members roster load + live re-emit; family GoalsBloc
load + request/approve/complete/archive transitions (mirror
member_profile_bloc_test.dart).
Flow / golden: Household tab shows read-only member tiles (wallet glance +
goal chip) + a Family Goals card; tapping a tile → MemberProfile; a family goal
request → "awaiting approval"; (members-management page lives in its own flow
test under Profile → Account).
Widget: member tile renders glance + goal chip; family-goal tile states.
Build order (after IA sign-off)
- Household tab restructure — read-only member tiles (wallet glance + 🎯 goal chip) + tap→MemberProfile; remove inline add/edit from the tab.
- Family Goals card — family-scope goals list + add + request→approve (reuse the member-profile goal components/state machine).
- Members-management page under Profile → Account — relocate the editor, add role grants + remove (T7 P2).
- (Conditional on IA decisions) house-config header tile; Rooms management
(needs
updatePlace); economy/giving in Profile → Settings (needsgiveDestinationName).
Each step ships with its tests per the test plan and goes through a flutter review gate, same as the member-profile feature.