Skip to content

Domain State Machines

Guard duplicated from ARCHITECTURE §11.6 + §15.2 — ARCHITECTURE wins on conflict.

⚠️ SILENT DATA CORRUPTION: writing a status column directly (bypassing the transition check) lets an illegal transition through. State machines here are app-enforced — there is NO DB CHECK constraint backing them. The code is the only guard.

  • NEVER write a status/state column with a raw .set({ status }). Go through the transition helper for that machine.
  • Terminal states are immutable — reject any transition out of a terminal state.
  • Adding a state = update (1) the enum, (2) the allowed-transitions map, and (3) every switch over the machine. Use exhaustive switches (no silent default) so a new state fails to compile until handled.

Sesi — lesson_sessions.status (session_status enum)

Section titled “Sesi — lesson_sessions.status (session_status enum)”
REQUESTED → APPROVED → IN_PROGRESS → COMPLETED
REQUESTED → REJECTED (terminal)
APPROVED → CANCELLED | RESCHEDULED (terminal)
IN_PROGRESS → NO_SHOW_STUDENT | NO_SHOW_TUTOR (terminal)
  • Initial: REQUESTED.
  • Terminal: COMPLETED, REJECTED, CANCELLED, RESCHEDULED, NO_SHOW_STUDENT, NO_SHOW_TUTOR.
  • REQUESTED → APPROVED captures the pricing snapshot — see domain-pricing-snapshot.md.
  • → COMPLETED / → NO_SHOW_STUDENT auto-creates settlements — see domain-settlement.md.
  • Transitions live in the service layer (@packages/service sessions ops). Full spec: ARCHITECTURE §15.2.
PENDING_INTERVIEW → APPROVED → ACTIVE → SUSPENDED → ARCHIVED
  • Allowed transitions are per user_type — use canTransition(user_type, from, to) from packages/auth/src/state-machine.ts; throw InvalidStateTransitionError on a bad transition. Never assume the DB will catch it.
  • ARCHIVED is terminal (no data deletion — audit retention).
  • Iter 1: all users start ACTIVE; PENDING_INTERVIEW / APPROVED idle (see iter-boundaries.md). Full spec: ARCHITECTURE §11.6.
  • billing_periods.status: OPEN → CLOSING → CLOSED → LOCKEDLOCKED immutable. See domain-billing-period.md.
  • schedules.status: ACTIVE | PAUSED | ENDED.