Skip to content

service-automation: a restart re-arms the trigger of a ledger-disabled packaged flow — registerTrigger ignores the activation ledger, and every matching event then logs an ERROR claiming a run-history record that is never written #20677

Description

@objectstack-fleet

QA-source: #20674 · automation.packaged-flow-disable-durable · c3

What happens

A packaged flow switched off through the ADR-0126 activation ledger comes back bound after a cold restart. Execution is still refused (no run is recorded, so the kill switch itself holds), but the trigger is armed again, every matching mutation fires it, and each firing is logged at ERROR as a failed trigger-fired run whose failure "is recorded in the flow's run history" — while the run history holds nothing.

Measured on main at 6bff748b (showcase, objectstack dev, file DB), reproduced on two consecutive cold boots over the same DB file.

Reproduction

  1. Boot with a file DB; as the seeded admin POST /api/v1/automation/showcase_urgent_task_alert/toggle {"enabled":false} → 200. GET /api/v1/automation/_status → enabled:false, bound:false; the ledger row reads active: false.
  2. Stop the server process entirely; boot again over the same DB file (OS_LOG_LEVEL=info shows the lines below).
  3. GET /api/v1/automation/_status. Expected: enabled:false, bound:false. Actual: enabled:false, bound:true, stable after waiting.
  4. Boot-log order: [Automation] Activation ledger: 1 packaged flow(s) are switched off for this installation and were left unbound — 'showcase_urgent_task_alert'. → [Automation] Bound 30 flow(s) from the protocol at kernel:ready → Trigger registered: record_change.
  5. POST /api/v1/data/showcase_task with priority: 'urgent' (plus the required title, project, status): the server logs ERROR Trigger-fired run of flow 'showcase_urgent_task_alert' failed (trigger 'record_change') — no caller holds this result and nothing retries the run; the terminal failure is recorded in the flow's run history… carrying the FLOW_DISABLED sentence; GET /api/v1/automation/showcase_urgent_task_alert/runs (also ?status=failed) shows no new run.

Mechanism (read from source at 6bff748b)

  • AutomationEngine.registerTrigger (packages/services/service-automation/src/engine.ts) iterates every registered flow not in boundFlowTriggers and calls activateFlowTrigger(name) when its trigger type matches — without consulting isFlowEnabled(name). activateFlowTrigger has no enablement check either.
  • Trigger plugins register their trigger at kernel:ready, which fires after AutomationServicePlugin.start() pulled the flows and ran hydrateFlowActivations() (which correctly unbound the flow and logged so).
  • registerFlow does honour the ledger ("A ledger-disabled flow is NOT re-armed here…"); this second arming path does not. The engine pins in flow-activation-ledger.test.ts cover hydration and re-registration, not a trigger registered after hydration.

Why it matters

  • /_status — the Studio status badges' source — reports a disabled flow as bound after every deploy.
  • An administrator's deliberate switch-off produces an ERROR line per matching event, and that line claims a run-history record that does not exist, which reads as a production failure.
  • The item's P0 contract ("a restart that re-arms the flow (enabled or bound true…) is a FAIL against the whole point of ADR-0126 §7.2") is red on main. RUNNER rule 7 applies: re-derive independently before acting.

Expected

After a restart a ledger-disabled flow stays unbound regardless of when its trigger type registers; no trigger-fired failure is logged for it.

Full evidence chain: #20674 (F-2).


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:workflowApprovals and automation — the work that runs without a person driving itbugSomething isn't workingdomain:servicespriority:p1High: required for production / M2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions