@agenticprimitives/verification-receipts
Verifier-retained verification receipts — the portable evidence that a verifier checked an agent's authority at execution time (signature, scope vs. transaction parameters, current revocation status), retained independently by the counterparty.
Spec: specs/303-verification-receipts.md · Doctrine:
ADR-0010 amendment 2026-07-07 ("the Smart Agent address is the accountability root, not the default
presentation identifier") · Standing measurement:
acting-on-behalf alignment audit.
Why
When an agent transacts before its principal reviews the action, the counterparty's protection is the verifier's diligence — and diligence that leaves no retained artifact is unprovable. This package produces that artifact. Naively, a rich receipt (principal address, tool name, args hash, exact timestamp) would also be a correlation surface; receipts here are born privacy-split:
- Public receipt (
VerificationReceiptV1) — exportable, counterparty-retained. Carries the verifier identity (services are public), the decision, coarse reason, revocation evidence (chain/block), a UTC-day time bucket, already-public artifact hashes (delegation / invocation proof), and HMAC commitments — never raw values — for the principal and arguments. - Private detail (
VerificationReceiptDetailV1) — vault-resident. Raw principal, tool, args hash, exact time, and thereceiptKeythat opens the public commitments. Destroying the key and detail degrades the public receipt to an anonymous verdict whose signature still verifies — the GDPR-erasure-friendly path.
Use
import {
mintVerificationReceipt,
verifyVerificationReceipt,
openReceipt,
} from '@agenticprimitives/verification-receipts';
// At the verify pipeline's terminal point (allow AND deny):
const { receipt, detail } = await mintVerificationReceipt(
{
verifier: serviceSa,
decision: 'allow',
reasonCode: 'verified',
principal, toolName, argsHash,
delegationHash, invocationProofHash,
scopeDecision: 'in_scope',
status: { revocation: 'active', chainId, blockNumber, blockHash },
verifiedAt: new Date().toISOString(),
verifierPolicyVersion: 'policy-v1',
},
{ sign: (receiptHash) => hostSigner.sign(receiptHash) }, // injected — KMS/EIP-712/ECDSA
);
// → receipt: return to the caller (`_meta.ap_receipt`) + durable sink
// → detail: write to the principal's vault (classification `receipt.private`)
// Counterparty, offline, no AP runtime:
const ok = await verifyVerificationReceipt(receipt, { verifySignature });
// Dispute: does the vault detail open this receipt?
const opens = await openReceipt(receipt, detail);
Signing and signature verification are injected ports — this package is dependency-free (WebCrypto only) and never picks a crypto mechanism for you. One scheme per deployment, no fallbacks.
Non-goals
The mint-point wiring, durable storage, and vault residency belong to mcp-runtime and consuming
apps (spec 303 W2). Audit events remain @agenticprimitives/audit's job — receipts share hashes
with audit rows (one incident, joinable evidence) but face the counterparty, not the substrate.
Status
w1-mint-verify — types, commitment profile, canonical hashing, mint/verify/open, unit suite.
Runtime wiring (W2), A2A task receipts + ap verify-receipt CLI (W3), and relationship-record
anchoring (W4) are tracked in the spec.