EconomyFindings
Paid Reveal
How a purchased finding reaches the buyer, and why the kernel captures payment only for a delivery that matched.
Overview
A paid reveal is one governed call. The buyer invokes read_finding under a grant the provider minted for this sale. The kernel authorizes the accepted price as a reversible hold, dispatches, hashes the value the seller returned, and captures the hold only when that hash equals the digest the seller committed to in the signed finding. A delivery that fails any check releases the hold and signs a Deny.
The generic half of the rule is the delivery contract: any grant may fix the digest of the output it pays for, and the durable finalizer compares before the first money decision. A finding purchase adds the market's half: a purchase marker on the grant, a two-field reveal envelope, a media-type comparison, and a signed failed-delivery terminal that gives the buyer standing to challenge.
The grant a purchase mints
The provider answers a bid with a signed AskResponse whose token_offer is the minted capability token, bound to the buyer subject under the provider's issuer key (crates/economy/chio-open-market/src/bidding.rs). The kernel admits that grant only against a closed profile, in purchase_marked_grant. Each condition below denies the call with a carrier error before a nonce, budget, or dispatch mutation.
- Exactly one
RequireFindingPurchasemarker. A second marker denies. - The marker's
settlementselector isLocalReversibleHold. The other variant ofFindingSettlementSelector,CrossOrgEscrow, is registered for wire compatibility and denies with “purchase-marked delivery requires the local reversible-hold settlement rail”. - Exactly one
OutputDigestSha256constraint, carrying the digest the delivered value must hash to. dpop_requiredistrue, so the buyer proves possession of the key the grant names.max_invocationsis1. The grant authorizes one reveal and no replay of the token.
The grant alone does not establish who is paying for what. The buyer carries two size-bounded base64 documents in the governed intent, under the reserved keys chio_finding_purchase_context_b64 and chio_finding_status_proof_b64, and the kernel re-verifies both from their bytes. A purchase-marked request that carries no status proof denies with “finding purchase requires a portable status proof”. The verified purchase context must bind the same finding and listing as the marker, commit the same payload_sha256 as the digest constraint, name a non-empty advertised media type, name a payer key equal to the capability subject, and price the sale at exactly the grant's max_cost_per_invocation and max_total_cost.
The seller's reveal server is buyer-blind
read_finding holds finding identities and sealed payload bytes. It holds no buyer identity, no price, and no reservation state, so it cannot decide who may read a finding. The kernel makes every admission and money decision before the server is reached, which is why the checks in this section run on the grant and the purchase context rather than at the seller.The rail is fixed for the same reason. A rail that settles inside the authorize call leaves nothing to release when a delivery fails, so the kernel reads the payment adapter's rail mode after grant selection and denies any rail other than ReversibleHold before authorize_payment_if_needed runs. Governed MustPrepay and PrepaidFinal are both refused for this profile, and a request with no durable admission record is refused with them.
The reveal envelope
The digest comparison hashes the whole response value: receipt_content_for_output takes the SHA-256 of the canonical JSON bytes of the value, never of a sub-field. For read_finding that value is one shape, the reveal envelope, and the type that defines it denies unknown fields.
{
"media_type": "text/x-diff",
"payload_b64": "<base64 of the sealed payload bytes>"
}The finding's payload_sha256 is the digest of that envelope, not of the bytes inside it: finding_payload_sha256 canonicalizes the envelope and hashes the result. Two consequences follow. The media type is inside the commitment, so the same payload under a different media type has a different digest. And the envelope omits finding_id, because finding_id is itself the digest of a body that already carries payload_sha256.
After the digest matches, the kernel strict-parses the returned bytes as that envelope in check_reveal_envelope: an unknown field, an empty media_type, or a payload_b64 that does not decode as standard base64 is a malformed envelope. A parsed envelope whose media_type differs from the signed finding's payload_media_type is a media-type mismatch.
Hold, dispatch, check, capture
The coordinator reserves the buyer budget and the seller's liability exposure before the sale is accepted, so neither the reservation nor the acceptance moves the reveal price. The kernel then runs the purchase checks, requires an empty post-invocation pipeline so the seller-origin envelope reaches the finalizer unchanged, and authorizes the quoted price as a reversible hold. Only then does it dispatch.
- Hold. The price is authorized, not captured. Nothing is spent.
- Dispatch. The pre-dispatch invocation capture commits, and the seller's server returns the envelope.
- Check.
evaluate_deliverycompares the post-transform content hash with the committed digest, then, for a purchase-marked delivery, strict-parses the envelope and compares the media type. - Capture. The finalizer stages the validated output and the terminal plan durably, captures the hold once, signs the Allow carrying the
delivery_contractandfinding_deliverymetadata blocks, persists the signedchio.finding.purchase-record.v1, and only then releases the response to the buyer.
Because the material is staged before the capture, a crash after the capture resumes to the same signed Allow and captures nothing a second time. The purchase record's purchase_key is derived from the accepted-bid envelope digest and the authoritative payment operation identifier, so a retry of one sale recomputes one key.
$ buyer_agent.py --credential market/buyer-client.json --chio chio \
--finding "$FINDING_ID" --patch ./verified-fix.patch{"baseRevision":"8ba43d4e022565634c03e83ac579b0498bc1c220","candidateRevision":"0ac3926063ef906937914686d6f88b9ea594c1ce","findingId":"889174058e27a9de2fa64ac6f7285a8cdfe6cb48cda571c576e973d3c10f90c3","patch":"~/chio/verified-fix.patch","settlement":"captured","verdict":"allow"}examples/cognition-market-pilot/buyer_agent.pyat fe56570chio finding buy drives the same path from the command line. It requires --id, --max-price in minor units, and --currency; --payer names the buyer principal the purchase context binds, and --deadline-secs sets how long the buyer allows for delivery before the failed-delivery terminal applies.
When a delivery fails
Every way a reveal can fail after dispatch resolves to one closed reason, recorded on the terminal so downstream evidence keys on the reason rather than re-deriving it from a message.
| Reason | Owning guard | Condition |
|---|---|---|
digest_mismatch | delivery_contract | The post-transform content hash did not equal the committed digest, or the output was not a single value. |
envelope_malformed | finding_delivery | The delivered value is not the strict two-field envelope with decodable payload bytes. |
media_type_mismatch | finding_delivery | The envelope parsed but advertises a media type the signed finding does not. |
finding_status_changed | finding_status | The purchased finding was no longer live at the terminal release boundary after the provider returned. |
All four take the same terminal. The admission operation moves to denied_after_delivery, a state legal only from finalizing, whose own doc comment reads: 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. Its settlement disposition is ContractualZeroCharge, which releases the open hold, captures zero, and reconciles realized spend to zero.
A mismatch consumes one invocation and zero currency
financial.cost_charged is zero while budget_remaining reflects a consumed invocation. The buyer pays nothing for a finding it did not receive and still spends one unit of quota to learn that.A released hold and a captured one look alike from outside, so the failure is written down. The kernel signs and checkpoints the Deny; only then may the purchase authority sign chio.finding.failed-delivery.v1 over the buyer, the accepted bid, the reservation and payment operation, the exact hold attempt and its release terminal, and both halves of the deny evidence. That terminal encodes realized_spend_units of zero and payout_eligible false rather than implying them, and it creates no purchase record.
It is also the buyer's standing. A digest_mismatch challenge is the one class whose standing branch is the signed failed-delivery terminal, which is why chio finding challenge --class digest-mismatch is the class a mismatched or wrong-media-type reveal files under. The evaluator then reads both metadata blocks from the checkpointed Deny. A media-type denial adjudicates as denial_media_type_mismatch, which is an evaluated-clean reason: the seller committed to a well-formed envelope of a different type, and that is not fraud. Only a mismatch against the seller's own committed payload digest reaches the penalty lane.
Guarantees and limits
Status: shipped on the durable admission path of the single-operator profile, in finalize_durable_tool_return and the replay lane that rebuilds the same receipt from persisted state. Three boundaries bound the claim.
- An Allow attests the reveal, not the buyer's copy. An Allow on
read_findingmeans the kernel accepted a value whose content hash equals the committed digest. It says nothing about whether the buyer's process persisted the bytes. A buyer that crashes between the Allow and its own write has paid for a payload it no longer holds. - The answer to that is a recovery grant, not a second purchase. The one-shot grant is consumed, and a receipt is evidence rather than invocation authority. The provider's recovery service verifies the checkpointed original Allow and the buyer's proof of possession, then mints a
RequireFindingRecoverygrant: no monetary ceilings, no authorization or capture path, the same committed output digest, and an invocation budget equal to the durable retry budget itsrecovery_idkeys. Re-minting the same authority cannot reset that budget. - The Deny does not confirm the payload. On a digest mismatch the receipt's
observed_digestis a domain-separated commitment keyed by the expected digest, and the delivered digest stays in privileged durable outcome evidence, so a public Deny cannot be used to test a candidate payload. AStreamoutput and a no-output Allow both deny under a committed digest.
The residual the market names is disclosure. In both shipped profiles the venue operator can see revealed content, and resale of a payload after a legitimate reveal is priced rather than prevented. Both sit in the residual-risk register of the threat model.
Next steps
- The Delivery Contract · the generic kernel rule, its terminal state, and the Lean and Kani claims over the comparison
- Finding Records · the
chio.finding.v1schema holdingpayload_sha256andpayload_media_type - Finding Status · the portable status proof a purchase pins and the rollback floor that accepts it
- Pricing a Finding · how the accepted price the hold is taken against gets set
- CLI Reference · every flag of
chio finding