Skip to content

Packaged-action disable is unavailable without the automation service — sys_metadata_activation has only one registrant #12359

Description

@claude

Measured on a real boot while root-causing the #7526 parity failure on PR #12348 (booted showcase stack, bootStack(showcaseStack), authenticated as the dev admin):

POST /api/v1/actions/_activation/showcase_task/showcase_mark_done {"enabled": false}
-> 503 SERVICE_UNAVAILABLE
"Cannot disable packaged action 'showcase_mark_done' — no activation ledger is attached to this
engine (sys_metadata_activation, ADR-0126 §4), so the flip could not be made durable and would
silently revert on the next restart."

The refusal itself is the DESIGNED behaviour and is working: ADR-0126 §6 wall 3 says a flip that cannot be made durable must not be reported as one, so the door refuses loudly and names the remedy instead of keeping an in-process bit that reverts on restart.

The gap

sys_metadata_activation is declared in packages/platform-objects, but the only thing that REGISTERS it today is the automation service plugin's manifest (registerRunObject, alongside sys_automation_run and sys_flow_dispatch) — because flows were the ledger's first and, until #12348, only consumer. Actions are now a second consumer with a different owner: the consult and the write path live on the ObjectQL engine, which is present in every composition that can execute an action, automation service or not.

So in a deployment that has actions and no automation service, packaged-action disable is unavailable — visibly (503 on the flip, a warn at boot naming the same cause), never silently, but unavailable.

Why it was not fixed inside #12348

Where the shared object gets registered is a decision that reaches beyond the action leg:

  • registering it from ObjectQLPlugin adds an @objectstack/objectql -> @objectstack/platform-objects dependency, which inverts the tiering (platform-objects is a catalog the engine serves);
  • registering it from PlatformObjectsPlugin — where the object is declared, beside SysMigration / SysMigrationJournal / SysSecret — is the natural home, but it would then be registered by two manifests in any deployment that also runs automation, and object ownership is governed (ADR-0029 D7 contributor kinds). Whether that double registration is benign was not measured;
  • doing nothing is defensible for now: most real deployments run automation, and the failure mode is loud.

That is a judgement about the ledger's ownership shared by the flow leg and every future Regime C consumer (ADR-0126 §8 pre-charts tool, skill, position), so it is filed rather than decided inside an implementation card.

Reproducing

packages/qa/dogfood boots exactly this composition. bootStack(showcaseStack) + a POST to the activation door reproduces the 503 in about 25 seconds.

Refs: PR #12348 · #12160 · #12296 (the flow leg that registers the object today) · ADR-0126 §4/§6 · ADR-0029 D7


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions