Files
atomic-design-poc/docs/project/backlog/README.md
ehoandClaude Sonnet 5 ae7781efef
CI / changes (push) Successful in 8s
CI / lint (push) Successful in 1m9s
CI / frontend (push) Successful in 2m27s
CI / backend (push) Successful in 1m56s
CI / e2e (push) Successful in 3m16s
CI / semgrep (push) Successful in 1m7s
CI / api-client-drift (push) Successful in 1m50s
CI / storybook-a11y (push) Successful in 11m4s
docs: close WP-72..75, regenerate behaviour spec
Four close-outs and their README rows. The behaviour spec is regenerated
once here rather than per-track — it derives from every test name in the
repo, so any track running it would have conflicted with the other three.

Records two findings the arc surfaced but did not cause: the /brief/preview
staleness for non-DemoOwner identities (blocking per-spec identity isolation
in brief-v2.spec.ts), and that WP-72/73 had to share a commit because both
edit Program.cs — separate execution waves prevented build collisions but
did not produce separable diffs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-19 16:34:54 +02:00

20 KiB
Raw Permalink Blame History

Backlog — showcase hardening

Ordered work packages that take this POC from "good" to reference showcase: CIBG design-system fidelity, DDD/FP consistency, Storybook as curriculum, and WCAG compliance with automated gates. Source: the architecture/CIBG/a11y audit of 2026-07-02 (plan: "Showcase hardening").

This backlog supersedes docs/project/SHOWCASE-ROADMAP.md.

Session protocol

  • One WP per session. Read CLAUDE.md, this README, the WP file, and the WP's "Read first" list — then execute. Do not start the next WP in the same session.
  • Match the model to the step, not the whole session (see CLAUDE.md's "Model routing for agent delegation"). Read the WP's Decisions block with the planner agent (Opus) if the current session isn't already Opus — the approach and edge cases deserve the stronger model. Implement directly if already on Sonnet, or hand off to the developer agent otherwise, once the plan is approved. Delegate simple, read-only CLI checks (running a test suite, grep/git status, verifying a file exists) to the task-runner agent (Haiku) — proportion cost to the step's difficulty, not the WP's.
  • The Decisions block in each WP is pre-made — don't relitigate it.
  • A WP ends GREEN (below) with its acceptance criteria checked off and its Status updated to done (+ commit hash).
  • No WP leaves a lint rule/check disabled without an inline justification comment and a cross-reference to the WP that will remove it.

GREEN (global definition of done)

npm run lint && npm run check:tokens && npm test && npm run build && npm run build-storybook

From WP-01 onward, additionally:

npm run test-storybook:ci

Phases 05 were frontend-only; phase 6 (Brief v2) touches backend/ — for those WPs cd backend && dotnet test is part of GREEN, and any wire change ends with npm run gen:api leaving no drift.

From WP-19 onward, npm run e2e is part of CI (its own job) but NOT part of the local GREEN one-liner above — it needs the real backend + npm start already running (see WP-19's own file), so it's a separate manual/CI step, not chained into the others.

Order

Gates land before the work they cover; each lint rule lands in the same WP as the fixes for its existing violations, so every WP ends green.

WP Title Phase Status
WP-01 Axe-on-every-story CI gate 0 · gates done
WP-02 Harden check:tokens + fix what it catches 0 · gates done
WP-03 Boundaries I: contracts purity + ApiClient confinement 0 · gates done
WP-04 Boundaries II: ui ↛ infrastructure + showcase sanction 0 · gates done
WP-05 Parse-don't-validate closure + MDX 1 · FP/DDD done
WP-06 Generic async template contexts — kill $any() 1 · FP/DDD done
WP-07 Brief on the shared idioms + RemoteData MDX 1 · FP/DDD done
WP-08 One store idiom + machine naming + TEA MDX 1 · FP/DDD done
WP-09 Pure-logic closure: dates + missing command specs 1 · FP/DDD done
WP-10 CIBG button fidelity 2 · CIBG done
WP-11 CIBG markup fidelity: application-link + absent-class triage 2 · CIBG done
WP-12 CIBG Datablock for application data 2 · CIBG done
WP-13 CIBG-gap register + hygiene + MDX 2 · CIBG done
WP-14 Storybook taxonomy reorg + Layers MDX 3 · Storybook done
WP-15 Missing stories: shell + brief components 3 · Storybook done
WP-16 Component a11y: description wiring + alert role 4 · a11y done
WP-17 App-level a11y: route focus, template lint, WCAG checklist 4 · a11y done
WP-18 ABAC capability spine (Principal + capabilities, phase P1) 5 · productie-volwassenheid done
WP-19 Playwright e2e smoke 5 · productie-volwassenheid done
WP-20 Second locale proof 5 · productie-volwassenheid done
WP-21 Resilience seams (correlation-id, idempotency, retry) 5 · productie-volwassenheid done
WP-22 Durable persistence (optional tier) 5 · productie-volwassenheid done
WP-23 Org-template backend + admin role 6 · Brief v2 done
WP-24 Letter canvas (edit on the letter) 6 · Brief v2 done
WP-25 Server-rendered letter preview (HTML; PDF deferred) 6 · Brief v2 done
WP-26 Admin org-template editor 6 · Brief v2 done
WP-27 Brief UX layer (undo/redo, standaardbrief, diff) 6 · Brief v2 done
WP-28 Brief v2 demo polish (scenarios, e2e, docs) 6 · Brief v2 done
WP-29 Stamdata beheer editor (low-code, PR-emitting) follow-on · ADR-0004 done
WP-30 CI performance follow-ups (node_modules cache, runner image, path filters) follow-on · CI/infra done
WP-31 Shared store helpers (ActionState/SaveState, history, debounced-save, RemoteData) 7 · refinements done
WP-32 Undo/redo in the stamdata editor (folded into WP-31 — no separate file) 7 · refinements done
WP-33 In-app dev switchers (scenario + role) 7 · refinements done
WP-34 Adres: phone field + BRP address read-only 7 · refinements done
WP-35 One Concept per case type (server-enforced) 7 · refinements done
WP-36 Admin cases page + admin delete 7 · refinements done
WP-37 Dev-switcher reset fix (scenario/role URL param) 8 · platform/DX/showcase done
WP-38 Dependency graph + declarative boundaries (visualize + enforce) 8 · platform/DX/showcase done
WP-39 Showcase: linked code snippets + teaching animations 8 · platform/DX/showcase done
WP-40 PII kernel: branded Bsn VO (elfproef) + masked-value atom 8 · platform/DX/showcase done
WP-41 Persisted, queryable authz/PII-reveal audit (no PII) 8 · platform/DX/showcase done
WP-42 Privacy & security showcase page (mask + no-PII log) 8 · platform/DX/showcase done
WP-43 Runnable generators: value-object / form-machine (plop; ui-component/bff = skills) 8 · platform/DX/showcase done
WP-44 Runnable generator: gen:context 8 · platform/DX/showcase done
WP-45 create-frontend bootstrap generator (mechanise new-ssp) 8 · platform/DX/showcase done
WP-46 Vitest coverage (report + report-only thresholds) 8 · platform/DX/showcase done
WP-47 Runtime feature flags (catalog-in-code, admin toggle, FE+backend) 8 · platform/DX/showcase done
WP-48 Stamdata deletion protection (CI referential gate + editor expire/warn) 8 · platform/DX/showcase done
WP-49 OpenZaak zaken read seam (IZaakSource + ZGW client, config-gated, offline default) 9 · OpenZaak/ZGW done
WP-50 OpenZaak create-zaak (first write slice) 9 · OpenZaak/ZGW done
WP-51 OpenZaak Documenten (DRC) upload + zaak link 9 · OpenZaak/ZGW done
WP-52 OpenZaak Notificaties (NRC) live status via webhook 9 · OpenZaak/ZGW done
WP-53 Inbound identity seam + citizen-scoping (per-request BSN, ZGW audit claims) 9 · OpenZaak/ZGW done
WP-54 Docker OpenZaak integration-test harness (opt-in, live round-trip) 9 · OpenZaak/ZGW done
WP-55 Real secrets + TLS for the OpenZaak harness 10 · OpenZaak hardening done
WP-56 Idempotent catalogus provisioning 10 · OpenZaak hardening done
WP-57 Least-privilege client scopes 10 · OpenZaak hardening done
WP-58 Real notifications (celery + scripted abonnement) 10 · OpenZaak hardening done
WP-59 Per-document-type confidentialiteit config 10 · OpenZaak hardening done
WP-60 Write-divergence resilience (local + ZGW writes) 10 · OpenZaak hardening done
WP-61 Bootstrap the behandelportal app 11 · Behandelportal done
WP-62 Backend: medewerker caller identity + authz seam 11 · Behandelportal done
WP-63 Backend: aanvraag status lifecycle as a published DTO 11 · Behandelportal done
WP-64 Behandelportal: werkvoorraad (queue) screen 11 · Behandelportal done
WP-65 Behandelportal: zaak detail + beoordeling (decision) screen 11 · Behandelportal done
WP-66 Wire the decision into OpenZaak 11 · Behandelportal done
WP-67 Merge behandelportal into this repo as a monorepo 11 · Behandelportal done
WP-68 Aggregate invariants + status modelling (architecture review) 12 · DDD hardening done
WP-69 Enforce the scholing threshold server-side 12 · DDD hardening done
WP-70 Test-data builders: illegal fixtures unrepresentable (ADR-0006) 12 · DDD hardening done
WP-71 Test framework coherence: BDD/DDD alignment, close the escape hatches 12 · DDD hardening done
WP-72 Delete the dead legacy submit endpoints 12 · DDD hardening done
WP-73 RegistrationStatus and Aanvraag as closed unions 12 · DDD hardening done
WP-74 E2E isolation without a new backend endpoint 12 · DDD hardening done
WP-75 Close the remaining FE/BE seams 12 · DDD hardening done

Sequencing dependencies (stated in the WPs too): 01 before 1015 (axe covers story churn); 03/04 before 0509 (boundaries stop new violations during refactors); 06 before 07 (typed <app-async> before brief adopts it); 13 defines the gap-marker format that 11/12 reference — if 11/12 run first, they define it and 13 adopts it. 1822 (phase 5, "productie-volwassenheid") are independent of each other and of phases 14 — pick any order; 18 is the recommended first pick (it's the headline gap: no authorization spine exists yet, and it closes the FE-computed-authz anti-pattern in brief.store.ts). 22 is explicitly lower priority — the current in-memory persistence is a documented, defensible POC choice, not a bug. Phase 6 (Brief v2, the "Brief opstellen v2" PRD) is strictly ordered 23 → 24 → 25 → 26 → 27 → 28: 24 needs 23's orgTemplate on the wire, 25 needs 24's letter.css contract, 26 needs 23's endpoints + 24's canvas, 27/28 polish on top. Phase 7 (refinements, WP-31..36): only 31 → 32 is ordered (32 reuses the createHistory helper 31 extracts); 3336 are independent — pick any order. Phase 8 (platform/DX/showcase, WP-37..46): goal is BOTH a teaching showcase AND a production starter template. Priority: WP-37 (P0 quick fix) → WP-46 + WP-38 + WP-39 (P1, parallel) → WP-40 (P2) → WP-43 (P3) → WP-41 → WP-42 → WP-44 → WP-45 (P4). Ordering constraints: 41 needs 40's PII kernel; 42 needs 40+41; 44 (gen:context) needs 38 (declarative boundaries make the generator simple) + 43; 45 (create-frontend) needs 43+44. 37/38/39/40/43/46 are otherwise independent. Two open tool forks, decided as step 1 of their WP: 38 dependency-cruiser vs Sheriff; 43 plop vs Angular schematics. Phase 9 (OpenZaak/ZGW integration, WP-49..52) is strictly ordered 49 → 50 → 51 → 52: 49 lands the source seam + ZGW client the rest reuse; 50 (create) needs a zaak to exist; 51 (documents) links to 50's zaak; 52 (notificaties) reacts to changes on the zaken 4951 manage. All slices stay behind Zgw:Enabled (default off) so the POC keeps running offline. Two cross-cutting WPs sit alongside that read→write arc: 53 (a real per-request identity seam + citizen-scoping — replaces the stubbed owner/BSN; production-blocking for a real deployment of 4952) and 54 (a docker OpenZaak harness + opt-in integration test — makes 50/51/52 developable against a live instance instead of only fixtures). 53 is independent of the CRUD arc and can land any time; 54 depends on 49 (something to read) and unlocks realistic testing for the rest. Both are self-contained (each WP file carries its own current-state handoff) and sized for a fresh Sonnet session. Phase 10 (OpenZaak production hardening, WP-55..60 — now done) and Phase 11 (Behandelportal, WP-61..66) are two independent tracks that can be worked concurrently — neither blocks the other. Within phase 10: 55/59/60 were fully independent; 57 and 58 both built on 56's provisioning mechanism, otherwise independent of each other. Within phase 11: 61 (bootstrap), 62 (backend medewerker identity), and 63 (backend status DTO) are independent of each other and can land in any order; 64 needs all three (61 for the app to exist, 62 for identity, 63 for the status it reads); 65 needs 64; 66 needs 65 and — now that WP-60 has landed (bounded retry + flagged divergence in ZgwHttpClient/Program.cs) — inherits that retry for free, but must call RecordZgwDivergence on its own besluit write path to get the flagging half too.

WP template

# WP-NN — Title

Status: todo | in-progress | done (<commit>)
Phase: N — name

## Why

## Read first

## Decisions (pre-made, don't relitigate)

## Files

## Steps

## Acceptance criteria

## Verification

## Out of scope

## Risks