Architecture — a C4 model
This is a C4 model of Rewhaven: a zoom-in from the whole system (who uses it, what it talks to) down to the load-bearing code. It is the living source of truth for the architecture — when a load-bearing decision changes, update these pages. They are hand-authored (not generated), because the value is the curation and the why.
:::tip For AI agents & humans — start here
These pages plus graphify are the canonical reference for this codebase.
graphify answers "where is the code / how are things related" (graphify query "<q>"); these pages answer "how it fits together, why, and what's
external or planned". Dashed nodes are planned / gaps — never assume a
dashed thing is built. When a load-bearing decision changes, update these pages.
:::
Read top-down:
- L1 — System Context — actors and external systems.
- L2 — Containers — the runnable/deployable pieces.
- L3 — Components — inside the app and the SDK.
- L4 — Code — the invariant-bearing aggregates + domain shape.
- Dynamic — key flows — how a request moves through the layers.
Cross-cutting & platform:
- Authentication & sessions — auth shape + the deferred wiring.
- Authorization, personas & consent — proposed MVP-1 design ①: owner/role capability matrix (service + RLS dual gate), consent substrate, supervised-action.
- Observability — Mixpanel, Sentry, the bloc DevTools bridge.
- Infrastructure & external products — Supabase, Cloudflare, dev hosting.
- Design system & Widgetbook — tokens → theme → atoms, and the live gallery.
- Requirements traceability — which C4 elements satisfy which requirement epics, plus privacy & data-protection (GDPR / CCPA) by design.
Diagram legend
Every C4 diagram uses the same colour vocabulary (the design_system calm-dusk palette). Dashed nodes are planned / stubbed, not yet built.
The one data path
Every UI-to-storage interaction flows through exactly one chain. Domain rules live in the SDK Service; repositories are thin presentation delegates.
- Widget — dumb leaf UI; no logic, no I/O.
- Bloc / Cubit — state + side effects (created in a page's
wrappedRoute()). - Repository — a thin delegate adapting the SDK facade to blocs; no domain rules.
- Client (facade) — the
client_sdkpublic surface; the only data-layer type presentation knows. - Service — where the domain rules live.
- Adapter — pure I/O against the local store (Drift) or cloud (Supabase).
Load-bearing rules
- Invariants enforced in the service AND the schema — append-only ledger, zero-floor balances (a debit throws and a SQL trigger blocks it), expectation-pays-zero, household-scoped RLS.
- SDK construction is config-driven —
createClient({required ClientConfig config});ClientConfig(api: ApiConfig(...))switches local→cloud. The production local store is a write-through cache over Drift. - Presentation never imports
drift/supabase— only theclient_sdkfacade. - Brand lives only in
app/lib/inside/i18n+ store metadata — never in names.
Inside vs Outside
The app layer splits singletons built before the widget tree (outside — client providers, effect providers, repositories) from things created inside it (blocs, effects, widgets/pages). Only repositories and effect providers cross from inside to outside; nothing in the tree touches a client provider directly.
Evolution from the POC
These diagrams encode what the POC (Chore_app) taught us. The biggest shifts:
- Mutable balances → an append-only ledger. The POC mutated wallet balances
in place; the rebuild projects balances from immutable
LedgerEntryrows with a zero-floor invariant. See POC domain gap analysis. - Monolithic client → facade + services + adapters. The POC's single client grew unbounded; the SDK now splits a thin facade over domain services over swappable adapters. See the rebuild spec.
- Brand baked into class/file names → i18n + store metadata only, so the engine is brand-agnostic.
- Hand-maintained
.g.dart→ CI codegen, with model-agnostic design_system tokens. See design system decisions. - Testing as an afterthought → a two-layer pyramid (flow + integration). See testing strategy.
- Engagement track (Wave-1/2) → a new architectural pattern: pure projections. Celebration, achievement badges, weekly streaks, and the child timeline are derived read-only views over existing facade reads — zero new storage. This pattern (cubit/bloc as projection, not as mutation owner) is now the canonical model for motivational features.
Current strategic frame: depth in the ND-child vertical, not wider — per
docs/market-analysis-2026-07-expanded-positioning.md.
Future authors: the product direction is a focused neurodiversity-affirming tool;
resist drift toward super-app or "cover every household need" scope.