# SIM Order & Lifecycle States This document stays in sync with the strongly typed lifecycle definitions that live in the SIM domain package. When workflow steps change, update the types first and then revise this doc so deployments, QA, and onboarding all use the same vocabulary. ## Core Types The lifecycle exports below are the single source of truth for state names and transitions. ```1:120:packages/domain/sim/lifecycle.ts export const SIM_LIFECYCLE_STAGE = { CHECKOUT: "checkout", ORDER_PENDING_REVIEW: "order.pendingReview", ACTIVATION_PROCESSING: "activation.processing", ACTIVATION_FAILED_PAYMENT: "activation.failedPayment", ACTIVATION_PROVISIONING: "activation.provisioning", SERVICE_ACTIVE: "service.active", PLAN_CHANGE_SCHEDULED: "planChange.scheduled", PLAN_CHANGE_APPLIED: "planChange.applied", CANCELLATION_SCHEDULED: "cancellation.scheduled", SERVICE_CANCELLED: "service.cancelled", } as const; export const SIM_MANAGEMENT_ACTION = { TOP_UP_DATA: "topUpData", CHANGE_PLAN: "changePlan", UPDATE_FEATURES: "updateFeatures", CANCEL_SIM: "cancelSim", REISSUE_ESIM: "reissueEsim", } as const; ``` - `SimLifecycleStage` — union of the keys above. - `SimManagementAction` — canonical action names referenced by BFF services, workers, and docs. - `SIM_ORDER_FLOW` — ordered list of activation transitions. - `SIM_MANAGEMENT_FLOW` — per-action transitions that describe how a request moves between states. ## Order + Activation Flow (`SIM_ORDER_FLOW`) | Step | Transition | Details | | ---- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | `checkout.createOrder`: `checkout → order.pendingReview` | `orderWithSkuValidationSchema` ensures the cart is valid before the BFF writes a Salesforce order. | | 2 | `orders.activateSim`: `order.pendingReview → activation.processing` | `SimOrderActivationService` locks the request (cache key) and kicks off billing. | | 3a | `payments.failure`: `activation.processing → activation.failedPayment` | WHMCS capture failed. Invoice is cancelled via `SimBillingService`, user must retry. | | 3b | `payments.success`: `activation.processing → activation.provisioning` | Payment succeeded; Freebit provisioning and add-on updates run. | | 4 | `provisioning.complete`: `activation.provisioning → service.active` | Freebit returns success, cache records the idempotent result, and the monthly WHMCS subscription is scheduled for the first of next month via `SimScheduleService`. | ## SIM Management Actions (`SIM_MANAGEMENT_FLOW`) All customer-facing actions execute through `SimActionRunnerService`, guaranteeing consistent notifications and structured logs. The table below maps directly to the typed transitions. | Action (`SimManagementAction`) | Transition(s) | Notes | | ------------------------------ | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | `topUpData` | `service.active → service.active` | One-time invoice captured through `SimBillingService`; Freebit quota increases immediately. | | `changePlan` | `service.active → planChange.scheduled → planChange.applied → service.active` | `SimScheduleService.resolveScheduledDate` auto-picks the first day of next month unless the user provides `scheduledAt`. | | `updateFeatures` | `service.active → service.active` | Voice toggles run instantly. If `networkType` changes, the second phase is queued (see below). | | `cancelSim` | `service.active → cancellation.scheduled → service.cancelled` | Default schedule = first day of next month; users can override by passing a valid `YYYYMMDD` date. | | `reissueEsim` | `service.active → service.active` | Freebit eSIM profile reissued; lifecycle stage does not change. | ## Deferred Jobs Network-type changes are persisted as BullMQ jobs so they survive restarts and include retry telemetry. - Enqueue: `SimPlanService` → `SimManagementQueueService.scheduleNetworkTypeChange` - Worker: `SimManagementProcessor` consumes the `sim-management` queue and calls `FreebitOrchestratorService.updateSimFeatures` when the delay expires. ## Validation & Feedback Layers | Layer | Enforcement | Customer feedback | | --------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | Frontend | Domain schemas (`orderWithSkuValidationSchema`, SIM configure schemas) | Immediate form errors (e.g., missing activation fee, invalid EID). | | BFF | `SimOrderActivationService`, `SimPlanService`, `SimTopUpService` | Sanitized business errors (`VAL_001`, payment failures) routed through Secure Error Mapper. | | Background jobs | `SimManagementProcessor` | Logged with request metadata; failures fan out via `SimNotificationService`. | Keep this file and `packages/domain/sim/lifecycle.ts` in lockstep. When adding a new stage or action, update the domain types first, then describe the change here so every team shares the same model.