npm run gen:context scaffolds a bounded context: folders + starter page, the @<ctx>/* tsconfig alias, a dependency-cruiser boundary entry, and a lazy authGuard route. Refactors .dependency-cruiser.js's per-context contextRule calls into a single CONTEXT_ALLOWED map that every rule derives from, so adding a context is really one config entry (verified behavior-preserving: same dep:check counts, same graph output). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
15 KiB
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. Plan/design under Opus (
/model opus) — a WP's approach and edge cases deserve the stronger model. Switch to Sonnet to write the code once the plan is approved — routine implementation against a pre-made Decisions block doesn't need Opus. Delegate simple, read-only CLI checks (running a test suite,grep/git status, verifying a file exists) to a Haiku subagent where the harness supports it — 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 0–5 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 | todo |
| 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 | todo |
| 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 | todo |
| WP-51 | OpenZaak Documenten (DRC) upload + zaak link | 9 · OpenZaak/ZGW | todo |
| WP-52 | OpenZaak Notificaties (NRC) live status via webhook | 9 · OpenZaak/ZGW | todo |
| WP-53 | Inbound identity seam + citizen-scoping (per-request BSN, ZGW audit claims) | 9 · OpenZaak/ZGW | todo |
| WP-54 | Docker OpenZaak integration-test harness (opt-in, live round-trip) | 9 · OpenZaak/ZGW | todo |
Sequencing dependencies (stated in the WPs too): 01 before 10–15 (axe covers story churn);
03/04 before 05–09 (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. 18–22 (phase 5, "productie-volwassenheid")
are independent of each other and of phases 1–4 — 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); 33–36 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 49–51 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 49–52) 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