Skip to main content

C4 Architecture Diagrams — design spec (2026-06-21)

Brainstormed + approved 2026-06-21. A full C4 model (Context → Container → Component → Code, plus Dynamic/sequence flows) of the Rewhaven app, authored as Mermaid under the developer portal, as an evolving source of truth grounded in the POC learnings and the decisions already made.

Goal

A hand-curated set of C4 diagrams (Mermaid) under docs/developer/architecture/, organized by C4 level, that documents the current decided architecture so we don't re-derive it each time — a reference that evolves as load-bearing decisions change.

Why

The architecture is settled (CLAUDE.md's load-bearing rules + the decision log), but it lives as prose + tribal memory. A C4 diagram set makes the boundaries explicit, gives reviews and onboarding a shared map, and records why each boundary exists (the POC taught it). It is authored, not generated — the value is the curation.

Scope (approved)

  • Full C4: L1 Context, L2 Container, L3 Component, L4 Code, plus a Dynamic (sequence) page.
  • L4 is scoped to the load-bearing aggregates only — the economy (append-only ledger + zero-floor wallet) and chore → submission → approval → completion — NOT all ~30 models (those would only rot).
  • Organized by C4 level as a new architecture/ subtree.

Structure

A new authored subtree at app/test-gallery/authored/developer/architecture/ (the build copies authored/developer/** into docs/developer/** recursively, so nested dirs just work). Today's prose architecture.md is folded into the subtree's index.md (the overview); the standalone architecture.md is removed and its inbound links updated.

FileLevelsidebar_position
architecture/index.mdOverview + legend + "Evolution from the POC" + the inside/outside & one-data-path narrative (from today's architecture.md)1
architecture/context.mdL1 System Context2
architecture/containers.mdL2 Container3
architecture/components.mdL3 Component (app + client_sdk)4
architecture/code.mdL4 Code (economy + chore-flow aggregates)5
architecture/dynamics.mdDynamic (sequence flows)6

The folder gets _category_.json {label:"Architecture", position:2} (right after Getting Started). architecture/index.md carries slug so the category links to the overview.

Mermaid / C4 conventions (the legend)

  • Use flowchart/graph TB with subgraphs as C4 boundaries + a shared classDef legend — NOT Mermaid's native C4Context/C4Container (still experimental, renders unreliably in the Docusaurus mermaid theme @3.10.1).
  • The legend (defined once on index.md, applied consistently):
    • classDef person fill:#… — actors (Parent / Co-parent / Kid)
    • classDef external fill:#… — external systems (Supabase, on-device store, AI)
    • classDef container fill:#… — deployable/runnable units
    • classDef component fill:#… — code units inside a container
  • Dynamic flows use sequenceDiagram (well-supported).
  • Every diagram is preceded by a one-line caption and followed by a short "Why / changed-from-POC" callout.

Per-page content (the diagrams to author)

L1 — context.md

Actors: Parent, Co-parent (delegated scopes), Kid (incl. watch-only). System: Rewhaven. External: Supabase (cloud data/auth), on-device store (offline-first), AI recommender (planned). Relationships labelled (uses, authenticates against, syncs to, reads suggestions from). Why-note: offline-first + cloud-optional tiers (cite homebase-offline-first-mvp

  • the product-tiers decision); RLS/household-scoping from the rebuild spec.

L2 — containers.md

Containers: Flutter app (app/, inside/outside), client_sdk (pure Dart data layer), design_system (model-agnostic UI), Supabase (Postgres + Auth

  • RLS + Edge Functions), local Drift DB. Show the config-driven local↔cloud switch (createClient({config}), ClientConfig(api: ApiConfig)), and that presentation depends ONLY on the client_sdk facade (not on Drift/Supabase). Why-note: config-driven construction + pure-Dart SDK + DS-has-no-SDK-dep (CLAUDE.md invariants; design-system-decisions).

L3 — components.md (two diagrams)

(a) App container: routes/pages → blocs (inside/blocs) → repositories (outside/repositories: approvals, auth, chores, household, places) → the client_sdk facade; plus effect_providers (auth_change, feature_flags, mixpanel, shared_prefs) and client_providers (sentry). Show repositories as the thin presentation seam; effect/client providers off to the side. (b) client_sdk container: facade (client/Client, ClientImpl, createClient, ClientConfig) → services (approval_service, chore_service, economy_service, entitlement_service, household_service, ledger_service, + chore_period/id_generator helpers) → adapters (local = Drift [3], cached = write-through [1], memory = in-memory [1]; cloud + ai = planned/stubbed, shown dashed) → models. Why-note: domain rules live in services, repos are thin (CLAUDE.md); adapter swap is config not injection. Honesty: cloud and ai adapters are currently stubs — render them dashed / "planned", do not imply they're built.

L4 — code.md (two aggregate diagrams, classes + relationships)

(a) Economy aggregate: LedgerEntry (append-only) ← LedgerService; Wallet/buckets (bucket.dart, give/save/spend/bank) with the zero-floor invariant (debit throws + SQL trigger); EconomyService orchestrating; the expectation-pays-zero rule. (b) Chore-flow aggregate: Chore (ChoreKind expectation|bounty) → ChoreSubmissionApproval (ApprovalKind completion|redemption; ApprovalStatus) → ChoreCompletion; ChoreService + ApprovalService. Why-note: append-only + invariants-in-service-AND-schema (CLAUDE.md); the POC's mutable-balance bug → the ledger-projected model (poc-domain-gap-analysis).

Dynamic — dynamics.md (sequence diagrams)

  1. Chore completion: Kid taps done → Bloc → ChoresRepository → ChoreService submitCompletion → Approval(pending) → Parent approves → ApprovalService → EconomyService credits Wallet via LedgerEntry → cache/stream updates the UI.
  2. Spend → redemption: Kid requests spend → SpendRequest/Approval(redemption) → affordability check → Parent approves → debit (zero-floor) → Redemption.
  3. Cache-first read (write-through): Bloc reads → Repository → facade → cached adapter → (hit → return; miss → local/cloud → populate) — the offline-first path.
  4. Auth/onboarding → setup: sign-in → AuthenticatedGuard → no household → SetupRoute → SetupBloc creates household + members. Why-notes cite today-jtbd-funnels (the completion funnel) + the offline-first
  • auth-guard decisions.

Living source of truth

  • Fully authored / hand-curated — no codegen (L4 especially would only rot if generated). index.md states: "these are the source of truth; update them when a load-bearing decision changes."
  • Each page cross-links the decision docs it derives from (relative links into Developer → Decisions) so a diagram and its rationale stay tied.

Build / wiring

  • New authored pages under app/test-gallery/authored/developer/architecture/; the existing generateDeveloperDocs() copy step already handles the nested dir.
  • Remove authored/developer/architecture.md; update its inbound links (getting-started + the guides reference ./architecture → point to ./architecture/ i.e. the overview).
  • _category_.json for the subtree.
  • Mermaid already wired (markdown.mermaid: true + @docusaurus/theme-mermaid).

Testing / verify

  • node scripts/build_test_gallery.mjsdocs/developer/architecture/ has the 6 pages.
  • npm run build → BUILD=0, [SUCCESS]; every Mermaid diagram parses/renders (a broken diagram fails the build or renders an error box — check the build log
    • spot-check the deployed pages).
  • After deploy-developer-gallery.sh: Developer → Architecture shows the subtree; the L1–L4 + Dynamic diagrams render; no broken links from the folded architecture.md.

Out of scope

  • Diagramming all ~30 models at L4 (aggregates only).
  • Auto-generating any diagram from source.
  • Re-architecting anything — this documents the current decided design (and marks cloud/ai adapters as planned, honestly).
  • C4-PlantUML / Structurizr tooling — Mermaid only.

Sequencing (for the plan)

  1. Overview + legend (index.md): fold architecture.md prose in, define the classDef legend + "Evolution from the POC", _category_.json, fix inbound links, remove the old architecture.md. Build green.
  2. L1 + L2 (context.md, containers.md).
  3. L3 (components.md — app + SDK).
  4. L4 (code.md — economy + chore-flow aggregates).
  5. Dynamic (dynamics.md — the 4 sequences).
  6. Build + deploy + verify (every diagram renders under Developer → Architecture).