Status Machines
All protocol status enums with valid state transitions, triggers, and domain applicability.
Every major protocol entity has a status field that follows a defined state machine. This page documents all valid states, transitions, and the conditions that trigger each transition. Terminal states have no outgoing transitions.
ProductStatus
The lifecycle state of a SmartProduct. Stored as the status column on the SmartProduct table.
States
| Status | Meaning | Terminal? |
|---|---|---|
DRAFT | Contract not yet deployed. Product is being configured off-chain. | No |
PUBLISHED | Contract deployed on-chain. Accepting ProductInstance mints. | No |
LOCKED | Minting window closed. Finalization phase in progress. | No |
SETTLED | Results finalized. Prizes are claimable by winners. | No |
FAILED | Contract deployment or critical execution failed. | No |
ARCHIVED | Product removed from active listing. No further changes. | Yes |
Valid transitions
| From | To | Trigger |
|---|---|---|
DRAFT | PUBLISHED | Contract deploy transaction confirmed on-chain (chainhook event) |
DRAFT | FAILED | Deploy transaction fails or times out |
DRAFT | ARCHIVED | Creator or admin archives a draft |
PUBLISHED | LOCKED | The tournament is locked on chain (PREDICTION domain only) |
PUBLISHED | FAILED | Critical execution failure (PREDICTION domain only) |
PUBLISHED | ARCHIVED | Creator or admin archives the product |
LOCKED | PUBLISHED | The tournament is unlocked on chain (PREDICTION domain only) |
LOCKED | SETTLED | Settlement transaction confirmed - results written on-chain |
LOCKED | ARCHIVED | Admin archives a locked product (dispute or abandonment) |
SETTLED | ARCHIVED | Creator or admin archives after settlement period |
FAILED | ARCHIVED | Cleanup - failed products are archived |
Domain applicability
Not all status values apply to all domains:
| Status | PAGE | EVENT | PREDICTION | GAME |
|---|---|---|---|---|
DRAFT | Yes | Yes | Yes | Yes |
PUBLISHED | Yes | Yes | Yes | Yes |
LOCKED | No | No | Yes | No |
SETTLED | No | No | Yes | No |
FAILED | Yes | Yes | Yes | Yes |
ARCHIVED | Yes | Yes | Yes | Yes |
Every domain except PREDICTION follows the path: DRAFT - PUBLISHED - ARCHIVED (or FAILED - ARCHIVED).
PREDICTION products can also pass through LOCKED and SETTLED before archival.
GameMatchStatus
A GAME lobby stays PUBLISHED while it hosts matches; each match carries a status of its own.
| Status | Meaning |
|---|---|
IN_PROGRESS | Both seats bought in and the match started. Moves land here |
WON | A line was made. The winner has not claimed the kitty yet |
DRAWN | A full board with no line, or a stalled match closed as a draw. Seats have not all claimed yet |
SETTLED | Paid out: the winner claimed (and holds the trophy), or every seat of a draw claimed its half |
OPEN | In the enum and never written; a match is created IN_PROGRESS when it starts |
IN_PROGRESS -> WON or DRAWN -> SETTLED. A settled match is final.
InviteStatus
The lifecycle state of an Invite. Stored as the status column on the Invite table.
States
| Status | Meaning | Terminal? |
|---|---|---|
DRAFT | Invite is being composed. Code exists but has not been distributed. | No |
SENT | The holder has sent it - the app yields a claim link and the person delivers it themselves; there is no email dispatch. | No |
CLAIMED | Recipient redeemed the invite code. Role-on-claim (if set) was granted. | Yes |
REVOKED | The creator (or an Admin) cancelled the invite. Code is no longer valid. | Yes |
EXPIRED | TTL exceeded without claim. Automatically set by background process. | Yes |
Valid transitions
| From | To | Trigger |
|---|---|---|
DRAFT | SENT | The creator or the assigned holder sends the invite, optionally binding it to an email, X handle or address |
DRAFT | EXPIRED | Automatic - the daily reaper silently expires an assigned draft whose date passed unsent |
SENT | CLAIMED | Recipient presents a valid code at the claim endpoint |
SENT | REVOKED | The creator (or an Admin) revokes after sending (code immediately invalidated) |
SENT | EXPIRED | Automatic - the daily reaper sweeps invites whose TTL passed without a claim |
Notes
- Only a
SENTinvite can be revoked. ADRAFThas reached nobody, so it is discarded with a hard delete (rtClient.invites.remove) rather than a status. - Assigning an invite to a holder is not a status: an assigned invite is still
DRAFTuntil someone sends it. - Role-on-claim (optional field) is granted via
grantRoleToUserat theCLAIMEDtransition, creating an audit trail viaUserRole.grantedViaInviteId. - The claim endpoint returns a generic
{ valid: false }for EXPIRED, REVOKED, or nonexistent codes to prevent status enumeration. - Daily mint quotas gate invite creation, not claiming: Member, Open Beta and Early Adopter = 0/day during the alpha, Admin = unlimited. Claiming a valid code is never quota-limited.
FundingGroupStatus
The lifecycle state of a FundingGroup. Stored as the status column on the FundingGroup table.
States
| Status | Meaning | Terminal? |
|---|---|---|
PENDING | Application submitted. Awaiting admin review. | No |
APPROVED | Admin approved. Group can receive FUNDING_GROUP revenue splits. | No |
VERIFIED | On-chain proof of settlement received. | No |
REJECTED | Admin denied the application. Cannot be reversed. | Yes |
SUSPENDED | Temporarily disabled by admin for policy review. | No |
Valid transitions
| From | To | Trigger |
|---|---|---|
PENDING | APPROVED | Admin grants approval |
PENDING | REJECTED | Admin denies application |
APPROVED | VERIFIED | Chainhook confirms on-chain settlement to this group |
APPROVED | SUSPENDED | Admin suspends for policy review |
VERIFIED | SUSPENDED | Admin suspends a verified group |
SUSPENDED | APPROVED | Admin restores from suspension (was previously APPROVED) |
SUSPENDED | VERIFIED | Admin restores from suspension (was previously VERIFIED) |
Notes
REJECTEDis terminal. A rejected organization must submit a new FundingGroup application.- FundingGroups in
APPROVEDorVERIFIEDstatus can be selected by creators for FUNDING_GROUP splits. SUSPENDEDgroups cannot receive new allocations and are hidden from the creator picker UI.- The
SUSPENDED-APPROVEDvsSUSPENDED-VERIFIEDrestoration depends on whether the group had been verified before suspension.
PendingTxStatus
The lifecycle of a broadcast transaction as the protocol tracks it, from broadcast to a
terminal outcome. Stored as the status column on the PendingTransaction table and readable
through rtClient.pendingTransactions. This machine is why a client can close on broadcast:
the server owns confirmation.
States
| Status | Meaning | Terminal? |
|---|---|---|
BROADCAST | Registered at broadcast; not yet processed. Covers both in-mempool and mined-but-unprocessed - "mined" is a fact carried by the row's block columns, not a status. | No |
REPLAYING | The reconciler has asked the ingestion layer to re-deliver a mined transaction whose event never arrived. | No |
CONFIRMED | The backend processed the transaction's event - terminal success. | Yes |
HANDLER_FAILED | The event arrived but processing threw; the dead-letter queue owns recovery. | No |
FAILED | The chain reports the transaction aborted on-chain. | Yes |
DROPPED | Never mined within the abandonment window, or recovery attempts were exhausted. | No* |
Valid transitions
| From | To | Trigger |
|---|---|---|
BROADCAST | CONFIRMED | Event processed - inline by the handler on delivery, or by the reconciler observing the processed record |
BROADCAST | REPLAYING | Reconciler finds the transaction mined but its event undelivered |
REPLAYING | CONFIRMED | The re-delivered event processes |
BROADCAST / REPLAYING | HANDLER_FAILED | The event arrived and the handler threw |
HANDLER_FAILED | CONFIRMED | Dead-letter replay succeeds |
BROADCAST | FAILED | Chain reports an on-chain abort |
BROADCAST | DROPPED | Abandonment window elapses un-mined, or attempts exhaust |
DROPPED | BROADCAST | *Operator reopens a retry-exhausted drop - a transaction the chain accepted is never abandoned silently |
AppAccessStatus
Whether a user may act inside a gated app. One row per (user, app) on the AppAccessGrant
table; the row flips rather than being deleted, so access history survives.
| Status | Meaning | Terminal? |
|---|---|---|
GRANTED | The user may act in this app. | No |
REVOKED | Access withdrawn; the row remains as history. | No |
Transitions are operator- or invite-driven: a claim mints GRANTED, an operator can revoke,
and a revoked grant can be re-granted. Enforcement is fail-closed on the acquisition and
participation routes; owner-property actions (burn, transfer, detach) are deliberately exempt -
ownership never expires.
RenderJobStatus
Out-of-band rendering work (rasterize + store an edition's artwork), enqueued at the event and drained on a schedule.
| Status | Meaning | Terminal? |
|---|---|---|
PENDING | Enqueued, not yet rendered. | No |
RUNNING | A worker tick claimed it. | No |
COMPLETED | The render and store succeeded. | Yes |
FAILED | Max attempts exhausted - terminal and operator-owned. | Yes |
AutoDetachJobStatus (the post-render job that archives an edition on a custodial
owner's behalf) follows the same shape, adding SKIPPED for owners whose keys the
protocol does not hold - recorded for visibility, no work to do.
ChainhookStatus
The registration lifecycle of a per-contract event subscription.
| Status | Meaning | Terminal? |
|---|---|---|
PENDING | Created, registration not yet confirmed upstream. | No |
ACTIVE | Registered and delivering. | No |
RETRYING | Registration or delivery is being retried. | No |
FAILED | Registration failed; retry budget available. | No |
ABANDONED | Retry budget exhausted - operator-owned. | No |
Ingestion does not depend on this machine alone: the chain-sourced floor reads the chain directly as an independent second route, so a subscription outage delays events rather than losing them. See Chainhooks.