GOVERNANCE_STATE_MACHINE.md 0. Purpose
This document defines protocol-level state machines for each domain enforced by packages/core/*.
Resolving locale, route permissions, and workspace projection.
Current scope: Guest
Category: 20_procedures | Version: v1.0.0
Owner: DOCUMENT_CUSTODIAN | Review cycle: 90 days
Approval authority: GOVERNANCE_ADMIN, COMPLIANCE_OFFICER
Documentation portal is read-only. Editing and mutation endpoints are disabled.
Kvary platform is originally created in Georgian. Where a Georgian version exists, Georgian is authoritative for platform UI, documentation, and legal interpretation.
Translations into other languages are provided for convenience. Some records may originate in other languages and carry their own source or legal locale for a specific flow, but where a Georgian version is available, the Georgian version prevails for platform-level wording and interpretation.
Metadata incomplete: Document ID, Version, Status, Owner Role, Last Review Date, Next Review Date, Change Log
GOVERNANCE_STATE_MACHINE.md 0. Purpose
This document defines protocol-level state machines for each domain enforced by packages/core/*.
It provides:
Visual diagrams (Mermaid)
Logical transition matrices (deterministic rules)
Authorization gates (ACCESS_DECISION requirements)
Traceability requirements (decision hash binding)
All rules here are ledger-driven and must remain deterministic.
State is derived from scanning the append-only ledger:
LedgerEntry.payload.recordType
LedgerEntry.payload.action
LedgerEntry.payload.decision
LedgerEntry.payload.metadata
No external DB state is trusted.
1.2 Latest-decision-wins authorization
For any executable action X, authorization requires:
A matching ACCESS_DECISION for (subjectId, policyHash, action=X)
Latest matching decision wins
Latest DENY blocks
1.3 Cryptographic traceability
When an action is executed (record appended), the resulting record MUST embed:
authDecisionEntryHash
authDecisionPayloadHash
authDecisionAction
authDecisionPolicyHash
So every execution can be proven to be authorized.
SETTLEMENT_INTENT (action: SETTLEMENT.CREATE)
SETTLEMENT_EVENT (action: SETTLEMENT.<EVENT_TYPE>)
Settlement events (eventType):
ESCROW_OPENED
DEPOSIT_CONFIRMED
RELEASE_REQUESTED
RELEASE_EXECUTED
REFUND_EXECUTED
RAIL_ERROR (informational / error signaling)
2.2 Visual State Machine (high-level) Diagram stateDiagram-v2 [*] --> IntentCreated: SETTLEMENT.CREATE (requires ALLOW)
IntentCreated --> EscrowOpened: SETTLEMENT.ESCROW_OPENED (requires ALLOW) IntentCreated --> DepositConfirmed: SETTLEMENT.DEPOSIT_CONFIRMED (requires ALLOW) / if escrowRequired=false
EscrowOpened --> DepositConfirmed: SETTLEMENT.DEPOSIT_CONFIRMED (requires ALLOW)
DepositConfirmed --> ReleaseRequested: SETTLEMENT.RELEASE_REQUESTED (requires ALLOW) ReleaseRequested --> ReleaseExecuted: SETTLEMENT.RELEASE_EXECUTED (requires ALLOW)
DepositConfirmed --> RefundExecuted: SETTLEMENT.REFUND_EXECUTED (requires ALLOW) RefundExecuted --> [*]
ReleaseExecuted --> [*]
IntentCreated --> RailError: SETTLEMENT.RAIL_ERROR (requires ALLOW) EscrowOpened --> RailError: SETTLEMENT.RAIL_ERROR (requires ALLOW) DepositConfirmed --> RailError: SETTLEMENT.RAIL_ERROR (requires ALLOW)
NOTE: Lifecycle constraints may invalidate some edges (see matrix).
2.3 Transition Matrix: SettlementIntent From (derived) Action Required prior auth Emits recordType Notes none SETTLEMENT.CREATE ACCESS_DECISION(ALLOW) for SETTLEMENT.CREATE SETTLEMENT_INTENT Intent is blocked unless latest decision is ALLOW Hard rule
SettlementIntent must require ALLOW decision (already implemented)
2.4 Transition Matrix: SettlementEvent Precondition Event Action Required prior auth Emits recordType Required metadata trace intent exists SETTLEMENT.ESCROW_OPENED ALLOW for SETTLEMENT.ESCROW_OPENED SETTLEMENT_EVENT authDecisionEntryHash, authDecisionPayloadHash escrowRequired=true AND escrowOpened=false SETTLEMENT.DEPOSIT_CONFIRMED ALLOW for SETTLEMENT.DEPOSIT_CONFIRMED SETTLEMENT_EVENT must be invalid at lifecycle verification deposit confirmed SETTLEMENT.RELEASE_REQUESTED ALLOW for SETTLEMENT.RELEASE_REQUESTED SETTLEMENT_EVENT milestoneId required release requested(milestone) SETTLEMENT.RELEASE_EXECUTED ALLOW for SETTLEMENT.RELEASE_EXECUTED SETTLEMENT_EVENT milestoneId required any before refund SETTLEMENT.REFUND_EXECUTED ALLOW for SETTLEMENT.REFUND_EXECUTED SETTLEMENT_EVENT after refund, no releases allowed any SETTLEMENT.RAIL_ERROR ALLOW for SETTLEMENT.RAIL_ERROR SETTLEMENT_EVENT requires error metadata Lifecycle invariants (validator-level)
DEPOSIT_CONFIRMED cannot occur before ESCROW_OPENED when escrowRequired=true
RELEASE_EXECUTED requires prior RELEASE_REQUESTED for same milestone
RELEASE_* not allowed after REFUND_EXECUTED
KES_VERSION_PROPOSED (action: KES.PROPOSE_VERSION)
KES_VERSION_RATIFIED (action: KES.RATIFY_VERSION)
3.2 Visual State Machine (per contract) Diagram stateDiagram-v2 [*] --> NoVersions
NoVersions --> V1Proposed: KES.PROPOSE_VERSION(v=1) (requires ALLOW + chain) V1Proposed --> V1Ratified: KES.RATIFY_VERSION(v=1) (requires ALLOW + stricter rule)
V1Ratified --> V2Proposed: KES.PROPOSE_VERSION(v=2) (requires ALLOW + strict chain + prev ratified) V2Proposed --> V2Ratified: KES.RATIFY_VERSION(v=2) (requires ALLOW + stricter rule)
V2Ratified --> VnProposed: KES.PROPOSE_VERSION(v=n) VnProposed --> VnRatified: KES.RATIFY_VERSION(v=n)
VnRatified --> [*]
3.3 Transition Matrix: PROPOSE_VERSION (strict chain) Condition Action Required prior auth Additional chain constraints Emits Trace no versions exist KES.PROPOSE_VERSION v=1 ALLOW for KES.PROPOSE_VERSION v must be 1; no prevVersionHash KES_VERSION_PROPOSED decision hashes + chain expected/provided versions exist KES.PROPOSE_VERSION v=n ALLOW for KES.PROPOSE_VERSION n must be contiguous; prevVersionHash must match last versionHash; prev must be ratified (strict+) KES_VERSION_PROPOSED decision hashes + chain expected/provided
Strict chain error codes (enforced):
FIRST_VERSION_MUST_BE_1
V1_MUST_NOT_HAVE_PREV_HASH
NON_CONTIGUOUS_VERSION
MISSING_PREV_HASH
PREV_HASH_MISMATCH
PREV_NOT_RATIFIED
DUPLICATE_VERSION
3.4 Transition Matrix: RATIFY_VERSION (stricter rule) Condition Action Required prior auth Stricter constraints Emits Trace version proposed exists KES.RATIFY_VERSION(v, hash) ALLOW for KES.RATIFY_VERSION proposed version must exist; hash must match proposed; cannot ratify twice KES_VERSION_RATIFIED decision hashes
Ratify enforcement error codes:
MISSING_PROPOSE_VERSION
VERSION_HASH_MISMATCH
VERSION_ALREADY_RATIFIED
MISSING_ALLOW_DECISION
DENIED_BY_LATEST_DECISION
(Fill-in section keep governance anchored. If you already have AUCTION_TRANSITION rules, map them here.)
4.1 Records
AUCTION_TRANSITION (action: AUCTION.<STATE_CHANGE>)
4.2 Suggested Visual Skeleton Diagram stateDiagram-v2 [*] --> Draft Draft --> Published: AUCTION.PUBLISH (requires ALLOW) Published --> Bidding: AUCTION.OPEN_BIDDING (requires ALLOW) Bidding --> Settling: AUCTION.CLOSE_BIDDING (requires ALLOW) Settling --> Completed: AUCTION.COMPLETE (requires ALLOW) Published --> Cancelled: AUCTION.CANCEL (requires ALLOW) Bidding --> Cancelled: AUCTION.CANCEL (requires ALLOW)
4.3 Matrix Template From Action Required auth action Emits Notes Draft AUCTION.PUBLISH ACCESS_DECISION for AUCTION.PUBLISH AUCTION_TRANSITION Published AUCTION.OPEN_BIDDING ... AUCTION_TRANSITION Bidding AUCTION.CLOSE_BIDDING ... AUCTION_TRANSITION triggers SettlementIntent gate 5. Domain: Tender 5.1 Records
TENDER_TRANSITION (action: TENDER.<STATE_CHANGE>)
5.2 Visual Skeleton Diagram stateDiagram-v2 [*] --> Draft Draft --> Open: TENDER.OPEN (requires ALLOW) Open --> Evaluating: TENDER.CLOSE (requires ALLOW) Evaluating --> Awarded: TENDER.AWARD (requires ALLOW) Awarded --> Settling: TENDER.SETTLE (requires ALLOW) Settling --> Completed: TENDER.COMPLETE (requires ALLOW) Open --> Cancelled: TENDER.CANCEL (requires ALLOW)
POLICY_FREEZE (action: POLICY.FREEZE or your exact action naming)
6.2 Invariant (recommended)
Once a policyHash is frozen:
New ACCESS_DECISION for that policyHash should be rejected (or ignored) by governance modules
Execution must bind to frozen policyHash only
(If this rule is not yet enforced in code, keep it as a formal specification and implement enforcement in core validation.)
When an Auction/Tender reaches an execution boundary (e.g., award or close):
it may create a SETTLEMENT_INTENT
but settlement is blocked unless:
ACCESS_DECISION(ALLOW) for SETTLEMENT.CREATE exists
7.2 KES Version -> Settlement Profile
KES version commitment includes settlementProfileHash.
Invariant:
Settlement execution referencing a KES contract should use the currently ratified version's settlementProfileHash (ledger-derived).
For each new domain transition:
Is action name stable and deterministic?
Is there an ACCESS_DECISION gate?
Is latest-decision-wins enforced?
Are decision hashes embedded for traceability?
Are lifecycle invariants verified by scanning the ledger?
Are error codes deterministic and stable?
SETTLEMENT.<EVENT>
KES.<OPERATION>
AUCTION.<TRANSITION>
TENDER.<TRANSITION>
POLICY.<OPERATION>