Skip to main content
An API key that may call POST /execute for a capability is not yet authority over every request for it. A grant says exactly what one agent may do: “the warehouse agent may release goods, up to 100000 INR per request, until 30 December”. A policy with requireAuthorityGrant decides a request only when its caller holds a grant in force and the request is within the grant’s limits (Business validation, RFC-0023 phase 3).
Status, 2026-10-11. Grants, their maker checker and their check at decision time are implemented and tested in the repository (docs/CLAIMS.md 2.55). They are not deployed until this change is merged and deployed, and no shipped policy requires a grant yet. The SDK methods for the routes below ship in the next SDK release; until then, call the routes directly.

What a grant is

One active grant per caller and capability. To change a grant, revoke it and grant again.

Rules

  1. Two different people propose and approve every grant, with the approver’s step up signature.
  2. No one grants authority to themselves: the proposer and the approver can never be the callerId.
  3. Only human keys propose, approve or reject.

Step 1: require grants in the policy

Do: set "requireAuthorityGrant": true in the policy that governs the capability, and approve the change through policy governance. Expect: GET /policies/in-effect?capability=erp:release-goods answers with "authorityGrantRequired": true. From then on, every request for the capability from a key without a grant in force is refused. Grant first, or grant and change the policy together.

Step 2: propose the grant

Do: as the maker, POST /authority-grants/changes:
Expect: 201 with "status": "PENDING_APPROVAL". Keep changeId. If not: INVALID_AUTHORITY_GRANT names the field; AUTHORITY_SELF_GRANT_DENIED means the grant is for your own key; 409 means the agent already holds a grant for the capability or a change is pending. See Propose an authority grant change.

Step 3: approve it

Do: as a second person, who is not the agent, sign a step up authorization for changeId and action approve, then POST /authority-grants/changes/{changeId}/approve. Expect: 200 with "status": "APPROVED". GET /authority-grants lists the grant as active, with validFrom set to the approval time.

What the agent gets

Every status but AUTHORIZED refuses the request before any business system is asked, with a Refusal Record whose matchedRuleId is authority-not-authorized, authority-expired or authority-unclear. A signed approval cannot cure it. AUTHORIZED still needs everything else the policy requires, the signed approval included.

In the record

The decision’s assessment.authority.grant holds the grant checked, as it stood: its id, the caller, the capability, validFrom, validUntil and limits. It is signed inside the Execution Trust Record or Refusal Record, so a reader can see which grant authorized an action, or which one had expired.

Revoke

Propose { "action": "revoke", "callerId": "warehouse-agent", "capability": "erp:release-goods", "reason": "…" } and have a second person approve it. The agent’s next request is refused. The revoked grant stays listed.

Limits

  • A grant limits each request on its own. It does not count: “100000 per day” is not expressible yet.
  • A grant names a caller id that the server does not check exists; a grant to a key that does not exist has no effect.
  • Authority is checked when the request is decided, not again when the action is released (RFC-0023 phase 4).
  • See Limitations, G-93.