# 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 - [ADR-0005 — OpenZaak behind the BFF](../reference/architecture/0005-openzaak-behind-bff.md) - [openzaak-integration.md](../reference/openzaak-integration.md) ## 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). - `IZaakSource` is sync (matches the endpoint + local store); OpenZaak source does sync-over-async. ## Files - `Data/IZaakSource.cs`, `Data/LocalZaakSource.cs` - `Zgw/{ZgwOptions,ZgwTokenProvider,ZgwZaakMapper,OpenZaakZaakSource}.cs` - `Program.cs` (DI + resolve `IZaakSource` in `/admin/cases`), `appsettings.json` (`Zgw` section) - tests: `ZgwTokenProviderTests`, `ZgwZaakMapperTests`, `OpenZaakZaakSourceTests` ## Steps 1. Extract the cases read into `IZaakSource`; `LocalZaakSource` delegates to `ApplicationStore`. 2. Build the `Zgw/` client (options, JWT minter, ZGW→DTO mapper, paginating HTTP source). 3. Wire DI by config; refactor `/admin/cases` to resolve `IZaakSource`. 4. Unit-test the minter, mapper, and source (fixtures + stub `HttpMessageHandler`). ## Acceptance criteria - [x] `/admin/cases` serves identical DTOs via `LocalZaakSource` (default, offline). - [x] `OpenZaakZaakSource` follows pagination, resolves+caches zaaktype labels, sends a Bearer token. - [x] JWT verifies (HS256) with the required claims. - [x] `dotnet test` green (142); `npm run ci` green 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).