ADR-092: read:actions scope — action-registry read access; module approval stays operator-only
ADR-092: read:actions scope — action-registry read access; module approval stays operator-only
Context
ADR-086 D4 carried read:agents forward unchanged from the prior tenancy model as the scope granting action discoverability — the capability a programmatic caller uses to learn which actions a domain exposes. Two precision problems surfaced in the Codex review:
- The name names the wrong resource. “Agents” is not what the scope reads. The resource is the domain’s action registry — the registered actions and their input contracts (per the discoverability endpoint, ADR-089). The
verb:resourcescope shape (ADR-006 §4) calls for the resource the scope actually grants. - ADR-086 D5 deferred a permission-review question — whether
admin:domainshould automatically grantapprove:modules(ADR-080 D3). D5 explicitly left it as “a follow-up Phase 4 implementation concern.”
Both are scope-taxonomy precision issues on the same ADR-086 surface. This ADR resolves them together.
Decision
D1 — read:actions replaces read:agents
The scope is renamed read:actions. It grants read-only access to the bound domain’s action registry: the set of registered actions and their input contracts, sufficient for action discovery — including MCP tool-listing (per ADR-088) and the discoverability endpoint (per ADR-089). The name follows the action:resource shape with actions as the resource actually read. read:agents retires.
D2 — read:actions is a minimal scope, distinct from read:domain
read:actions grants the action registry only — the registered actions and their input contracts — and nothing more: no decision history, no audit records, no other domain-scoped data. It is deliberately narrower than read:domain, which covers reading domain state beyond the registry. A caller that needs only to discover and invoke actions carries read:actions + decide:domain; read:domain is broader than discovery requires and is not granted for it.
D3 — API keys carry read:actions + decide:domain
The complete programmatic-caller scope set is discovery (read:actions) + invocation (decide:domain). API keys carry both, bound to the key’s (org_id, domain_id) pair per ADR-084 D1. Action discovery is a genuine programmatic-caller need (including MCP tool-listing per ADR-088), so keys carry the discovery scope alongside invocation. ADR-086 D4 lists the same key scope set in lockstep.
D4 — Role grants align
ADR-086 D5’s role grants align: the admin and contributor roles carry read:actions (was read:agents); observer is unchanged (read:domain only). Role names and the rest of each role’s grants are unchanged.
D5 — Module approval is operator-only; admin:domain does not grant approve:modules
This resolves the ADR-086 D5 deferred note. approve:modules is the enshrinement gate (ADR-080 D3) — a Spectral-operator authority. No customer role, including the domain admin, carries it: enshrinement is not a customer action, and the customer dashboard cannot approve modules (per ADR-077). approve:modules lives only with the operations role (Spectral staff). admin:domain grants domain administration — membership, API keys, domain settings — and stops there.
Alternatives considered
Keep read:agents. Rejected — it names a non-resource and misleads a reader about what the scope grants.
Drop the scope; have API keys carry decide:domain only. Rejected — programmatic callers and MCP clients genuinely need to discover available actions. The need is real; only the scope’s name and breadth were wrong.
Widen discovery to read:domain. Rejected — over-broad. It pulls in decision history and other domain state a discovery-only caller never needs, violating least privilege.
Defer the admin:domain / approve:modules question again. Rejected — it is a one-line clarification with an unambiguous answer (module approval is operator-only); deferring it a second time leaves the customer role model needlessly ambiguous.
Consequences
read:actionsis the action-registry read scope (D1) and theadmin/contributorrole grants carry it (D4); ADR-086 D4/D5 list the aligned scope and role model in lockstep. The ADR-086 D5 deferred permission-review note is resolved here: module approval is operator-only (D5).- Codex sweep:
read:agents→read:actionsacross the access-control, API-usage, and authentication pages and the rest of the corpus; the API-key scope set reconciles toread:actions+decide:domaineverywhere. approve:agents— the otheragents-named scope in ADR-086 D4/D5, marked there as “deprecation status separate” — is not addressed by this ADR. It is tied to the retired Spectral Agent (ADR-078); its cleanup is tracked separately.- Scope-literal rename in schema and auth middleware is Phase 4 implementation work, in the same migration epic as ADR-086 D8’s rename scope.
- The action registry
read:actionsgrants read access to is realized by ADR-104 (worlds.actions+worlds.action_rules);approve:modules(D5) approves modules per declared action once ADR-104 deploys one module per action rather than the single v0 wildcard.