The two highest-value OpenZaak roadmap gaps, each written self-contained (a "current state" handoff section) so a fresh session can execute from the file + repo alone: - WP-53: replace the stubbed owner/BSN with a real per-request CallerIdentity (pluggable stub, not DigiD), threading it into Authz, the ZGW JWT user claims, and a citizen-scoped read (rol__…__inpBsn). Production-blocking for a real deployment. - WP-54: a separate docker-compose OpenZaak + scripted bootstrap + opt-in Category=Integration test — makes 50/51/52 developable against a live instance instead of only fixtures; kept out of the default gate. Indexed in the backlog README (rows + phase-9 ordering note) and cited from openzaak-integration.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
115 lines
6.7 KiB
Markdown
115 lines
6.7 KiB
Markdown
# WP-54 — Docker OpenZaak integration-test harness
|
|
|
|
Status: todo
|
|
Phase: 9 — OpenZaak / ZGW integration
|
|
|
|
## Why
|
|
|
|
Everything ZGW so far is verified against **fixtures + a stub `HttpMessageHandler`** — nothing
|
|
exercises a real OpenZaak. That is fine for unit-testing the mapper/JWT/pagination, but it does
|
|
not prove the BFF actually talks to OpenZaak (auth accepted, real response shapes, real
|
|
pagination, zaaktype resolution). This WP stands up a **local OpenZaak via docker**, seeds a
|
|
minimal catalog + a client credential matching `ZgwOptions`, and adds an **opt-in** integration
|
|
test that points the BFF at it with `Zgw:Enabled=true`. It closes the "no live instance" gap
|
|
called out in the roadmap and makes WP-50/51/52 developable against something real.
|
|
|
|
## Context — current state (read before designing; self-contained handoff)
|
|
|
|
- **What exists to test**: `backend/src/BigRegister.Api/Zgw/OpenZaakZaakSource.cs` (lists zaken,
|
|
follows `{count,next,previous,results}`, resolves zaaktype labels from Catalogi, Bearer auth
|
|
via `ZgwTokenProvider`), selected when `Zgw:Enabled=true`. Config is the `Zgw` section of
|
|
`appsettings.json` (`ZrcBaseUrl`, `ZtcBaseUrl`, `ClientId`, `Secret`, `UserId`,
|
|
`UserRepresentation`) → `Zgw/ZgwOptions.cs`.
|
|
- **Current tests** (the pattern to extend, not replace): `ZgwZaakMapperTests` (inline JSON),
|
|
`OpenZaakZaakSourceTests` (stub handler). These stay as fast unit tests; the new integration
|
|
test is a **separate, opt-in** category so the default `dotnet test` and CI stay fast/offline.
|
|
- **Existing compose**: repo root `docker-compose.yml` runs FE + BFF only (Swagger at :5000).
|
|
Do **not** bolt OpenZaak onto it — OpenZaak is heavy (postgres + redis + celery). Use a
|
|
**separate** compose file so `docker compose up` stays light for everyone else.
|
|
- **Test project**: `backend/tests/BigRegister.Tests/` (xunit). It uses
|
|
`Microsoft.AspNetCore.Mvc.Testing` (`TestWebApplicationFactory.cs`) — the factory can be
|
|
configured to override the `Zgw` config section to point at the compose instance.
|
|
- **CLAUDE.md / backlog GREEN**: the default local gate and CI must remain runnable without
|
|
docker/OpenZaak. Anything requiring the harness is explicitly separate (like e2e is today —
|
|
a distinct job, not chained into `npm run ci`).
|
|
|
|
OpenZaak facts that shape the harness (from the ZGW research):
|
|
|
|
- OpenZaak is the reference impl of the 5 ZGW APIs; the published
|
|
`docker-compose.yml` (github.com/open-zaak/open-zaak) brings up **openzaak (web + celery),
|
|
postgres, redis** and (optionally) Open Notificaties. A one-time **bootstrap** is required:
|
|
create a superuser, register an **Application** in the Autorisaties API with a **Client
|
|
ID/Secret + scopes** (`zaken.lezen`, `catalogi.lezen`, …), and import/create a **Catalogus
|
|
with a zaaktype** (published) so there is something to read.
|
|
- Auth = the HS256 JWT the BFF already mints; the harness's client credentials must **match**
|
|
`ZgwOptions.ClientId`/`Secret`.
|
|
- Reading a zaak needs read scope on **both** Zaken and Catalogi (zaaktype resolution).
|
|
|
|
## Read first
|
|
|
|
- [openzaak-integration.md](../reference/openzaak-integration.md) (the seam + config keys).
|
|
- [ADR-0005](../reference/architecture/0005-openzaak-behind-bff.md).
|
|
- WP-19 (`WP-19-e2e-smoke.md`) — the precedent for a heavy, separate, opt-in test job (mirror
|
|
its "not chained into the default gate" structure).
|
|
- Upstream: OpenZaak docker docs (https://open-zaak.readthedocs.io/) + the repo's
|
|
`docker-compose.yml` and its `import` fixtures for a demo catalogus.
|
|
|
|
## Decisions (pre-made, don't relitigate)
|
|
|
|
- **Separate compose file** (e.g. `backend/openzaak/docker-compose.openzaak.yml`), never merged
|
|
into the root compose. `docker compose up` stays FE+BFF only.
|
|
- **Opt-in test category.** Tag the integration test `[Trait("Category", "Integration")]`;
|
|
exclude it from the default run (`dotnet test --filter Category!=Integration`) and from the
|
|
standard CI jobs. Provide a documented command / optional manual CI job to run it.
|
|
- **Bootstrap is scripted, not manual.** A checked-in setup (compose `import` fixture or a small
|
|
bootstrap script) creates the client credentials (matching `ZgwOptions`), a catalogus, and one
|
|
published zaaktype + one zaak — so the test is deterministic and repeatable.
|
|
- **Provider stays stubbed** (WP-53) — this WP is about the ZGW round-trip, not real user auth.
|
|
|
|
## Files
|
|
|
|
- New: `backend/openzaak/docker-compose.openzaak.yml` + bootstrap fixture/script + a short
|
|
`backend/openzaak/README.md` (how to bring it up, credentials, teardown).
|
|
- New: `backend/tests/BigRegister.Tests/OpenZaakIntegrationTests.cs` (Category=Integration):
|
|
configure the BFF (`WebApplicationFactory`) with `Zgw:Enabled=true` + the compose URLs/creds,
|
|
hit `/admin/cases`, assert the seeded zaak comes back mapped.
|
|
- Edit: `docs/reference/openzaak-integration.md` (add a "Run against real OpenZaak" section);
|
|
optionally a manual/gated CI job in `.github/workflows/ci.yml` mirroring the e2e job's shape.
|
|
|
|
## Steps
|
|
|
|
1. Add the separate compose file bringing up OpenZaak + postgres + redis; pin image versions.
|
|
2. Script the bootstrap: superuser, Autorisaties Application (Client ID/Secret = `ZgwOptions`),
|
|
a catalogus + one published zaaktype + one zaak with a natuurlijk-persoon rol (the seeded BSN).
|
|
3. Write the opt-in integration test: point the BFF at the compose instance, assert the mapped
|
|
zaak (id = uuid, type = zaaktype label, status) via `/admin/cases`.
|
|
4. Document `docker compose -f … up` + the run command; optionally add a manual CI job.
|
|
|
|
## Acceptance criteria
|
|
|
|
- [ ] `docker compose -f backend/openzaak/docker-compose.openzaak.yml up` yields a reachable
|
|
OpenZaak with the seeded catalogus + zaak, and credentials matching `ZgwOptions`.
|
|
- [ ] The Category=Integration test passes against it; the BFF returns the seeded zaak mapped to
|
|
`ApplicationSummaryDto` through the real HTTP + JWT path.
|
|
- [ ] Default `dotnet test` and `npm run ci` are unaffected (integration test excluded, no docker
|
|
needed); `docker compose up` (root) is unchanged.
|
|
|
|
## Verification
|
|
|
|
`docker compose -f backend/openzaak/docker-compose.openzaak.yml up -d` →
|
|
`dotnet test --filter Category=Integration` → green; then teardown.
|
|
|
|
## Out of scope
|
|
|
|
Documenten/DRC + Notificaties services in the harness (add when WP-51/52 land), a permanent
|
|
always-on CI job (keep it opt-in/manual — OpenZaak startup is slow), performance testing.
|
|
|
|
## Risks
|
|
|
|
- OpenZaak startup is slow + resource-heavy → keep it opt-in; a permanent CI job would blow the
|
|
same runner budget WP's storybook cap just fixed.
|
|
- ZGW API/version drift vs the pinned image can change response shapes → pin image versions and
|
|
keep the fixture in the repo.
|
|
- Bootstrap client scopes must include `catalogi.lezen` or zaaktype resolution 403s — cover in
|
|
the setup script.
|