EconomyPrices
Outcome-Based Pricing
One provider price, one signed predicate over the delivered bytes, and a hold that captures in full or releases to zero.
A provider advertises one price for one predicate. The price assessment reads the exact bytes the caller received, tests them against the predicate the provider signed, and returns the full price or zero. There is no partial capture, no attempt fee, and no prepayment. The artifacts, the evaluator, and the assessment are pure code in crates/economy/chio-listing/src/outcome/. The schema-id constants and the request extension live in chio-core-types, and chio-kernel owns the request-side checks and the settlement disposition.
The chio-outcome family
The family holds 11 schema files under spec/schemas/chio-outcome/v1/, of which the registry lists 9. The other 2 files describe unsigned projections: spec/PROTOCOL.md states that chio.outcome.request.v1 and chio.outcome.verdict.v1 are not signed-artifact schemas, so the file exists and the registry carries no id for it. Every registered kind uses the outcome_ prefix and is introduced by verified-outcome-pricing-v1.
| File | Title | Registry id |
|---|---|---|
request.schema.json | Chio Verified Outcome Request V1 | unregistered |
predicate.schema.json | Chio Outcome Predicate V1 | chio.outcome.predicate.v1 |
pricing.schema.json | Chio Outcome Pricing V1 | chio.outcome.pricing.v1 |
sla.schema.json | Chio Outcome SLA V1 | chio.outcome.sla.v1 |
eligibility.schema.json | Chio Outcome Eligibility V1 | chio.outcome.eligibility.v1 |
delivery-checkpoint.schema.json | Chio Outcome Delivery Checkpoint V1 | chio.outcome.delivery-checkpoint.v1 |
delivery-acknowledgement.schema.json | Chio Outcome Delivery Acknowledgement V1 | chio.outcome.delivery-acknowledgement.v1 |
delivery-nonacceptance.schema.json | Chio Outcome Delivery Nonacceptance V1 | chio.outcome.delivery-nonacceptance.v1 |
output-provenance.schema.json | Chio Outcome Output Provenance V1 | chio.outcome.output-provenance.v1 |
contractual-zero.schema.json | Chio Outcome Contractual Zero V1 | chio.outcome.contractual-zero.v1 |
verdict.schema.json | Chio Outcome Verdict V1 | unregistered |
Every signed body is RFC 8785 canonical JSON with deny_unknown_fields, camelCase keys, and a versioned schema id. Each body carries its own id, and that id is a domain-separated SHA-256 over the canonical body with its own id omitted, so a body already carrying its id is never re-hashed. Every time value is Unix milliseconds, and its field name says so.
The verified-outcome contract
The provider signs the price and the predicate separately. OutcomePricingBodyV1 binds one predicate to one amount and one failure mode. OutcomeFailureModeV1 has a single variant, zero_charge, so a pricing record cannot declare any other behavior on a failure.
// schema: chio.outcome.pricing.v1 (id preimage: chio.outcome.pricing.id.v1)
pub struct OutcomePricingBodyV1 {
schema: String,
pricing_id: String, // sha256 over the body with pricingId removed
provider_id: String,
predicate_id: String, // 64-hex; the predicate's own derived id
predicate_digest: String, // 64-hex
outcome_price: MonetaryAmount,
failure_mode: OutcomeFailureModeV1, // ZeroCharge, the only variant
sla_digest: Option<String>, // omitted when absent
issued_at_unix_ms: u64,
expires_at_unix_ms: u64, // > issued_at_unix_ms
}A caller reaches that price through the metered billing context on a governed request. The billing unit is the literal verified_outcome, and the unit carries a typed VerifiedOutcomeRequestV1 extension on MeteredBillingContext. The extension names the records by id and digest and never carries their bodies:
// schema: chio.outcome.request.v1 (unsigned projection, camelCase on the wire)
pub struct VerifiedOutcomeRequestV1 {
pub schema: String,
pub listing_id: String, // trimmed text, <= 2048 chars
pub listing_digest: String, // every remaining value is 64-hex
pub provider_binding_digest: String,
pub pricing_id: String,
pub pricing_digest: String,
pub predicate_id: String,
pub predicate_digest: String,
pub sla_digest: Option<String>,
pub receiver_binding_digest: String,
}validate_verified_outcome_request in the kernel pairs the unit and the extension in both directions: the unit requires the extension, and any other billing unit that carries the extension is denied. It then requires MeteredSettlementMode::HoldCapture (hold_capture on the wire), requires quoted_units to equal one, requires max_billed_units to equal one when the caller sets it, and rejects an extension whose own validate fails.
A request that clears all five checks is denied anyway. The validator falls through to an unconditional GovernedTransactionDenied whose reason reads verified outcome pricing is not activated. So the kernel settles nothing against these artifacts. Everything below is a library a caller builds, signs, and checks offline: assess_outcome_price returns a disposition, and something else has to act on it.
The deterministic predicate
A predicate is an AND-list of assertions carried by chio.outcome.predicate.v1. The list holds between one and 256 assertions, and two assertions with the same canonical bytes are rejected. Each assertion carries one RFC 6901 JSON Pointer pointer of at most 2048 characters and exactly one comparator, tagged by kind. The empty pointer selects the whole document. All assertions must hold for the output to pass.
| Comparator | Operand | Comparison |
|---|---|---|
exists | None | Passes on any selected value; a missing target fails. |
eq, ne | Attached JSON value | Compared by RFC 8785 canonical bytes. |
lt, lte, gt, gte | Attached JSON integer | Both operands parsed by checked integer conversion. |
The comparator is a tagged object, not a bare key. An assertion on the wire is { "pointer": ..., "comparator": { "kind": ..., "value": ... } }, and the exists comparator has no value member at all. The published schema states the same three shapes as a oneOf, and bounds an ordered operand to the I-JSON safe integer range.
{
"schema": "chio.outcome.predicate.v1",
"predicateId": "<64-hex, derived over the body without predicateId>",
"providerId": "<the provider this record was signed for>",
"assertions": [
{ "pointer": "/status", "comparator": { "kind": "eq", "value": "complete" } },
{ "pointer": "/findings/0/id", "comparator": { "kind": "exists" } },
{ "pointer": "/rows_reviewed", "comparator": { "kind": "gte", "value": 1000 } }
],
"issuedAtUnixMs": 1752192000000,
"expiresAtUnixMs": 1752278400000
}evaluate_outcome_predicate takes the predicate and the output bytes and returns a verdict, an output digest, the predicate id, and the predicate envelope digest. The verdict is Passed, Failed { assertion_index, reason }, or Unevaluable { reason }. A failure names the assertion that decided it by index.
| Verdict and reason | What the evaluator saw |
|---|---|
Failed, assertion_mismatch | The pointer selected a value and the comparator rejected it. |
Failed, missing_target | The pointer selected nothing, for any comparator including exists. |
Unevaluable, target_not_integer | An ordered comparator found a non-integer on either side. |
Unevaluable, invalid_output_json | The bytes are not UTF-8, not JSON, or not RFC 8785 canonical. |
The remaining three reasons come from outside the evaluator: delivery_cancelled, output_blocked, and output_mutation_after_evaluation are set by the price assessment from the delivery evidence it is handed. There is no JSONPath, regex, WASM, floating-point comparison, user code, or model-judged outcome in the comparator set above.
Delivery evidence
Charging for a result requires proving the caller received that result, so two different keys sign the delivery evidence. An anchor signs the chio.outcome.delivery-checkpoint.v1 records, and a receiver signs the terminal record. OutcomeReceiverBindingV1 hashes the anchor identity, key, and epoch together with the receiver identity, key, and epoch into one receiverBindingDigest, and the eligibility record carries that digest, so which pair of keys may speak for a delivery is fixed before the call runs.
A checkpoint chain is exactly two records. The first is pending at sequence one, with no predecessor and no blob fields. The second is acknowledged or cancelled, and advance builds it only from a pending predecessor, refuses a trusted clock that moves backwards, bumps the sequence by checked addition, and sets predecessorDigest to the previous envelope digest. Authentication then re-checks all of that against the record it already holds, and requires every identity, binding, and digest field to be unchanged across the transition. An acknowledged record must carry a blob reference and a blob digest equal to the output digest; a canceled record must carry no blob at all, a blob-absence proof digest, and a cancellation fence digest.
The receiver then signs its own record, built from the checkpoint rather than asserted freely. OutcomeDeliveryAcknowledgementBodyV1::from_receiver_assertion refuses a checkpoint whose state is not acknowledged or whose request id, eligibility digest, and receiver binding do not match the eligibility record. It copies deliveryAcceptedAtUnixMs from the checkpoint's trusted clock high-water mark, so the receiver cannot backdate acceptance, and it requires finalOutputDigest to equal durableBlobDigest, so the bytes the acknowledgement covers are the bytes durably held. chio.outcome.delivery-nonacceptance.v1 is the symmetric record for a canceled checkpoint.
Two kernel-signed records classify what happened to the bytes. chio.outcome.output-provenance.v1 binds the provider output digest, the final output digest, the post-guard policy and evidence digests, an optional redaction proof, and a provenanceClass of provider or caller_policy. chio.outcome.contractual-zero.v1 records a zero charge that never opened a delivery slot, with a reason of output_blocked or output_mutation_after_evaluation and a proof that no slot was opened.
Price assessment
assess_outcome_price takes the delivery evidence, the verified pricing record, and the kernel-signed eligibility record, and returns an OutcomePriceAssessmentV1. Before it looks at delivery it checks that the eligibility record and the pricing record agree on the pricing id, the pricing digest, the provider, the predicate id and digest, the SLA digest, and the price. The evidence enum has four arms, and the table below covers all of them.
| Delivery evidence | Disposition | Verdict recorded | Attribution |
|---|---|---|---|
Acknowledged, evaluation Passed | FullPrice | Passed | From the provenance class |
Acknowledged, any other evaluation | ZeroPrice | The evaluation as it stands | From the provenance class |
Cancelled | ZeroPrice | Unevaluable { delivery_cancelled } | platform |
NotAttempted | ZeroPrice | Unevaluable with the contractual-zero reason | caller_policy or platform |
Unknown | Indeterminate | None | None |
Evidence decides attribution. An acknowledged delivery takes provider or caller_policy straight from the provenance class, so a guard block or a byte-changing redaction attaches to the caller's policy rather than the provider. A canceled delivery is platform. A pre-delivery zero splits on its reason: output_blocked is caller_policy and output_mutation_after_evaluation is platform. The Unknown arm assesses zero and records nothing: it is the state to recover from, not a decision.
On the kernel side a resolved tool outcome carries one SettlementDispositionV1: Capture { amount }, ContractualZeroCharge { currency }, or NotApplicable. The disposition rides alongside the evaluation id, the resolved output blob reference, the post-guard decision digest, and the pricing verdict digest, so the amount and the evidence that produced it move together.
chio.outcome.verdict.v1 is the receipt-side projection of all of it. Its body binds the request id, the listing id and digest, the provider id and provider-binding digest, the pricing id and digest, the predicate id and digest, the quote digest, the eligibility digest, and the provider acceptance digest; then the tagged deliveryDisposition with whichever of the acknowledgement, nonacceptance, or contractual-zero digests applies, and the deliveredOutputDigest; then the verdict, its optional reasonCode and assertionIndex, the slaAttribution, the chargedAmount, and the railAuthorizationRef.
The SLA commitment
A provider may sign one further record. An SLA commitment states the failure rate the provider commits to over a fixed window, and a pricing record references it by digest through its optional slaDigest. The eligibility record carries the same digest, and the price assessment refuses to proceed when the two disagree.
// schema: chio.outcome.sla.v1 (id preimage: chio.outcome.sla.id.v1)
pub struct OutcomeSlaBodyV1 {
schema: String,
sla_id: String, // sha256 over the body with slaId removed
provider_id: String,
listing_digest: String,
max_failure_bps: u16, // <= 10_000
minimum_sample_count: u64, // > 0
window_seconds: u64, // > 0
window_anchor_unix_ms: u64, // > 0, and <= effective_at_unix_ms
effective_at_unix_ms: u64,
expires_at_unix_ms: u64, // > effective_at_unix_ms
}The anchor and the window fix the cadence rather than leaving the interval to whoever measures it: validation rejects an anchor later than effectiveAtUnixMs and rejects a window whose length in milliseconds would overflow past the anchor. The commitment is a signed term of the contract. The records above carry no rate measured against it.
What a passed verdict proves
Passed verdict means that the delivered JSON satisfied the predicate the provider signed. It does not prove factual correctness or objective value, and the comparator set above bounds what it can mean: JSON Pointer targets, canonical-byte equality, and integer ordering. Assessment is a pure function that returns a disposition and an amount. Moving money is the rail's job, and no part of chio_listing::outcome touches one.See also
- Pricing Models for the standard metered models and the
HoldCapturesettlement mode this contract requires. Use that page for flat, per-invocation, per-unit, and hybrid metering. - Reconciliation for the general authorize, capture, and release hold lifecycle the outcome assessment feeds.
- Autonomous Pricing for how a provider sets the
outcomePriceit stakes on the predicate. - Schemas and Errors for the whole signed-artifact registry, including the families this page does not cover.