feat(workflow): document-wait task + 30-day timeout cancellation (S-10a, closes #102) #105

Merged
not merged 23 commits from feat/102-document-wait-timeout into main 2026-07-20 09:42:03 +00:00
23 Commits
Author SHA1 Message Date
notandClaude Opus 4.8 5f77dae587 test(e2e): provide documents on the live self-service tab after the zaak opens (refs #102)
CI / lint (pull_request) Successful in 1m20s
CI / build (pull_request) Successful in 1m2s
CI / unit (pull_request) Successful in 1m12s
CI / frontend (pull_request) Successful in 2m35s
CI / mutation (pull_request) Successful in 5m15s
CI / verify-stack (pull_request) Successful in 7m54s
The process only parks at WachtOpDocumenten once the OpenZaak worker has opened the
zaak, so providing documents immediately after submit raced the wait and no-op'd.
Check the openbaar INGEDIEND row on a second page (proving the zaak is open, hence
the process is at the wait) while the self-service tab keeps its submitted state,
then provide documents there — unblocking the werkbak.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 11:22:07 +02:00
notandClaude Opus 4.8 8d936ffdaa test(acceptance): CapturingDomainClient implements ProvideDocumentsAsync (refs #102)
CI / unit (pull_request) Successful in 1m10s
CI / lint (pull_request) Successful in 1m22s
CI / build (pull_request) Successful in 1m2s
CI / frontend (pull_request) Successful in 2m42s
CI / mutation (pull_request) Successful in 5m28s
CI / verify-stack (pull_request) Failing after 15m47s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:48:58 +02:00
notandClaude Opus 4.8 990db61ba7 docs(backlog): S-10a includes the provision trigger; S-10b is real ZGW storage (refs #102)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:46:45 +02:00
notandClaude Opus 4.8 5402bc179c docs(workflow): S-10a owns the document-provision trigger (ADR-0017, demo) (refs #102)
Records why the provision trigger (domain + BFF + portal 'Documenten aanleveren')
lives in S-10a — the WachtOpDocumenten gate would otherwise leave the e2e red — and
narrows S-10b to the real ZGW document storage. Notes the withdrawal-while-waiting
follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:46:13 +02:00
notandClaude Opus 4.8 2b60f8e51f feat(portal): 'Documenten aanleveren' action on the self-service page (refs #102)
After submitting, the zorgprofessional supplies their documents; the page posts to
the BFF keyed by the reference and confirms ("Uw documenten zijn aangeleverd"), with
a surfaced failure + retry. The registration e2e provides documents before the
behandelaar step, since the process now parks at WachtOpDocumenten first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:45:24 +02:00
notandClaude Opus 4.8 07139324a3 feat(domain): timeout worker skips an already-resolved registration (refs #102)
Expire only a still-open (INGEDIEND/IN_BEHANDELING) registration; an already
resolved one (expired, or withdrawn/decided while it waited) is left untouched so
the job completes without violating the aggregate invariant (§8.6). Closes the
S-10a/S-11 race where a withdrawal-while-waiting would loop the expiry job.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:45:11 +02:00
notandClaude Opus 4.8 0d1e2825e5 test(domain): timeout worker no-ops on an already-resolved registration (refs #102)
RED: if the citizen withdrew while parked at WachtOpDocumenten, the RegistratieVerlopen
job finds a terminal (INGETROKKEN) aggregate; the worker must no-op and let the job
complete, not throw into a redelivery loop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:45:11 +02:00
notandClaude Opus 4.8 cf1c77489d test(portal): self-service offers 'documenten aanleveren' after submit (refs #102)
RED: after submitting, a "Documenten aanleveren" action posts to the BFF keyed by
the reference and the page confirms; a failure surfaces an alert and keeps the
action. Regenerates the api-client from the updated BFF spec.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:42:36 +02:00
notandClaude Opus 4.8 404454d270 feat(bff): POST /self-service/registrations/{id}/documents (S-10a) (refs #102)
Authenticated self-service endpoint that takes the bsn from the DigiD token,
forwards "documenten aanleveren" to the domain, and relays 404 for an unknown or
not-owned registration. Regenerates the committed openapi.json.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:41:11 +02:00
notandClaude Opus 4.8 771450d46d test(bff): self-service documents endpoint forwards id + bsn to the domain (refs #102)
RED: POST /self-service/registrations/{id}/documents requires a digid token, takes
the bsn from the token, forwards to the domain, and relays the domain's 404 for an
unknown/not-owned registration. Adds the IDomainClient.ProvideDocumentsAsync port +
client + fake; the endpoint itself follows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:39:31 +02:00
notandClaude Opus 4.8 c21becd5b9 feat(domain): ProvideDocuments completes the wait + POST /registrations/{id}/documents (refs #102)
The provide-documents use case completes the WachtOpDocumenten task via the
Workflow Client (owner-scoped by bsn, best-effort), exposed as an owner-scoped
domain endpoint. This is the trigger that unblocks the process; the real file
upload + ZGW storage lands in S-10b.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:37:25 +02:00
notandClaude Opus 4.8 7ceb22d46d test(domain): providing documents completes the WachtOpDocumenten wait (refs #102)
RED: the ProvideDocuments use case completes the document wait via the Workflow
Client, owner-scoped by the caller's bsn (a different bsn is NotFound), and is
best-effort when no process was started yet — mirroring WithdrawRegistration.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:36:21 +02:00
notandClaude Opus 4.8 d943b54ce8 docs(workflow): ADR-0017 + demo note for the document-wait timeout (refs #102)
CI / lint (pull_request) Successful in 1m18s
CI / build (pull_request) Successful in 59s
CI / unit (pull_request) Successful in 1m10s
CI / frontend (pull_request) Successful in 2m33s
CI / mutation (pull_request) Successful in 10m22s
CI / verify-stack (pull_request) Failing after 11m24s
Records the interrupting P30D WachtOpDocumenten timer, the RegistratieVerlopen
worker, and the new terminal Verlopen status; notes the S-10a/S-10b boundary
(ZGW zaak-close deferred). Demo covers both branches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:59:36 +02:00
notandClaude Opus 4.8 00c5077fe4 test(infra): verify-domain drives the document wait + 30-day timeout live (refs #102)
Every registration now parks at WachtOpDocumenten first, so each existing block
completes that task (documents received) before expecting Beoordelen/CBGVAdvies.
Adds a timeout block: a registration whose documents never arrive has its P30D
timer fired via the management-API move idiom, and the domain expires it to VERLOPEN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:58:08 +02:00
notandClaude Opus 4.8 5180253826 test(acceptance): document-termijn verloopt (both branches) (refs #102)
BDD for S-10a: a registration parked at WachtOpDocumenten expires to VERLOPEN when
the 30-day timer fires, and does NOT expire when documents arrive first. Drives the
real RegistratieVerlopenProcessor + ExpireRegistrationWorker against an in-memory
Flowable stand-in, mirroring the escalation feature.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:55:47 +02:00
notandClaude Opus 4.8 9bd71f1e78 feat(workflow): WachtOpDocumenten wait task + 30-day timeout cancellation (refs #102)
Inserts a WachtOpDocumenten user task after OpenZaakAanmaken with an interrupting
P30D boundary timer: "documents received" completes it and the process continues to
the diploma routing; on timeout the RegistratieVerlopen external-worker task runs
and the process ends as verlopen (ADR-0017). Verified live against flowable-rest:
complete -> routes to Beoordelen; timer fire -> RegistratieVerlopen job (carrying
registrationId) + the wait task cancelled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:53:01 +02:00
notandClaude Opus 4.8 3f04cb856f feat(infra): Flowable RegistratieVerlopen worker + document-wait completion (refs #102)
FlowableWorkflowClient implements IRegistratieVerlopenClient (acquire/complete the
RegistratieVerlopen jobs) and CompleteDocumentWaitAsync (complete WachtOpDocumenten,
best-effort). Wires the RegistratieVerlopenProcessor + hosted RegistratieVerlopenPump
into the domain host and excludes the pump from mutation (like the other pumps).
Fakes updated for the new IWorkflowClient member.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:48:38 +02:00
notandClaude Opus 4.8 9421aa007a test(infra): Flowable client acquires/completes RegistratieVerlopen + completes wait task (refs #102)
RED: the Workflow Client posts the RegistratieVerlopen topic and parses the
correlated registration id, completes the expiry job, and (documents-in-time)
completes the WachtOpDocumenten user task in the instance — best-effort no-op if
that task is no longer open.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:45:26 +02:00
notandClaude Opus 4.8 c536c965de feat(domain): RegistratieVerlopen worker + processor expire on document timeout (refs #102)
Adds RegistratieVerlopenJob, IRegistratieVerlopenClient, the ExpireRegistrationWorker
application handler, and the RegistratieVerlopenProcessor drain loop — the timeout
counterpart to the OpenZaak/escalation worker trios.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:44:15 +02:00
notandClaude Opus 4.8 5add817c10 test(domain): RegistratieVerlopen worker expires the correlated registration (refs #102)
RED: ExpireRegistrationWorker loads the registration a RegistratieVerlopen job
correlates to and expires it (idempotent on redelivery, throws on unknown so the
job is redelivered); RegistratieVerlopenProcessor drains the parked jobs and
completes each, leaving a failing one un-completed (§8.6). Mirrors the OpenZaak
and escalation worker/processor pairs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:43:13 +02:00
notandClaude Opus 4.8 11ef26d8cc feat(domain): Registration.Expire() lapses an open registration to Verlopen (refs #102)
Adds the terminal Verlopen status and Expire(), reusing the RequireOpenForDecision
guard so only an INGEDIEND/IN_BEHANDELING registration can lapse; idempotent once
Verlopen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:42:07 +02:00
notandClaude Opus 4.8 f39ec2afa3 test(domain): a document-wait timeout expires the registration to Verlopen (refs #102)
RED: Registration.Expire() moves an open registration to a new terminal
Verlopen status, needs no zaak, is idempotent on redelivery, and is rejected
once the registration has been decided or withdrawn.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:41:29 +02:00
notandClaude Opus 4.8 67a60e7f63 docs(backlog): split S-10 into S-10a (#102) and S-10b (#103) (refs #102)
S-10 (#11) spanned six net-new surfaces incl. a new ZGW boundary — too large
for one slice (§13). S-10a is the workflow/timeout spine (backend); S-10b is
the document-upload vertical (ACL Documenten API + portal). #11 closed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 09:36:10 +02:00