CI / frontend (push) Successful in 2m59s
CI / backend (push) Successful in 1m27s
CI / semgrep (push) Successful in 58s
CI / e2e (push) Successful in 2m30s
CI / api-client-drift (push) Canceled after 1m14s
CI / storybook-a11y (push) Canceled after 29m8s
Stamdata: add beroepen, opleidingen (temporal), and specialismen tables to the schema-driven catalog (zero UI code). opleidingen.beroep and specialismen.beroep both reference beroepen.code — the first stamdata->stamdata references, enforced by two new StamdataRef entries in the CI gate. OpenZaak/ZGW (WP-49, slice 1 — read-only zaken): introduce IZaakSource as the cases read seam. Default LocalZaakSource reads the local SQLite store (offline); an OpenZaakZaakSource (Zgw/ client: HS256 per-call JWT, ZGW->existing-DTO mapper, paginating HTTP source) is selected behind Zgw:Enabled (default false). The FE never changes — same ApplicationSummaryDto, no api-client drift. Unit-tested with fixtures + a stub HttpMessageHandler; no live OpenZaak needed. Docs: ADR-0005, reference/openzaak-integration.md, WP-49..52 roadmap, stamdata.md update, README index rows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.5 KiB
2.5 KiB
WP-49 — OpenZaak zaken read seam (slice 1)
Status: done Phase: 9 — OpenZaak / ZGW integration
Why
The POC serves cases from local SQLite. To grow toward production it must be able to source them from a real ZGW backend (OpenZaak) without changing the frontend (BFF-lite, ADR-0001). The backend had no data-access abstraction to swap behind, no outbound HTTP, and no JWT. This is the first thin vertical slice: read-only zaken.
Read first
Decisions (pre-made, don't relitigate)
- OpenZaak's anti-corruption layer lives in the BFF, never the browser.
- Source selected by config (
Zgw:Enabled, default false) → POC still runs offline. - Each source maps into the existing
ApplicationSummaryDto→ no api-client drift, no FE change. - Fresh HS256 JWT per call (no refresh flow). Hand-rolled (no new NuGet).
IZaakSourceis sync (matches the endpoint + local store); OpenZaak source does sync-over-async.
Files
Data/IZaakSource.cs,Data/LocalZaakSource.csZgw/{ZgwOptions,ZgwTokenProvider,ZgwZaakMapper,OpenZaakZaakSource}.csProgram.cs(DI + resolveIZaakSourcein/admin/cases),appsettings.json(Zgwsection)- tests:
ZgwTokenProviderTests,ZgwZaakMapperTests,OpenZaakZaakSourceTests
Steps
- Extract the cases read into
IZaakSource;LocalZaakSourcedelegates toApplicationStore. - Build the
Zgw/client (options, JWT minter, ZGW→DTO mapper, paginating HTTP source). - Wire DI by config; refactor
/admin/casesto resolveIZaakSource. - Unit-test the minter, mapper, and source (fixtures + stub
HttpMessageHandler).
Acceptance criteria
/admin/casesserves identical DTOs viaLocalZaakSource(default, offline).OpenZaakZaakSourcefollows pagination, resolves+caches zaaktype labels, sends a Bearer token.- JWT verifies (HS256) with the required claims.
dotnet testgreen (142);npm run cigreen with no api-client drift (FE untouched).
Verification
cd backend && dotnet test; npm run ci; manual: /beheer/zaken still lists cases with Zgw:Enabled=false.
Out of scope
Create-zaak (WP-50), Documenten/DRC (WP-51), Notificaties (WP-52), real inbound OIDC/JWT, OpenZaak in docker-compose.
Risks
Sync-over-async blocks a thread under load if OpenZaak becomes the default → make the read path async then (noted at the call site).