You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The REST /actions route resolved the DECLARATION from the URL segment as a
name but dispatched the HANDLER using that same segment as a registry key.
For a target-bound action those differ, so the documented curl resolved the
declaration then 404ed, while the Console's target-addressed call dispatched
fine and resolved no declaration — silently skipping the ADR-0066 D4 gate and
the ADR-0104 param contract.
D1/D2 — identity is the declarative name on every surface; handler-key
candidates are derived from the resolved declaration via a rotation now shared
with the MCP run_action bridge.
D3 (BREAKING) — resolution is a trichotomy: declared -> gate + dispatch;
metadata plane unreachable -> 503 (MetadataManager.loadDiagnosed tells a clean
miss from an outage); genuinely undeclared -> 404 naming the defineAction to
add, instead of executing ungated with system privileges.
OS_ALLOW_UNDECLARED_ACTIONS=1 is the migration valve, removed in 18.
D5 — reconcileActionRegistrations + ObjectQLEngine.listRegisteredActions power
a kernel:ready inventory of undeclared handlers and unbound declarations.
D6 — security-gate strictness is opt-out, never opt-in.
Ships in lockstep with objectui#2970.
Copy file name to clipboardExpand all lines: docs/adr/0110-action-identity-and-declaration-admission.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,7 @@
1
1
# ADR-0110: An action's identity is its `name`; anything executable over a governed surface must have a declaration (the declaration-admission gate)
2
2
3
-
**Status**: Proposed (2026-07-29) — **targeted at protocol 17** (`@objectstack/spec@17.0.0-rc.0`, in RC now). The fail-closed inversion lands in that major rather than staging across two, joining its two siblings already in the v17 breaking set: *"A flow run with no trigger user may not touch data"* (#3760 — missing identity fails closed) and *"A datasource that cannot connect fails the boot"* (#3741/#3758/#3826 — an unreachable dependency refuses rather than degrades).
3
+
**Status**: **Accepted — implemented** (2026-07-29) in protocol 17 (`@objectstack/spec@17.0.0-rc.0`). The fail-closed inversion landed in that major rather than staging across two, joining its two siblings in the v17 breaking set: *"A flow run with no trigger user may not touch data"* (#3760 — missing identity fails closed) and *"A datasource that cannot connect fails the boot"* (#3741/#3758/#3826 — an unreachable dependency refuses rather than degrades).
4
+
Evidence: D1/D2 — `action-execution.ts` (`resolveActionHandlerKeys`, `executeRegisteredAction`) shared by `domains/actions.ts` and `invokeBusinessAction`, pinned by `http-dispatcher.actions-identity-addressing.test.ts` (the documented curl now gates AND dispatches). D3 — the trichotomy in `domains/actions.ts`, reading the `degraded` signal `MetadataManager.loadDiagnosed` supplies (`metadata-manager.ts`). D5 — `reconcileActionRegistrations` + `ObjectQLEngine.listRegisteredActions`, wired to the `kernel:ready` inventory in `app-plugin.ts`, covered by `action-reconciliation.test.ts`. D1 client — `../objectui``useConsoleActionRuntime.tsx`. D4 + migration — `content/docs/ui/actions.mdx`, `content/docs/releases/v17.mdx`.
4
5
**Deciders**: ObjectStack Protocol Architects
5
6
**Builds on**: [ADR-0049](./0049-no-unenforced-security-properties.md) (enforce-or-remove gate; a security property that parses but does nothing is worse than absent), [ADR-0066](./0066-unified-authorization-model.md) (D4 — action `requiredPermissions`, dual-surface, server is source of truth), [ADR-0078](./0078-no-silently-inert-metadata.md) (no silently inert metadata — this ADR is its **converse**: no silently ungoverned executable), [ADR-0096](./0096-execution-surface-identity-admission.md) (missing **identity** must not fail open; this ADR extends the same posture to missing **declaration**), [ADR-0104](./0104-field-runtime-value-shape-contract.md) (D2 — declared action param contract), [ADR-0109](./0109-ai-tool-authoring-model.md) (every declarative action materialises `action_<name>`; the declaration IS the AI-facing capability)
0 commit comments