Skip to main content
The 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.
Two budgets on one metric over two windows is the ordinary shape, and it is one spend measured against two windows rather than two spends. A budget is consumed when the effect is reserved, in the same transaction, so two processes cannot both pass a check and then both spend. It is released only when the effect reaches 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 of actions, 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, environments each a subset;
  • constraints no looser on any argument;
  • expires_at no later than the parent’s.
Omitting a dimension the parent constrains is rejected, not inherited. A child that leaves out 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