Files
atomic-design-poc/backend/openzaak
ehoandClaude Sonnet 5 5cb3e1a9f0 feat(zgw): docker OpenZaak integration-test harness (WP-54)
Opt-in docker-compose (postgres+redis+OpenZaak, no celery/nginx) +
bootstrap-catalogus.sh seed a real OpenZaak instance; OpenZaakIntegrationTests
(Category=Integration, excluded from default dotnet test/CI) proves the ZGW
seam against it for the first time. That live run caught a real bug:
ZgwHttpClient never sent Content-Crs/Accept-Crs headers, so every write would
412 against a spec-compliant OpenZaak — fixed alongside the harness.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 09:08:35 +02:00
..

OpenZaak integration harness (WP-54)

A real OpenZaak, for developing/testing the ZGW seam (backend/src/BigRegister.Api/Zgw/) against something that isn't a fixture or a stub HttpMessageHandler. Deliberately not part of the root docker-compose.yml and not wired into npm run ci / CI — see docs/reference/openzaak-integration.md for the full picture; this is just "how to run it".

Bring it up

cd backend/openzaak
docker compose -f docker-compose.openzaak.yml up -d   # postgres, redis, migrate+configure, OpenZaak
./bootstrap-catalogus.sh                               # seeds a catalogus/zaaktype/zaak to read back

bootstrap-catalogus.sh waits for OpenZaak to answer, then over plain REST + a hand-rolled HS256 JWT (same shape as ZgwTokenProvider.cs, matching the bigregister-test client setup_configuration/data.yaml creates): a catalogus, a published zaaktype ("Herregistratie arts", with the statustypen/resultaattype/roltype OpenZaak requires before a zaaktype can be published), and one zaak (BIG-2026-000123) with an initiator rol for the seeded BSN (111222333 — the same fixture BSN OpenZaakZaakSourceTests.cs uses). It writes what it seeded to seeded.env (gitignored) and prints a summary.

Not idempotent — re-running against the same (already-seeded) instance fails on OpenZaak's domein+rsin uniqueness constraint for the catalogus. Reset with:

docker compose -f docker-compose.openzaak.yml down -v && docker compose -f docker-compose.openzaak.yml up -d

Run the integration test against it

cd backend
dotnet test --filter Category=Integration

OpenZaakIntegrationTests.cs points a WebApplicationFactory<Program> at Zgw:Enabled=true + http://localhost:8000 with the harness's credentials, hits GET /api/v1/admin/cases, and asserts the seeded zaak comes back — through the real HTTP + JWT + Catalogi-label-resolution path, not a mock. This test is tagged Category=Integration and is excluded from the default dotnet test run and from CI (ci.yml, scripts/ci-local.sh both filter Category!=Integration) — it only passes with this harness up, so it never runs where the harness doesn't exist.

Tear down

docker compose -f docker-compose.openzaak.yml down -v

What's in here / what isn't

  • docker-compose.openzaak.yml — postgres (postgis), redis, a one-shot web-init (runs Django migrations then setup_configuration against setup_configuration/data.yaml), and web (the OpenZaak API on :8000). Pinned to openzaak/open-zaak:1.29.1. No celery/celery-beat/celery-flower/nginx — trimmed for a lean, fast-booting harness; add them back only if a later WP needs a real async notification delivery round-trip here (WP-52's webhook is already covered by fixture tests against no live instance). NOTIFICATIONS_DISABLED=true is required, not optional: without it, OpenZaak 500s (and rolls back the whole create) on any notified resource — see the compose file's comment.
  • setup_configuration/data.yaml — the declarative, scripted alternative to clicking through the Django admin (upstream's own documented setup_configuration CLI mechanism): creates the one bigregister-test client (heeft_alle_autorisaties: true — this instance never exists for anything but this harness, so there's no least-privilege boundary worth modeling).
  • bootstrap-catalogus.sh — the business content (catalogus/zaaktype/zaak/…) setup_configuration has no YAML for; every field value here was checked against OpenZaak's own OpenAPI spec and a live run of this exact script, not guessed (two OpenZaak quirks it works around: a zaaktype needs ≥1 resultaattype and 2 statustypen before it can be published, and its selectielijstklasse and the zaaktype's selectielijstProcestype must reference the same procesType on the public VNG selectielijst API).
  • Not here: Documenten (DRC) / Notificaties (NRC) content — add if a later WP needs to prove those round-trips against a live instance too (WP-51/52 are fixture-tested today).