Payment Evidence Frame (PEF) v1 -- AlgoVoi's canonical wrapper for payment-lifecycle receipts
Project description
AlgoVoi is available for acquisition -- docs.algovoi.co.uk/acquisition
algovoi-pef
Payment Evidence Frame (PEF) v1 -- a canonical wrapper format for
AlgoVoi payment-lifecycle receipts. Each frame carries a byte-deterministic
frame_id (SHA-256 of the JCS-canonical preimage) and an optional detached
RFC 9421 signature field.
Normative spec: draft-hopley-x402-payment-evidence-frame-00 (IETF I-D, published 2026-05-30).
Canonicalisation pin: urn:x402:canonicalisation:jcs-rfc8785-v1.
Install
pip install algovoi-pef # Python
npm install @algovoi/pef # TypeScript / JavaScript
Quick start
from algovoi_pef import build_pef, verify_pef
# Wrap a compliance receipt in a PEF frame
frame = build_pef(
claim_type="payment_admission",
receipt={
"canon_version": "urn:x402:canonicalisation:jcs-rfc8785-v1",
"jurisdiction_flags": ["EU", "UK"],
"payer_ref": "sha256:abc123...",
"prev_hash": None,
"screen_provider_did": "did:web:api.algovoi.co.uk",
"screen_result": "ALLOW",
"screen_timestamp_ms": 1748534600000,
},
frame_provider_did="did:web:api.algovoi.co.uk",
frame_timestamp_ms=1748534600000,
)
result = verify_pef(frame)
assert result["valid"]
print(frame["frame_id"])
# sha256:09929082c83d5006f61f06bb12eb58cc2c21acebd70a31bca3cb26169c11b6bf
import { buildPef, verifyPef } from "@algovoi/pef";
const frame = buildPef({
claim_type: "payment_settlement",
receipt: {
canon_version: "urn:x402:canonicalisation:jcs-rfc8785-v1",
settled_payment_ref: "sha256:abc123...",
settlement_chain: "ethereum:84532",
settlement_provider_did: "did:web:api.algovoi.co.uk",
settlement_result: "SETTLED",
settlement_timestamp_ms: 1748534700000,
},
frame_provider_did: "did:web:api.algovoi.co.uk",
frame_timestamp_ms: 1748534700000,
});
const result = verifyPef(frame);
console.log(result.valid); // true
console.log(frame.frame_id); // sha256:...
Claim types
PEF defines five claim types, each mapping to an IETF I-D-anchored receipt format:
claim_type |
receipt_format |
IETF I-D | Platform source |
|---|---|---|---|
payment_admission |
compliance-receipt-v1 |
draft-hopley-x402-compliance-receipt |
/compliance/screen |
payment_settlement |
settlement-attestation-v1 |
draft-hopley-x402-settlement-attestation |
/checkout/{t}/verify |
payment_cancellation |
cancellation-receipt-v1 |
draft-hopley-x402-cancellation-receipt |
mandate cancel endpoints |
payment_refund |
refund-receipt-v1 |
draft-hopley-x402-refund-receipt |
refund endpoints |
composite_verdict |
composite-trust-query-v1 |
draft-hopley-x402-composite-trust-query |
/compliance/trust-query |
Frame structure
{
"canon_version": "urn:x402:canonicalisation:jcs-rfc8785-v1",
"claim_type": "payment_admission",
"frame_id": "sha256:<64-hex-chars>",
"frame_provider_did": "did:web:api.algovoi.co.uk",
"frame_timestamp_ms": 1748534600000,
"pef_version": "1",
"receipt": { "..." : "..." },
"receipt_format": "compliance-receipt-v1",
"receipt_hash": "sha256:<64-hex-chars>",
"signature": "<RFC 9421 detached JWS -- optional>"
}
frame_id derivation
receipt_hash = "sha256:" + hex(sha256(JCS(receipt)))
preimage = {
canon_version, claim_type, frame_provider_did,
frame_timestamp_ms, pef_version, receipt,
receipt_format, receipt_hash
}
frame_id = "sha256:" + hex(sha256(JCS(preimage)))
signature is appended after frame_id is set and is excluded from both
hash inputs. Signing the frame_id (rather than the full frame body) keeps
the signature stable across re-serialisations.
API
Python
from algovoi_pef import build_pef, verify_pef, pef_frame_id, CLAIM_TYPES
# Build a frame
frame = build_pef(
claim_type="payment_admission", # str -- must be in CLAIM_TYPES
receipt={...}, # dict
frame_provider_did="did:...", # str
frame_timestamp_ms=1748534600000, # int, epoch-ms
signature="...", # str, optional RFC 9421 JWS
)
# Verify structural integrity (does NOT verify the RFC 9421 signature)
result = verify_pef(frame)
# {"valid": True, "errors": []}
# Re-derive frame_id from an existing frame
fid = pef_frame_id(frame)
# Inspect the closed enum
print(CLAIM_TYPES)
# {"payment_admission": "compliance-receipt-v1", ...}
TypeScript
import {
buildPef, verifyPef, pefFrameId,
CLAIM_TYPES, PEF_VERSION, CANON_VERSION,
type BuildPefOptions, type Pef, type VerifyResult,
} from "@algovoi/pef";
const frame: Pef = buildPef({ claim_type, receipt, frame_provider_did, frame_timestamp_ms });
const result: VerifyResult = verifyPef(frame);
const fid: string = pefFrameId(frame);
Platform integration
shared.utils.pef_wrapper in the AlgoVoi gateway provides soft-import helpers
so each router can emit PEF-wrapped receipts alongside existing fields:
from shared.utils.pef_wrapper import (
wrap_compliance_receipt, # payment_admission
wrap_settlement_attestation, # payment_settlement
wrap_cancellation_receipt, # payment_cancellation
wrap_refund_receipt, # payment_refund
wrap_trust_query_response, # composite_verdict
)
# compliance_gate.py -- returns None gracefully if algovoi-pef not installed
pef_frame = wrap_compliance_receipt(
compliance_receipt_dict,
screen_timestamp_ms=screen_ts,
)
All wrappers use pef_or_none() -- they return None during a rolling deploy
before algovoi-pef is added to the platform requirements, so existing API
responses are unaffected.
Cross-implementation validation
frame_id derivation has been independently validated across eight JCS
implementations in eight programming languages -- 64/64 byte-for-byte
agreements across all five claim types (both receipt_hash and frame_id
layers per vector):
| Language | Runtime | JCS library | Author |
|---|---|---|---|
| Python | CPython 3.12 | rfc8785 0.1.4 |
Trail of Bits |
| JavaScript | Node.js v24 | canonicalize 1.0.8 |
Samuel Erdtman |
| Ruby | Ruby 3.4 | json-canonicalization 1.0.0 |
RubyGems community |
| PHP | PHP 8.4 | inline pure-stdlib JCS | AlgoVoi |
| Go | Go 1.26 | gowebpki/jcs v1.0.1 |
Web PKI Working Group |
| Rust | Rust 1.95 | serde_jcs 0.2.0 |
l1h3r |
| Java | JDK 17 | erdtman/java-json-canonicalization 1.1 |
Anders Rundgren (RFC 8785 author) + Samuel Erdtman |
| .NET | .NET 9 | Baqhub.Packages.JsonCanonicalization 1.0.1 |
Baqhub |
Full attestation record and reproducible runner harnesses:
_attestations/2026-05-30-8-impl-pef-v1.md
in chopmob-cloud/algovoi-jcs-conformance-vectors.
The same corpus now has 576/576 cumulative byte-for-byte agreements across eight vector sets covering the full AlgoVoi agentic-payment receipt stack (admission, settlement, cancellation, refund, composite verdict, PEF).
Tests
# Unit tests (24 tests)
python -m pytest tests/test_pef.py -v
# Integration smoke tests -- platform-realistic receipt shapes + JS parity (32 tests)
python -m pytest tests/test_smoke_pef_platform.py -v
# Full suite (56 tests)
python -m pytest tests/ -v
# Live API integration test (requires network access to api.algovoi.co.uk)
python -m pytest tests/test_smoke_pef_platform.py -v -m live
# TypeScript tests (20 tests)
npm run build && npm test
Specification
- Normative spec:
draft-hopley-x402-payment-evidence-frame-00(IETF I-D, published 2026-05-30) - Canonicalisation pin:
draft-hopley-x402-canonicalisation-jcs-v1 - Receipt format I-Ds:
- Upstream x402 PRs: #2493 / #2494 / #2495 / #2524 / #2525
- Conformance vectors:
pef_v1inchopmob-cloud/algovoi-jcs-conformance-vectors
Acknowledgments
Cross-implementation validation is possible because of the independent JCS
libraries listed in the matrix above. AlgoVoi acknowledges with thanks:
Trail of Bits (rfc8785), Samuel Erdtman (canonicalize and
java-json-canonicalization), Anders Rundgren (RFC 8785 author, Java
implementation), Web PKI Working Group (gowebpki/jcs), l1h3r (serde_jcs),
Baqhub (Baqhub.Packages.JsonCanonicalization), and the RubyGems community
(json-canonicalization).
Licence
Apache 2.0. See LICENSE.
Author
AlgoVoi (Christopher Hopley, chopmob-cloud)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file algovoi_pef-0.1.1.tar.gz.
File metadata
- Download URL: algovoi_pef-0.1.1.tar.gz
- Upload date:
- Size: 19.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81a1fccfd697d7e93e033728ede8aeaf912cec8de49bc22a4b35974a02255d66
|
|
| MD5 |
ce0818daf3e81dddffd7a004a7052c97
|
|
| BLAKE2b-256 |
98d05272af4169f6bd7498de9780f44ad4c4c22208f79c85bf64700419af995d
|
File details
Details for the file algovoi_pef-0.1.1-py3-none-any.whl.
File metadata
- Download URL: algovoi_pef-0.1.1-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52808f8168bb08254a9228b3c3ffee7baa2edb6bcddc28170d7258ff26e52c13
|
|
| MD5 |
b63f3104e8917447399ec4276a7ccdde
|
|
| BLAKE2b-256 |
e4ada099d4598816830984e95ca47408bd65401858c345acbeb1890cdcd8dab1
|