One-time prettier --write so the new format:check CI gate starts green.
.prettierignore excludes generated (api-client.ts, documentation.json),
vendored (public/cibg-huisstijl), and backend (dotnet format owns it).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Turn the interactive Storybook a11y addon into a build gate:
- @storybook/test-runner + axe-playwright over the static build
(.storybook/test-runner.ts reads the a11y tags from story context)
- test-storybook / test-storybook:ci scripts; storybook-a11y CI job
- triage: escape-hatch a11y.disable on stories whose display:contents
wrapper splits <ul>/<li> or <dl>/<dt>/<dd> (structural, deferred to
WP-11/WP-12, each with justification + cross-ref)
- fix trivial violations: footer/wizard-shell contrast, text-input label,
wizard stories missing provideApiClient
Verified: broken story fails the gate; 133 stories pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Fold UploadState into both wizard machines; route via { tag: 'Upload', msg }
- Gate step validation on requiredCategoriesSatisfied; include deliveryRefs in submit
- Shared createUploadController (effectful glue: categories, transport, focus-poll, File map)
- rejectReason pure format validator + specs; bump registratie storage key to v2
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Step 1 was a single field, making the wizard feel thin. Add "Aantal jaren
werkzaam" beside "Gewerkte uren" on the same step (no new step): Draft/Valid
gain `jaren`, `next` validates both step-1 fields before advancing, and
`validate` parses it for the submitted payload. Verified live: an empty jaren
blocks advancing with an inline error.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reorganise from atomic-design-only folders into bounded contexts
(auth / registratie / herregistratie) over a shared kernel, each split into
domain / application / infrastructure / ui layers. Dependencies point inward;
the domain layer is framework-free. Path aliases (@shared/@auth/@registratie/
@herregistratie) make import direction explicit.
State management (Elm-style, native TS, no new deps):
- shared/application/store.ts — createStore(init, update): pure reducer + signal
- shared/application/remote-data.ts — add map/map2/map3/andThen combinators so
several services fold into one RemoteData; <app-async> gains an [rd] input
- registratie/application/big-profile.store.ts — root singleton combining the
BIG-register and BRP services via map2 into one state; holds the optimistic
herregistratie flag shared with the dashboard
- herregistratie: machine gains a WizardMsg union + pure reduce; submit is a
command that calls infra and dispatches the result, with optimistic update +
rollback against the shared store
- auth: SessionStore + DigiD adapter + functional route guard; login establishes
the session, protected routes use canActivate
Rich domain: registration.policy.ts (statusColor/label, herregistratie
eligibility, invariants); BigNummer/Postcode/Uren value objects with smart
constructors. status-badge is now domain-free (colour/label inputs).
Specs for the reducer, RemoteData combinators, and eligibility policy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>