Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

b7n0de, Verified AI Work

proofbundle

AI eval results need receipts.

Turn an AI evaluation result into one portable, offline-verifiable receipt. It proves who signed these exact bytes and that nothing changed since — not that the number is true. Ed25519 + RFC 6962 Merkle, one file, no server, no network.

CI PyPI Python License: MIT Ruff Mutation tested

The problem

Every AI eval number you read — a safety benchmark, a capability score, a leaderboard entry — is an unverifiable claim. You trust the lab. There's no portable way to check, offline, that a result was signed by a stated party, hasn't been altered, and covers the samples it claims.

proofbundle is that check. It's a small MIT-licensed Python tool (a compact, auditable trusted core, depends only on cryptography) that turns a result into a signed receipt anyone can verify from a single file — and it's honest about the line it does not cross.

60-second try (offline, no setup)

pip install "proofbundle[eval]"
proofbundle demo

You'll see an honest receipt verify => OK, then six independent tampers each verify FAILED, then a swapped sample get caught — all in memory. The command exits non-zero if any tamper slips through, so it's also a self-test. Full walkthrough: docs/DEMO.md.

# your own receipt, from a signed payload:
proofbundle emit --payload-file result.json --new-key signer.key --out receipt.json
proofbundle verify receipt.json        # exit 0 = OK, 1 = failed, 2 = malformed

What a receipt proves — and what it doesn't

✅ It proves ❌ It does not prove
These exact bytes were signed by this key (authorship) That the number is true
Nothing changed since signing (integrity, Ed25519 + RFC 6962) That the issuer is honest
The result is attributable to a stated issuer That the eval was well-designed
A threshold was met while hiding the model/dataset (salted commitments) That there was no cherry-picking — unless pre-registered
Optionally: individual samples, offline-auditable (per-sample Merkle) That the computation was correct — that needs a TEE or independent reproduction

This boundary is the point, not a weakness. A receipt makes a claim attributable, tamper-evident, and — with pre-registration and per-sample auditing — bounded and spot-checkable. Full detail: THREAT_MODEL.md.

In plain language

A proofbundle receipt is the cash-register receipt of an AI test result: it shows who claimed the number and that nobody quietly changed it afterwards. It does not show the test was good — the way a cash-register receipt does not show the meal was good — but without a receipt there is nothing to check at all.

How it fits together

flowchart LR
    H["eval harness<br/>inspect_ai · lm-eval · promptfoo · pytest"] --> A["adapter → signed claim<br/>salted commitments · provenance · samples root"]
    A --> R["receipt<br/>one portable file"]
    R --> V{{"proofbundle verify — offline"}}
    V --> C["signature · Merkle inclusion · SD-JWT/KB ·<br/>witness quorum · status list · sample openings"]
    C --> OK(["=> OK / FAILED"])
    style V fill:#D6248A,stroke:#D6248A,color:#fff
    style OK fill:#D6248A,stroke:#D6248A,color:#fff

What's in the box

  • Core — Ed25519 signature + RFC 6962 / 9162 Merkle inclusion, verified fully offline. Checks a real Sigstore Rekor proof, so correctness isn't self-referential.
  • Eval receipts — a signed claim (metric ⋈ threshold, n, salted model/dataset commitments, assurance level, provenance) from your run. See EVAL_CLAIM.md.
  • Selective disclosure — SD-JWT (RFC 9901) with Key Binding: prove a threshold while withholding the exact score.
  • Transparency-log interop — C2SP tlog-checkpoint / cosignature / .tlog-proof, with post-quantum ML-DSA-44 witness cosignatures. Optional Token-Status-List revocation snapshots.
  • Per-sample audit — commit to every sample; an auditor challenges random indices (with a fresh nonce or a public randomness beacon, v1.9) and openings must bind to the signed root. With such an auditor-supplied or beacon-bound challenge, 300 samples catch 1% sample-doctoring with 95% confidence, regardless of run size — a challenge the issuer chose itself does not give this guarantee.
  • Pre-registrationproofbundle prereg <plan> commits to the protocol before the run, so best-of-many publishing becomes visible.
  • Integrations — opt-in inspect_ai end-of-task hook and pytest plugin (emit only when PROOFBUNDLE_EMIT=1 / --proofbundle), plus a Hugging Face Community Evals bridge. See INTEGRATIONS.md, or the end-to-end walkthrough docs/INSPECT_HAPPY_PATH.md — run an eval, get a receipt, verify it offline.
  • External time anchors (v2.0 beta, the [anchors] extra) — an optional anchors[] layer that attaches external evidence of when a commitment or receipt existed, from a party the producer does not control. Two built-in types verify offline: RFC 3161 TSA tokens (against a frozen cert chain) and OpenTimestamps Bitcoin proofs (honest pending → confirmed lifecycle). A register_anchor_type extension interface lets a third party ship its own fail-closed type; two worked examples ship — a first-party chia-datalayer/v1 (offline Merkle inclusion of a canonical root under a published Chia DataLayer root) and a third-party markovian-provenance/v1 (a wallet-attributable, Bitcoin-anchored stamp). See docs/ANCHORS.md.

Docs

For… Read
Skeptics (why not SHA-256 / Sigstore / trust the issuer) docs/FAQ.md
New to this? plain-terms glossary docs/GLOSSARY.md
Reviewers (30-minute adversarial audit path) docs/REVIEWERS.md
Where every trust anchor comes from docs/TRUST_ANCHORS.md
The demos, tier by tier docs/DEMO.md
The normative format + verification order SPEC.md
Honest comparison to Rekor / in-toto / OMS / ValiChord INTEROP.md
Regulatory mapping (and what to never claim) COMPLIANCE.md
Funders / role fit docs/PROJECT_BRIEF.md
External time anchors + the bring-your-own-type extension interface (v2.0 beta) docs/ANCHORS.md
Preview: TEE-attestation bridge (v2.0 beta) docs/EXPERIMENTAL_ENCLAVE.md

Install

pip install proofbundle                 # core: offline verify + plain emit (dependency-free)
pip install "proofbundle[eval]"          # + eval receipts, prereg, and the demo (adds an RFC 8785 JCS canonicalizer)
pip install "proofbundle[inspect]"      # inspect_ai adapter + hook
pip install "proofbundle[pq]"           # verify ML-DSA-44 (post-quantum) witness cosignatures

Requires Python 3.10+. The verify path never rolls its own crypto — Ed25519 comes from cryptography; Merkle hashing is RFC 6962.

Status & scope

Beta, SemVer-committed, with a CI test suite behind a mutation gate + property-based parser fuzzing. Correctness is anchored to external RFC 6962 vectors and a real Rekor proof, not just its own bundles. It is not a log service, a full in-toto client, a TEE, a consensus network, or a compliance product by itself — it is the small, offline, standards-native receipt layer between them. Security policy: SECURITY.md.

Contributing

See CONTRIBUTING.md and the Code of Conduct. Good first issues are labeled good-first-issue; security findings go through SECURITY.md. The verifier core aims to stay small, dependency-light, and correct.

License

MIT — see LICENSE.


proofbundle is part of b7n0de, Verified AI Work · b7n0de.com

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

proofbundle-2.0.0b3.tar.gz (187.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

proofbundle-2.0.0b3-py3-none-any.whl (136.0 kB view details)

Uploaded Python 3

File details

Details for the file proofbundle-2.0.0b3.tar.gz.

File metadata

  • Download URL: proofbundle-2.0.0b3.tar.gz
  • Upload date:
  • Size: 187.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for proofbundle-2.0.0b3.tar.gz
Algorithm Hash digest
SHA256 e7312e909c1ee2a9e0c7e7acb68b046b90955926f3ac29a4dfff9c9cb75eccd2
MD5 70d4b29d3c6eb2afed9704ae4160e9e9
BLAKE2b-256 647267609c047325a6f9483330908e01b1b79cd567eea845a85d31cab5260762

See more details on using hashes here.

Provenance

The following attestation bundles were made for proofbundle-2.0.0b3.tar.gz:

Publisher: release.yml on b7n0de/proofbundle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file proofbundle-2.0.0b3-py3-none-any.whl.

File metadata

  • Download URL: proofbundle-2.0.0b3-py3-none-any.whl
  • Upload date:
  • Size: 136.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for proofbundle-2.0.0b3-py3-none-any.whl
Algorithm Hash digest
SHA256 cec86a02f2e3d83644a160711a420caf7182eeaf5de6e18d0d9949cf567a048a
MD5 a3cb56abd7192784c18d9959e8c828bd
BLAKE2b-256 0e4a208af326a2a8b49fcae582812fd22349150dfcfd9a631115f092c5196c13

See more details on using hashes here.

Provenance

The following attestation bundles were made for proofbundle-2.0.0b3-py3-none-any.whl:

Publisher: release.yml on b7n0de/proofbundle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page