Skip to content

feat(approvals): mirror every HITL approval into the shared OpenRegister task service - #1812

Merged
rubenvdlinde merged 1 commit into
developmentfrom
feat/hitl-on-shared-tasks
Sep 2, 2026
Merged

feat(approvals): mirror every HITL approval into the shared OpenRegister task service#1812
rubenvdlinde merged 1 commit into
developmentfrom
feat/hitl-on-shared-tasks

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What

The adoption seam for wave 2 of the fleet task consolidation (openspec change hitl-on-shared-tasks). Depends on ConductionNL/openregister#3338 (merged): tasks now carry onTimeout/onReject and the shared timer sweep enforces expiresAt.

  • Every ApprovalService::suspend*() (endpoint rule, flow step, synchronization gate, subscription gate) also creates ONE shared task through OpenRegister's TaskService::import(): approver group as candidate group, requester, expiresAt, and the record's onTimeout/onReject when they are in the shared vocabulary. The task uuid lands on the approval_request as taskUuid.
  • completeApproval()/reject() close the mirror with the matching outcome (approved, rejected, or dead_letter when the record's onReject routed it there), attributed to the deciding user.
  • Expiry of the mirror is OWNED by OpenRegister's sweep (the task declares onTimeout); integriq's own ApprovalTimeoutSweepJob keeps resolving the record. Both are idempotent, so the pair converges without coordination.
  • A mirror failure never gates the approval flow: logged, swallowed, record unchanged.
  • Test stubs for the shared service copy the REAL signatures (import(array $data, ?string $actor): Task, applyTimerOutcome(string $uuid, string $outcome, string $source, string $reason): Task).

What this deliberately does NOT do

The approval_request stays the system of record for suspend/resume orchestration (FlowToken snapshots, resume ordering, consumption) — four callers compose that around this service, and retiring it in the seam PR would be a half-delete. Follow-ups are itemised in the openspec change's tasks.md section 2 and the tracking issue: task-first resolution via TaskTransitionedEvent, retiring the app-local sweep for mirrored rows, delegating the approver notification, translating the mirror copy.

Verification

  • Full unit suite: 2707 tests green.
  • phpcs, phpmd, phpstan, psalm: clean.
  • hydra gates --scope-to-diff: all 30 applicable gates green.

…ter task service

The adoption seam for the fleet task consolidation (wave 2, depends on
openregister task-expiry-and-outcomes): every suspension creates one shared
task through TaskService::import() carrying the approver group, requester,
expiresAt and the record's onTimeout/onReject, linked back via taskUuid;
approve and reject close the mirror with the matching outcome; the shared
timer sweep owns the mirror's expiry. A mirror failure never gates the
approval flow. Full retirement of the app-local machinery is tracked as
follow-up in the openspec change.
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/integriq @ 0302e1b

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
build
check-specs
test-l10n
format
check-schema-l10n
check-l10n-js
composer ✅ 141/141
npm ✅ 537/537
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright ⏭️ deferred — runs on the promotion into beta/main, not on a pull request into development
Hydra gates

Quality workflow — 2026-09-02 13:05 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit b97ac6a into development Sep 2, 2026
51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant