Chio/Docs
LOGIN · JOIN

Finding Status

Check that a finding is still live before buying it, with a signed proof no operator can later roll back.

Concept chio@5f63e6e

On this page

Finding status lets a buyer prove, at the moment of purchase, that the finding it pays for is still live. Once the buyer has accepted an epoch, no operator can make it accept a lower one.

Each finding names its status feed in status_feed_ref, and a sale is admitted only while that feed proves the finding's exact key absent. The feed publishes signed epochs of a sparse retraction map; the buyer checks one epoch and keeps a durable floor that rejects any lower epoch. The examples follow the repair sale in The Cognition Market.

A validly signed lower epoch still fails at the floor

The feed records one status value, retracted. A finding is live at an epoch when that epoch proves no leaf holds its key, so absence is the live state. The buyer accepts an epoch only at or above the floor it has recorded for the same pinned feed and operator authorization.

Status floorChoose a proof.
1011121314map_epochfloor 12retractionsbelow the floorσepoch 111011121314map_epochfloor 12retractionsbelow floorσepoch 11

A lower epoch is rejected even with a valid signature

The acceptor has recorded epoch 12 for this feed and operator authorization. A proof at epoch 11 verifies in isolation and is rejected as below the durable rollback floor. The rollback floor.

One acceptor's durable floor for one pinned status feed and operator authorization, on the map_epoch axis. Epoch numbers are illustrative; operator key epochs and freshness windows are left out.

In this run the buyer has accepted epoch 12. A proof at epoch 11 is rejected even with a valid signature. An epoch 12 with a different epoch ID or root conflicts with the floor. A valid epoch 13 with the exact key absent passes and advances the floor; the same epoch carrying a retraction leaf makes the finding non-live. Once a retraction is observed, an absence proof at a later epoch is rejected as a revival.

Passing the status check lets the other purchase checks continue. Paid reveal rechecks current finding status before capture and output release.

The proof travels inside the purchase

A status answer is a set of bytes anyone can recheck. The feed is a 256-bit sparse authenticated map whose key path comes from the finding ID and a fixed numeric nonce, so a finding keeps one position for the life of the feed. A non-inclusion path carries one sibling hash per level, and a verifier recomputes the root from it without asking the operator.

governed-intent-fragment.jsonjson
{
  "chio_finding_status_proof_b64": "<base64 of the canonical status proof>"
}

The buyer places the canonical proof, base64 encoded, under the reserved governed-intent key chio_finding_status_proof_b64, and a purchase-marked reveal without it is refused. On a matched delivery the kernel stamps what it checked into the finding_delivery receipt block as status_proof: the feed ID, the nonce, the map epoch, the signed-epoch envelope digest, the proof digest, the root hash, and the trusted-time observation the proof bound. Each value comes from the proof and its epoch, never from caller metadata.

Why finding status runs its own map

Chio runs a separate revocation oracle for credentials (see passkey capabilities). That oracle is an append-only Merkle tree with a local membership map. Its NonInclusionProof { key, epoch_root, checked_at_unix_ms } carries no path, and verify_non_inclusion answers from the verifier's own state, so a third party would have to ask again to recheck it, and a sibling path cannot be retrofitted onto that root.

The status feed is therefore a separate backend, and the protocol enforces the separation: the append-only root, its signed root envelope, and its local absence result MUST reject under the status verifier even when a root digest happens to match.

The floor survives restarts and key rotation

An operator that keeps signing a superseded root, or signs two roots at one epoch, produces records that each verify alone. Every acceptor therefore stores a durable high-water mark for the admission-pinned feed and operator authorization: the feed ID, the operator ID and rotation policy, the key domain nonce, the operator key epoch, and the tuple (map_epoch, epoch_id, root_hash). Five observations are rejected against it.

  • Regression. A map_epoch below the floor, even with a valid signature.
  • Equivocation. The same map_epoch with a different epoch ID or root.
  • Key equivocation. The same operator key epoch with a different operator key.
  • Authorization regression. An operator key epoch below the recorded one.
  • Revival. A non-inclusion proof for a finding already observed retracted.

A locally observed retraction is sticky and is stored beside the floor. An authenticated retraction whose epoch sits below the floor still rejects as a rollback, and the retraction is retained, so a later higher-epoch absence proof cannot revive the finding. A restart that finds no floor for a feed the deployment declares established fails closed. Rotation keeps the feed identity, the key domain, the map semantics, and the floor.

Every trust input of chio finding status is a required flag, because each supplies something the proof cannot establish about itself. The command fetches the venue-verified portable status proof for one finding.

Terminalbash
chio finding status \
  --id "$FINDING_ID" \
  --feed "$STATUS_FEED" \
  --operator-authorization operator-authorization.json \
  --service-bond service-bond.json \
  --rollback-floor status-floor.json \
  --max-epoch-age-secs "$MAX_EPOCH_AGE"

chio finding verify applies the same rule to finding verification: --status-rollback-floor is required whenever the evidence bundle carries a portable status proof, and it may point at the same floor file. Command flags describes each input.

A retraction stops later sales and quarantines later reads

A retraction comes from the seller, or from a final enforcement decision after the seller impairment is confirmed. A bare challenge outcome or a reversible hold never inserts one; the challenge and appeal path ends in that final decision.

Finding lifecycleChoose a stage.
φsubmitρverifyBpriceKrevealχchallengeσretractimpairmentopt inBSlashBonda₁sellerσstatus feedPurchase refusedretractedgQuarantine guardbuyer's own agentφρBKχσretractimpairmentBSlashBonda₁sellerσstatus feedPurchase refusedretractedgQuarantine guardbuyer's own agent

Retraction reaches every later purchase through the status feed

After appeal finality, SlashBond pays the slashed collateral pro rata to the verified harmed purchases, with the remainder to the community fund. A retraction comes from the seller or from final enforcement after confirmed impairment, never from a bare challenge outcome. The durable outbox inserts the finding's key into the status feed and publishes a new signed epoch; purchases stay refused while publication is pending and after it. A buyer that holds the finding can opt into a quarantine guard that refuses its own agent's use of it. Finding status.

The lifecycle of one chio.finding.v1 finding, from admission to retraction; challenge and retraction run only when a finding is disputed. The bid figures are the basic_discount vector in USD minor units; fee arithmetic, audit sampling, and the hosted profile are left out.The cognition market

Publication is coupled to enforcement. The appeal-final transition atomically persists its outcome, a publication_pending marker, and one idempotent retraction outbox item before any external effect, and pending status refuses new sales. The item stays dispatch-ineligible until the exact seller impairment is confirmed final, and the liability settles only after publication is confirmed, so a failed, ambiguous, or quarantined impairment never publishes an irreversible retraction.

After appeal finality, SlashBond distributes the slashed collateral pro rata to the verified harmed purchases, with the remainder to the registered community fund, and the outbox inserts the finding's key and publishes a new signed epoch.

For a buyer that already holds the finding, an opt-in profile of MemoryGovernanceGuard governs later reads. The profile pins a resolver instance and the admission-pinned feed ID, and the guard refuses to build without the resolver it names. For one exact memory key the resolver composes three durable boundaries.

  1. Provenance. The kernel's verified memory-provenance chain resolves the store and key to the governed write receipt and capability.
  2. Lineage. A verified typed lineage edge resolves that write to its parent finding-delivery receipt and finding ID.
  3. Status. An authenticated local status cache, built only from an authorized signed epoch and a verified portable proof, resolves the finding to Live, Pending, or Retracted against that feed.

A missing, unavailable, stale, or cross-bound value at any boundary fails closed. When the resolver is unavailable or the finding is no longer live, the guard refuses the read and marks that key quarantined locally, and the stored value stays in place for audit.

A transient resolver failure can clear after a verified live result; an observed retraction stays durable. The guard derives no new state and leaves untouched any entries the buyer later derived from the payload; tracing those is downstream work over the receipt trail. Outside this profile, memory behaves as it does by default.

A fresh root proves the keys it includes

A fresh signed root proves consistency with the keys it includes. Whether the operator inserted every intent it owed is outside what any proof over one root can show, so the completeness of voluntary and cross-operator retractions rests on the signed intent, the inclusion window, alerts, and a slashable service bond.

  • Signed intent. Each voluntary or cross-operator request carries an authenticated retraction-intent receipt and a bounded inclusion service level. A fresh root that omits a known pending intent is censorship and stays refused.
  • Service bond. A qualified operator keeps a live service bond allocated to the feed. Its signed policy names the objective missed-inclusion and equivocation conditions, the inclusion window, the evidence source, and the penalty path. Admission rejects a missing, expired, revoked, underfunded, or differently allocated bond.
  • Race window. A retraction published between a buyer's proof check and the close of its sale lands too late for that sale. The freshness window and the maximum epoch age set how wide the window is.

An operator job publishes epochs on the operator's own schedule, such as an external cron job. Anchoring cadence and status cadence are configured and monitored separately.

Read more in the Cognition Market threat model, which ranks selective omission and equivocation with the market's other residual risks.

Status epoch and proof reference

Status epoch envelope

A status epoch is a whole-feed root and makes no statement about one finding. It travels as a signed export envelope, { body, signerKey, signature }, and the outer signature covers the complete body. The body carries no finding ID. It holds everything a verifier needs to reproduce the map: the domain labels, the tree parameters, the operator identity and key epoch, the root, the anchoring references, and the validity window.

The shape below is the registered schema at spec/schemas/chio-finding/v1/status-epoch.schema.json, with its fixed values written out and its patterns standing in for the per-epoch ones. Every member is required and no others are admitted.

status-epoch shapejson
{
  "schema": "chio.finding.status-epoch.v1",
  "status_epoch_id": "^[0-9a-f]{64}$",
  "signature_domain": "chio.finding.status.v1",
  "status_map_version": "sparse_map_v1",
  "proof_semantics": "siblings_leaf_to_root_v1",
  "feed_id": "^[ -~]*[!-~][ -~]*$",
  "key_domain_nonce": 3318287169837494,
  "map_epoch": "<integer, 1 .. 2^53 - 1>",
  "operator_id": "^[ -~]*[!-~][ -~]*$",
  "operator_key": "^[0-9a-f]{64}$",
  "operator_key_epoch": "<integer, 1 .. 2^53 - 1>",
  "root_hash": "^[0-9a-f]{64}$",
  "tree_depth": 256,
  "hash_algorithm": "sha256",
  "key_hash_domain": "chio.finding.status.v1:key",
  "empty_leaf_domain": "chio.finding.status.v1:empty-leaf",
  "occupied_leaf_domain": "chio.finding.status.v1:occupied-leaf",
  "branch_domain": "chio.finding.status.v1:branch",
  "empty_leaf_hash": "80a7fe55f5efd9a02893aca68310d8ebd7f0ed7b8dd36686abda7704755a6755",
  "anchor_refs": [],
  "generated_at": "<unix seconds>",
  "valid_from": "<unix seconds>",
  "valid_until": "<unix seconds>"
}

Epoch ID and envelope digest

status_epoch_id is the SHA-256 digest of "chio.finding.status-epoch.v1\0" followed by the canonical JSON of the body with only status_epoch_id set to the empty string. The digest a proof references is a different value: the SHA-256 of the complete canonical signed envelope. Both appear in a portable proof, and both are checked against the epoch it carries.

Key domain nonce

chio.finding.status.v1 is the signature domain and the prefix of the four hash-domain labels. The wire nonce is the integer 3318287169837494 (0x0bc9f6f00559b6), the first 53 bits in network bit order of SHA-256 over that label, chosen below 253 so I-JSON and RFC 8785 carry it exactly. It is a selected wire constant: an implementation compares against it and never derives or negotiates it.

Operator authorization

The envelope authorizes nothing by itself. Governance pins one finding_status_operator authorization for each stable feed_id, and a verifier MUST require the outer signerKey, the body's operator_key and operator_id, the key epoch, the feed, the validity window, the rotation chain, and the revocation state to agree with it. A key revoked at verification time cannot advance status state. Rotation preserves the feed identity, the fixed key domain, the map semantics, and the epoch floor; it never resets the map or makes an observed retraction live again.

Sparse map hashing

The backend is a 256-bit sparse authenticated map with domain-separated key, empty-leaf, occupied-leaf, and branch hashes. The key path is derived from the finding ID and the fixed numeric nonce, so a finding occupies one position for the life of the feed, and map_epoch, which advances monotonically with each published root, never moves it.

Sparse map hashingtext
K        = H("chio.finding.status.v1:key\0"          || key_domain_nonce || len(finding_id) || finding_id)
empty[0] = H("chio.finding.status.v1:empty-leaf\0")
leaf     = H("chio.finding.status.v1:occupied-leaf\0" || K || "retracted" || I)
branch(left, right) = H("chio.finding.status.v1:branch\0" || left || right)
empty[n+1] = branch(empty[n], empty[n])

H is SHA-256, integers and lengths are unsigned big-endian 64-bit values, K is the 32-byte key hash, and I is the 32-byte retraction-intent digest. The root of an empty map is empty[256]. A path carries one sibling hash per level, ordered leaf to root, and at position h the branch direction is bit 255 - h of K. An inclusion path starts from the occupied leaf; a non-inclusion path starts from empty[0] and proves that the exact key path terminates in the defined empty leaf.

Proof carrier

The carrier is chio.finding.status-proof-input.v1, an unsigned closed tagged union whose proof_kind is exactly non_inclusion or inclusion. Both branches bind the schema, the feed ID, the fixed nonce, the map epoch, the finding ID, the status-epoch ID and complete-envelope digest, base64 of the exact canonical signed epoch bytes, the root hash, the complete fixed-depth sibling path, and checked_at. The inclusion branch adds the exact status retracted and the retraction-intent digest.

An inclusion-only member on a non-inclusion branch, a missing member, an unknown field, and an unknown branch tag all reject at parse time.

Verifier obligations

A verifier holding the proof bytes recomputes the root without contacting the operator. It MUST enforce the encoded and decoded size bounds before trusting content, byte-identical I-JSON canonical form for both the proof and the epoch it encloses, the epoch's schema, domain, map version, and hashing semantics, the operator authorization and signature, the epoch ID and envelope digest, every feed, nonce, epoch, root, and finding cross-binding, and the sparse path.

Freshness is checked against trusted time and a locally configured maximum epoch age, applied to both checked_at and the epoch's own generation time. A freshness claim made by the caller is not policy, and the unsigned carrier never substitutes for the signed epoch inside it.

Command flags

Every flag of chio finding status is required. The full command tree is in the CLI reference.

  • --id: the finding ID whose current status proof is fetched.
  • --feed: the governance-pinned status feed the venue configured.
  • --operator-authorization: the governance-pinned operator authorization, as strict canonical JSON.
  • --service-bond: the governance-pinned current status service bond, as strict canonical JSON.
  • --rollback-floor: the durable floor file. Its sibling .retractions directory holds the sticky observations and is retained with it.
  • --max-epoch-age-secs: the maximum accepted age of the signed epoch, in seconds.

Source

The status verifier, the floor, and the proof carrier are implemented in crates/economy/chio-finding/src/status.rs.

Next: buy against a status proof