Fiscal Charters
Change a credit ceiling or premium schedule through signed approvals and a timelock that a restored backup cannot undo.
On this page
An operator's economic parameters change only by amendment. Credit ceilings, discount curves, premium schedules, and market fees move after a signed proposal collects approvals from a fixed signer set and waits out a timelock, and a continuity anchor keeps a superseded schedule from returning.
The running example raises one marketplace credit ceiling from USD 1,000 to USD 1,500. The active charter requires two distinct approvals from three signers and a one-hour timelock; the operator who signs the charter chooses those settings.
A ceiling moves only after approval and the timelock
Four signed records carry the change from proposal to the consumer that prices a call. The clock starts at admission.
Admission starts the clock
The trusted admission authority signs a FiscalProposalAdmission that stamps admitted_at, an admission_sequence, and proposal_expires_at, which equals admitted_at + proposal_ttl_seconds. The draft's proposed_at is provenance only. Fiscal charters.
FiscalProposal to the FiscalResolution a consumer reads. Charter rotation, the bootstrap fallback, and the continuity checkpoint fields are left out.- 09:00, admission. The signed admission fixes
admitted_atand the proposal expiry, and the one-hour clock starts. - 09:20, approvals. Two distinct charter members approve, each naming the same proposal and admission digests.
- 09:30, too early. The threshold is met and the timelock has not elapsed, so no valid activation exists and the USD 1,000 schedule stays in force.
- 10:00, activation. With every record inside its validity window and continuity checks passing, the consumer resolves USD 1,500 and retains the schedule id and sequence.
At the pricing or limit consumer, FiscalResolver::resolve takes the domain and the requested currency and returns a FiscalResolution. The consumer uses Governed parameters, handles the bootstrap Fallback only where the anchor proves the domain was never activated, and stops on Denied.
A charter governs five parameter domains of one deployment
A FiscalCharter (chio.fiscal.charter.v1) names the governing operator, its domains, an explicit signer set, and the amendment rules: approval threshold, timelock, and time-to-live windows. Each FiscalSchedule (chio.fiscal.schedule.v1) is a typed parameter set bound to that charter by digest, and its params variant must match its FiscalDomain.
| Domain | FiscalParams variant | Rule on the values |
|---|---|---|
| Tier limits | TierLimits { ceilings: [MonetaryAmount; 4] } | One ISO 4217 currency, non-decreasing units |
| Marketplace discount | MarketplaceDiscountPerHundred { discounts: [u32; 4] } | Each at most 100, non-decreasing |
| Decision premium | DecisionPremiumBasisPoints { approve, reduce_ceiling } | Non-decreasing by risk class; reduce_ceiling at least approve |
| Insurance premium | InsurancePremiumSchedule { ... } | Premium floors plus score_adjustments_bps |
| Open-market fees and bonds | OpenMarketFeeAndBondSchedule { legacy_body } | Publication, dispute, participation fees and bonds |
The domains are the parameters live pricing and penalty consumers already read. Tier limits are the marketplace credit-limit tier ceilings and replace MARKETPLACE_TIER_LIMIT_UNITS. The discount is the reputation-tier invocation discount and replaces TIER_DISCOUNT_PER_HUNDRED in its per-hundred unit. Decision premiums are the underwriting basis-point tables, the insurance score_adjustments_bps are fixed-point, and the open-market schedule carries the exact OpenMarketFeeScheduleArtifact body as a bound compatibility projection. Premium money math is checked integer arithmetic, with finite f64 confined to behavioral risk classification.
Activation changes parameters and nothing else: it moves and holds no funds, issues no token, and takes no custody. A schedule is signed intent scoped to one charter, so it governs one operator's own parameters and carries no authority over a peer.
Four signed records carry a change, and one holds durable state
A FiscalProposal names a candidate schedule or a charter rotation. A FiscalProposalAdmission from the trusted admission authority stamps admitted_at, a checked-monotonic admission_sequence, and proposal_expires_at. Distinct members each sign a FiscalApproval, and a FiscalActivation aggregates them once the threshold is met and the timelock has passed.
The admission is the timelock anchor. Its proposal_expires_at equals admitted_at + proposal_ttl_seconds, each approval's approval_expires_at equals approved_at + approval_ttl_seconds, and the activation's activation_not_before equals admitted_at + timelock_seconds. A signed proposed_at or a caller-selected time leaves the delay unchanged.
Only the admission has stored state. FiscalProposalAdmissionState wraps the signed admission with its digest, a version, activationDigest, activatedSequence, and a status of admitted or activated; admission creates it at version 1 with both optional fields absent. The store records only those two values; awaiting signatures and waiting out the clock are conditions of the change. The state moves from Admitted to Activated by compare-and-swap, so two concurrent activations for one admission have exactly one winner.
When an activation is valid
Every nested signature verifies, distinct charter signers reach approval_threshold, all approvals sign the same proposal digest, the candidate is inside its validity window, and verify_at is at or past activation_not_before while still inside the proposal, approval, charter, and candidate windows. A CharterRotation is evaluated against the predecessor charter's membership and carries one successor-bound replacement for every activated domain; a missing, extra, or parameter-changing replacement rolls back the whole rotation.
On the capability ladder the transition is fiscal.amendment_activate: mode receipt_backed, destructive: true, cross_org_visibility: private, and consistency_model: totally-ordered anchored at external-checkpoint. Its co_sign is none, because the m-of-n charter approvals are the domain's own authorization, and spec/CHIO_LADDER.md sets its local authority floor at high assurance.
Consumers read parameters through one resolver that fails closed
Consumers call one pure resolver instead of reading a parameter table. A Governed value exists only after the complete activation chain verifies: schema admission, every record signature, the locally anchored admission authority, threshold and uniqueness, the authenticated timelock, the validity window, the monotonic sequence, and the supersession lineage. The resolver walks a fixed order and stops at the first outcome it can prove:
- Bootstrap.
Fallbackonly when the anchored genesis checkpoint proves the domain was never activated, using the exact built-in constant or the pinned genesis-policy currency map. - Active. A verified, in-window active schedule resolves to
Governed { source: Active }. - Last known good. When the newest candidate is bad, the prior verified in-window schedule resolves to
Governed { source: LastKnownGood }. - Fail closed. With no valid charter, the resolver returns
Denied, and the consumer does not price, bind, charge, or penalize.
Once the anchored ever_activated marker is true for a domain, unavailable governed state resolves to Denied and the built-in constant never reappears. Rejection and resolution are separate code paths, so a bad amendment leaves trustworthy state in place.
A stalled change has one of three causes. If the timelock has not elapsed, wait for the authenticated activation time; waiting leaves each approval's expiry where it was. If an approval expired, collect fresh approvals under a live proposal and admission, or prepare a new change. If continuity is unavailable, restore the checkpoint and anchor relationship. A signed timestamp is never edited to fit.
An anchor outside the database keeps an old schedule from returning
Local SQLite state is a cache and staging store. Resolution in production requires a configured FiscalStateAnchor that lives outside the database's backup and restore domain, such as a remote append-only witness or a hardware-backed monotonic store. Missing, unavailable, unauthenticated, or non-monotonic anchor state fails startup before any fiscal read or mutation is served.
The anchor holds the operator's latest signed chio.fiscal.continuity-checkpoint.v1: a monotonic continuity_sequence and the previous digest, the FiscalGenesisPolicy id and body digest, the pinned charter, the runtime-readiness digest, per-domain ever_activated with active and last-known-good heads, the trusted-clock high-water second, and any staged transition needed for recovery.
- Stage. The transition and the next checkpoint are written in an
ImmediateSQLite transaction while consumers still read the prior state. - Swap. The independent anchor moves by compare-and-swap from the exact prior checkpoint to the next signed one. It accepts only a
VerifiedFiscalContinuityAdvance: acontinuity_sequence + 1step, a non-decreasing clock floor, an unchanged genesis-policy digest, and anever_activatedbit that moves only from false to true. - Finalize. The local store finalizes against the anchored checkpoint.
A signed rollback, a skipped sequence, a cleared activation bit, or a reduced clock is rejected before the anchor mutates. Recovery reads the anchor first: if it is ahead of a restored database, the snapshot is stale and startup fails closed. Restoring SQLite alone can never reopen the bootstrap fallback or move the time boundary backward.
Fiscal records and schemas
Search for approval_threshold, FiscalDenialReason, or genesis-policy.
Schema family
The family holds 9 schema files under spec/schemas/chio-fiscal/v1/, of which spec/schemas/registry.json lists 8. The other 1 is the genesis policy, which an operator configures instead of signing and exchanging: it carries the constant chio.fiscal.genesis-policy.v1 and its own id preimage, and the registry lists no id for it. Every registered kind uses the fiscal_ prefix. The records, the amendment lifecycle, the resolver, and the continuity anchor live in the chio-fiscal crate.
| File | Title | Registry id |
|---|---|---|
charter. | Chio Fiscal Charter | chio. |
schedule. | Chio Fiscal Schedule | chio. |
proposal. | Chio Fiscal Proposal | chio. |
proposal- | Chio Fiscal Proposal Admission | chio. |
approval. | Chio Fiscal Approval | chio. |
activation. | Chio Fiscal Activation | chio. |
continuity- | Chio Fiscal Continuity Checkpoint | chio. |
consumer- | Chio Fiscal Consumer Readiness | chio. |
genesis- | Chio Fiscal Genesis Policy | unregistered |
Charter and schedule
Both records are canonical JSON (RFC 8785) inside a SignedExportEnvelope<T>. Every id is a content hash over a preimage that omits the self id and the signature, so a body that already carries its id is never re-hashed. The charter preimage (chio.fiscal.charter.id.v1) sorts governed domains and signer keys canonically, so two wire bodies cannot share a normalized id, and each FiscalSigner key id is the lowercase SHA-256 of its canonical public-key bytes.
// schema: chio.fiscal.charter.v1 (id preimage: chio.fiscal.charter.id.v1)
pub struct FiscalCharter {
pub schema: String,
pub charter_id: String, // sha256 over the sorted id preimage
pub governing_operator_id: String,
pub governed_domains: Vec<FiscalDomain>, // sorted, deduplicated, non-empty
pub signer_set: Vec<FiscalSigner>, // FiscalSigner { key_id, public_key }
pub approval_threshold: u32, // in 1..=signer_set.len()
pub timelock_seconds: u64, // > 0
pub proposal_ttl_seconds: u64, // > timelock_seconds
pub approval_ttl_seconds: u64, // > 0
pub issued_at: u64,
pub expires_at: u64, // required; > issued_at
pub issued_by: String,
pub sequence: u64,
pub predecessor_charter_digest: Option<String>,
}
// schema: chio.fiscal.schedule.v1 (id preimage: chio.fiscal.schedule.id.v1)
pub struct FiscalSchedule {
pub schema: String,
pub schedule_id: String,
pub charter_id: String,
pub charter_digest: String, // sha256 of the signed charter
pub domain: FiscalDomain,
pub params: FiscalParams, // active variant must match domain
pub sequence: u64, // first is 1, then + 1 checked
pub supersedes_schedule_id: Option<String>,
pub valid_from: u64,
pub valid_until: u64, // required; > valid_from
pub issued_at: u64,
pub issued_by: String,
}A genesis charter is accepted only against an operator-configured FiscalGenesisPolicy that pins the exact charter digest, the bootstrap authority key, the fiscal-anchor identity and namespace, and a bounded currency-to-ceiling bootstrap_tier_limits map. A later charter is approved and activated under the threshold of the charter pinned at the time; its own new signer set cannot authorize its adoption. The first schedule for a domain carries sequence = 1 and no supersedes id, and every successor increments the sequence with checked arithmetic and names the exact active schedule, so a gap, a duplicate, or a cross-domain predecessor is rejected at load.
Proposal, approval, and activation
// schema: chio.fiscal.proposal.v1
pub struct FiscalProposal {
pub schema: String,
pub proposal_id: String,
pub target: FiscalProposalTarget, // Schedule { candidate } | CharterRotation { successor }
pub rationale_digest: String, // sha256 of an out-of-band rationale document
pub proposed_by: String,
pub proposed_at: u64, // signed provenance only, not the timelock clock
}
// schema: chio.fiscal.approval.v1 (one single-signer envelope per charter member)
pub struct FiscalApproval {
pub schema: String,
pub approval_id: String,
pub signer_key_id: String, // must be a member of the active signer_set
pub proposal_id: String,
pub proposal_digest: String,
pub admission_id: String,
pub admission_digest: String,
pub approved_at: u64,
pub approval_expires_at: u64, // approved_at + charter.approval_ttl_seconds
}
// schema: chio.fiscal.activation.v1 (aggregates m-of-n, valid only past the timelock)
pub struct FiscalActivation {
pub schema: String,
pub activation_id: String,
pub proposal_id: String,
pub proposal_digest: String,
pub admission_id: String,
pub admission_digest: String,
pub charter_id: String,
pub charter_digest: String,
pub approval_set_digest: String, // sha256 over the sorted (signer_key_id, envelope_digest) list
pub target: FiscalActivationTarget, // Schedule { .. } | CharterRotation { .. }
pub approvals: Vec<SignedFiscalApproval>,
pub activation_not_before: u64, // admitted_at + charter.timelock_seconds
pub activated_at: u64,
pub issued_by: String,
}Resolution types
pub enum FiscalResolution<P> {
Governed { schedule_id: String, sequence: u64, source: GovernedSource, params: P },
Fallback(FiscalFallbackReason),
Denied(FiscalDenialReason),
}
pub enum GovernedSource { Active, LastKnownGood }
pub enum FiscalFallbackReason { AuthoritativeBootstrap, NeverActivated }
pub enum FiscalDenialReason {
AnchorUnavailable,
AnchorRollbackOrDivergence,
ActivatedStateUnavailable,
NoValidLastKnownGood,
ClockRollback,
VerificationFailed,
}