Local aanvraag/document writes and their paired ZGW writes aren't transactional; a ZGW failure after the local write succeeds used to diverge silently. ZgwHttpClient now retries transport-shaped failures (not 500, which can follow a partial commit on the non-idempotent statussen/rollen POSTs), and a ZGW failure that survives retry sets Aanvraag.ZgwError plus a zgw:divergence audit row instead of failing or diverging quietly. No outbox/reconcile job: three request-triggered write paths don't justify a persisted queue that would also need to carry citizen PII for the JWT audit claims. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
73 lines
2.9 KiB
Markdown
73 lines
2.9 KiB
Markdown
# WP-66 — Wire the decision into OpenZaak
|
|
|
|
Status: todo
|
|
Phase: 11 — Behandelportal
|
|
|
|
## Why
|
|
|
|
WP-65's decision currently only updates local state (`LocalZaakSource`). For the
|
|
behandelportal to actually function against a real register, the recorded decision needs
|
|
to also write a besluit/status transition to ZGW — extending the write capability that
|
|
already partially exists (`CreateStatusRequest`, `CreateRolRequest` in
|
|
`OpenZaakZaakSource.cs`) rather than building a new ZGW client from scratch.
|
|
|
|
## Read first
|
|
|
|
- `backend/src/BigRegister.Api/Zgw/OpenZaakZaakSource.cs` (existing write records)
|
|
- ZGW's Besluiten API (referenced in `openzaak-integration.md` if covered, or the ZGW
|
|
standard docs) for besluit creation
|
|
- [WP-50](WP-50-openzaak-create-zaak.md) (the first ZGW write slice, for the pattern to
|
|
follow)
|
|
|
|
## Decisions (pre-made, don't relitigate)
|
|
|
|
- Extend `IZaakSource`/`OpenZaakZaakSource` with a besluit/status-transition write,
|
|
following the same pattern WP-50 established for create-zaak (a records + mapper
|
|
addition, not a new abstraction).
|
|
- Gated by `Zgw:Enabled` like every other ZGW write — the behandelportal keeps working
|
|
against `LocalZaakSource` when it's off.
|
|
- Best done after Phase 10's WP-60 (write-divergence resilience) lands, since this is
|
|
exactly the second write pair that resilience work should already cover — but not
|
|
strictly blocked on it if Phase 10 is still in progress (call out the residual risk
|
|
explicitly if shipped first).
|
|
|
|
## Files
|
|
|
|
`Zgw/OpenZaakZaakSource.cs` (besluit/status write), `Data/IZaakSource.cs` (new write
|
|
method), tests.
|
|
|
|
## Steps
|
|
|
|
1. Add the besluit/status-transition write to `OpenZaakZaakSource`, mirroring WP-50's
|
|
create-zaak pattern.
|
|
2. Wire WP-65's decision command to call it when `Zgw:Enabled=true`.
|
|
3. Integration test against the WP-54 harness (extend `OpenZaakIntegrationTests`).
|
|
|
|
## Acceptance criteria
|
|
|
|
- [ ] A recorded decision writes a real besluit/status transition to OpenZaak when
|
|
`Zgw:Enabled=true`.
|
|
- [ ] Behandelportal still works unchanged against `LocalZaakSource` when
|
|
`Zgw:Enabled=false`.
|
|
- [ ] `OpenZaakIntegrationTests` covers the new write.
|
|
|
|
## Verification
|
|
|
|
`cd backend && dotnet test --filter Category=Integration` against the (ideally
|
|
Phase-10-hardened) OpenZaak harness; manual smoke with `Zgw:Enabled=true`.
|
|
|
|
## Out of scope
|
|
|
|
Any further behandelportal screens beyond beoordeling.
|
|
|
|
## Risks
|
|
|
|
WP-60 (write-divergence resilience) has landed: bounded retry lives in `ZgwHttpClient`, so
|
|
this write pair inherits it automatically. It does **not** get the flagging half for free —
|
|
call `RecordZgwDivergence` (or the equivalent for whichever endpoint hosts the besluit write) on
|
|
this path's catch too, the same way `Program.cs`'s submit endpoint does for create-zaak/document
|
|
writes, or this becomes the "second, currently-unprotected write pair" WP-60's own scope note
|
|
anticipated.
|
|
|
|
Depends on: WP-65.
|