The Delivery Contract
Make payment conditional on receiving the committed output by checking its digest in the kernel before capture.
On this page
Agents can buy another system’s work under terms checked at delivery. The grant commits to a digest of the expected output, and the kernel compares the delivered value with it before capturing payment. A mismatch releases the hold and records a denial with zero currency charged.
The kernel can enforce it because it governs both the call that returns the output and the capture of the payment hold. The Cognition Market uses it for paid finding reveals, and any call on the durable, output-aware execution path can carry it. Unpriced calls need no delivery commitment.
A grant can commit to the bytes it pays for
Consider an executor whose complete final JSON value is {"text":"ready"}. With one string property, its canonical UTF-8 form is exactly the compact JSON below, with no trailing newline. The SHA-256 is calculated from those bytes, not captured from a payment run.
{"text":"ready"}203ff3603ac6fda47de11921349c1a4c5a2177edb87beb07eeea129b0594a11f
{"text":"changed"}e97aeabd4ca363c10046e89eaf8f8f1cdb755970c17690a6dc4bb31d8d6a010a
The committed value matches and can proceed to capture once the remaining checks pass. The changed value is refused after delivery: the reversible hold is released and zero is charged, while the dispatched budgeted invocation remains consumed.
Commit to the final value the executor returns, after any output transformation. If the protocol wraps the document in an envelope, hash the canonical envelope rather than its decoded text. The captured market purchase does this on a real finding reveal: the buyer commits to the envelope’s canonical JSON digest, media type and base64 payload included.
The constraint’s wire form and variants
Constraint is an adjacently tagged enum in crates/core/chio-core-types/src/capability/scope.rs: a type tag, a value, and deny_unknown_fields. The digest variant serializes as below, with the design record’s placeholder in place of a digest.
{"type":"output_digest_sha256","value":"<64 lowercase hex>"}Three variants carry delivery policy:
OutputDigestSha256(String), wire tagoutput_digest_sha256. An Allow is valid only if the final post-transform output content hash equals this digest, a canonical lowercase 64-character hex SHA-256 digest.RequireFindingPurchase(Box<FindingPurchaseMarkerV1>), wire tagrequire_finding_purchase. One purchased finding reveal. The provider-signed marker names the finding and listing being sold and closes over the settlement rail.RequireFindingRecovery(Box<FindingRecoveryMarkerV1>), wire tagrequire_finding_recovery. A bounded no-charge redelivery of a finding whose paid delivery already settled. Recovery never satisfies a purchase marker and never enters a payment path.
Attenuation of all three is structural equality: a child grant keeps a digest or marker only by carrying the identical one, so a delegation cannot loosen or drop the expected output. Unlike the argument-side constraints, the request matcher admits the digest variant only as a carrier; the comparison runs at the output-aware terminal.
Three inputs decide whether a call can settle
The settlement check reads three facts: whether the grant commits to a digest, whether the tool delivered a single value, and whether that value’s digest equals the commitment. Without a commitment, this check never denies. A committed call settles only when a single value arrived with a matching digest.
Corner c 1, d 1, e 0: the delivery check denies settlement. digest differs from the commitment; guard: delivery_contract; result: mismatched; hold released, zero captured.
In Rust · kani_public_harnesses.rs:172921 lines
let constrained = kani::any::<bool>();
let delivered_value = kani::any::<bool>();
// … committed = Some(expected) when constrained
let denies = delivery_denies_settlement(committed, observed_str, delivered_value);
if constrained && !denies {
assert!(delivered_value);
assert!(expected == observed);
assert!(delivery_contract_admits(expected_str, observed_str) == DeliveryVerdict::Allow);
}
if !constrained {
assert!(!denies);
}
if constrained && !delivered_value {
assert!(denies);
}
if constrained && delivered_value && expected == observed {
assert!(!denies);
}
let retry = delivery_denies_settlement(committed, observed_str, delivered_value);
assert!(retry == denies);
The Kani harness asserts each combination the figure draws. A match establishes content identity: the final canonical value has the committed digest. The remaining checks still apply, so a match alone does not imply Allow. A claim that a finding is correct or useful needs its own evidence.
Unsupported carriers are refused before dispatch
A commitment is useful only where payment can still be withheld. The kernel refuses an unsupported digest-constrained request before it issues an execution nonce, consumes invocation quota, or authorizes payment:
- A no-output authorization path. Execution-nonce preflight authorizes without producing output, so a selected grant carrying the constraint is denied there.
- A path with no release. After grant selection the kernel reads the payment adapter’s rail mode, and it denies a request with no durable admission record, a configured rail other than
ReversibleHold(aPrepaidFinalrail settles inside the authorize call), or a governedMustPrepayrequest beforeauthorize_payment_if_neededruns. No prepayment settles. - A downgraded carrier. The request matcher rejects
Constraint::Custom("output_digest_sha256", ..)withInvalidConstraint, because failing only that grant would let an unconstrained sibling serve the call. A kernel that does not know the variant cannot deserialize the token (the tag is adjacent and unknown fields are denied), so it denies the call.
These refusals carry urn:chio:error:kernel:delivery-contract-unsupported-carrier: a request that carried a delivery contract the evaluator cannot enforce.
The kernel checks output before payment capture
On the paid path, reversible payment authorization happens before dispatch, and the comparison precedes capture. The durable admission operation records each step:
- Hold. The kernel authorizes a reversible payment hold before the tool runs. On the budgeted durable path, dispatch also captures one invocation, which a later mismatch does not restore.
- Dispatch and finalize. After the tool returns, the operation moves to
finalizing.finalize_durable_tool_returnincrates/kernel/chio-kernel/src/kernel/admission_coordinator/terminal.rsrefuses to start from any other state. - Hash. The kernel runs the post-invocation transforms, then
receipt_content_for_outputtakes the SHA-256 of the canonical JSON bytes of the whole response value: the observed digest. - Compare.
evaluate_deliverycallsdelivery_denies_settlementinchio_kernel_core::formal_core, a pure function that denies unless the output is a single value whose digestdelivery_contract_admitsfinds byte-identical to the expected digest. - Plan payment. The delivery checks contribute to the terminal decision, which is folded into
post_guard_decision_digest. Only then doesdurable_payment_dispositionplan the payment.
A match captures; a mismatch charges nothing
When the digest matches and the remaining delivery checks allow completion, a positive realized cost is captured from the hold, and a successful zero-cost call releases it. The kernel signs an Allow whose delivery_contract block reads result: matched.
On a mismatch the operation moves to denied_after_delivery, which is legal only from finalizing. The settlement disposition is ContractualZeroCharge: the open hold is released, zero is captured, and realized spend reconciles to zero. The kernel signs a Deny whose decision.guard is delivery_contract, with the block reading result: mismatched.
The Deny receipt’s financial.cost_charged is zero, and the invocation captured with dispatch stays consumed. A replayed terminal finds the same release already recorded in the payment journal and issues no second release.
The admission states
When payment applies, the hold sits on a ReversibleHold payment rail, and a mismatch settles by releasing it. The admission operation is the durable record of the governed call: AdmissionOperationState has 18 states, 7 of them terminal, and denied_after_delivery is the terminal a mismatch reaches. Its doc comment in the enum states the outcome: The delivered output did not match a grant's committed output digest. A signed Deny is persisted; the open hold is released and zero is captured.
pub enum AdmissionOperationState {
Prepared,
BrokerAttemptRegistered,
ApprovalRequired,
BudgetAuthorized,
ApprovalReserved,
ReadyToDispatch,
CapturePending,
DispatchCommitted,
Finalizing,
Completed,
CompensatedBeforeDispatch,
NotAcceptedAfterDispatchCommit,
OutcomeUnknownAfterDispatch,
/// The delivered output did not match a grant's committed output
/// digest. A signed Deny is persisted; the open hold is released and
/// zero is captured.
DeniedAfterDelivery,
MutationReady,
MutationSubmitted,
EconomicMutationApplied,
EconomicMutationNotApplied,
}A mismatched Deny does not confirm the payload
The actual output and its digest stay in the durable outcome store for privileged challenge handling. The public receipt’s content_hash and observed_digest carry a deterministic redaction hash derived from the expected digest. That hash is independent of the mismatched payload, so a candidate payload cannot be checked against the Deny.
The kernel merges the block last and rejects caller or hook metadata that already carries a delivery_contract key. Its two digest fields below show the schema’s pattern, not a digest.
{
"schema": "chio.delivery-contract.v1",
"expected_digest": "^[0-9a-f]{64}$",
"observed_digest": "^[0-9a-f]{64}$",
"result": "matched"
}Every field is required and no others are admitted. The block feeds the receipt id and the signing body, so the enclosing receipt authenticates it and it carries no signature of its own. It appears only on a digest-constrained request, because its presence would change every other receipt id.
A mismatch carries urn:chio:error:kernel:delivery-contract-digest-mismatch: a delivered output that did not hash to the frozen expected digest. Both error URNs are registered in spec/errors/registry.yaml.
A reproducible build can be a payment condition
The same constraint works outside the market wherever the buyer knows the right bytes in advance. Every honest build of one source revision produces the same bytes, so you, holding a reference build of pricing-rs, can pay your partner's build agent to reproduce it, and pay only when the bytes agree.
The application defines the value the build tool returns; for a binary, that is a canonical JSON envelope carrying the bytes. You compute the digest of that value from your reference build and places it in the agent’s grant as output_digest_sha256.
- The reproduced binary matches. The kernel captures the realized cost from the hold and signs an Allow with
result: matched. - Different bytes, from a stale cache entry, a patched dependency, or a substituted binary, end in
denied_after_delivery: a signed Deny, the hold released, zero currency charged, and one invocation consumed.
A tool server that substitutes bytes is paid nothing, whatever it reports, because the kernel hashes the final post-transform value itself before any payment decision. Each attempt consumes one invocation, so the grant’s max_invocations bounds how many deliveries one grant can test. How the agent produced the bytes is outside what the digest records, and outside the market a mismatch carries no seller sanction: the signed Deny is the record.
Read more in What You Can Build.
What is proved, and where it stops
The contract ships on the durable admission path, in finalize_durable_tool_return and the replay path that rebuilds the same receipt from persisted state. The non-durable path lacks this output-aware settlement finalizer, so it refuses the constraint before dispatch. The formal claim is narrower than the shipped behavior; Formal Assurance explains how to read a claim’s evidence and its edge.
The proof record
- Status. Proved.
- Claim. Settlement is admitted only on an Allow, an Allow under a digest requirement implies the expected and observed digests are equal, and a
deniedAfterDeliverydecision never opens the settlement gate. Over the Rust functions, a constrained delivery that is not denied is a single-value delivery with byte-identical digests. - Subject. The bounded Lean model
Chio.Proofs.DeliveryContractover four opaque digest identities, and the pure functionsdelivery_contract_admitsanddelivery_denies_settlementinchio_kernel_core::formal_core. - Evidence. Theorems
settlement_admission_requires_verified_evidence,allow_requires_verified_evidence, anddenied_after_delivery_cannot_settleinformal/lean4/Chio/Chio/Proofs/DeliveryContract.lean; the Kani harnesspublic_delivery_contract_allow_implies_digest_matchregistered in.kani/harnesses.toml. - Assumptions. Digest identities are opaque and already validated. The model’s finding-purchase Boolean is an input recording the composition boundary with purchase admission; the model does not verify a purchase.
- Limit. The model does not implement SHA-256, canonical JSON, signatures, persistence, payment rails, or external settlement, and it is not a refinement proof of the Rust finalizer. The Kani harness covers the comparison functions, not the state transition or the hold release around them.
Three properties of the shipped check bound what a record can tell you:
- It binds one canonical JSON value. A
Streamoutput uses a different content-binding format and never satisfies this contract, even if its aggregate digest matches. A no-output Allow hashes tosha256_hex(b"null"), which the admission gate rejects as an expected digest. - It compares the final post-transform value. A post-invocation transform produces a mismatch when the final value no longer hashes to the commitment, and a commitment can intentionally describe the transformed value.
- It records that the value differed, not why. The block is generic delivery evidence; a finding reveal attaches a sibling
finding_deliveryblock for the purchase-specific checks, and a generic digest denial alone triggers no seller sanction.