# 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/SHOWCASE-ROADMAP.md`**.

## Session protocol

- **Switch to Opus first** (`/model opus`) before tackling any WP.
- **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.
- 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)

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

From WP-01 onward, additionally:

```bash
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](WP-01-axe-ci-gate.md)           | Axe-on-every-story CI gate                                   | 0 · gates                   | done   |
| [WP-02](WP-02-check-tokens.md)          | Harden `check:tokens` + fix what it catches                  | 0 · gates                   | done   |
| [WP-03](WP-03-contracts-purity.md)      | Boundaries I: contracts purity + ApiClient confinement       | 0 · gates                   | done   |
| [WP-04](WP-04-ui-not-infrastructure.md) | Boundaries II: `ui ↛ infrastructure` + showcase sanction     | 0 · gates                   | done   |
| [WP-05](WP-05-parse-boundaries.md)      | Parse-don't-validate closure + MDX                           | 1 · FP/DDD                  | done   |
| [WP-06](WP-06-typed-async.md)           | Generic async template contexts — kill `$any()`              | 1 · FP/DDD                  | done   |
| [WP-07](WP-07-brief-idioms.md)          | Brief on the shared idioms + RemoteData MDX                  | 1 · FP/DDD                  | done   |
| [WP-08](WP-08-store-idiom.md)           | One store idiom + machine naming + TEA MDX                   | 1 · FP/DDD                  | done   |
| [WP-09](WP-09-pure-logic.md)            | Pure-logic closure: dates + missing command specs            | 1 · FP/DDD                  | done   |
| [WP-10](WP-10-button-fidelity.md)       | CIBG button fidelity                                         | 2 · CIBG                    | done   |
| [WP-11](WP-11-markup-fidelity.md)       | CIBG markup fidelity: application-link + absent-class triage | 2 · CIBG                    | done   |
| [WP-12](WP-12-datablock.md)             | CIBG Datablock for application data                          | 2 · CIBG                    | done   |
| [WP-13](WP-13-cibg-gap-register.md)     | CIBG-gap register + hygiene + MDX                            | 2 · CIBG                    | done   |
| [WP-14](WP-14-storybook-taxonomy.md)    | Storybook taxonomy reorg + Layers MDX                        | 3 · Storybook               | done   |
| [WP-15](WP-15-missing-stories.md)       | Missing stories: shell + brief components                    | 3 · Storybook               | done   |
| [WP-16](WP-16-component-a11y.md)        | Component a11y: description wiring + alert role              | 4 · a11y                    | done   |
| [WP-17](WP-17-app-a11y.md)              | App-level a11y: route focus, template lint, WCAG checklist   | 4 · a11y                    | done   |
| [WP-18](WP-18-abac-capability-spine.md) | ABAC capability spine (Principal + capabilities, phase P1)   | 5 · productie-volwassenheid | done   |
| [WP-19](WP-19-e2e-smoke.md)             | Playwright e2e smoke                                         | 5 · productie-volwassenheid | done   |
| [WP-20](WP-20-second-locale.md)         | Second locale proof                                          | 5 · productie-volwassenheid | done   |
| [WP-21](WP-21-resilience-seams.md)      | Resilience seams (correlation-id, idempotency, retry)        | 5 · productie-volwassenheid | done   |
| [WP-22](WP-22-durable-persistence.md)   | Durable persistence (optional tier)                          | 5 · productie-volwassenheid | done   |
| [WP-23](WP-23-org-template-backend.md)  | Org-template backend + admin role                            | 6 · Brief v2                | done   |
| [WP-24](WP-24-letter-canvas.md)         | Letter canvas (edit on the letter)                           | 6 · Brief v2                | done   |
| [WP-25](WP-25-letter-preview-html.md)   | Server-rendered letter preview (HTML; PDF deferred)          | 6 · Brief v2                | todo   |
| [WP-26](WP-26-org-template-editor.md)   | Admin org-template editor                                    | 6 · Brief v2                | done   |
| [WP-27](WP-27-brief-ux-layer.md)        | Brief UX layer (undo/redo, standaardbrief, diff)             | 6 · Brief v2                | todo   |
| [WP-28](WP-28-brief-v2-demo-polish.md)  | Brief v2 demo polish (scenarios, e2e, docs)                  | 6 · Brief v2                | 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.

## WP template

```markdown
# 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
```
