Skip to content

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 integrity block: 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.

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

  1. Download the signed JSON.
  2. Remove the integrity block and recompute sha256 over the canonical JSON (sort_keys=True, separators (",", ":")).
  3. Check the ECDSA P-256 signature in integrity.signature against the public keys enclosed in vault_proof.signing_keys.
  4. 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 = client.enforce.get_authorisation_coverage(window_days=30)
{
  "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.