Skip to content

The boot action-governance inventory reads type only, so every declarative operation: 'update' action is warned as "a button wired to nothing" #15444

Description

@os-litant

Filed out of scope from #15079 (the runtime executor for the declarative row-level operation: 'update' action, ruled on #14092). Found while auditing whether the card's list of four type-only readers is complete — it is not, and this is the fifth.

What happens

reconcileActionRegistrations in packages/objectql/src/action-governance.ts builds the unboundDeclarations finding — "a declared script action with no body and no handler under any candidate key: a button wired to nothing" — from a type-only test:

for (const { action, objectName, storeKey } of declarations) {
    if ((action?.type ?? 'script') !== 'script') continue; // only script needs a handler
    if (action?.body) continue;                            // its handler is synthesized

A declarative update action is exactly that shape and is meant to be: ActionSchema refuses target and body beside operation: 'update', and its type stays at the materialized default 'script' because the platform action route IS where the write is performed. So every such action falls through both continues and lands in unboundDeclarations.

runActionGovernanceInventory then logs, at every boot and on every metadata:reloaded:

[action-governance] declared script actions with NO handler — a button wired to
nothing (ADR-0078); add a `body`, or register a handler under the declared `target`

Once the runtime executor lands, that sentence is false for these actions and its prescription is actively wrong: adding a body or a target is refused at parse time for an operation: 'update' action.

Why it is not just noise

The inventory is the ADR-0110 D5 governance surface an operator reads to find real dead buttons. A population that is never actionable and grows with every declarative update action an app author writes is how a diagnostic stops being read — and the undeclared-handler 404 on the /actions door cites [action-governance] by name as the place to look.

Blast radius, measured

  • Warn-only. runActionGovernanceInventory is documented as "warn-only and exception-proof"; nothing refuses a boot or a dispatch on it, and the route dispatches the update correctly regardless. No behaviour is wrong — the diagnostic is.
  • It reaches every host that boots the engine plugin, once per boot plus once per metadata reload whose fingerprint changed.

The fix, in one line of the same shape the runtime took

Read operation before type, as the runtime doors now do:

if (action?.operation === 'update') continue;   // the platform performs the write

@objectstack/objectql is where the reader lives, so this is that package's card. The runtime side deliberately did not widen into it: the executor does not need this seam, and #15079's file surface says to report rather than widen silently.

Refs

#15079 (the runtime executor) · #14092 (the ruling) · PR #15077 (the spec half, where operation/patch land) · ADR-0110 D5 (the inventory) · ADR-0078

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions