Guard · Scope contracts
Scope contracts
No agent acts outside its lane. Scope contracts split every actor's authority into read, write, and action scopes (bounded per tenant and per account), and multi-approver holds layer on top so a cross-tenant action waits for every named approver before it lands.
Start here if you want to approve or deny the actions an agent has queued: Actions queue. A cross-scope hold is one of the holds that queue enforces.
Where to find it
- Source:
lib/identity/scope-contract.mjs(the read, write and action ops and theenforcecheck) - Holds:
lib/identity/cross-scope-policy.mjs::computeCrossScopeHolds, one hold per crossed tenant or account boundary - Policy:
lib/actions/policy.mjs::decideAction, which denies anything outside scope before the verb runs - Pre-grants:
grants.jsonvialib/identity/grants.mjs; a matching (actor, scope, op) row lets the action proceed without a per-action approval
What it does for you
An agent only writes where it's allowed.Every registered actor (human, agent, cron, webhook, or service) carries a scope. When the caller wires a registered actor and a scope, an action outside its declared tenant and account is denied at the policy gate, before the verb executes, and an
action.denied audit row records the refusal.Cross-tenant writes need every approver.When an action would cross a residency boundary and no pre-grant covers it,
computeCrossScopeHolds emits one hold per crossed boundary (tenant first, then account), each carrying the foreign requiredApproverScope. The action goes through the normal team-policy and blast-radius evaluation, then waits in the approval queue until an approver from each required scope signs off; the queue checks each hold against the approver's scope before clearing it.The unified actor model makes it audit-clean.The unified actor registry means every action is attributed to a real principal with a known scope, so the audit log answers "who did this and were they allowed?" from the action row itself.
Read more
Last updated