S-10c · Close the ZGW zaak on document-timeout expiry (closes#106)
Completes the S-10a/S-10b boundary flagged in ADR-0017: when a registration's 30-day document term lapses, the domain now cancels the ZGW zaak as well as marking the aggregate Verlopen, so OpenZaak and the register no longer diverge.
What it does
On expiry the ExpireRegistrationWorker calls the ACL to set the zaak to a distinct, non-terminal Geannuleerd status with a Vervallen resultaat (vs the approval Afgehandeld + Geregistreerd), resolved by omschrijving in the ACL — the ACL-first ordering mirrors approval so a failed ZGW call leaves the job for redelivery rather than diverging the two.
ACL gateway — SetZaakToCancellationStatusAsync (Geannuleerd + Vervallen by name); approval now resolves its Geregistreerd resultaat by name too (a second resultaattype now exists).
ACL service/API — AclService.CancelZaakAsync + POST /annuleringen.
Domain — IAclClient.CancelZaakAsync + client; expiry worker cancels the zaak before advancing to Verlopen, guarded against redelivery double-cancel.
Seed — non-terminal Geannuleerd statustype (volgnummer 2; Afgehandeld → 3) + Vervallen resultaattype, both idempotent by omschrijving and sharing the zaaktype's procestype.
Verify/integration — ACL↔OpenZaak integration test (live Geannuleerd + resultaat); run-domain-check.sh fires the real P30D timer and asserts the zaak reaches Geannuleerd end-to-end; BDD scenario asserts cancel-on-timeout vs untouched-when-in-time.
ZGW allows only one eindstatus per zaaktype, so Geannuleerd is modelled as a non-terminal status (it records a cancellation status + resultaat but does not set einddatum). This follows the issue's explicit "distinct statustype + resultaat" outcome; the shared-eindstatus alternative is recorded in the ADR.
Tests
Unit + acceptance all green locally (Acl 38, Big 134, Acceptance 17, Bff 33, EventSubscriber 19). Integration + verify-stack run in CI (need live OpenZaak + selectielijst egress).
## S-10c · Close the ZGW zaak on document-timeout expiry (closes #106)
Completes the S-10a/S-10b boundary flagged in ADR-0017: when a registration's 30-day document term lapses, the domain now cancels the **ZGW zaak** as well as marking the aggregate `Verlopen`, so OpenZaak and the register no longer diverge.
### What it does
On expiry the `ExpireRegistrationWorker` calls the ACL to set the zaak to a distinct, non-terminal **`Geannuleerd`** status with a **`Vervallen`** resultaat (vs the approval `Afgehandeld` + `Geregistreerd`), resolved **by omschrijving** in the ACL — the ACL-first ordering mirrors approval so a failed ZGW call leaves the job for redelivery rather than diverging the two.
**Path:** Flowable P30D timer → `RegistratieVerlopen` job → domain `ExpireRegistrationWorker` → ACL `POST /annuleringen` → ZGW `resultaten` + `statussen` (Geannuleerd) → aggregate `Verlopen`.
### Layers touched (each red→green)
- **ACL gateway** — `SetZaakToCancellationStatusAsync` (Geannuleerd + Vervallen by name); approval now resolves its `Geregistreerd` resultaat by name too (a second resultaattype now exists).
- **ACL service/API** — `AclService.CancelZaakAsync` + `POST /annuleringen`.
- **Domain** — `IAclClient.CancelZaakAsync` + client; expiry worker cancels the zaak before advancing to `Verlopen`, guarded against redelivery double-cancel.
- **Seed** — non-terminal `Geannuleerd` statustype (volgnummer 2; `Afgehandeld` → 3) + `Vervallen` resultaattype, both idempotent by omschrijving and sharing the zaaktype's procestype.
- **Verify/integration** — ACL↔OpenZaak integration test (live `Geannuleerd` + resultaat); `run-domain-check.sh` fires the real P30D timer and asserts the zaak reaches `Geannuleerd` end-to-end; BDD scenario asserts cancel-on-timeout vs untouched-when-in-time.
- **Docs** — ADR-0019 (cancellation modelling decision), demo-script, BACKLOG.
### Design note (ADR-0019)
ZGW allows only one eindstatus per zaaktype, so `Geannuleerd` is modelled as a **non-terminal** status (it records a cancellation status + resultaat but does not set `einddatum`). This follows the issue's explicit "distinct statustype + resultaat" outcome; the shared-eindstatus alternative is recorded in the ADR.
### Tests
Unit + acceptance all green locally (Acl 38, Big 134, Acceptance 17, Bff 33, EventSubscriber 19). Integration + verify-stack run in CI (need live OpenZaak + selectielijst egress).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
S-10c: the document-timeout branch must set the zaak to a distinct
cancellation statustype (Geannuleerd) + resultaat (Vervallen), resolved by
omschrijving. With a second resultaattype present, approval must also
resolve its resultaat (Geregistreerd) by name rather than taking the first.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SetZaakToCancellationStatusAsync resolves the cancellation statustype and
resultaat by omschrijving and posts resultaat-then-status, mirroring the
approval path. Approval now resolves its Geregistreerd resultaat by name too,
since a second resultaattype now exists.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The ACL exposes zaak cancellation as a service operation the domain calls on
document-timeout expiry; it default-fills the zaaktype and dates the status
today, translating the domain intent to the ZGW cancellation status/resultaat.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
S-10c: expiring the aggregate to VERLOPEN is not enough — the ZGW zaak must
also be cancelled through the ACL (§8.1). Adds IAclClient.CancelZaakAsync and
its client/fakes, and asserts the worker cancels a still-open registration's
zaak but leaves an already-resolved one untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The expiry worker asks the ACL to cancel the zaak before advancing the
aggregate to VERLOPEN, so a lapsed document term is reflected in ZGW and not
only in the domain. Ordered ACL-first for redelivery safety; guarded so a
redelivered job neither re-saves nor re-cancels.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extends the S-10a feature to S-10c: a timed-out registration's zaak is
cancelled via the ACL, while documents-in-time leave the zaak untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
S-10c needs a distinct cancellation status/resultaat. Adds a non-terminal
Geannuleerd statustype (between Ontvangen and the Afgehandeld eindstatus) and a
second Vervallen resultaattype, both idempotent by omschrijving. Both
resultaattypen draw their selectielijstklasse from the zaaktype's single
procestype so they validate on publish.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds an ACL↔OpenZaak integration test asserting SetZaakToCancellationStatusAsync
records the Geannuleerd status + a resultaat against real OpenZaak, and extends
the domain verify script to confirm a timed-out registration's zaak is cancelled
to Geannuleerd end-to-end.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Records the ZGW cancellation-modelling decision (distinct non-terminal
Geannuleerd status + Vervallen resultaat, resolved by name) and documents the
end-to-end timeout-cancellation path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The new SetZaakToCancellationStatusAsync added surviving mutants (uncovered
null-guards and the failure-action messages) that dropped the ACL mutation
score below the 90% break threshold. Add null-argument and rejected-POST tests
for the cancellation path; score back to 93.46%.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cancellation reaches OpenZaak correctly (Geannuleerd status_created), but
the verify read-back ran 'docker run python:3-slim python -' without -i, so the
heredoc never reached the container's stdin and the script was empty — the check
always saw an empty status. Add -i so the read actually queries OpenZaak.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
not
merged commit c8fdfbb699 into main2026-07-21 13:58:16 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
S-10c · Close the ZGW zaak on document-timeout expiry (closes #106)
Completes the S-10a/S-10b boundary flagged in ADR-0017: when a registration's 30-day document term lapses, the domain now cancels the ZGW zaak as well as marking the aggregate
Verlopen, so OpenZaak and the register no longer diverge.What it does
On expiry the
ExpireRegistrationWorkercalls the ACL to set the zaak to a distinct, non-terminalGeannuleerdstatus with aVervallenresultaat (vs the approvalAfgehandeld+Geregistreerd), resolved by omschrijving in the ACL — the ACL-first ordering mirrors approval so a failed ZGW call leaves the job for redelivery rather than diverging the two.Path: Flowable P30D timer →
RegistratieVerlopenjob → domainExpireRegistrationWorker→ ACLPOST /annuleringen→ ZGWresultaten+statussen(Geannuleerd) → aggregateVerlopen.Layers touched (each red→green)
SetZaakToCancellationStatusAsync(Geannuleerd + Vervallen by name); approval now resolves itsGeregistreerdresultaat by name too (a second resultaattype now exists).AclService.CancelZaakAsync+POST /annuleringen.IAclClient.CancelZaakAsync+ client; expiry worker cancels the zaak before advancing toVerlopen, guarded against redelivery double-cancel.Geannuleerdstatustype (volgnummer 2;Afgehandeld→ 3) +Vervallenresultaattype, both idempotent by omschrijving and sharing the zaaktype's procestype.Geannuleerd+ resultaat);run-domain-check.shfires the real P30D timer and asserts the zaak reachesGeannuleerdend-to-end; BDD scenario asserts cancel-on-timeout vs untouched-when-in-time.Design note (ADR-0019)
ZGW allows only one eindstatus per zaaktype, so
Geannuleerdis modelled as a non-terminal status (it records a cancellation status + resultaat but does not seteinddatum). This follows the issue's explicit "distinct statustype + resultaat" outcome; the shared-eindstatus alternative is recorded in the ADR.Tests
Unit + acceptance all green locally (Acl 38, Big 134, Acceptance 17, Bff 33, EventSubscriber 19). Integration + verify-stack run in CI (need live OpenZaak + selectielijst egress).
🤖 Generated with Claude Code