Skip to content

Receipt Capture

Every billable and lifecycle event mints a receipt. Receipts are appended, one per line, to a daily JSONL ledger on local disk.

data/receipts/YYYY-MM-DD.receipts.jsonl

One receipt per line (newline-delimited JSON). The directory is core/config.py’s receipts_dir (default ./data/receipts), created on first write.

FieldNotes
receipt_idrcpt_{hex} (uuid4 hex).
receipt_typeOne of the types below.
member_idThe member the event bills/belongs to.
job_idJob id, or null.
dataset_idsList of dataset ids (may be empty).
amount_usdDecimal serialized to a 2-dp string.
metadataFree-form event context.
seqMonotonic chain index, starting at 0 (the house chain).
parent_hashThe checksum_sha256 of the prior receipt; genesis is 64 zeros.
created_atISO-8601 timestamp.
checksum_sha256sha256 over the canonical JSON of all other fields (incl. seq + parent_hash).

checksum_sha256 = sha256( canonical_json(receipt without checksum) ), where canonical_json normalizes the payload and serializes deterministically:

  • Decimal → 2-dp string (e.g. "10.00")
  • datetimes → .isoformat() (ISO-8601)
  • json.dumps(..., sort_keys=True, separators=(",", ":"), ensure_ascii=True)
  • the checksum_sha256 field itself is excluded from the hashed payload

To verify a line: parse the JSON, drop checksum_sha256, recompute, and compare.

Router receipts are hash-chained, mirroring the DefendableCloud per-org chain. Each receipt carries a seq (monotonic from 0) and a parent_hash equal to the prior receipt’s checksum_sha256 — and because those two fields are inside the hashed body, the link is itself tamper-evident. The genesis receipt’s parent_hash is 64 zeros (0000…0000). The router keeps one house-wide chain (single-tenant spine), where the Cloud keeps one chain per org.

Verify the whole chain:

  • GET /receipts — the chain in seq order (coordinates only).
  • GET /receipts/verify — recomputes every checksum_sha256, confirms seq runs 0,1,2,… with no gaps, and confirms each parent_hash links to the prior receipt. Returns { ok, receipts_checked, errors }.
  • CLI: defendable-router verify-ledger (exit 0 if ok, 1 otherwise).

Tamper with any stored receipt and /receipts/verify flips ok: false and pinpoints the offending seq — the same guarantee the Cloud’s /ledger/verify gives.

membership · dataset_access · compute_quote · compute_job · fine_tune_job · worker_registered · job_leased · worker_job_accepted · artifact_reported · worker_job_completed · worker_job_failed · lease_expired

A job that is a fine_tune mints fine_tune_job receipts; all other job types mint compute_job receipts. Lifecycle receipts (job_leased, worker_job_accepted, worker_job_failed, lease_expired, worker_registered) carry amount_usd of 0.00.


🐝 Operator-grade · books and records · to the shed.