@axiorank/audit-verify
Independently verify AxioRank audit receipts offline, with nothing but a public key. No AxioRank account, no API call, no trust in AxioRank.
A receipt proves three things about a single governed action:
- Membership. The audit row is in the sealed RFC 6962 Merkle tree (an inclusion proof).
- Integrity. That tree's root was signed by the log (an Ed25519 signed tree head).
- Provenance. Who or what authorized the action, as a signed delegation chain (operator who approved, the agent key, the upstream trace step).
This package re-implements the verification primitives (JCS canonicalization, RFC 6962 Merkle, Ed25519) in about 200 lines with zero dependencies, so you can read all of it in a few minutes and trust nothing else.
Install
npm install @axiorank/audit-verifyRequires Node 18 or newer.
Verify in code
import { verifyReceipt } from "@axiorank/audit-verify";
// `jwks` is a key you pinned out of band (see "Trust model" below).
const result = verifyReceipt(receipt, jwks);
if (result.ok) {
console.log("verified");
} else {
console.error(`failed: ${result.reason}`, result.checks);
}Verify on the command line
# Verify against a key you pinned and stored alongside your records.
npx @axiorank/audit-verify receipt.json --jwks key.json
# ✓ leaf hash
# ✓ inclusion proof
# ✓ signed tree head
# ✓ delegation provenance
#
# VERIFIEDExit code is 0 when verified, 1 when verification fails, 2 on a usage error.
Verify an Agent Action Seal
An Agent Action Seal is a portable, signed proof-of-governance an agent carries and presents at the moment it acts, before the audit window seals. Verify one the same way:
npx @axiorank/audit-verify seal ./seal.json --jwks key.json
# ✓ seal format
# ✓ seal signature
# ✓ embedded provenance
# ✓ provenance binds to action
# ✓ human approver signature
# ✓ freshness (within window)
#
# VERIFIEDIn code, use verifyPassport(seal, jwks) (the function name is the stable protocol API).
The full format is documented in SEAL.md. Once the audit window seals, upgrade
the Seal to a full Merkle inclusion receipt with verifyReceipt.
Verify an agent-commerce conformance seal
When an AI agent makes a purchase on a person's behalf, a Commerce Conformance Seal proves
the purchase stayed within the user or issuer's signed mandate (a spend cap, an allowed set
of merchants and categories, a currency, a time window). It is an Action Seal carrying a
signed commerce block, so a merchant, an issuer, or the buyer can all check it offline,
without trusting any network:
import { verifyCommerceSeal } from "@axiorank/audit-verify";
// Without the mandate: confirms the seal is genuine and reports its signed verdict.
const r = verifyCommerceSeal(seal, jwks);
// r.checks.commerce === true, seal.commerce.inScope === true | false
// With the mandate (pinned out of band): also confirms the seal references that exact
// mandate and that the in-scope verdict is not a lie.
const r2 = verifyCommerceSeal(seal, jwks, { mandate });
// r2.checks.mandateBinding -> the seal is bound to THIS mandate
// r2.checks.inScopeHonest -> the signed verdict is not refuted by re-running the mandateevaluateMandate(purchase, mandate) and mandateHash(mandate) are exported so you can
re-run the conformance check yourself. AxioRank consumes the mandate (for example an AP2
Intent Mandate); it does not issue it.
Trust model
A receipt is only as trustworthy as the key you check it against. For genuine independence, pin the public key out of band: fetch it once from https://app.axiorank.com/api/v1/audit/public-key, confirm the kid, and store that key with your records. Then verify every receipt against the pinned key.
The package ships a fetchJwks() convenience that pulls the live JWKS, but fetching the key from the same party that issued the receipt is not independent verification. Use it for tooling, never as your trust anchor.
What a verified receipt does and does not prove
A verified receipt proves the action is in a signed, append-only log and was authorized as the provenance chain states, and that the record was not altered after sealing. It does not, on its own, protect against a split-view attack (a malicious operator showing different signed histories to different parties); that requires gossiping signed tree heads to an external witness. Pin tree heads over time (GET /api/v1/audit/checkpoints/{seq}) to detect a retroactive edit yourself.
License
MIT