Implementation: ENABLED (signed chain for effect receipts) · IMPLEMENTED (keys and chain-check routes) · Exposure: INTERNAL. See status labels. A receipt is the durable evidence that something happened in a run: an effect, an input, a policy decision, a verification result, a control action. Receipts are what completion, resume, audit and replay are built on.

Architecture contract

What a receipt proves

A receipt proves that a specific, typed event was recorded at a specific position in a run’s history, with specific content, by the platform. It does prove:
  • Content. The receipt body has not changed since it was written (content hash).
  • Order and completeness. The receipt sits at a fixed index after a specific predecessor, and nothing was inserted or removed before it (hash chain).
  • Origin. The platform’s key signed it, for this schema and this purpose (signature with domain tag).
  • Source and trust. Each receipt lists where its inputs came from and their trust class (provenance).
It does not prove:
  • That a recorded result is correct. A verification receipt records that a verifier ran and what it returned. Whether the verifier is adequate is a separate question.
  • Anything about events that were never receipted.

Receipt types

Rules

  • Append-only. A receipt is never edited or deleted. A correction is a new receipt whose supersedes field points at the old one.
  • Content-addressed. Each receipt is identified by the hash of its content.
  • Input before effect. Human input and control requests are receipted before they take effect.
  • Idempotency before retry. An action with an external or irreversible effect needs an idempotency key and an action receipt before it may be retried.
  • Sufficient for replay. Every node emits a receipt or trace event sufficient to reconstruct what it saw and did.

Hash chain

Receipts for one run form a chain in index order.
  • content_hash is SHA-256 over the canonical JSON (RFC 8785, JCS) of every field of the receipt except content_hash and signature. It is written sha256: followed by 64 lowercase hex characters.
  • prev_hash is the content_hash of the previous receipt in the same run. It is null only at index 0.
Because prev_hash is part of the hashed content, changing, removing or inserting any earlier receipt changes every hash after it.

Signature and domain tag

Each receipt is signed with Ed25519. The signed material is not the raw content hash alone. It is the JCS-canonical form of this object:
Binding the schema ID, schema version and the domain-separation tag allternit.receipt.v1 into the signature means a signature made for one kind of receipt cannot be presented as a signature over a different schema, a different version, or a different protocol that happens to use the same key. The signature object carries alg (ed25519), key_id, value (base64url), domain and jwks_url. Public keys are published as a JWKS document at /.well-known/jwks.json. Today that document is served by the internal work runtime service, not through the public origin. See Availability.

Verifying a chain

To verify a run’s receipts independently:
  1. Fetch all receipts for the run in chain order.
  2. For each receipt, remove content_hash and signature, canonicalize the rest with RFC 8785, hash with SHA-256, and compare with content_hash.
  3. Check that prev_hash equals the previous receipt’s content_hash, and is null at index 0. Check that index increases by one each step.
  4. For each signature, build the four-field object above, canonicalize it, and verify the Ed25519 signature with the JWKS key whose kid equals signature.key_id.
  5. Check that the run’s terminal receipt (Run.output.run_receipt_id) is in the chain you verified.
The Agency API also offers a server-side check. It is a convenience, not the trust root: a client that needs assurance verifies with the published keys itself. Code for both is in Agency API: Receipts.

Current implementation

The per-run receipt chain is on main in the work runtime:
  • Hashing and chaining. content_hash is SHA-256 over the RFC 8785 canonical form of the receipt without content_hash and signature, and prev_hash links each receipt to the one before it, null at index 0, as described above.
  • Signatures. Each chained receipt is signed with Ed25519 over the four-field object with the domain tag allternit.receipt.v1. The signing key is loaded from configuration. Outside production a key is generated on first use, with a warning; in production, key generation is refused.
  • Effect receipts. Tool calls that go through the gate are recorded on the chain as effect (action) receipts. Each effect runs at most once per idempotency key; a repeat returns the recorded result, and a failed effect is recorded as failed. Calls marked read-only or no-effect are not chained. See Retries and idempotent effects.
  • Keys and verification routes. The work runtime service serves the public keys (at /.well-known/jwks.json and /v1/receipts/jwks, with no private material) and a server-side chain check for a run (/v1/receipts/chain/{run_id}/verify). This service is internal. These routes are not exposed through https://api.allternit.com yet, so an outside client cannot fetch the keys or run the check today.
Other receipt types (run, verification, policy, input and so on) are still written as content-hashed records and are not yet on the signed chain.

Availability

Developer relevance

Receipts are how you audit a run without trusting the platform’s word for it. Once the keys are reachable through the public origin, verify chains yourself with them; the server-side check is a convenience, not the trust root. Store receipt_id values from errors and attention answers, because they point at the exact evidence.