Chio/Docs
LOGIN · JOIN

EconomyTools

Listing Disputes, Freezes, and Sanctions

Signed charters and cases for registry listings, evaluated into an effective state and admission decision.


Charter and case records

Both record types scope to a namespace and a governing operator, and both reference a listing identity from chio-listing. A charter is issued once and authorizes a set of case kinds; cases are issued against individual listings under that charter.

Record typeSchema tagPurpose
GenericGovernanceCharterArtifactchio.registry.governance-charter.v1Grants a governing operator authority over a namespace and the case kinds it may open.
GenericGovernanceCaseArtifactchio.registry.governance-case.v1Records one dispute, freeze, sanction, or appeal against a single listing under a charter.

Each record is wrapped in a SignedExportEnvelope<T> containing the body, an Ed25519 signer key, and a signature over the RFC 8785 canonical JSON body. The aliases are SignedGenericGovernanceCharter and SignedGenericGovernanceCase. The crate is re-exported by chio-core and chio-open-market as governance.

The charters on this page govern registry listings: their dispute, freeze, sanction, and appeal lifecycle. The economic parameters an economy runs on, credit tiers, discount curves, premium schedules, fees, and bonds, are governed by a separate, specialized charter family whose amendments move through a propose, m-of-n approval, timelock, then activate lifecycle before they take effect. That fiscal system is documented in Fiscal Charters.


The charter

A charter names the governing operator, the namespace it covers, the case kinds it may open, and an optional set of escalation operators. Its authority_scope can pin the charter to specific listing publishers and actor kinds; an empty list on either field means the scope is unrestricted on that axis, because evaluation only tests a list it finds non-empty (crates/trust/chio-governance/src/evaluation.rs:169-196).

crates/trust/chio-governance/src/generic.rs133-149rust
pub struct GenericGovernanceCharterArtifact {
    pub schema: String,
    pub charter_id: String,
    pub governing_operator_id: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub governing_operator_name: Option<String>,
    pub authority_scope: GenericGovernanceAuthorityScope,
    pub allowed_case_kinds: Vec<GenericGovernanceCaseKind>,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub escalation_operator_ids: Vec<String>,
    pub issued_at: u64,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub expires_at: Option<u64>,
    pub issued_by: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub note: Option<String>,
}

The schema is the constant GENERIC_GOVERNANCE_CHARTER_ARTIFACT_SCHEMA, chio.registry.governance-charter.v1 (crates/trust/chio-governance/src/generic.rs:12), and the scope the charter carries is its own type:

crates/trust/chio-governance/src/generic.rs79-87rust
pub struct GenericGovernanceAuthorityScope {
    pub namespace: String,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub allowed_listing_operator_ids: Vec<String>,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub allowed_actor_kinds: Vec<GenericListingActorKind>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub policy_reference: Option<String>,
}

allowed_case_kinds must be non-empty, and a validated charter with an expires_at requires it to be strictly greater than issued_at. build_generic_governance_charter_artifact (crates/trust/chio-governance/src/generic.rs:407-442) derives the identifier as a content hash over the issuing operator, the normalized namespace, the allowed case kinds, and the issue time, so the same inputs always yield the same charter id:

crates/trust/chio-governance/src/generic.rs416-427rust
let charter_id = format!(
    "charter-{}",
    sha256_hex(
        &canonical_json_bytes(&(
            local_operator_id,
            normalize_namespace(&request.authority_scope.namespace),
            &request.allowed_case_kinds,
            issued_at,
        ))
        .map_err(|error| error.to_string())?
    )
);

The builder returns an unsigned body; the governing operator signs it with a governance-authority keypair issued through chio-federation-authority:

rust
let charter = build_generic_governance_charter_artifact(
    "origin-a",
    Some("Origin A".to_string()),
    &request,
    130,
)?;
let signed = SignedGenericGovernanceCharter::sign(charter, &authority_keypair)?;

The case

A case binds a charter to one listing and carries the case kind, its lifecycle state, at least one evidence reference, and optional links to a prior case for appeals and supersession.

crates/trust/chio-governance/src/generic.rs185-212rust
pub struct GenericGovernanceCaseArtifact {
    pub schema: String,
    pub case_id: String,
    pub charter_id: String,
    pub governing_operator_id: String,
    pub kind: GenericGovernanceCaseKind,
    pub state: GenericGovernanceCaseState,
    pub namespace: String,
    pub listing_id: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub activation_id: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub subject_operator_id: Option<String>,
    pub opened_at: u64,
    pub updated_at: u64,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub expires_at: Option<u64>,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub escalated_to_operator_ids: Vec<String>,
    pub evidence_refs: Vec<GenericGovernanceEvidenceReference>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub appeal_of_case_id: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub supersedes_case_id: Option<String>,
    pub issued_by: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub note: Option<String>,
}

Each entry in evidence_refs names what the case is built on, and an optional sha256 is validated as a 64-character hex digest when it is present:

crates/trust/chio-governance/src/generic.rs104-111rust
pub struct GenericGovernanceEvidenceReference {
    pub kind: GenericGovernanceEvidenceKind,
    pub reference_id: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub uri: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub sha256: Option<String>,
}

Body validation enforces the shape independently of any evaluation context: the schema must match, evidence_refs must be non-empty, an appeal must carry appeal_of_case_id (and no other kind may), and an escalated case must list at least one escalated_to_operator_ids.

build_generic_governance_case_artifact (crates/trust/chio-governance/src/generic.rs:445-509) verifies the signatures on the charter, listing, and (when present) trust activation before minting the body, and it refuses a case whose charter is governed by a different operator, or whose trust activation was issued by anyone other than the governing operator. The case id is a content hash of the same shape as the charter id:

crates/trust/chio-governance/src/generic.rs467-482rust
let case_id = format!(
    "case-{}",
    sha256_hex(
        &canonical_json_bytes(&(
            local_operator_id,
            &request.charter.body.charter_id,
            &request.listing.body.listing_id,
            request.kind,
            request.state,
            opened_at,
            &request.appeal_of_case_id,
            &request.supersedes_case_id,
        ))
        .map_err(|error| error.to_string())?
    )
);

Case kinds

Four kinds cover the adjudication lifecycle. A charter must list a kind in allowed_case_kinds before a case of that kind evaluates.

KindActive effective stateCan block admissionExtra requirement
disputedisputedNonone
freezefrozenYes, when enforcedMatching trust activation from the governing operator
sanctionsanctionedYes, when enforcedMatching trust activation from the governing operator
appealappealedNoappeal_of_case_id plus a matching non-appeal prior_case

Effective state and admission

Evaluation resolves a case to a GenericGovernanceEffectiveState (one of clear, disputed, frozen, sanctioned, appealed) and a boolean blocks_admission. The mapping is driven by the case lifecycle state and kind together.

Case stateEffective stateBlocks admission
resolved, denied, supersededclearNo, for every kind
open, escalatedMirrors the kind (disputed / frozen / sanctioned / appealed)No, for every kind
enforcedMirrors the kindOnly freeze and sanction

One rule blocks admission

Exactly one combination sets blocks_admission = true: an enforced case whose kind is freeze or sanction. A dispute or appeal never blocks, and a resolved, denied, or superseded case resolves to clear regardless of kind. The relying party consumes blocks_admission as the gate; the effective state is the human-readable status.

Case evaluation

evaluate_generic_governance_case takes the current listing, the current publisher, the charter, the case, and optionally a trust activation and a prior case. It returns a GenericGovernanceCaseEvaluation.

crates/trust/chio-governance/src/evaluation.rs8-11rust
pub fn evaluate_generic_governance_case(
    request: &GenericGovernanceCaseEvaluationRequest,
    now: u64,
) -> Result<GenericGovernanceCaseEvaluation, String> {

The request is GenericGovernanceCaseEvaluationRequest (crates/trust/chio-governance/src/generic.rs:291-303), whose evaluated_at falls back to the now argument when it is absent. Every path returns the same record, whether evaluation completes or stops at a finding:

crates/trust/chio-governance/src/generic.rs392-405rust
pub struct GenericGovernanceCaseEvaluation {
    pub listing_id: String,
    pub namespace: String,
    pub charter_id: String,
    pub case_id: String,
    pub governing_operator_id: String,
    pub kind: GenericGovernanceCaseKind,
    pub state: GenericGovernanceCaseState,
    pub effective_state: GenericGovernanceEffectiveState,
    pub evaluated_at: u64,
    pub blocks_admission: bool,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub findings: Vec<GenericGovernanceFinding>,
}

Evaluation is ordered. The first failure ends evaluation and returns a finding without an Err:

  • Validate the listing body and the current_publisher shape. These are the only hard Err paths, alongside an internal crypto or canonicalization error.
  • Verify the signature and body of the listing, charter, and case, and of the activation and prior case when present.
  • If an activation is present, its local_operator_id must equal the charter's governing_operator_id.
  • Charter, case, and listing must agree on governing operator, charter id, namespace, and listing id.
  • Neither the charter nor the case may be expired as of evaluated_at; expiry is exclusive at the boundary (expires_at <= evaluated_at is rejected).
  • The charter must allow the case's kind and, where its scope is set, admit the current publisher operator id and the listing subject actor kind.
  • A freeze or sanction case requires a trust activation whose activation_id matches the case; a superseding case requires a matching prior_case; an appeal requires a matching non-appeal prior_case.
  • On success, the case state and kind map to an effective state and the blocks_admission flag, and the evaluation carries an empty findings list.

Failure handling

Shape and signature failures resolve to an Ok evaluation carrying a single finding, with effective_state = clear and blocks_admission = false. An unverifiable or malformed case does not block admission, and the finding explains why. Only an internal crypto or canonicalization error returns Err(String). A clear result on a failed case means "could not enforce".

Finding codes

When evaluation short-circuits it emits one GenericGovernanceFinding with a typed code and a human-readable message. The codes:

CodeMeaning
ListingUnverifiableListing signature or body failed verification
ActivationUnverifiableTrust activation signature or body failed verification
CharterUnverifiableCharter signature or body failed verification
CaseUnverifiableCase signature or body failed verification
PriorCaseUnverifiableReferenced prior case signature or body failed verification
CharterExpiredCharter expires_at reached as of evaluation
CaseExpiredCase expires_at reached as of evaluation
CharterScopeMismatchCurrent publisher or listing actor kind falls outside the charter scope
CharterKindUnsupportedCharter does not authorize this case kind
CaseMismatchCharter or case does not match the current listing identity or namespace
MissingActivationA freeze or sanction case was submitted without a trust activation
ActivationMismatchActivation was not issued by the governing operator, or its id does not match the case
AppealTargetMissingAppeal is missing appeal_of_case_id or its prior_case
AppealTargetInvalidAppeal target does not match a valid, non-appeal prior case
SupersessionTargetMissingSuperseding case is missing its prior_case
SupersessionTargetInvalidSupersession target does not match the referenced prior case

Worked example: an enforced freeze

Operator origin-a governs the namespace https://registry.chio.example under a charter that allows all four case kinds. It freezes listing listing-artifact-1 and signs the case, referencing a trust activation it also issued. On the wire the case envelope uses camelCase fields and snake_case enum values:

The field names below are the record's own. The values are made up for the example, and the two digests are shortened to their first bytes so the shape stays readable; a real envelope carries a full 64 characters of hex in each.

json
{
  "body": {
    "schema": "chio.registry.governance-case.v1",
    "caseId": "case-6f2a9c...",
    "charterId": "charter-1d4b0e...",
    "governingOperatorId": "origin-a",
    "kind": "freeze",
    "state": "enforced",
    "namespace": "https://registry.chio.example",
    "listingId": "listing-artifact-1",
    "activationId": "activation-8c71...",
    "subjectOperatorId": "origin-a",
    "openedAt": 140,
    "updatedAt": 140,
    "expiresAt": 500,
    "evidenceRefs": [
      { "kind": "trust_activation", "referenceId": "activation-8c71..." }
    ],
    "issuedBy": "governance@chio.example",
    "note": "freeze"
  },
  "signerKey": "9f2c1a...",
  "signature": "b0e4d7..."
}

A relying party evaluates it against the live listing at now = 150:

rust
let evaluation = evaluate_generic_governance_case(
    &GenericGovernanceCaseEvaluationRequest {
        listing,
        current_publisher,
        activation: Some(activation),
        charter,
        case,
        prior_case: None,
        evaluated_at: Some(150),
    },
    150,
)?;

assert!(evaluation.findings.is_empty());
assert_eq!(evaluation.effective_state, GenericGovernanceEffectiveState::Frozen);
assert!(evaluation.blocks_admission);

Drop the activation from the request and the same case resolves to a single MissingActivation finding with blocks_admission = false: a freeze the crate cannot substantiate does not silently take effect. Move the case to resolved and the effective state becomes clear with no block, which is how a lifted freeze reads.


Leases and receipts in the same crate

chio-governance defines charter and case records plus two other record groups. The other groups govern action authority instead of listing status and use the same signature and schema checks:

  • Capability leases (chio.capability-lease.v1) carry a scope digest and an action class of ScopedObservation, DelegatedAction, or NarrowDestructive. verify_capability_lease checks schema, signature, the validity window, and an exact scope_digest match.
  • Destructive-action governance receipts (chio.governance-receipt.v1) authorize a single destructive workflow step. verify_destructive_authorization binds a receipt to an expected lease id, workflow id, and step hash, and verify_step_governance_boundary requires a valid, unexpired receipt for any step marked destructive and none otherwise.

Those two families, their issuance path, and the checks the crate deliberately leaves to the caller are documented in Capability Leases. See Capabilities for the scoped, time-bounded authority these leases attenuate, and Mandates & Capabilities for how the kernel enforces a destructive-step boundary at runtime.


  • Capability Discovery · the chio-listing marketplace module whose listing identity a case references
  • Operating an Economy · how an operator wires governance authority into a running economy
  • Assurance Model · the admission and trust-activation decisions a governance case gates
  • Compliance Certificates · the session-scoped attestation that shares this crate's canonical-JSON signing substrate