authority: section says which principal may propose which action. It lives at the top of
ctrlrun.yaml from ctrlrun.policy/v3, or in a standalone document passed with --authority
whose only keys are schema and authority. It is opt-in and then fail-closed: absent, nothing
changes; present, every principal needs a matching grant and no grant means denied. A test
asserts this page names every key the loader accepts.
The section
Break-glass envelopes
An incident needs authority nobody was granted in advance. The wrong answer is a flag: a flag leaves no record, expires never, cannot be revoked and cannot be narrowed. What an envelope declares is the ceiling for a grant opened beneath it during an incident.
The envelope decides nothing, by construction. It lives in a mapping separate from
grants:,
and the candidate set an evaluation walks is grants: unconditionally — so an envelope cannot
authorize an action even by accident. A deployment with an envelope and nothing opened beneath it
evaluates exactly as one without it.
It carries no delegable and no expires_at, and both are load errors. An envelope exists
only to be a parent, so “delegable” is what it means rather than a key it sets; and what bounds it
in time is max_ttl, which every grant beneath it obeys. It is covered by the policy hash,
max_ttl included, so widening the widest authority an incident can reach moves every receipt.
Opening one is an act with its own command, ctrlrun break-glass --envelope <id> --file grant.yaml --reason "<incident>". There is no --as: the opener is the principal the deployment’s
approver identity resolves, and a deployment that names none cannot open one at all. A grant opened
beneath an envelope must carry an expires_at inside max_ttl, is contained on every
dimension, is revocable, attenuates, and is named on the receipt of every action taken under it.
An id declared in both grants: and break_glass: is a load error naming both, and a standalone
--authority document may not declare break_glass at all: it carries no control registry to
resolve the gate against, so the only envelope it could express is an ungated one.
A grant
budgets
constraints bounds one action; a budget bounds the aggregate. They are different
questions, and a grant that answers only the first permits a thousand actions that each pass it.
FAILED, which is the one state where the executor proved nothing happened. An AMBIGUOUS
effect holds its consumption until a human or a reconcile hook resolves it: ambiguity is
not a refund, because otherwise an agent able to manufacture ambiguity is able to manufacture
authority. ctrlrun inspect --grant shows what is held and what holds it.
A delegation’s budget must be contained by its parent’s: no higher limit, and no shorter
window, because a shorter window over the same limit is a higher rate and therefore more
authority.
An action a budgeted grant covers must resolve an effect key. Without one there is nothing
to charge against, so the action is refused rather than spending nothing for ever.
A grant carries no decision:. How much autonomy an action has is the policy’s answer, the same
for everyone; the grant answers whether this principal may ask at all.
runnable
How a grant matches
A grant covers an action when the subject matches the principal, the action name matches one ofactions, the resolved resource matches one of resources, the environment is in
environments, every constraint holds over the arguments, and expires_at has not passed.
Every failing reason is collected and the reported one follows a fixed order, so the evidence
for a configuration does not depend on the order grants appear in the file. Where several
grants match, the receipt names the lowest id.
Delegation
ctrlrun delegate --parent <id> --file grant.yaml --as AGENT[/USER] writes a delegated grant
beneath a delegable one. The file has the keys above minus id. It is accepted only if it is
provably a subset of its parent on every dimension, at creation and again at every evaluation:
- a narrower or equal subject (never a wildcard, never dropping the parent’s
user); actions,resources,environmentseach a subset;constraintsno looser on any argument;expires_atno later than the parent’s.
resources: would authorize resources its parent never could. ctrlrun revoke <id> cuts a
chain of any depth with one write and is not reversible.
What the section does not do
It does not authenticate anybody: the principal comes from the identity provider, and--as on
the command line is an assertion recorded as created_via: cli. It does not match on a token
claim, does not propagate across an agent-to-agent hop, and does not hot-reload: revocation and
expiry are live, an edited file takes effect when the process next loads it.
Next
- Authority and delegation: the concept.
- Policy YAML reference: the other axis.
- Get started · Why.