Skip to main content

inspect-receipts — Ed25519-signed measurement receipts for Inspect

UK AISI's Inspect is the standard eval framework, but it has no cryptographic signing of results. inspect-receipts fills that gap: a small, dependency-light package that hooks Inspect's lifecycle and emits an Ed25519-signed, hash-chained, offline-verifiable measurement receipt for every task and run.

Doctrine: measurement, not certification. A receipt is non-repudiable evidence of what was claimed and when — not proof that an eval is honest, uncontaminated, or correct. Deterministic. Nobody ranked pays; humans never pay.

This repo open-sources the receipt format + exporter only. The axes, predicates, and benchmarks stay closed and are not in this repo.

How it works

  • Hook, no fork. Registers through Inspect's inspect_ai setuptools entry-point group (the same mechanism inspect-mlflow uses). Inspect imports the module and the @hooks-decorated class self-registers, hooking the real lifecycle: on_task_end and on_run_end.
  • Signs the EvalLog object model, not raw .eval bytes. The physical .eval file is a version-dependent zstd ZIP-of-JSON; hashing those bytes is fragile across Inspect releases. Instead the receipt canonicalises a stable field subset of the EvalLog object — eval id, run id, task, model, dataset identity, scores/metrics, timestamps — into deterministic JSON (recursively sorted keys, no whitespace), then SHA-256-hashes and Ed25519-signs that.
  • Content-addressed + hash-chained. content_id = sha256(canonical body); each receipt's prev links the previous receipt's content_id.
  • Verify against a published key. Signatures are verifiable offline against the CSOAI board-attestation key published at did:web:csoai.org (https://csoai.org/.well-known/did.json, verificationMethod / publicKeyJwk) — the same key path the live board /api/gspc uses. A stranger verifies against the published key, not a key the receipt vouches for itself.
  • No private key ever ships. The signing key is provisioned by the owner via INSPECT_RECEIPTS_KEY (a 0600 seed file / secret). With no key configured, the hook emits an UNSIGNED receipt with an explicit status — a signature is never fabricated.

Install

pip install inspect-receipts        # once published to PyPI (owner-gated)
# or from source:
pip install -e .

Emit receipts from an eval run

Opt-in via env; the hook does nothing unless INSPECT_RECEIPTS=1.

export INSPECT_RECEIPTS=1
export INSPECT_RECEIPTS_KEY=/run/secrets/inspect_receipts_ed25519.seed  # owner-provisioned, 0600
export INSPECT_RECEIPTS_KID="did:web:csoai.org#keys-1"                   # optional; default keys-1
export INSPECT_RECEIPTS_DIR=./receipts                                   # optional; default ./receipts

inspect eval my_task.py --model openai/gpt-4o
# -> ./receipts/task-<id>.receipt.json and run-<id>.receipt.json

Verify (what a UK AISI maintainer runs)

# offline integrity + signature (embedded key — integrity only)
inspect-receipts verify receipts/task-*.receipt.json

# trust path: fetch the PUBLISHED key from did:web:csoai.org and require the
# signature to verify under it
inspect-receipts verify receipts/task-*.receipt.json --did-web

verify exits non-zero on any failure. UNSIGNED receipts report as UNSIGNED and fail (they are content-addressed but not attributable to a key).

CLI

inspect-receipts keygen <seed-file>            # 32-byte Ed25519 seed, mode 0600 (publish only the PUBLIC key)
inspect-receipts sign  <log.eval> [--key SEED] [--out FILE]   # receipt from an EvalLog object
inspect-receipts verify <receipt.json> [...] [--did-web [URL]]

What is and isn't anchored

Real today: Ed25519 signatures + a SHA-256 content-address and per-run hash-chain, verifiable offline against the did:web:csoai.org published key.

Roadmap / optional (NOT wired): transparency-log inclusion (Rekor), RFC 3161 timestamping, and OpenTimestamps anchoring. These are not implemented; no receipt claims them. Do not rely on any timestamp-authority anchoring here.

Receipt shape (abridged)

{
  "schema": "csoai.inspect-receipt/0.2",
  "kind": "task",
  "issued_at": "2026-08-20T01:39:22Z",
  "eval_id": "…", "run_id": "…", "prev": null,
  "eval_log": { "status": "success", "eval": { "eval_id": "…", "task": "…", "model": "…", "dataset": {} }, "results": {}, "stats": {} },
  "eval_log_sha256": "…",
  "content_id": "sha256(canonical body)",
  "verify": { "did": "did:web:csoai.org", "command": "inspect-receipts verify <file> --did-web", "anchoring": "Ed25519 + SHA-256 hash-chain only; Rekor/RFC3161/OTS are roadmap." },
  "signature": { "status": "SIGNED", "alg": "Ed25519", "kid": "did:web:csoai.org#keys-1", "signer_public_key": "…", "sig": "…" }
}

Tests

pip install -e ".[test]"
pytest -q            # or: python tests/test_receipt.py

Status

0.2.0. Coordinate-first: answers Inspect issue #4413 with a common signed-receipt envelope. License: Apache-2.0.

Download files

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

Source Distribution

inspect_signed_receipt-0.2.0.tar.gz (15.8 kB view details)

Uploaded Source

Built Distribution

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

inspect_signed_receipt-0.2.0-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

Details for the file inspect_signed_receipt-0.2.0.tar.gz.

File metadata

  • Download URL: inspect_signed_receipt-0.2.0.tar.gz
  • Upload date:
  • Size: 15.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for inspect_signed_receipt-0.2.0.tar.gz
Algorithm Hash digest
SHA256 9a66b209016f36b39a989bebcb30ddf4503adfe969055291a4cc5ab0b742e612
MD5 58a5170991cd0543862a392ef124e9de
BLAKE2b-256 33acaea9dcd176ce0c500e5fa609172816c29428dc661e872758c4d810c84838

See more details on using hashes here.

Provenance

The following attestation bundles were made for inspect_signed_receipt-0.2.0.tar.gz:

Publisher: publish.yml on CSOAI-ORG/inspect-receipts

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

File details

Details for the file inspect_signed_receipt-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for inspect_signed_receipt-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c752c81c3506b6e0f06b1b3c0b82b7db74443766d67d98972988f6045840f79a
MD5 2ebbcc3544e2ce584fa1c7feb03a3b1f
BLAKE2b-256 91d5e25977ebd62342c5ca0636a083d528b95b094b67207e31f76724950e65f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for inspect_signed_receipt-0.2.0-py3-none-any.whl:

Publisher: publish.yml on CSOAI-ORG/inspect-receipts

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