Chio/Docs
LOGIN · JOIN

EconomyFindings

Finding Status

The signed sparse-map feed that proves a finding is not retracted, and the durable floor a verifier accepts it against.

Overview

Every finding names a feed in status_feed_ref, and a sale is admitted only while that feed proves the finding's exact key is absent from it. Absence is the live state: the feed represents one status value, retracted, and a finding is live because no leaf holds its key. A retraction insert comes from the seller, or from a final enforcement decision after the seller impairment is confirmed, and never from a bare challenge outcome or a reversible hold.

Chio already runs a revocation oracle for credentials (see passkey capabilities), and it cannot carry this. 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 cannot recheck the answer without asking again. A sibling path cannot be retrofitted onto that root. The status feed is a separate backend, and the protocol makes the separation enforceable: 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 signed status epoch

A status epoch is a whole-feed root, not a 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 at all. Everything a verifier needs to reproduce the map is in it: 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.

json
{
  "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>"
}

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.

The nonce is a number, not the domain label

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 does not derive or negotiate it.

Nothing in the envelope authorizes 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.


The sparse map and its portable proof

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.

text
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.

That path is what makes the answer portable. 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.

A verifier holding those bytes recomputes the root without asking the operator anything. 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.

A purchase carries the same bytes. The buyer places the canonical proof, base64 encoded, under the reserved governed-intent key chio_finding_status_proof_b64; a purchase-marked reveal with no proof denies. On a matched delivery the kernel stamps what it verified 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. Those values come from the proof and its epoch, never from caller metadata.


The rollback floor

A valid signature is not a fresh answer. An operator that keeps signing an older root, or signs two roots at one epoch, produces artifacts that each verify in isolation, so every acceptor stores a durable high-water mark for the admission-pinned feed and operator authorization and refuses anything that regresses against it. The floor holds 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).

ObservationOutcome
map_epoch below the floorRejected as below the durable rollback floor, even with a valid signature.
Same map_epoch, a different epoch id or rootRejected as equivocation at the floor.
Same operator key epoch, a different keyRejected: the operator key equivocated within one epoch.
An operator key epoch below the recorded oneRejected: the operator authorization regressed.
Non-inclusion for a finding already observed retractedRejected: the response attempts to revive a durably retracted finding.

A locally observed retraction is sticky, and it is stored beside the floor rather than inside it. An authenticated retraction whose epoch sits below the floor still rejects as a rollback, and the retraction is retained anyway, so a later higher-epoch non-inclusion cannot revive the finding. A restart that finds no floor for a feed the deployment declares established fails closed rather than starting fresh.

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

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

chio finding verify carries the same rule into 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.


Retraction and quarantined reads

A retraction does not reach back into memory a buyer has already written. What it changes is what a later read returns, through an opt-in profile of MemoryGovernanceGuard. The profile pins a resolver instance and the admission-pinned feed id, and the guard refuses to build without the resolver it names.

The resolver composes three durable boundaries for one exact memory key. The kernel's verified memory-provenance chain resolves the store and key to the governed write receipt and capability. A verified typed lineage edge resolves that write to its parent finding-delivery receipt and finding id. 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 pinned resolver is unavailable or the finding is no longer live, the guard denies the read and marks that key quarantined locally. The stored value stays where it is, preserved for audit and for restoration if the status changes back. The guard derives no new state from it, and it does not invalidate entries a buyer later derived from the payload; tracing those is downstream work over the receipt trail. Outside this profile, the default memory behavior is unchanged.


Guarantees and limits

Status: shipped in the venue-operated profile. A fresh signed root proves consistency with the keys it includes. It does not prove that the operator inserted every intent it owed, and no proof over one root can.

The market narrows that gap rather than closing it. 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 denies 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. Voluntary and cross-operator requests carry an authenticated retraction-intent receipt and a bounded inclusion service level, and a fresh root that omits a known pending intent is censorship and stays denied. A qualified operator maintains a live service bond allocated to the feed, whose 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.

  • Completeness is audited. Voluntary and cross-operator retraction completeness remains an assumption backed by the signed intent, the inclusion window, alerts, and the slashable bond.
  • A valid proof has a race window. A retraction published just after a buyer checked its proof lands after the sale has closed. The freshness window and the maximum epoch age tune how wide that window is; they do not remove it.
  • Operators publish on their own schedule. An operator publishes epochs from an external cron job or an equivalent operator job. Chio starts no publication daemon of its own, and anchoring cadence and status cadence are configured and monitored separately.

Next steps

  • Paid Reveal · the purchase that pins a status proof and the terminal that fires when a finding stops being live mid-call
  • Finding Records · status_feed_ref and the rest of the chio.finding.v1 body
  • Listing Disputes · the challenge and appeal path whose final outcome a retraction publishes
  • Threat Model · selective omission, equivocation, and the residuals this feed leaves open
  • CLI Reference · every flag of chio finding