Skip to content

State Machines (FSM)

These diagrams summarize core lifecycle rules. They are intentionally compact; see service docs for operation details and error tags.

User (UAS)

unverified -> verified <-> suspended -> doomed
      \-> doomed

Transitions:
- unverified -> verified (primary email verified + passcode set)
- verified <-> suspended (operator-only)
- unverified|verified|suspended -> doomed (operator-only, terminal)

Session (USM)

active -> doomed -> archived

Transitions:
- active -> doomed (close/expire/logout; revoke markers doom)
- doomed -> archived (sweeper/archiver job)
- no transitions out of archived

Org (OFM)

unverified -> verified <-> parked
     \         \-> suspended
      \         \-> frozen (operator-only)
       \-> doomed (operator-only)
frozen -> doomed (terminal)

Transitions:
- operator-only: unverified->verified, verified<->suspended, *->frozen, frozen->doomed, *->doomed
- owner-only: verified<->parked (48h cooldown)
- frozen blocks all tenant writes (operator break-glass only)
- doomed is terminal

Sales Channel (OFM)

draft -> active <-> inactive -> doomed
   \-> doomed

Transitions:
- owner-only: draft->active, inactive->doomed, draft->doomed
- active->inactive; inactive->active (owner-only)
- delegated members (facility-grant) may update drafts
- doomed is terminal

Product Revision (PMC)

offline -> online -> offline

Rules:
- each publish creates a new revision (immutable)
- only one revision can be online per product identity
- online/offline is the only mutable field

Transfer Request (ICS)

Transfer-level:
  requested -> submitted -> approved -> shipped -> received
                                                \-> received_with_exceptions

Shipment-level:
  shipped -> received
  shipped -> received_partial

Transitions (transfer-level):
- requested -> submitted (submit for approval)
- submitted -> approved (approval granted)
- approved -> shipped (first shipment recorded)
- shipped -> received (all shipments received, no exceptions)
- shipped -> received_with_exceptions (all shipments received, some exceptions)

Note: `received_partial` is a shipment-level status indicating a shipment was
received with partial quantities. The transfer itself remains `shipped` until
all shipments are resolved, then transitions to `received` or
`received_with_exceptions` depending on whether any exceptions occurred.

Inventory Promise (SCM ↔ ICS)

available -> reserved -> allocated -> committed
   \            \          \        /
    \------------> released --------

Rules and invariants:

  • Reserve creates a TTL-bound hold on available stock.
  • Allocate converts reserved quantity to a pick/fulfillment allocation (may be partial).
  • Commit finalizes consumption (irreversible; reduces on-hand).
  • Release returns reserved or allocated quantity to available (explicit or TTL expiry).
  • Partial fulfill: commit the fulfilled portion; remaining allocation must be released or reallocated.
  • Compensation paths: payment failure, approval failure, cancel-after-allocate, and return-after-commit must emit compensating ICS adjustments with source refs.
  • Reconciliation: ICS is the inventory source of truth; SCM adapts order state based on ICS confirmations (backorder/cancel/adjust), not the other way around.
  • Idempotency: each step must be idempotent and safe to replay; duplicates must not double-consume or double-release.

Sales Order (SCM)

draft/quote -> placed -> allocated -> fulfilled -> closed
   \-> cancelled
   \-> returned -> closed

Transitions:
- quote -> placed (accept/convert)
- placed -> allocated (inventory committed)
- allocated -> fulfilled (ship/pickup)
- fulfilled -> closed (financially settled)
- placed/allocated -> cancelled (policy)
- fulfilled -> returned (RMA flow)

Return / RMA (SCM)

requested -> authorized -> received -> inspected -> resolved

Transitions:
- requested -> authorized (RMA number issued, return approved)
- authorized -> received (merchandise physically received)
- received -> inspected (QC/condition assessment)
- inspected -> resolved (refund/exchange/credit issued, terminal)

Purchase Order (PCM)

draft -> approved -> issued -> partially_received -> received -> closed
   \-> cancelled

Transitions:
- draft -> approved (approval required by policy)
- approved -> issued (sent to vendor)
- issued -> partially_received (receipt recorded, not all lines fulfilled)
- issued -> received (receipt recorded, all lines fulfilled)
- partially_received -> received (subsequent receipt fulfills remaining lines)
- received -> closed (admin close / financial settlement)
- any state -> cancelled (policy)

Auto-transition: When pcm/receipt/record is called with a po_id, the handler
automatically transitions the PO based on cumulative received qty vs ordered qty.
A po-receipt-completed event is emitted when PO reaches "received" (consumed by
SCM for special order auto-arrival).

Price Rule / Promotion (PPM)

active -> ended

Transitions:
- Promotions are created as `active` by default (caller may override initial status)
- active -> ended (explicit end or effective window closes)
- No `draft`, `scheduled`, or `disabled` states exist in the current implementation
- Scheduling is handled via `effective_from` / `effective_to` date ranges, not via state transitions

Note: PPM uses temporal logic (effective_from/to date ranges) rather than explicit status
state machines. Promotions are created as active by default; their effective window determines
applicability. There are no draft/scheduled/ended status transitions in code.

Loyalty Account (CRM/Loyalty)

active -> suspended -> active
   \-> closed

Transitions:
- active -> suspended (fraud/abuse or policy)
- suspended -> active (reinstated)
- active|suspended -> closed (terminal)

Influencer Earnings (Influencer/Affiliate)

accrued -> held -> payable -> paid
   \-> clawed_back

Transitions:
- accrued -> held (hold period)
- held -> payable (cleared)
- payable -> paid (payout)
- held|payable -> clawed_back (return/fraud)