Skip to main content

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 successfully
  • 1 — 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.

aiyoplane.com


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)

Source distribution for aiyoplane-verify 1.0.2
File Size Uploaded
aiyoplane_verify-1.0.2.tar.gz 18.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aiyoplane-verify 1.0.2
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

1.0.2 This release

2 release files

1.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page