Skip to main content
What a governed run produces

How a decision becomes a signed record.

Signed so a third party can re-derive it offline, with no callback and no proprietary tools. What follows is how that record gets built, and why you can check it without trusting us.

evidence-bundle.json Signed
receipts4
algorithmEd25519-SHA256-JCS
merkle root8dad97.. chained
checkpointsigned verified
re-derivable offline · no callback · no proprietary tools

Three-phase architecture

Each phase in detail, and the artifact it hands to the next: the sealed policy, the runtime decisions, and the receipt chain that records them.

01
Sealat build

Policy Artifact

Approve

Subject + Policy

permitted operations

policy (architecture sketch, not a shipped schema)

{ "subject": "agent-3.2.0", "tools": ["mcp.fetch", "mcp.write"] }

Sign

Ed25519 (live default)

the npm library's hybrid ML-DSA-65 export signs receipts and checkpoints, not policy artifacts

signature (first 32 bytes hex)

8e2af1d9 73c4b605 a91e2f7c 18d5ebb3 f60c7a44 9d1eaa72 4f8b0c63 c1e2d098

Sealed Artifact

In aga-mcp-server, a tamper-evident policy with its validity window bound into the signature

signed under an issuer key generated per process, so no key survives a restart to pin; a delegated child artifact checks only against that process's key, and a pinned-key check ships only in the private reference runtime

02
Captureruntime

Launch check and measurement

Validate

In the request-access Kubernetes component, an admission webhook checks the artifact before a labeled pod starts, against the key the artifact carries; it pins no issuer key

not in the published packages

admission check (request-access component)

verify(artifact.signature) → OK · now within [effective, expiration] → OK · governance sidecar container present → OK

Measure

Architecture: sampling at the cadence the artifact specifies. The published aga-mcp-server measures on demand, over content the caller passes

scheduled classes are in the private reference runtime

measurement (aga-mcp-server, on request)

sha256(content) == subject.bytes_hash && sha256(canon(metadata)) == subject.metadata_hash ? (both supplied by the caller)

Decide

Hash matches the sealed baseline?

autonomous, no human in the loop

Match

Continue, and record a signed receipt that finds no drift.

Mismatch

Record a signed drift receipt carrying the artifact-defined decision.

In 3.6.0 through 3.6.2 this receipt stays in the reference server's process; it is not in the exported bundle.

03
Proveat audit

Evidence Bundle

Record

Signed receipt per recorded decision

Ed25519 · hybrid profile as a library export

receipt (excerpt of the 15 fields)

{ "timestamp": "2026-05-24T18:42:11.000Z", "tool_name": "mcp.fetch", "decision": "PERMITTED", "previous_receipt_hash": "4f9c..", "signature": "8e2a.." }

Chain

Hash-linked, append-only

tamper-evident

chain link

next.previous_receipt_hash = sha256(canon(receipt))

Evidence Bundle

Receipt chain + signed checkpoint + Merkle proofs in one portable file. On aga-proxy each receipt binds the policy by hash; the policy itself is not included

offline-verifiable by any third party

Three phases; what gets exported differs by package. On aga-proxy, each recorded tools/call decision is a signed receipt, chained into one exported sequence (known issue 7 on /security describes the calls refused without a receipt). aga-mcp-server 3.6.0 through 3.6.2 keeps its measurement and quarantine receipts in a separate chain that its bundle export does not include.

Worked example

One decision, end to end

An agent asks to fetch a URL. Follow that one decision through aga-proxy, from its policy file to the signed receipt that anyone can re-derive offline. A representative fixture in the shipped formats, not live data.

PolicyThe policy allows the tool
{ "mode": "allowlist", "constraints": { "mcp.fetch": { "name": "mcp.fetch", "allowed": true } } }

An unsigned JSON file passed with --policy. aga-proxy signs the SHA-256 of its canonical JSON into every receipt as policy_reference, which binds the policy to each decision by hash.

DecideThe call, checked against the policy
tools/call "mcp.fetch" → PERMITTED ("tool permitted by allowlist")

aga-proxy decides per tools/call, against the policy. Scheduled hashing of an executable image or configuration is in the private reference runtime; memory sampling is architecture only.

RecordA signed receipt records the decision
{ "timestamp": "2026-05-24T18:42:11.000Z", "method": "tools/call", "tool_name": "mcp.fetch", "decision": "PERMITTED", "reason": "tool permitted by allowlist", "policy_reference": "3b1f..", "previous_receipt_hash": "4f9c..", "signature": "8e2a.." }

An excerpt of the receipt's 15 fields, signed with Ed25519 over its canonical JSON.

ChainThe receipt chains onto the prior hash
next.previous_receipt_hash = sha256(canon(receipt)) = 7b3e..

Append-only. Against the pinned key, reordering or deleting a receipt breaks the chain forward, and deleting the last one contradicts the signed checkpoint.

VerifyAnyone re-derives it offline
$ aga-verify evidence-bundle.json --pubkey <key> → VERIFIED

Recompute each receipt hash, walk the chain, re-check every signature. No callback to us.

One decision, three artifacts, one signed chain under one signing key, re-derivable offline from the bundle alone.

Cryptographic primitives policy

Industry-standard primitives. No proprietary algorithms.

Both the hash and the signature algorithm are named in a single suite identifier, signed in each receipt and the checkpoint and repeated, unsigned, on the bundle (for example Ed25519-SHA256-JCS, or ML-DSA-65+Ed25519-SHA256-JCS). aga-verify, aga-proxy verify and /verify check the bundle's and the checkpoint's identifier, and aga-governance 0.3.2 the bundle's and each receipt's; each reports FAILED for a bundle whose suite it does not recognize, and /security lists which labels each leaves unchecked.

Checked against a pinned key, the suite cannot be silently downgraded: a changed receipt or checkpoint identifier breaks its signature, and an unknown bundle identifier fails closed. That keeps the architecture algorithm-agile without softening verification.

ClassicalRFC 8032

Ed25519

Policy-artifact and receipt signatures for classical deployments, and the reference baseline outside the post-quantum threat model.

Post-QuantumFIPS 204

ML-DSA-65

Post-quantum receipt and checkpoint signatures at NIST security category 3, inside the hybrid composite, which the npm package ships as a library export; it does not sign policy artifacts.

PrimaryFIPS 180-4

SHA-256

Addresses every artifact and chains each receipt to the one before it; also the leaf hash beneath the Merkle checkpoint.

PrimaryJCS-lineage

JSON canonicalization

A JCS-lineage canonicalization with sorted keys, defined by the conformance vectors, so signature inputs reproduce identically across implementations.

PrimaryVector-defined, no-prefix SHA-256 (not RFC 6962)

Merkle Trees

A signed checkpoint with per-receipt inclusion proofs. The format carries a proof for each receipt; the published verifiers check the whole bundle.

Cryptographic Foundation

Standard cryptography, checked by two implementations that agree

AGA is built from published primitives: Ed25519 (RFC 8032), SHA-256, and the NIST post-quantum standard ML-DSA-65 (FIPS 204). The canonicalization, the Merkle tree and the composite encoding are AGA-defined and pinned by published vectors. The post-quantum primitive is checked against NIST known-answer vectors in the private reference runtime's test suite, and in the public repository two implementations in different languages are shown to agree on all 28 v2 cases. The composite is not the IETF LAMPS composite, which is still an Internet-Draft, and does not interoperate with it.

Two profiles, one construction. A signed record carries a versioned signature profile. The classical profile, live today, signs with Ed25519 (RFC 8032), with SHA-256 chaining the receipts and binding the signed checkpoint. The hybrid profile, implemented as a library export and cross-verified by two oracles in different languages (@noble in JavaScript and CIRCL in Go), signs with a composite of ML-DSA-65 (NIST FIPS 204) and Ed25519: both components cover the same bytes, and both must verify for the record to be accepted. An attacker would have to break ML-DSA-65 and Ed25519 to forge a record, so it holds as long as either scheme stands. Canonicalization, hashing, the Merkle tree, and the checkpoint are identical across profiles. Only the signature primitive changes.

Built to migrate, not to break. A verifier reads the profile from the bundle and checks the signatures accordingly. Records signed under the classical profile stay verifiable, and a verifier that understands the hybrid profile still accepts them. Post-quantum migration is additive: the profile is defined and cross-verified before any record needs to depend on it.

Supported signature modes

Classical

Algorithm
Ed25519-SHA256-JCS
Security
Ed25519, ~128-bit classical
Status
Default · live

Hybrid (post-quantum)

Algorithm
ML-DSA-65+Ed25519-SHA256-JCS
Security
Ed25519 (~128-bit classical) and ML-DSA-65 (NIST security category 3); both must verify
Status
Library export · cross-verified

Hybrid mode produces both signatures. Verification requires both to pass. No downgrade fallback. Ed25519-only artifacts remain verifiable.

Checked by two implementations

In the private reference runtime's test suite (evaluation access), the post-quantum primitive is checked against the NIST ACVP known-answer vectors for key generation, signing, and verification, a fixed external oracle; the public repository does not run those vectors. Beyond those vectors, the implementations are exercised against the shared cross-language conformance corpus, 61 classical and 28 post-quantum cases, and the equality check is concrete: for the same input they must produce byte-identical canonical JSON, identical signature bytes, and the same Merkle root, and each must verify what the others produced. The composite encoding around it is AGA-defined, so there the evidence is two implementations in different languages agreeing on all 28 cases, with no external oracle.

Measured performance

385 µs
hybrid sign + verify, per decision
~0.4%
of a 100 ms budget
0
allocations to verify on the Ed25519 path

Measured on the Go reference code (go test -bench, evaluation access); the published Node gateway was not benchmarked. Per decision, the cryptography is small next to the tool call it records. In 3.6.0 through 3.6.2 the bottleneck is elsewhere: bundle export is quadratic in the receipt count and holds governed calls while it runs. The classical Ed25519 path signs in tens of microseconds with one 64-byte allocation and verifies with none; the hybrid figure is dominated by the ML-DSA-65 component and is reported as the full per-decision sign-and-verify cost, not a best case. The full benchmark tables, key and signature sizes, and the standard each primitive implements are on the specification page.

View specification and benchmarks

What a verified record proves, exactly

A passing verification against a key you pinned proves the signed record has not changed since it was signed, and any third party can re-derive it offline with no callback to us. It does not rule out the key holder re-signing a different history. It does not prove an agent was prevented from acting; whether an action was blocked is a property of how the system is deployed. It does not prove a recorded value is true, and says nothing about identity or legal standing. The proof is about the record, because an instrument that overstates what it measures is not an instrument.

MCP integration

Cryptographic governance for agentic tool use over the Model Context Protocol.

Tool-call request path

each evaluated tools/call is recorded

AI Agent

model + reasoning

MCP Client

tool discovery

Gateway

MCP gateway, signing boundary

MCP Tool

external resource

In a governed deployment, tool calls are routed through the gateway. The published aga-proxy listens on raw TCP (newline-delimited JSON-RPC) and bridges to a stdio MCP server (its --upstream-url mode forwards raw JSON-RPC over HTTP POST and does not implement the MCP Streamable HTTP transport, so a spec-conformant HTTP MCP server rejects it); a standard stdio MCP client reaches it through a stdio-to-TCP relay, which the package does not include. In the HTTP mode, a message that repeats its method member can carry a tools/call that the proxy never evaluates and that no receipt records (known issue 6 on /security); the stdio default is not affected. The gateway holds the signing keys; when it runs under its own identity, the subject holds none and cannot mint a call that passes as approved or a valid receipt. Routing is arranged by the deployment: when the subject reaches external tools only through the gateway, the chain holds a signed receipt for each tools/call the gateway evaluated (known issue 7 on /security describes the exceptions). What AGA proves is the record of calls that went through the boundary, not that no call ever evaded a misconfigured or root-compromised host.

The Model Context Protocol defines how agents discover and invoke external tools.

aga-proxy sits in the MCP tool-call path and signs a governance decision for every tools/call it evaluates (known issue 7 on /security describes the calls refused without a receipt). The policy file lists the approved tools and constraints; each call is evaluated against it, and each decision produces a signed receipt, carrying the SHA-256 of the policy's canonical JSON, that chains onto the receipt before it. That makes AGA the cryptographic decision-and-evidence record for securing autonomous agents at the protocol boundary, where an application that routes through the gateway cannot reach the tool without producing a signed receipt in the stdio default (with an HTTP upstream, see known issue 6 on /security).

Architecture

Two-process separation.

Core security property, when the gateway runs under its own identity: the governed subject holds no signing keys. On aga-proxy it has no tool that changes its policy. In aga-mcp-server 3.6.0 through 3.6.2 the MCP client can re-attest its own baseline through attest_subject, and the exported bundle does not record it.

Gateway (Governance Engine)

  • Holds the signing key
  • Parses and validates policy artifacts
  • Signs each decision: PERMITTED or DENIED for tool calls (aga-proxy, whose default profile, permissive, denies nothing on policy grounds; policy denial needs --profile standard or restrictive, or a --policy file in allowlist or denylist mode); QUARANTINE on a measurement mismatch and TERMINATE on a TTL expiry found at the next measurement (aga-mcp-server, into its in-process chain, which the exported bundle does not include)
  • In aga-mcp-server, a revoke_artifact call terminates the active artifact at once and adds a REVOCATION event to that chain; the exported bundle carries the revoke_artifact call (PERMITTED) and every later governed call, DENIED with GOVERNANCE_BLOCKED, until the governed client calls attest_subject. That call lifts a quarantine, revocation or termination, and the exported bundle does not record it
  • Generates and signs all receipts
  • Manages the receipt chain

Subject (Governed Agent)

  • Holds no signing keys (when the gateway runs under its own identity)
  • Cannot sign a receipt
  • In aga-mcp-server 3.6.0 through 3.6.2, can re-attest its own baseline through attest_subject; the exported bundle does not record it
  • Cannot make an action it takes outside the gate appear governed
  • Cannot forge or reorder an exported receipt without breaking the chain against the pinned key
  • In aga-mcp-server, measured on request against the subject hashes sealed into its artifact (the content hash and the metadata hash), over content and metadata the caller supplies

These hold because the subject has no key. Process isolation between the gateway and the subject is supplied by the deployment, and is stated as an assumption in the security model below.

Deployment architecture

Where the gateway exists in your stack.

The gateway runs as its own process and holds the gateway's signing key. (In 3.6.0 through 3.6.2 a key supplied through AGA_GATEWAY_KEY or AGA_GATEWAY_KEY_FILE is also inherited by a stdio upstream; see /security.) The governed agent runs as a separate process, with no key access when the gateway runs under an OS identity the agent cannot read. That two-process separation is the core security primitive. In the request-access Kubernetes component, an admission webhook refuses to start a labelled pod whose artifact signature or validity window fails; the published packages do not include it.

In the request-access Kubernetes component the gateway deploys as a sidecar alongside the agent container. The published aga-proxy runs as a co-process on the same host. For agents routed to the outside world through MCP, each tool invocation that transits the gateway is decided and recorded at the protocol layer before it leaves the boundary.

AGA operates at the process level, so its trusted computing base is the gateway process plus the host kernel and the deployment's process isolation. An operator with root on the host sits inside that boundary and can interfere with governance. Bundles already exported off the host keep their signatures through a later host compromise. Anything signed after the compromise is suspect, because the published gateway holds its key in process memory or in a file on that host. Where the host operator must sit outside the boundary, the architecture runs the gateway inside a Trusted Execution Environment (Intel SGX, ARM TrustZone, AMD SEV), which shrinks the trusted base to the enclave. No published component does this today, and none records an enclave attestation quote.

POD · K8Sagent-1agent-2agent-3Gateway

Container Sidecar

Deploys alongside agent containers in Kubernetes or Docker. This topology is the request-access component, not a published package; the published aga-proxy runs as the co-process shown next.

EDGE HOSTAgentGatewayOFFLINE OK

Edge Co-Process

Paired process on bare metal or any single host: the gateway runs on any host with Node 20 or later and listens on a TCP port (in 3.6.0 through 3.6.2 on every network interface, with no authentication, so firewall it: known issue 1 on /security). No container runtime is required, and the same standard cryptographic primitives carry into disconnected operation.

HOSTAgentTEEGatewayattestation quote

TEE-Hardened (architecture)

The gateway runs inside a hardware enclave, moving the host operator outside the trusted base while the enclave holds. In the architecture, the enclave’s attestation quote becomes one measurement input, so a verifier sees which enclave produced the record. No published component implements this today.

Ten Classes

Measurement inputs.

Architecture, not a shipped feature: the design evaluates runtime state through policy-defined measurement classes, each at its own cadence. The published aga-mcp-server measures on request over content the caller passes. No published package implements scheduled measurement, and memory and control-flow measurement exist in no implementation today.

Binary integrity

exe + weights hash

Configuration

runtime params

Module checksums

loaded modules

Container image

image digest

SBOM digest

supply chain

Environment

host metadata

File system

filesystem state

Network config

routes + interfaces

Memory samples

region snapshots

Control flow

execution graph

In the architecture, classes apply at different cadences: binary verification once on startup, configuration every minute, memory sampling every second. The sealed Policy Artifact sets which classes apply and how often. Memory and control-flow are sampled, not observed continuously, so the sampling interval is the security model’s detection window.

Integrity drift detection

Hash comparison against the sealed baseline, sample by sample.

Hash sample stream

representative sequence

A representative measurement sequence from the architecture, not live telemetry; the published aga-mcp-server measures only when called. Each tick is one measurement. Every measurement hash is compared for exact equality against the sealed value; the first hash that does not match fires a DRIFT_DETECTED receipt. There is no tolerance band. Equality is binary.

= sealed hashmeasurement cycle →DRIFT_DETECTED
match (equal to sealed hash)mismatchfirst hash that does not match → DRIFT_DETECTED receipt

In aga-mcp-server, each measurement is compared with the hash sealed into its artifact, and a mismatch produces a signed drift receipt, which in 3.6.0 through 3.6.2 stays in that server's process rather than the exported bundle. Governance decisions rest on deterministic hash equality: the comparison checks whether values match, with no interpretation of model outputs.

Hardware Independence

No hardware root of trust required.

AGA needs no internet connectivity or cloud service: it runs offline on commodity hardware, and the gateway runs on any host with Node 20 or later, listening on a TCP port (in 3.6.0 through 3.6.2 on every network interface; known issue 1 on /security). In the architecture, hardware attestation becomes a measurement input when it is available; no published component records it today.

AGA architecture

Software cryptography on every platform.

The gateway signs governance decisions using standard primitives (Ed25519, SHA-256, JSON canonicalization; an ML-DSA-65 hybrid is a library export, not the live default) and is designed to run on commodity hardware, including isolated networks with no internet access. In the architecture, TPM, TEE, HSM or secure-boot attestation quotes become measurement inputs when present; no published component records them today.

  • Standard cryptographic primitives

  • Runs where TPM, TEE, or HSM are unavailable

  • TPM 2.0 quotes as an input (architecture)

  • Intel SGX, ARM TrustZone, AMD SEV as inputs (architecture)

  • HSM-backed key custody on the roadmap, never required

  • Secure-boot chain as one measurement (architecture)

Governance Mode

Quarantine: a signed decision, containment wired per deployment

Phantom execution is the quarantine mode of the governance design. What ships today is narrower. In the reference MCP server (aga-mcp-server 3.6.0 through 3.6.2) the drift finding and the QUARANTINE decision are recorded in a receipt in that server's in-process chain, which is not part of the exported bundle. During quarantine the server signals it in-band: each governed call is refused with an explicit GOVERNANCE_QUARANTINED error and recorded as a DENIED receipt carrying that reason. aga-proxy has no integrity measurement and no quarantine mode. Keeping outputs flowing into the sealed record while cutting them off downstream is the design, and an integration point wired per deployment. By design we do not claim the quarantined agent cannot detect containment.

In the design, the result is an observation window for a subject that has already drifted. In 3.6.0 through 3.6.2 the governed client can end quarantine itself by re-attesting through attest_subject, and the exported bundle does not record that. In the shipped reference server, each governed call during quarantine is recorded as a DENIED receipt with the reason GOVERNANCE_QUARANTINED, which any verifier can tell apart from normal entries; the eight-field forensic capture is implemented and tested in the demo orchestrator and is not in a published package. In the architecture, an investigator observes a drifted agent under containment that the deployment wires.

In aga-mcp-server 3.6.0 through 3.6.2 the server records QUARANTINE on a measurement mismatch, and TERMINATE on a TTL expiry found at the next measurement, in its in-process chain. A revoke_artifact call terminates it at once and records a REVOCATION event in that chain; the exported bundle carries the revoke_artifact call (PERMITTED) and every later governed call, DENIED with GOVERNANCE_BLOCKED, until the governed client calls attest_subject. That call lifts a quarantine, revocation or termination, and the exported bundle does not record it. SAFE_STATE and ALERT_ONLY are decision types in the library that the server does not reach. The handlers that effect each action are wired per deployment.

Privacy

Verification without the argument payload

Arguments are committed by SHA-256 hash. Every receipt records an arguments_hash, a SHA-256 of the tool call's arguments, so anyone can verify the signatures, the hash chain, the Merkle inclusion, and the signed checkpoint without the arguments leaving the producing system. Three things do appear in clear text: tool names and, in 3.6.2 and earlier, the offending path in a path-constraint denial's signed reason and the matched pattern in a denied-pattern denial's. The hash is unsalted, so anyone holding a bundle can confirm a guessed argument set, and low-entropy arguments can be enumerated.

receipt.arguments_hash = SHA-256(canon(arguments)) // the receipt stores this hash in place of the arguments

An auditor confirms the chain is intact, that every link hashes to the next, and that every signature verifies, all without seeing the argument contents. When a specific payload must be disclosed, the recipient re-hashes it and confirms it matches the arguments_hash the producer signed, so a withheld or swapped payload cannot pass as valid. The auditor verifies the record and its ordering, not the truth of the data inside it.

Security Model

What AGA assumes, and what it proves.

Assumes

  • 1.The gateway process is not compromised at signing time. A compromised gateway could sign an artifact or receipt of an attacker’s choosing.
  • 2.In the architecture, the measurement cadence is set to catch drift before it causes harm. The right interval is a per-deployment risk decision.
  • 3.The deployment environment applies process isolation between the gateway and the governed subject, so the subject cannot reach the signing keys.
  • 4.The signature algorithm (Ed25519 in the published gateway; the ML-DSA-65 composite where the library profile is used) and SHA-256 stay computationally secure for the artifact’s validity period.
  • 5.The host clock is roughly accurate. AGA records a self-reported time, so receipts establish ordering and integrity, not an independently attested wall-clock time.

Proves

  • Without the issuer's signing key, any modification to a sealed policy artifact invalidates its signature, so a verifier checking against the issuer's pinned key rejects the altered artifact. The property holds for a verifier that pins the issuer's key, and that check ships only in the request-access Go runtime: the published aga-mcp-server signs its artifact under an issuer key generated per process, so no issuer key survives a restart to pin. It does not return that artifact; delegate_to_subagent returns a signed child artifact, which checks against the issuer_public_key that get_server_info reports for the same process only. The request-access admission webhook does not pin one: it checks the artifact against the key the artifact carries, and its validity window is outside the signed fields, so it does not stop a re-signed or re-dated artifact. Whether a rejection stops the subject from launching is a deployment property.
  • Receipt ordering and contents, as the verifier reads them, are tamper-evident against the pinned key: deleting or reordering an existing entry breaks the hash chain forward, or, for a deletion at the tail, contradicts the signed checkpoint's leaf count and chain head, and a verifier detects it. A verified chain proves the entries it contains are intact and correctly ordered, not that none is missing, and not that it is the latest: an earlier genuine export presented as the current one verifies, because the verifier has no freshness input. A field name repeated in the file still verifies: the verifiers read the last copy, so read the verifier's parsed output (known issue 5 on /security).
  • Evidence bundles can be verified by any party using standard cryptographic primitives, with no callback to the producing system.
  • Verification never requires disclosing argument contents, so auditors verify the record without the data inside the arguments. In 3.6.0 through 3.6.2 a path-constraint denial names the offending path in its signed reason, a denied-pattern denial names the matched pattern (which shows the argument contained it), and tool names are plaintext.
  • Each recorded governance decision is signed. A receipt in the chain is bound to the key that produced it, so a holder of that key cannot credibly claim a chain entry was not produced under it. This binds the key, not a legal identity, and holds while that key is uncompromised.

Indexed by adversary

If an attacker can do this, here is what AGA catches, what it does not, and what closes the gap.

Adversary canAGA detectsAGA does notResidual mitigation
Tamper with the sealed policy artifactThe signature breaks; a verifier that pins the issuer key rejects the altered artifact. That check is in the request-access Go runtime; the published aga-mcp-server signs under a per-process issuer key, so there is no key to pin across restartsNothing beyond detectionDetection is the property
Delete or reorder existing receiptsThe hash chain breaks forward from the changed entry; a deletion at the tail leaves the chain intact and contradicts the signed checkpoint's leaf count and chain head. Verifiers detect bothRecover deleted contentBind the chain with a signed checkpoint
Withhold or truncate the receipt tail (compromised gateway)A single receipt can be proven to belong to a checkpoint (a property of the format; the published verifiers check the whole bundle)Prove no entry is missing from the chain aloneCompare against a copy of a signed checkpoint held outside the gateway
Present an earlier genuine export as the current oneNothing: it verifies, because the verifier has no freshness inputTell an earlier export from the latestCompare against the latest checkpoint you obtained independently
Swap the binary or config at runtimeIn the architecture, the next measurement catches it; the published aga-mcp-server measures only when called, over content the caller suppliesPrevent action between two measurementsIn the architecture, a faster cadence at higher resource cost
Hold the signing key and re-sign a different historyNothing, if the new history is internally consistentTell it apart from the history originally signedKeep a copy of an earlier signed checkpoint outside the producer, and compare
Exfiltrate the gateway signing keyNot detected by AGA itself; later artifacts and receipts are suspectStop forged artifacts and receipts until rotationScheduled rotation, HSM storage, out-of-band key verification
Run an ungoverned subject beside a governed oneOut of scopeProve anything about the ungoverned subjectOperator deployment policy
Full threat model
Transparency

Failure modes and limits

These are the scenarios where AGA offers reduced or no protection.

Gateway Compromise

An attacker who exfiltrates the gateway signing key can forge artifacts and receipts until the next rotation. Mitigations are scheduled rotation, HSM storage, and out-of-band key verification.

Measurement Cadence

In the architecture, AGA detects drift at measurement intervals; the published aga-mcp-server measures only when called. Between intervals, a compromised subject could act outside policy. Faster cadence reduces the window but increases resource cost.

Key Management

AGA specifies the cryptographic protocol but not the key management infrastructure. Deployments must implement secure key storage, rotation, and revocation appropriate to their threat model.

Deployment Governance

AGA proves the record of the governance decisions it made. It does not prevent an operator from deploying an ungoverned subject alongside a governed one; that subject simply produces no receipts. Deployment policy governance is the operator's responsibility.

Record Integrity, and Its Boundary

A verified chain proves the entries it contains are intact and correctly ordered. It does not by itself prove none is missing. The subject cannot remove a receipt from an exported bundle without failing verification against the pinned key, but receipts not yet exported live in the gateway's memory and are lost if its process ends, and a compromised gateway could withhold one or truncate the tail. The signed Merkle checkpoint binds a root, so a single receipt can be proven to belong to a checkpoint; detecting a truncated tail requires comparing against a copy of a checkpoint held outside the gateway. The same holds for an earlier genuine export presented as the current one: it verifies, because the verifier has no freshness input.

61 cases, one verdict across 3 toolchains (JS, Go, Python), as the harness feeds them28 post-quantum cases, 2 oracles428 automated tests in the 3.6.0 release CI, reviewed September 21, 2026
Verify us without trusting us

The verifier is published. Check us with it

The same Ed25519-SHA256-JCS construction the gateway signs with is published as a standalone command-line verifier on npm. It is our own package, so the point is not that we vouch for it: run it yourself. The format is specified so you can re-implement it. Version 2.2.3 was manually published without a SLSA provenance attestation. Its retained archive hash and registry signature are separate checks; inspect the release evidence.

$ npx -y @attested-intelligence/aga-verify@2.2.3 evidence-bundle.json

What you get depends on the key. Without a pinned key the verifier confirms integrity only: that the bundle is internally consistent under its own key. A separately trusted expected key also checks that the record was signed under that key. Connecting the key to a person or organization requires a trusted identity mapping. A key copied from the file does not establish its issuer, because a re-signed bundle carries its own matching key. A pin does not rule out the key holder signing a different history under the same key.

The sample-bundle signing key is a published fixture that no gateway holds, and the live demo gateway key is published at that gateway’s /pubkey. A deployment’s key persists only when AGA_GATEWAY_KEY or a valid AGA_GATEWAY_KEY_FILE is set; otherwise it is per-process.

Recorded decisions, signed and chained. Verifiable offline.