aiyoplane-verify
Offline Ed25519 verifier for Aiyo execution receipts.
Aiyo issues cryptographically-signed execution receipts at the moment it authorizes a consequential action. Every receipt is verifiable offline against Aiyo's published JWKS — no round-trip to Aiyo required at verification time, no Aiyo-side infrastructure needed. This package is the Python verifier.
Aiyoplane, Inc. · Apache 2.0 licensed · aiyoplane.com
The npm port (same spec, same JWKS, same semantics) is published as @aiyoplane/verify.
Install
pip install aiyoplane-verify
Requires Python 3.9+ and the cryptography package (installed automatically as a dependency).
Command-line usage
The install registers a console script aiyo-verify in your Python environment:
# Verify a receipt from a file
aiyo-verify path/to/receipt.txt
# Verify a receipt passed inline
aiyo-verify --receipt "v2.eyJpaWQiOiJpbnRlbnRfMTIz...Q.MEQCIH...IDA"
# Read from stdin
cat receipt.txt | aiyo-verify -
# Emit JSON output for CI/CD or machine consumption
aiyo-verify --json path/to/receipt.txt
# Override the JWKS URL (e.g., for a self-hosted Aiyo instance)
aiyo-verify --jwks-url https://api.example.com/.well-known/aiyo-jwks.json path/to/receipt.txt
Exit codes:
0— receipt verified successfully1— receipt invalid (bad signature, expired, malformed, unknown key)2— usage error (missing input, unrecognized flag, etc.)
Programmatic usage
from aiyoplane_verify import verify, ReceiptExpiredError, ReceiptSignatureError
receipt = "v2.eyJpaWQiOiJpbnRlbnRfMTIz...Q.MEQCIH...IDA"
try:
result = verify(receipt)
claims = result["claims"]
print(f"Authorized action {claims['iid']} for merchant {claims['mid']}")
print(f"Receipt valid until {claims['exp']}")
except ReceiptExpiredError:
# Receipt was validly signed but has expired.
...
except ReceiptSignatureError:
# Signature did not verify — possible tampering or key mismatch.
...
Options
from datetime import datetime, timezone
import os
from aiyoplane_verify import verify
result = verify(
receipt,
# Override the JWKS URL (default: https://api.aiyoplane.com/.well-known/aiyo-jwks.json)
jwks_url="https://api.example.com/.well-known/aiyo-jwks.json",
# Required for v1 HMAC receipts (local development only).
hmac_secret=os.environ.get("AIYO_HMAC_SECRET"),
# Override "now" for expiration checks (useful in tests). Accepts a
# datetime or a float of epoch seconds.
now=datetime(2026, 9, 28, 14, 24, tzinfo=timezone.utc),
# Clock-skew tolerance in seconds (default: 30).
clock_skew_seconds=60,
# Timeout for JWKS fetch, if needed. Default 10 seconds.
timeout_seconds=5.0,
)
Typed errors
Every verification failure raises one of these typed exceptions. Handle specific failure modes distinctly:
from aiyoplane_verify import (
verify,
ReceiptFormatError,
ReceiptSignatureError,
ReceiptExpiredError,
JwksFetchError,
UnknownKeyError,
UnsupportedVersionError,
)
try:
verify(receipt)
except ReceiptExpiredError:
# Receipt was validly signed but has expired.
...
except ReceiptSignatureError:
# Signature did not verify — possible tampering or key mismatch.
...
except JwksFetchError:
# Could not reach the JWKS endpoint — treat as transient and retry.
...
except (ReceiptFormatError, UnknownKeyError, UnsupportedVersionError):
# Malformed receipt, unknown kid, or unsupported version.
...
Receipt format
Aiyo receipts are strings of the form:
v2.<base64url(payload_json)>.<base64url(ed25519_signature)>
The payload is a JSON object with these required claims:
| Claim | Type | Meaning |
|---|---|---|
iid |
string | Intent ID — the specific action this receipt authorized |
mid |
string | Merchant ID — whose policy this decision was under |
exp |
number | Expiration timestamp (unix seconds) |
iat |
number | Issued-at timestamp (unix seconds) |
cid |
string | Context ID — correlation across a broader flow (optional) |
kid |
string | Key ID — which JWKS key was used to sign (optional) |
The signature is Ed25519 over the base64url-encoded payload segment (JWS-style compact signing).
The v1 format (v1.…) uses HMAC-SHA256 with a shared secret and is intended for local development / in-process use only. Production receipts should always be v2.
JWKS
The default JWKS URL is:
https://api.aiyoplane.com/.well-known/aiyo-jwks.json
Keys are cached in-memory (respecting Cache-Control: max-age where present, defaulting to 10 minutes). If a receipt references a kid not in the cache, the JWKS is automatically refreshed once — handling key rotation gracefully.
To force a fresh JWKS fetch in a long-running process:
from aiyoplane_verify import clear_jwks_cache, fetch_jwks
clear_jwks_cache()
fetch_jwks() # Refetches from the default URL
Why offline verification matters
Third parties — auditors, downstream systems, merchants' own compliance tooling — can verify Aiyo receipts without depending on Aiyo being available at verification time. The receipt is a portable, independently-verifiable artifact. That's the property that makes Aiyo's authorization decision durable across systems, and it's the property this package makes trivial to use.
For the broader architectural context, see the DMARC precedent post and the MCP-authz reference implementation.
About Aiyo
Aiyo is the settlement-verified Economic Execution Authorization plane for autonomous systems. Its Runtime Decision Point verifies that settlement actually occurred on a real rail, evaluates merchant policy, and issues a portable authorization artifact that unlocks the action a payment — or any qualifying condition — was supposed to enable. Verify First. Execute Second.
License
Apache License 2.0 © 2026 Aiyoplane, Inc. — see LICENSE and NOTICE.
Metadata
Release files for aiyoplane-verify 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aiyoplane_verify-1.0.2.tar.gz | 18.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aiyoplane_verify-1.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.6 kB
Release files / aiyoplane_verify-1.0.2.tar.gz
| Download URL | aiyoplane_verify-1.0.2.tar.gz |
|---|---|
| Size | 18.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5c8fad33d7aa2b7b435f69a5decaf0baa31ee7c66ce2e7e28547cfa710219ae2
|
|
BLAKE2b-256 checksum How to use checksums |
78991afe47042db2763db4cfa9bef5841a1688bc41d214af2e55d1c788ed5071
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / aiyoplane_verify-1.0.2-py3-none-any.whl
| Download URL | aiyoplane_verify-1.0.2-py3-none-any.whl |
|---|---|
| Size | 17.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
edfed0255e9a4cdec04c68aa260b50dc8eb75f7596e47bbeb044e965abe43968
|
|
BLAKE2b-256 checksum How to use checksums |
dc058e7836688decf335a9ece9f2b24967703759c939bd66e847f42626d49aed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|