⚠️ OpenSpec-managed issue — this content is automatically synced
from the openspec/ directory. Manual edits will be overwritten on next sync.
Artifacts
Summary
The delegation of contract / besluit / bezwaar / advice decisions from dossiq to decidesk
was implemented against a transport that does not exist. ContractDecisionDelegationService
resolves decidesk by calling
container->get('OCA\OpenRegister\Service\IntegrationService')->getLeaf(name:'decidesk') and then
->createDecision(payload:...). There is no OCA\OpenRegister\Service\IntegrationService class and
no getLeaf() / createDecision() method — every call throws, is caught, and resolveIntegrationService()
returns null, so delegation always fail-closes and never reaches decidesk. The flow is only
"safe" because it fails closed; it has never actually delegated a decision.
decidesk has since MERGED a concrete event contract on its development branch. The chosen transport
is the Nextcloud IEventDispatcher: a consumer dispatches OCA\Decidesk\Event\DecisionRequestedEvent
synchronously, decidesk's in-process listener handles it and writes the result back onto the event
(isHandled() + getDecisionId()), and decidesk later dispatches OCA\Decidesk\Event\DecisionConcludedEvent
carrying the terminal outcome. This change rewires dossiq's delegation services onto that contract.
What changes:
ContractDecisionDelegationService injects OCP\EventDispatcher\IEventDispatcher. raiseContractDecision()
and raiseDecision() build and dispatchTyped() a DecisionRequestedEvent
(guarded by class_exists(\OCA\Decidesk\Event\DecisionRequestedEvent::class) — fail closed when
decidesk is absent), then read back isHandled() / getDecisionId(). The dead getLeaf /
IntegrationService / createDecision(payload:...) / getDecisionOutcome / resolveIntegrationService()
/ consumeOutcome() paths are removed.
- A new
DecisionConcludedListener listens for DecisionConcludedEvent, filters
getSourceApp() === 'dossiq', builds the normalised outcome from the event getters, and drives
BesluitMaterialisationService to materialise the
Specs
Tasks
Design
See design.md for technical design details.
Synced from openspec/changes/dossiq-delegation-via-events by OpenSpec workflow
App: dossiq
Artifacts
Summary
The delegation of contract / besluit / bezwaar / advice decisions from dossiq to decidesk
was implemented against a transport that does not exist.
ContractDecisionDelegationServiceresolves decidesk by calling
container->get('OCA\OpenRegister\Service\IntegrationService')->getLeaf(name:'decidesk')and then->createDecision(payload:...). There is noOCA\OpenRegister\Service\IntegrationServiceclass andno
getLeaf()/createDecision()method — every call throws, is caught, andresolveIntegrationService()returns
null, so delegation always fail-closes and never reaches decidesk. The flow is only"safe" because it fails closed; it has never actually delegated a decision.
decidesk has since MERGED a concrete event contract on its
developmentbranch. The chosen transportis the Nextcloud
IEventDispatcher: a consumer dispatchesOCA\Decidesk\Event\DecisionRequestedEventsynchronously, decidesk's in-process listener handles it and writes the result back onto the event
(
isHandled()+getDecisionId()), and decidesk later dispatchesOCA\Decidesk\Event\DecisionConcludedEventcarrying the terminal outcome. This change rewires dossiq's delegation services onto that contract.
What changes:
ContractDecisionDelegationServiceinjectsOCP\EventDispatcher\IEventDispatcher.raiseContractDecision()and
raiseDecision()build anddispatchTyped()aDecisionRequestedEvent(guarded by
class_exists(\OCA\Decidesk\Event\DecisionRequestedEvent::class)— fail closed whendecidesk is absent), then read back
isHandled()/getDecisionId(). The deadgetLeaf/IntegrationService/createDecision(payload:...)/getDecisionOutcome/resolveIntegrationService()/
consumeOutcome()paths are removed.DecisionConcludedListenerlistens forDecisionConcludedEvent, filtersgetSourceApp() === 'dossiq', builds the normalised outcome from the event getters, and drivesBesluitMaterialisationServiceto materialise theSpecs
Tasks
OCP\EventDispatcher\IEventDispatcherintoContractDecisionDelegationService.raiseContractDecision()to build +dispatchTyped()araiseDecision()(shared core used by the bezwaar/advice siblings) the same way.resolveIntegrationService(),consumeOutcome(), and allcreateDecision(payload:...)/BezwaarDecisionDelegationService,lib/Listener/DecisionConcludedListener.phpimplementingIEventListener, filteringBesluitMaterialisationService::materialiseFromConcludedEvent()that maps the event getters\OCA\Decidesk\Event\DecisionConcludedEvent::classinBezwaar/DecisionService::applyToBezwaar()to stop polling decidesk viaconsumeOutcome()grep -rn "getLeaf|OCA\\OpenRegister\\Service\\IntegrationService|createDecision(payload:|consumeOutcome|getDecisionOutcome" lib/php -levery changed PHP file.scripts/run-hydra-gates.sh); report results.openspec validate dossiq-delegation-via-events --strictexits 0.Design
See design.md for technical design details.
Synced from
openspec/changes/dossiq-delegation-via-eventsby OpenSpec workflowApp:
dossiq