Check each evidence claim separately.
Evaluation can issue an Ed25519-signed decision receipt before a tool executes. A proof bundle adds its audit-event binding and Merkle inclusion under a signed checkpoint. These are distinct checks.
Built Receipt signing, proof export, signed checkpoints, and offline verification. Reviewed 19 October 2026.
Concept · illustrative
One call, four separate checks
A missing link makes a claim unverifiable. That differs from a failed signature or a mismatched proof.
All IDs, hashes, and outcomes shown here are illustrative. This page calls no backend and performs no cryptographic verification.
What the signed receipt actually contains
The compact decision payload names the tool call, agent, tenant, decision, decision time, and nonce. The current strict-audit path issues a version-2 receipt with its type, signing-key ID, and audit-event ID.
Request hashes, policy versions, rule IDs, delegation context, sequence numbers, and checkpoint roots are not all embedded in this signed payload. They belong to other records or proof components. A valid receipt alone does not authenticate arbitrary neighboring metadata.
With strict audit disabled, the gateway can issue an older unbound receipt. With strict signing enabled, an unsigned non-deny decision fails; a denial may still be returned without a valid receipt when signing fails.
| Fields | Meaning |
|---|---|
| tool_call_id, agent_id, tenant_id | Which evaluated call and identities the decision names |
| decision, decided_at, nonce | The verdict, its timestamp, and a random nonce |
| version, type, kid, audit_event_id | Current version-2 format, signing-key identifier, and audit binding |
| payload_b64, signature_b64 | Canonical payload bytes and their Ed25519 signature, in the envelope |
Audit events and asynchronous sequencing
Audit events carry IDs and payload hashes. Sequence numbers are assigned in background batches, not necessarily when evaluate returns. The implemented integrity structure is a Merkle tree over event ID, payload hash, and sequence number; it is not a previous-entry hash chain.
Database privileges restrict ordinary audit mutation, with controlled sequence assignment and retention operations. Retention and database-role configuration remain part of the deployment boundary.
| Seq | Event | Decision | Payload hash |
|---|---|---|---|
| 1041 | read request | allow | 9f2c…a1 |
| 1042 | delete request | deny | c418…6b |
| 1043 | message request | redact | 51de…f3 |
| 1044 | export request | require_approval | aa07…9c |
Merkle inclusion under a signed checkpoint
The checkpoint job hashes a batch into a Merkle root and signs its tenant, sequence range, event count, and root. An inclusion proof lets a verifier recompute the path from one event to that root. Optional external anchoring is a separate configuration.
Diagram · illustrative data
Event 1042 under a signed root
- Solid path from event 1042 to the root.
- Dashed sibling hashes the verifier needs to recompute it.
A newly evaluated call may not yet have a checkpoint. Missing or older proof components can make a claim unverifiable; that is different from a failed signature or mismatched proof.
Illustration: alter an event after checkpointing
Changing an event's payload hash changes its Merkle leaf. The original proof can no longer reach the signed root. The buttons illustrate that result; they do not run the real algorithm.
Tamper demonstration
No changes yet. Illustrative event values match the checkpoint example.
Offline verification with ghalta-verify
Export the tool call's proof bundle and obtain the gateway public key independently. The verifier does not trust a key merely because it appears inside the bundle.
- Verify the receipt signature against the separately trusted key and compare any independently expected identities or decision.
- Check receipt-to-audit-event binding and the event's Merkle inclusion proof.
- Authenticate the checkpoint's signed root and sequence range.
- Use a maximum age when checkpoint freshness matters. Without that option, no freshness claim is made.
ghalta-verify proof.json --gateway-pubkey gateway-key.json --json
# Optional freshness bound:
ghalta-verify proof.json --gateway-pubkey gateway-key.json --max-age 24h Commands match the implemented CLI. Files above are example names, not downloadable evidence. Exit codes: 0 verified, 1 failed, 2 unverifiable or usage error.
A receipt and inclusion proof do not prove that an external tool completed an action, that every call was captured, or that all exported request and policy metadata is authentic.
Reports and proof exports
Reports provide review context; a proof export supplies the signed objects and inclusion evidence required by the verifier. An export is not automatically a successful verification. Missing checkpoints and unsupported older formats must remain visible in the result.
-
tamper-proof and verifiable
In a draft paper, NIST asks the public how AI agents can keep tamper-proof, verifiable logs of their actions.
How can we ensure that agents log their actions and intent in a tamper-proof and verifiable manner?
Source: NIST National Cybersecurity Center of Excellence, retrieved
Next
Review the gateway path, policy behavior, and integration boundary, or ask about an evaluation.