Proof of Authorisation¶
The Xybern Authorisation Layer does not just authorise every agent action before it executes, it can prove it did, to anyone, without asking them to trust Xybern.
Authorise every action. Prove every authorisation.
Three artifacts make up the proof surface:
| Artifact | What it is | Who it's for |
|---|---|---|
| Authorisation Receipt | A per-action record proving one specific action was authorised, refused, escalated, or terminated before execution, with the rules and Risk Verdict that decided it and the Vault certificate that makes it independently verifiable | Engineers, counterparties, anyone disputing a single action |
| Proof of Authorisation Pack | A signed, self-contained bundle covering a period: every outcome, per-agent breakdown, receipts, the covered Vault entries with their signatures, and an ECDSA signature over the whole pack | Whoever asks your customer to prove their agents are controlled: an auditor, a regulator, an insurer, a procurement team |
| Authorisation Coverage | A live view of which agents operate under a declared authority (Access Profile, Intent Contract, agent-scoped Mandate) and which still hold standing, unscoped authority | You, to close the gaps |
Everything is built on the Provenance Vault: every decision is already hash-chained and asymmetrically signed the moment it happens, so proofs are generated from records that were sealed before anyone asked for them, never reconstructed after the fact.
Authorisation Receipts¶
Every enforcement decision can be exported as a standalone receipt.
from xybern import Xybern
client = Xybern(api_key="xb_live_...")
receipt = client.enforce.get_receipt("enf_ab12cd34ef56")
curl -H "X-API-Key: xb_live_..." \
https://www.xybern.com/api/v1/enforce/decisions/enf_ab12cd34ef56/receipt
Response shape:
{
"ok": true,
"receipt": {
"format": "xybern-authorisation-receipt/v1",
"receipt_id": "rcpt_enf_ab12cd34ef56",
"workspace_id": "ws_...",
"issued_at": "2026-07-08T10:00:00Z",
"action": {
"action_type": "send_payment",
"summary": "Refund of $180 to customer #4411",
"content_sha256": "9f2c...",
"occurred_at": "2026-07-08T09:58:41Z",
"agent": {"agent_id": "agt_...", "name": "Refund Agent"}
},
"authorisation": {
"outcome": "authorised after review",
"decision": "escalate",
"rules_triggered": [{"name": "Refunds above $100 need review"}],
"verdict": {"dimensions": {"blast_radius": {"score": 41}}},
"escalation": {
"status": "approved",
"resolved_by": "usr_...",
"resolved_at": "2026-07-08T09:59:30Z"
}
},
"proof": {
"format": "xybern-decision-certificate/v1",
"signing_keys": ["..."],
"entries": ["..."]
},
"proof_available": true
}
}
The proof block is a complete Vault certificate: the sealed entry, its chain position, the ECDSA P-256 signature, the public keys, and the exact hashing recipe. A recipient can verify it offline; altering any field breaks the verification.
Outcomes are reported in plain authorisation vocabulary: authorised, refused, escalated, authorised after review, refused after review, terminated.
The agent's own reason for each step¶
Receipts distinguish two kinds of reasoning: the authorisation reasoning (why the Authorisation Layer decided what it decided) and the agent's stated reason (why the agent says it took the step). Pass the latter at intercept time:
client.enforce.intercept(
action_type="send_payment",
action_content="Refund $180 to customer #4411",
metadata={"connector": "stripe", "amount_usd": 180},
reasoning="Customer reported a duplicate charge on order #4411; refund approved per returns policy.",
)
The raw API accepts the same as a top-level agent_reasoning field (or metadata.agent_reasoning). MCP tool calls that carry a reasoning, justification, or reason argument are captured automatically by the gateway. The stated reason is stored with the decision, sealed into the Vault entry, and rendered on every receipt and in the PDF appendix of every pack, so a reviewer sees, per step, what the agent tried to do, with which tools and parameters, why the agent says it did it, and why it was authorised or refused.
In the dashboard, every decision panel has a Download Authorisation Receipt button next to its Vault proof.
Proof of Authorisation Packs¶
A pack answers the question "prove your agents only did what they were authorised to do between these dates" in one signed document.
pack = client.enforce.create_proof_pack(
from_date="2026-06-01T00:00:00",
to_date="2026-06-30T23:59:59",
name="June, all agents",
)
packs = client.enforce.list_proof_packs()
full = client.enforce.get_proof_pack(pack["pack"]["pack_id"], verify=True)
curl -X POST -H "X-API-Key: xb_live_..." -H "Content-Type: application/json" \
-d '{"from_date": "2026-06-01T00:00:00", "to_date": "2026-06-30T23:59:59"}' \
https://www.xybern.com/api/v1/enforce/proof-packs
Each pack contains:
- a plain-language statement of what the pack attests to
- the summary: total actions, how many were authorised, refused, escalated, terminated, and how escalations were resolved by humans
- a per-agent breakdown
- the coverage snapshot at generation time
- one receipt per action (up to 2,000 per pack; narrower periods give complete coverage)
- the covered Vault entries with their asymmetric signatures and the public keys
- an
integrityblock: the SHA-256 of the canonical pack body and an ECDSA P-256 signature over it
Pack generation is itself sealed to the Vault, so the record that a proof was produced is as tamper-evident as the proofs inside it.
Share links¶
Every pack gets a read-only share link, https://www.xybern.com/proof/<pack_id>?t=<token>, that requires no Xybern account. The page re-verifies the pack signature server-side on every view, shows the summary, and offers the signed JSON and a PDF. Revoke or rotate the link at any time from the dashboard or the share endpoint; a revoked link stops working immediately.
Verifying a pack independently¶
- Download the signed JSON.
- Remove the
integrityblock and recomputesha256over the canonical JSON (sort_keys=True, separators(",", ":")). - Check the ECDSA P-256 signature in
integrity.signatureagainst the public keys enclosed invault_proof.signing_keys. - Optionally verify each enclosed Vault entry with the same keys and the enclosed hashing recipe.
No Xybern access, account, or goodwill required at any step.
Authorisation Coverage¶
{
"coverage": {
"headline": {
"agents_total": 12,
"agents_covered": 9,
"coverage_pct": 75,
"standing_authority_agents": 2,
"workspace_charter_active": true,
"actions_recent": 4180
},
"agents": [
{
"agent_id": "agt_...",
"name": "Refund Agent",
"access_profile": "active",
"intent_contract": true,
"covered": true,
"standing_authority": false,
"actions_recent": 812
}
]
}
}
An agent is covered when it operates under at least one declared authority: an active or shadow Access Profile, an active Intent Contract, or an agent-scoped Mandate. An agent with recent activity and none of these holds standing authority, the thing the Authorisation Layer exists to eliminate. The dashboard's Proof of Authorisation tab shows the same view with one-click paths to close each gap.
Endpoint reference¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/v1/enforce/decisions/<id>/receipt |
Authorisation Receipt for one decision |
POST |
/v1/enforce/proof-packs |
Generate and sign a pack (from_date, to_date, agent_id, name, all optional) |
GET |
/v1/enforce/proof-packs |
List packs |
GET |
/v1/enforce/proof-packs/<pack_id> |
Full signed pack document, ?verify=1 re-verifies server-side |
GET |
/v1/enforce/coverage |
Authorisation coverage, ?window_days=30 |
GET |
/proof/<pack_id>?t=<token> |
Public read-only verification page (no auth) |
SDK: get_receipt, create_proof_pack, list_proof_packs, get_proof_pack, get_authorisation_coverage, available from xybern 1.20.0; intercept(reasoning=...) from 1.21.0.