Chio/Docs
LOGIN · JOIN

Listing Disputes, Freezes, and Sanctions

Evaluate signed registry charters and cases into a listing's effective state, findings, and admission decision.

Concept chio@5f63e6e

On this page

Any relying party can tell whether a provider's listing is frozen or sanctioned by evaluating the same signed charter and case. A case blocks admission only as an enforced freeze or sanction backed by the governing operator's trust activation; a dispute or an appeal is recorded beside the listing.

The governing operator signs a charter naming the case kinds it may open, then signs each case against one listing. In the example, operator origin-a freezes listing-artifact-1 in the namespace https://registry.chio.example.

An enforced freeze blocks admission; an unsubstantiated one is recorded

A relying party evaluates the signed case against the live listing and reads back one effective state and one flag.

Case to admissionChoose a case.
kindscasesubstantiatesσcharterχcaseτtrust activationeevaluationevaluate_generic_governance_caseadmission blockedfrozen, sanctionedδrecorded, admitsdisputed, appealedcclearresolved, deniedffinding, no blockMissingActivationkindscasesubstantiatesσcharterχcaseτactivationeevaluationadmission blockedfrozen, sanctionedδrecorded, admitsdisputed, appealedcclearresolved, deniedffinding, no blockMissingActivation

An enforced freeze blocks admission

A charter that allows freeze, an enforced freeze case, and a trust activation from the governing operator whose activation_id matches the case resolve to frozen with blocks_admission = true. Listing disputes.

One chio.registry.governance-case.v1 case evaluated against its charter and an optional trust activation, ending in an effective state and the blocks_admission flag. Listing and publisher checks, prior cases for appeals, and the finding codes are left out.

With a valid charter, an enforced case, and a matching activation at the evaluation time, the listing reads frozen and admission is blocked. Without the activation, the same case returns one MissingActivation finding and blocks_admission = false, so a freeze the evaluator cannot substantiate has no effect on admission. Once the case is resolved, the listing reads clear and only its other admission checks apply.

Inspect the signed freeze case

The field names are the record's own, and each digest is shortened from its full 64 hex characters. The charter allows all four case kinds, and the case references a trust activation the same operator issued. The envelope uses camelCase fields and snake_case enum values.

governance-case.jsonjson
{
  "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 charter bounds which cases its operator may open

A charter names the governing operator, the namespace it covers, its allowed_case_kinds, and optional escalation operators. The builder returns an unsigned body, which the operator signs with a governance-authority keypair issued through chio-federation-authority.

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

authority_scope can pin a charter to specific listing publishers and actor kinds. An empty list leaves that axis unrestricted, because evaluation tests only a list it finds nonempty. The charter id is a content hash over the issuing operator, the normalized namespace, the allowed kinds, and the issue time, so the same inputs always yield the same id.

Registry charters govern listing status. Credit tiers, discount curves, premium schedules, fees, and bonds belong to a separate charter family whose amendments move through propose, m-of-n approval, timelock, and activate before they take effect.

Read more in Fiscal charters.

Case state and kind together decide the effective state

Evaluation maps the case's lifecycle state and kind to a GenericGovernanceEffectiveState (clear, disputed, frozen, sanctioned, or appealed) and the boolean blocks_admission.

Case stateEffective stateBlocks admission
resolved, denied, supersededclearNo, for every kind
open, escalatedMirrors the kindNo, for every kind
enforcedMirrors the kindOnly freeze and sanction

The relying party gates on blocks_admission; the effective state is the readable status. A freeze or sanction needs a trust activation from the governing operator whose activation_id matches the case, and an appeal needs appeal_of_case_id plus a matching non-appeal prior_case.

Read every kind's requirement in Case kinds.

Evaluation stops at the first failed check and names it

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 checks, in order:

  1. Shape. The listing body and the current_publisher shape are valid.
  2. Signatures. The listing, charter, and case verify, and so do the activation and prior case when present.
  3. Issuer. A present activation's local_operator_id equals the charter's governing_operator_id.
  4. Identity. Charter, case, and listing agree on governing operator, charter id, namespace, and listing id.
  5. Expiry. Neither charter nor case has expired at evaluated_at; expires_at <= evaluated_at is expired.
  6. Charter scope. The charter allows the case's kind and, where its scope is set, admits the current publisher operator id and the listing subject actor kind.
  7. Supporting records. A freeze or sanction has an activation whose activation_id matches; a superseding case has a matching prior_case; an appeal has a matching non-appeal prior_case.

Success maps the state and kind to an effective state and blocks_admission, with an empty findings list. A failed check returns an Ok evaluation carrying one finding, effective_state = clear, and blocks_admission = false; only a malformed listing or publisher shape, or an internal crypto or canonicalization error, returns Err(String). A clear result with a finding means the case could not be enforced, so read findings beside the other two fields.

Inspect the Rust evaluation

The relying party evaluates the example freeze against the live listing at now = 150, with the activation supplied. evaluated_at falls back to the now argument when it is absent.

evaluate.rsrust
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);

The same crate signs capability leases and destructive-step receipts

chio-governance also defines two record groups that govern action authority, with the same signature and schema checks as charters and cases.

  • Capability leases (chio.capability-lease.v1) carry a scope digest and an action class of ScopedObservation, DelegatedAction, or NarrowDestructive. verify_capability_lease checks the schema, the signature, the validity window, and an exact scope_digest match.
  • Destructive-action governance receipts (chio.governance-receipt.v1) authorize one 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 every step marked destructive and none for any other step.

Their issuance path and the checks a caller runs are in Capability leases. Capabilities covers the scoped, time-bounded authority a lease attenuates, and Mandates and capabilities covers how the kernel enforces a destructive-step boundary at runtime.

Charter, case, and finding reference

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

Record typeSchema tagPurpose
GenericGovernanceCharterArtifact
chio.registry.governance-charter.v1
Grants an operator authority over a namespace and its case kinds
GenericGovernanceCaseArtifact
chio.registry.governance-case.v1
Records one dispute, freeze, sanction, or appeal against one listing

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. chio-core and chio-open-market re-export the crate as governance.

Charter fields

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). The scope is its own type, and an empty list on either axis is unrestricted on that axis (crates/trust/chio-governance/src/evaluation.rs:169-196):

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 nonempty, 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 id as a content hash over the issuing operator, the normalized namespace, the allowed case kinds, and the issue time:

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())?
    )
);

Case fields

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. An optional sha256 is validated as a 64-character hex digest when 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 holds independently of any evaluation context: the schema matches, evidence_refs is nonempty, an appeal carries appeal_of_case_id (and no other kind may), and an escalated case lists at least one escalated_to_operator_ids entry.

build_generic_governance_case_artifact (crates/trust/chio-governance/src/generic.rs:445-509) verifies the signatures on the charter, the listing, and a present trust activation before minting the body. It refuses a case whose charter another operator governs, or whose trust activation another operator issued. 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())?
    )
);

The evaluation request is GenericGovernanceCaseEvaluationRequest (crates/trust/chio-governance/src/generic.rs:291-303), and every path returns the same record, whether evaluation completes or stops at a finding:

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

Case kinds

A charter lists a kind in allowed_case_kinds before a case of that kind evaluates.

KindActive effective stateCan block admissionExtra requirement
dispute
disputed
No
None
freeze
frozen
Yes, when enforced
Matching trust activation from the governing operator
sanction
sanctioned
Yes, when enforced
Matching trust activation from the governing operator
appeal
appealed
No
appeal_of_case_id plus a matching non-appeal prior_case

Finding codes

When evaluation stops, it emits one GenericGovernanceFinding with a typed code and a readable message.

  • ListingUnverifiable: the listing signature or body failed verification.
  • ActivationUnverifiable: the trust activation signature or body failed verification.
  • CharterUnverifiable: the charter signature or body failed verification.
  • CaseUnverifiable: the case signature or body failed verification.
  • PriorCaseUnverifiable: the referenced prior case signature or body failed verification.
  • CharterExpired: the charter's expires_at was reached as of evaluation.
  • CaseExpired: the case's expires_at was reached as of evaluation.
  • CharterScopeMismatch: the current publisher or the listing actor kind falls outside the charter scope.
  • CharterKindUnsupported: the charter does not authorize the case kind.
  • CaseMismatch: the charter or case differs from the current listing identity or namespace.
  • MissingActivation: a freeze or sanction case arrived without a trust activation.
  • ActivationMismatch: the activation was issued by another operator, or its id differs from the case.
  • AppealTargetMissing: an appeal lacks appeal_of_case_id or its prior_case.
  • AppealTargetInvalid: the appeal target fails to match a valid, non-appeal prior case.
  • SupersessionTargetMissing: a superseding case lacks its prior_case.
  • SupersessionTargetInvalid: the supersession target fails to match the referenced prior case.

Next: follow an enforced sanction to a bond