Receipts: what ran, and who says so

A receipt records what a check saw. It is a plain JSON object, it is emitted by several commands, and from 0.12.0 it can be signed with a key that outlives the call and verified by somebody who has nothing but the receipt and a public key.

Two corrections landed in 0.12.0 and both are worth reading before you rely on an older receipt.

The receipt describes the layout that ran

selection_receipt() used to describe the mapper’s recommendation, whatever the caller executed. A campaign here ran layout [6, 5, 4, 3, 2] and got a receipt naming {144, 143, 136, 123, 124}. The receipt was internally consistent and described a run that never happened.

Pass executed_layout= when you run something other than the recommendation:

import functools
from qb_compiler.passes.mapping import CalibrationMapper, selection_receipt

mapper = CalibrationMapper(backend)
result = mapper.run(circuit, {})

receipt = selection_receipt(
    result,
    calibration=backend,
    executed_layout={0: 6, 1: 5, 2: 4, 3: 3, 4: 2},
    scorer=functools.partial(mapper.score_layout, circuit=circuit),
)

What you get back:

field

meaning

selected_layout

the layout that ran

selected_score

its calibration score, computed by the scorer when you did not supply one

describes_executed_layout

always present, so nothing has to be inferred

recommended_layout, recommended_score

what the pass would have picked

executed_layout_matches_recommendation

whether those two are the same

score_penalty_vs_recommended

what the override cost, on the mapper’s own scale

divergence_note

a sentence saying which of the two happened

Without executed_layout the receipt is exactly what it always was, plus describes_executed_layout: true. Nothing that reads an older receipt breaks.

The score is a sum of weighted penalties on one calibration snapshot. It compares layouts against each other on that snapshot. It is not a fidelity and does not convert to one.

Signing, and what a signature is worth

Before 0.12.0, sign=True generated a fresh keypair for every call and put the public half into the receipt it had just signed. Every such receipt verified, against the key travelling inside it, and none of them said anything about where they came from. Do not treat a receipt carrying a public_key field as evidence of origin. The verifier reports those as LEGACY_SELF_SIGNED and refuses them.

Now:

receipt = selection_receipt(result, calibration=backend, sign=True)

The key is created once at ~/.qb-compiler/signing_key with mode 0600, or wherever QBC_SIGNING_KEY points, and reused afterwards. The receipt carries the key’s fingerprint, not the key. sign=True raises rather than quietly handing back an unsigned receipt.

Publish the public half so people can check your receipts:

from qb_compiler.signing import export_public_key
export_public_key("qbc-public-key.txt")

Verifying, which is free and offline

qbc verify-receipt receipt.json --key qbc-public-key.txt
from qb_compiler.signing import verify_receipt
result = verify_receipt(receipt, public_key=their_public_key)
print(result.status, result.ok)

verdict

means

VERIFIED

the bytes were signed by the holder of that key

UNSIGNED

no signature. The contents can still be read; nothing attests to their origin

NO_KEY

signed, but no key was supplied, so it cannot be checked

INVALID_SIGNATURE

altered after signing, or signed by a key you do not have

LEGACY_SELF_SIGNED

the pre-0.12.0 shape described above

MALFORMED

not a receipt this verifier can read

ok is true only for VERIFIED. “I could not check it” is never a pass.

The signature covers a canonical JSON serialisation of the whole receipt except the signature field itself, so changing any other field, including the fingerprint, breaks it.

Verification needs no key of your own, no account, and no network. It falls back to a pure Python Ed25519 implementation when a compiled one is not installed, so pip install qb-compiler is enough to check anybody’s receipt.

A signature says these bytes came from that key holder. It does not say the layout was good, the run was worth doing, or the numbers are right. verify_receipt prints that distinction rather than leaving a reader to assume the stronger one.

Where receipts come from

command

schema

selection_receipt()

qb.selection_receipt.v1

qbc chem-audit --json

qb.chem_audit.v1

qbc measure-plan --json

qb.measure_plan.v1

qbc dem-audit --json

observablegate.receipt/1

qbc when --json

qb.cross_vendor_advice.v1

qbc compile --receipt

compilation passport, see qb_compiler.receipts

Any of them can be signed with qb_compiler.signing.sign_receipt(receipt) and checked with qbc verify-receipt.

Calibration age rides on every selection receipt

A layout is chosen from calibration data, and that data has an age nobody surfaces. Every selection receipt carries it:

"calibration_freshness": {
  "calibration_timestamp": "2026-03-14T08:41:35.899941+00:00",
  "age_minutes": 59.99,
  "tolerance_minutes": 30.0,
  "tolerance_basis": "builtin_default_not_measured_for_this_device",
  "exceeds_default_tolerance": true,
  "timestamp_status": "measured",
  "note": "Age is measured, tolerance is a fixed default. ..."
}

The age is measured. The tolerance is one blunt default for every device, and tolerance_basis says so on every receipt, because a default presented as a measurement is worse than no number. A real tolerance is a property of a specific device and its recalibration schedule, and measuring one means comparing what was visible at a moment against what the vendor later reports was true at that moment, over weeks. That measurement is not in this package.

timestamp_status is measured, absent, unreadable, synthetic (static specs, which have no age) or clock_skew (a timestamp in the future, reported rather than treated as fresh).