9 Commits

Author SHA1 Message Date
44eb2d2186 chore(deps): update npm packages within declared ranges; reformat for prettier 3.9.4
Some checks failed
CI / frontend (push) Successful in 1m46s
CI / storybook-a11y (push) Successful in 4m23s
CI / backend (push) Successful in 1m14s
CI / codeql (csharp) (push) Has been cancelled
CI / codeql (javascript-typescript) (push) Has been cancelled
CI / api-client-drift (push) Has been cancelled
CI / e2e (push) Has been cancelled
npm update brought every package to the latest version its existing package.json
range allows (Angular tooling 22.0.2/22.0.4 -> 22.0.5, prettier 3.8.4 -> 3.9.4,
typescript-eslint 8.62.0 -> 8.62.1); package.json itself needed no range changes.

Auditing actual deprecation warnings (not just outdated versions) found nothing
further to fix: @angular/platform-browser-dynamic and @angular-devkit/build-angular
are deprecated by Angular but still required peer dependencies of the latest
published @storybook/angular (10.4.6 — peer range still `>=18.0.0 < 22.0.0`,
already why .npmrc sets legacy-peer-deps); jest-process-manager/expect-playwright
are transitive-only through @storybook/test-runner's latest stable (0.24.4). No
newer version of either Storybook package exists yet that drops them. The
remaining npm audit advisory (@babel/core, low severity) is the same
already-documented, deliberately-left issue in README.md (fixing it downgrades
Angular). Left package.json's overrides untouched.

The prettier bump alone changed formatting opinions on files this session didn't
otherwise touch (a stale markdown italics marker, a few object-literal wrap
points) — reformatted everything so `format:check` (part of CI) doesn't regress.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 10:29:36 +02:00
26c2c5acd0 feat(fp): WP-19 — Playwright e2e smoke against the real FE+backend
Adds a happy-path spec (login → dashboard → registratie wizard, including
a real identity-document upload → real submit) and a degraded-path spec
(?scenario=error → <app-async> error slot → retry), both driving the real
app against the real .NET backend, plus a CI job that boots both.

Writing the retry spec surfaced a real bug: AsyncComponent's retry() only
reloads a [resource]-fed instance, so every real page (all [data]-fed via
a store's RemoteData) had a silently no-op retry button. Added a
retryClicked output and wired it on the dashboard's two async blocks.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 10:13:40 +02:00
e272869f00 feat(fp): WP-17 — app-level a11y: route focus, template lint, WCAG checklist
Adds route-change focus management (new page's h1, afterNextRender) plus
scroll-position restoration wired once in app.config.ts; angular-eslint's
templateAccessibility bundle linting every inline template via
processInlineTemplates (verified firing with a planted violation, one real
hit fixed in rich-text-editor); docs/wcag-checklist.md and Foundations/
Accessibility MDX tying the four a11y layers (axe, lint, play tests,
manual checklist) together. The checklist pass already earned its keep —
it found a real 320px overflow in aanvraag-block's warning alert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 08:26:01 +02:00
97f7de4590 feat(a11y): WP-01 — axe-on-every-story CI gate
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>
2026-07-02 19:13:18 +02:00
94ffcf3d41 Step 1: i18n foundation (@angular/localize) + data inventory
Domain reference data already lives in the backend (per ADR-0001); the only
residual "move" was ~90 inlined Dutch UI strings with no i18n layer.

- Wire @angular/localize ($localize) — Angular first-party, no third-party lib
- Pin the pattern on shared/ui/async: Dutch fallbacks → language-agnostic
  input()s with localizable $localize defaults (English-shared-UI rule)
- CLAUDE.md: drop i18n (now in scope) + stale "real backend"/"OpenAPI codegen"
  (both already shipped); document the $localize convention

Bulk string sweep deferred to Step 2 to avoid touching ~36 files twice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 13:42:12 +02:00
d08f3877f7 Architect-review remediation: enforce conventions, prod-safe tooling, one form idiom, resilience seams
Acts on the showcase review. Four workstreams; all tests green
(npm run lint, 70 FE tests, ng build, 33 backend tests).

Enforcement + CI:
- eslint.config.mjs bans `any` and enforces layer/context boundaries
  (domain ≠ Angular; herregistratie → registratie → shared, auth → shared);
  `npm run lint` added; ajv 6 scoped to ESLint via nested override.
- .github/workflows/ci.yml: FE lint+check:tokens+test+build, backend dotnet test,
  and an API-client drift check.

One form idiom (the headline finding):
- change-request-form converged onto the wizard pattern — change-request.machine.ts
  (Model/Msg/reduce + value objects) + submit-change-request.ts (Result) + a real
  POST /api/v1/change-requests (server re-validates). Spec + story added; the detail
  page no longer holds an ad-hoc success signal.

Resilience/observability seam:
- api-client.provider.ts: request timeout, X-Correlation-Id, Idempotency-Key for
  writes; comments naming the retry/auth seams.
- Backend logs correlation id + a no-PII submit-audit line; /api/v1 prefix +
  backward-compat note; client regenerated.

Quick wins:
- Dev tooling excluded from prod: scenario.interceptor wired only under isDevMode()
  (?scenario= inert in prod); debug panel @if(isDev) (tree-shaken out).
- src/environments + apiBaseUrl into provideApiClient (angular.json fileReplacements).
- Backend /health + /health/ready.
- Debug view PII-minimised (redactProfile: name/address/DOB redacted, BIG masked).
- IntakePolicyAdapter (removes inline resource in the intake wizard).
- README de-staled; CLAUDE.md gains EN/NL + forms-one-idiom + lint/CI notes.
- Stories: text-input, link, data-row, site-header, site-footer, change-request-form.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 08:25:51 +02:00
cf570a8132 Add ASP.NET Core backend hosting business rules; FE consumes via typed client
Move the authoritative business rules off the frontend into a real backend,
realising the BFF-lite + decision-DTO design (ADR-0001) that until now lived
only in static mock JSON.

Backend (backend/):
- ASP.NET Core (.NET 10) minimal API, contract-first, Swagger UI at /swagger.
- DDD Domain/ rules layer: profession derivation + applicable policy questions
  (DiplomaRules), herregistratie eligibility + reason (HerregistratieRule),
  scholing threshold (IntakePolicy), submit rejections + reference generation
  (SubmissionRules). In-memory seeded data, ProblemDetails (RFC 7807) errors.
- 27 xUnit tests: rule units + endpoint integration incl. BRP no-address and
  DUO not-found fallbacks and 422 submit paths.

Frontend (only infrastructure/ + contracts/ change, as the architecture promised):
- NSwag-generated typed client (api-client.ts), routed through Angular HttpClient
  via a small fetch adapter so the ?scenario= interceptor still applies.
- GET adapters use resource({ loader: client.x }); submit commands call the client
  and map ProblemDetails -> err. The hardcoded uren==0 / manual-diploma rules are
  deleted (now server-side). Domain, stores, UI and format validators unchanged.
- Deleted the now-dead public/mock/*.json.

Tooling/docs:
- npm start proxies /api -> backend; npm run gen:api regenerates the client;
  docker compose up runs both (bind mounts use :z for SELinux/Fedora).
- backend/README.md walkthrough: adding a policy question is a one-file backend
  change, no FE change, no client regen. Updated CLAUDE.md + ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 20:05:53 +02:00
Claude
4e14152758 Content-only page transitions + dependency security overrides
- Persistent ShellComponent hosts the router-outlet so header/footer mount once
  (no re-mount flash); pages nest under a shell route. page-shell is now
  content-only; page-layout removed.
- Native withViewTransitions() cross-fades only the routed content (chrome gets
  stable view-transition-names); respects prefers-reduced-motion.
- package.json overrides pin patched transitive dev/build deps: npm audit 16
  (3 high/9 mod/4 low) -> 5 low; shipped app stays at 0 (npm audit --omit=dev).
  No Angular downgrade, no breaking Babel 8 bump. jsdom 28 -> 29.
- README: page-transitions section + honest dependency-security note.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 15:46:42 +02:00
Claude
033d6f0317 Atomic-design POC: BIG-register self-service portal (Angular + Rijkshuisstijl)
Atoms/molecules/organisms/templates/pages composing the NL Design System
(Utrecht) CSS themed Rijkshuisstijl via @rijkshuisstijl-community tokens.
Login -> dashboard -> registration detail, mock JSON over HttpClient, Storybook
organized by atomic layer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:23:11 +02:00