Files
atomic-design-poc/docs/project/backlog
ehoandClaude Sonnet 5 5cb3e1a9f0 feat(zgw): docker OpenZaak integration-test harness (WP-54)
Opt-in docker-compose (postgres+redis+OpenZaak, no celery/nginx) +
bootstrap-catalogus.sh seed a real OpenZaak instance; OpenZaakIntegrationTests
(Category=Integration, excluded from default dotnet test/CI) proves the ZGW
seam against it for the first time. That live run caught a real bug:
ZgwHttpClient never sent Content-Crs/Accept-Crs headers, so every write would
412 against a spec-compliant OpenZaak — fixed alongside the harness.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 09:08:35 +02:00
..

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 todo
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-ssp 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

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-ssp) 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.

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