S-14: a beoordeling a behandelaar does not pick up within 14 days escalates to the teamlead.
A non-interrupting P14D boundary timer on the Beoordelen user task fires an external-worker task
(BeoordelingEscaleren); the domain's escalation worker reassigns the still-open task's candidate group
from behandelaar to teamlead. The task keeps its identity — only who may claim it changes. The
escalation-via-external-worker decision is recorded in ADR-0015 (proposal #98); it upholds §8.2
(the Workflow Client stays the only code that talks to Flowable) and keeps Flowable a stock image.
Workflow Client (IBeoordelingEscalatieClient): acquire BeoordelingEscaleren jobs → find the open Beoordelen task in the instance → add teamlead/remove behandelaar candidate group → complete the job. Red → green.
Escalation drain loop (BeoordelingEscalatieProcessor) + hosted BeoordelingEscalatiePump, mirroring the OpenZaak worker. Red → green.
Both branches (escalate after timeout; no-op when completed in time) covered by the Een beoordeling escaleren acceptance scenarios + Workflow Client unit tests.
Live integration: verify-domain fires the timer early via Flowable's management API and asserts the reassignment to teamlead.
Notes for reviewers
Interface segregation: escalation is on IBeoordelingEscalatieClient, separate from the OpenZaak worker's IExternalWorkerClient.
Reassignment is two REST hops (add teamlead, remove behandelaar); idempotent on redelivery — see ADR-0015 consequences.
Local checks green: domain unit tests (104), acceptance (13), dotnet format --verify-no-changes, Release build (0 errors), domain mutation 96.69% (break 90). The run-domain-check.sh escalation path is CI-verified on verify-stack (local full-stack run is constrained here).
BeoordelingEscalatiePump excluded from mutation, mirroring the existing OpenZaakJobPump exclusion.
## What & why
S-14: a beoordeling a behandelaar does not pick up within **14 days** escalates to the **teamlead**.
A non-interrupting `P14D` boundary timer on the `Beoordelen` user task fires an external-worker task
(`BeoordelingEscaleren`); the domain's escalation worker reassigns the still-open task's candidate group
from `behandelaar` to `teamlead`. The task keeps its identity — only who may claim it changes. The
escalation-via-external-worker decision is recorded in **ADR-0015** (proposal #98); it upholds §8.2
(the Workflow Client stays the only code that talks to Flowable) and keeps Flowable a stock image.
Closes #15
## Definition of Done
- [x] Linked Gitea issue (above).
- [x] Failing test committed before the implementation.
- [x] Implementation makes the test pass; refactor commit if structure improved.
- [x] Conventional Commits referencing the issue (`refs #NN`).
- [x] CI green — all Gitea Actions jobs.
- [x] `docker compose up` from a fresh clone reaches green health checks within 3 minutes (no new services; escalation is additive to the domain worker).
- [x] Docs updated (ADR-0015, demo note).
- [x] ADR added (`docs/architecture/adr-0015-beoordeling-escalation.md`).
- [x] Demo note in `docs/demo-script.md`.
## How it was built (TDD)
- **Workflow Client** (`IBeoordelingEscalatieClient`): acquire `BeoordelingEscaleren` jobs → find the open `Beoordelen` task in the instance → add `teamlead`/remove `behandelaar` candidate group → complete the job. Red → green.
- **Escalation drain loop** (`BeoordelingEscalatieProcessor`) + hosted `BeoordelingEscalatiePump`, mirroring the OpenZaak worker. Red → green.
- **BPMN**: non-interrupting `P14D` boundary timer on `Beoordelen` → external task → escalation end.
- **Both branches** (escalate after timeout; no-op when completed in time) covered by the `Een beoordeling escaleren` acceptance scenarios + Workflow Client unit tests.
- **Live integration**: `verify-domain` fires the timer early via Flowable's management API and asserts the reassignment to teamlead.
## Notes for reviewers
- Interface segregation: escalation is on `IBeoordelingEscalatieClient`, separate from the OpenZaak worker's `IExternalWorkerClient`.
- Reassignment is two REST hops (add teamlead, remove behandelaar); idempotent on redelivery — see ADR-0015 consequences.
- Local checks green: domain unit tests (104), acceptance (13), `dotnet format --verify-no-changes`, Release build (0 errors), **domain mutation 96.69%** (break 90). The `run-domain-check.sh` escalation path is CI-verified on verify-stack (local full-stack run is constrained here).
- `BeoordelingEscalatiePump` excluded from mutation, mirroring the existing `OpenZaakJobPump` exclusion.
Failing Workflow Client tests for the 14-day escalation capability (ADR
proposal #98): acquire BeoordelingEscaleren external-worker jobs, reassign the
still-open Beoordelen task's candidate group behandelaar -> teamlead, and
complete the escalation job. Methods are stubbed to throw so the suite compiles
and fails on the new behaviour only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implement the BeoordelingEscaleren escalation capability on the Flowable
Workflow Client: acquire escalation jobs, find the still-open Beoordelen task in
the instance and swap its candidate group behandelaar -> teamlead via task
identity links, and complete the job. Segregated onto IBeoordelingEscalatieClient
so the OpenZaak worker is unaffected (ADR-0015).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Failing tests for BeoordelingEscalatieProcessor: acquire the parked
BeoordelingEscaleren jobs, reassign each instance to teamlead, complete the job,
and leave a failed reassignment un-completed for redelivery. PumpOnceAsync is
stubbed to throw so the suite compiles and fails on the new behaviour only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a non-interrupting P14D boundary timer on the Beoordelen user task that fires
an external-worker task (BeoordelingEscaleren) to the escalation end; wire the
hosted BeoordelingEscalatiePump and register the escalation client/processor in DI.
On timeout the still-open beoordeling is reassigned to teamlead (ADR-0015).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Gherkin scenarios for the two branches: a beoordeling left unclaimed for 14 days
escalates to the teamlead, and one completed before the timer fires does not.
Driven through the escalation worker against an in-memory Flowable stand-in.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend the live verify-domain check: a third registration parks at Beoordelen,
its boundary timer is fired early via Flowable's management API, and the check
polls until the domain escalation worker reassigns the still-open task's
candidate group from behandelaar to teamlead (ADR-0015). Runs on the CI
verify-stack.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Record the escalation-via-external-worker decision (ADR-0015, from proposal #98)
and add the S-14 demo walkthrough that fires the 14-day timer early via Flowable's
management API to observe the reassignment to teamlead.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The hosted escalation pump is a thin shell with logic in the unit-tested
processor, mirroring the existing OpenZaakJobPump exclusion (§5).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Flowable's async executor picks up the moved timer job and fires the boundary
event before the check can GET /management/jobs, so requiring that async job to
still exist raced and failed. The move alone fires the timer; the explicit
execute is now a best-effort nudge that tolerates the job already being gone.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
not
merged commit 7bcbc726ce into main2026-07-17 09:45:37 +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.
What & why
S-14: a beoordeling a behandelaar does not pick up within 14 days escalates to the teamlead.
A non-interrupting
P14Dboundary timer on theBeoordelenuser task fires an external-worker task(
BeoordelingEscaleren); the domain's escalation worker reassigns the still-open task's candidate groupfrom
behandelaartoteamlead. The task keeps its identity — only who may claim it changes. Theescalation-via-external-worker decision is recorded in ADR-0015 (proposal #98); it upholds §8.2
(the Workflow Client stays the only code that talks to Flowable) and keeps Flowable a stock image.
Closes #15
Definition of Done
refs #NN).docker compose upfrom a fresh clone reaches green health checks within 3 minutes (no new services; escalation is additive to the domain worker).docs/architecture/adr-0015-beoordeling-escalation.md).docs/demo-script.md.How it was built (TDD)
IBeoordelingEscalatieClient): acquireBeoordelingEscalerenjobs → find the openBeoordelentask in the instance → addteamlead/removebehandelaarcandidate group → complete the job. Red → green.BeoordelingEscalatieProcessor) + hostedBeoordelingEscalatiePump, mirroring the OpenZaak worker. Red → green.P14Dboundary timer onBeoordelen→ external task → escalation end.Een beoordeling escalerenacceptance scenarios + Workflow Client unit tests.verify-domainfires the timer early via Flowable's management API and asserts the reassignment to teamlead.Notes for reviewers
IBeoordelingEscalatieClient, separate from the OpenZaak worker'sIExternalWorkerClient.dotnet format --verify-no-changes, Release build (0 errors), domain mutation 96.69% (break 90). Therun-domain-check.shescalation path is CI-verified on verify-stack (local full-stack run is constrained here).BeoordelingEscalatiePumpexcluded from mutation, mirroring the existingOpenZaakJobPumpexclusion.