Products Demo Docs Blog Engineering About Contact Sign in Sign up
Engineering · · Philippe Laporte

What a Receipt Proves, and What It Does Not

The fields of an AI inference receipt, the three checks anyone can run offline, and the exact boundary of the claim.

Most writing about AI verification stays at the level of promises. This post goes one level down. It walks through the artifact Cyberian issues for each inference, shows the three checks a third party can run on it without contacting us or the operator, and then states precisely what passing those checks establishes and what it does not.

The boundary matters as much as the mechanics. A verification artifact that overstates its own reach is worse than none, because it invites reliance where none is warranted.

The receipt

A receipt is a small structured record, not a log file. Conceptually it carries these fields:

{
  "receipt_id":         "rcpt_9f2a...c71d",
  "issued_at":          "2026-06-04T14:22:08Z",
  "assurance_level":    "independent spot-check",
  "model_id":           "BAAI/bge-large-en-v1.5",
  "model_digest":       "sha256:4b1e...a9f0",
  "runtime":            "onnxruntime, CPU, pinned options",
  "input_digest":       "sha256:e7c3...11b8",
  "output_digest":      "sha256:0d54...8aa2",
  "batch_root":         "9c84...f3e1",
  "inclusion_path":     ["..."],
  "executor_id":        "node_47",
  "attestor_signature": "3045...be90"
}

Field names and values here are illustrative; the published schema is authoritative. Reading it:

That last separation is the rule the whole design rests on: the party that executes is never the party that attests.

Three checks anyone can run offline

Verification needs only three things: the receipt, the output you received, and the attestor's public key. It does not require network access to Cyberian, cooperation from the operator, or trust in either.

1. The output you hold is the output that was attested

Recompute the digest of the output bytes and compare it with the receipt:

import hashlib

def output_matches(output_bytes: bytes, receipt: dict) -> bool:
    digest = "sha256:" + hashlib.sha256(output_bytes).hexdigest()
    return digest == receipt["output_digest"]

If this fails, the output you hold is not the output the receipt covers. It was altered, substituted or re-serialized along the way.

Digests are computed over a canonical byte encoding. For structured outputs such as embedding vectors, the encoding, meaning byte order, float width and serialization format, is part of the specification. Two logically equal outputs serialized differently will not match, and that is intended: the check is about the exact bytes, not about similarity.

2. The job belongs to the committed batch

The leaf for this job is the digest of its canonical record. Walk the inclusion path from that leaf to the root and compare:

import hashlib

def sha256(data: bytes) -> bytes:
    return hashlib.sha256(data).digest()

def included_in_batch(leaf_hash: bytes, path: list, batch_root: bytes) -> bool:
    # path is a list of (sibling_hash, side) pairs, side is "left" or "right"
    node = leaf_hash
    for sibling, side in path:
        node = sha256(sibling + node) if side == "left" else sha256(node + sibling)
    return node == batch_root

If this fails, the job was not part of what the attestor committed to for that batch.

Merkle conventions differ between systems, most importantly in whether leaves and interior nodes are hashed with distinct prefixes, which prevents an interior node from being passed off as a leaf. The specification fixes the convention. The logic above is the same either way.

3. The attestation is authentic

Verify the attestor's signature over the canonical encoding of every other field, using the attestor's published public key:

def attestation_is_authentic(receipt: dict, attestor_public_key) -> bool:
    signed_fields = {k: v for k, v in receipt.items() if k != "attestor_signature"}
    message = canonical_encode(signed_fields)        # encoding defined by the spec
    signature = bytes.fromhex(receipt["attestor_signature"])
    return verify(attestor_public_key, signature, message)  # algorithm per the published key

If this fails, the receipt was not issued by the attestor, or it was modified after it was.

Everything in this check depends on where the public key came from. A key delivered alongside the receipt proves nothing, because whoever forged the receipt could forge the key with it. The key has to come from a trust anchor you can reach independently of both the receipt and the operator.

What passing all three establishes

Together, the three checks establish that:

That is integrity and attribution of a commitment. In the vocabulary of an earlier post, it establishes that the record is unaltered. Integrity, completeness and truth are separated properly in Three properties of an AI evidence record.

A perfectly signed commitment to a false claim still verifies.

What independent re-execution adds

Signature and inclusion checks cannot, on their own, establish that the declared model on the declared input actually produces the declared output. That property comes from the attestor doing the work again.

In the configuration live today, the attestor re-executes an unpredictable sample of each job on its own infrastructure and compares the result with the committed output. Where the execution path is bit-reproducible, such as inference pinned to CPU, the comparison is exact. Where floating-point nondeterminism makes bit equality unrealistic, the comparison uses a tolerance instead.

Two consequences follow, and both should be stated plainly.

Sampled re-execution is economic deterrence, not proof of every step. The executor cannot predict which work will be re-checked, so cheating anywhere risks detection. That makes cheating a losing bet, not an impossible one.

And the strength of a receipt's claim about truth depends on the assurance level of the job it came from, which is why the receipt records that level. Integrity is established identically for every receipt. Truth is established to the degree the assurance level states.

What a receipt does not establish

For engineers the boundary is sharper than the one usually drawn for buyers:

Why the artifact stays small

It would be easy to make a receipt say more: attach explanations, confidence scores, policy verdicts. Every one of those additions would be a claim the receipt cannot itself substantiate. The receipt stays small so that each field in it is something a third party can check without trusting anyone, and nothing in it asks for trust it has not earned.


The compliance-and-risk framing of this same idea — why a self-kept log stops being evidence exactly when you need it — is in the companion essay You Have Logs. Logs Can Be Edited.

PL
Philippe Laporte
Founder and CEO of Cyberian Systems, which issues independent cryptographic receipts proving what an AI system actually did — the exact model, input and output of every inference, attested by a party that never ran the job. Live in production today. Questions and challenges to anything in this post are welcome at philippe@cyberiansystems.ai.

Read the docs · Try the live demo · RSS