Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

3.1 KiB

Recurring Service-Period Lifecycle

Purpose

F233 defines the first explicit lifecycle model for persisted recurring service-period records created in F231-F232.

This checkpoint defines:

  • what each lifecycle state means
  • which transitions are allowed now
  • which states are terminal for v1

This checkpoint does not yet define edit operations, regeneration conflict handling, invoice linkage, or corrective flows. Those remain sequenced behind F238-F254.

State Meanings

State Meaning
generated A future period created directly from source recurrence rules with no user override yet applied.
edited A future period whose boundaries or scheduling semantics differ intentionally from the generated default.
skipped A future period that remains on the ledger for auditability but is intentionally excluded from billing selection.
locked A period whose boundaries are frozen for an upcoming billing action or operational review and should not be changed by normal authoring paths.
billed A period that has already been consumed by invoice linkage and is immutable in normal v1 flows.
superseded A period revision that has been replaced by a newer record for the same logical period slot.
archived A period retained only for history, audit, or storage-management purposes and no longer participates in live operational flows.

Allowed Transitions

The v1 lifecycle contract is intentionally conservative:

  • generated -> edited | skipped | locked | billed | superseded | archived
  • edited -> skipped | locked | billed | superseded | archived
  • skipped -> edited | locked | superseded | archived
  • locked -> billed | superseded | archived
  • billed -> archived
  • superseded -> archived
  • archived -> no further transitions

Terminal States

The v1 terminal states are:

  • billed
  • superseded
  • archived

locked is not terminal. It is intentionally a pre-billing freeze state that still permits lifecycle advancement into billed, superseded, or archived.

Lifecycle Invariants

  • billed periods are immutable in normal v1 flows. Later corrective flows must create explicit follow-on behavior instead of silently mutating billed records in place.
  • superseded periods remain queryable for provenance but are no longer eligible for normal due selection.
  • skipped periods remain visible on the ledger; skip is not the same thing as deletion.
  • archived is a storage and audit state, not a billing state.
  • transitions that are not explicitly listed above are invalid for v1 and must fail fast rather than being interpreted implicitly by callers.

Authoritative Runtime Contract

The shared lifecycle transition contract now lives in:

  • shared/billingClients/recurringServicePeriodLifecycle.ts

That module exports:

  • RECURRING_SERVICE_PERIOD_LIFECYCLE_TRANSITIONS
  • RECURRING_SERVICE_PERIOD_TERMINAL_STATES
  • canTransitionRecurringServicePeriodState(...)
  • isRecurringServicePeriodStateTerminal(...)

Future regeneration, editing, skip/defer, and billing-linkage flows should consume that shared transition contract rather than open-coding state rules locally.