Add the openbaar nginx image (serves the Angular app, reverse-proxies /openbaar to
the BFF, same-origin) and wire it into the compose stack on :8141, anonymous (no
Keycloak dependency). Add it to the health-wait list so the e2e can rely on it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implement RegisterPage: load the full public register from the BFF on open, filter
by the search term via /openbaar/register?q=, and show a results table (referentie +
status), a loading indicator, and an empty-state message. Anonymous, same-origin
relative calls. Adds the app-shell spec. All openbaar lint/test/build green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Scaffolds the anonymous openbaar Angular app (mirrors self-service: standalone +
signals, NL DS via the ui lib, no auth) and adds a failing register-page spec:
loads the public register from the BFF on open, searches by term, and shows an
empty-state message. The stub page renders only the heading, so the list/search/
empty-state assertions fail (red).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The token-attachment bug (secureRoutes set to the app origin, which a relative
api-client URL never matches) was only caught by the full-stack e2e. Add a fast
unit guard: drive the REAL angular-auth-oidc-client interceptor and the REAL
api-client against the production route value, faking only the config source and
the token storage. Asserts the bearer token rides the relative /self-service/
call and is withheld from the anonymous /openbaar/ call.
Extract the value to a shared SECURE_API_ROUTES constant so the test binds to
exactly what the app configures. Verified the guard fails (Authorization null)
if the value regresses to an origin.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add an error branch to submit(): on a failed BFF call, set a `failed` signal,
re-enable the button, and render a role="alert" message so the user knows the
submit did not go through and can retry — instead of the click silently doing
nothing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Failing test: when postSelfServiceRegistrations errors, the page should show an
alert, not the confirmation, and keep the submit button available for retry.
Currently submit() has no error handler, so the rejection is swallowed and the
page silently stays put — exactly the failure mode that hid the missing-token
bug behind a 90s e2e timeout.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After login the submit silently did nothing: the confirmation ("...is
ontvangen...") never rendered because the POST to the BFF went out with no
Authorization header, so the BFF rejected it and the no-error-handler
subscribe left the page unchanged.
Root cause: angular-auth-oidc-client's interceptor attaches the token when
`req.url.startsWith(secureRoute)`. The api-client calls the BFF with RELATIVE
URLs (same-origin via the nginx proxy), so `req.url` is `/self-service/...` —
but secureRoutes was configured as the app ORIGIN (`http://self-service`),
which a relative URL never starts with. No match → no token.
Configure secureRoutes with the relative `/self-service/` prefix instead. The
unit test mocked the api-client, so only the walking-skeleton e2e exercises the
real token attachment — now green.
Verified against a focused stack (keycloak + self-service + real BFF + stub
domain): the submit now carries the bearer token, the BFF forwards to the
domain, and the portal shows the confirmation with the returned reference.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The app loads /config.json at startup (main.ts) so the OIDC authority is set per
environment from one build; appConfig becomes a factory and derives redirectUrl +
secureApiOrigin from the app origin (same-origin as the BFF). A multi-stage
Dockerfile builds the app and serves it via nginx, reverse-proxying /self-service
+ /openbaar to the bff (relative URLs → no CORS); nginx resolves the BFF at request
time. The compose image bakes config.json with the keycloak:8080 authority so the
browser's token issuer matches the BFF (ADR-0010).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
RegistrationPage shows the signed-in BSN and submits to the BFF via the generated
api-client, confirming with the returned reference; built from NL Design System
(Utrecht) components. Wire the guarded route + app providers (DigiD OIDC + token
interceptor + HttpClient), the NL DS theme, and lang=nl. Component tests
(Testing Library) + axe (WCAG 2.1 AA) pass; a guard test covers libs/auth. Replace
the demo eslint depConstraints (scope:shop/shared) with a permissive default.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Scaffold libs/ui (NL Design System via Utrecht components) and libs/auth (DigiD OIDC
over angular-auth-oidc-client: mockable AuthService, provider, token interceptor,
authenticated guard). Failing component + axe tests for the RegistrationPage: it must
show the signed-in BSN, submit to the BFF (mocked api-client) and confirm, with no
WCAG 2.1 AA violations. The page is a stub, so the behaviour tests fail; green follows.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the generated Nx welcome page with a minimal self-service placeholder
(Dutch 'Zelfservice — BIG-registratie' heading + router-outlet); drop nx-welcome.
The login + submit form arrive in S-08c.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bootstrap the Nx (pnpm) workspace at the repo root with the self-service Angular
app (standalone + signals, Vitest via @angular/build, ESLint) — the frontend
foundation. Nx is scoped to apps/+libs/ only; the .NET services stay on
dotnet/Makefile (no @nx/docker inference). A failing test asserts the app renders
a 'Zelfservice' heading; it still shows the generated Nx welcome page, so it fails.
Green commit implements the placeholder.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>