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

2.4 KiB

Recurring Service-Period Regeneration

Purpose

F238 and F239 define the first regeneration algorithm for persisted future recurring service periods.

The v1 rule is intentionally conservative:

  • untouched generated future rows may be refreshed when source recurrence rules change
  • user-edited or repair-driven future rows must not be silently overwritten
  • replaced untouched rows become superseded
  • newly regenerated rows keep the logical slot identity by reusing the prior periodKey and incrementing revision

Authoritative Helper Surface

The shared v1 regeneration helper now lives in:

  • shared/billingClients/regenerateRecurringServicePeriods.ts
    • regenerateRecurringServicePeriods(...)

Regeneration Rules

The helper applies the following slot-order policy to future active rows on one schedule:

  1. Sort existing active rows and new candidate rows by service-period order.
  2. Preserve override rows instead of overwriting them. Override rows are currently:
    • provenance.kind = user_edited
    • provenance.kind = repair
    • lifecycle states edited, locked, or billed
  3. For untouched generated rows:
    • if the candidate row is equivalent, keep the existing row as-is
    • if the candidate row changed, write a new regenerated row that:
      • reuses scheduleKey
      • reuses periodKey
      • increments revision
      • points supersedesRecordId at the prior row
    • mark the prior row as superseded
  4. If an untouched existing future row no longer has any candidate slot, supersede it.
  5. If new candidate slots remain after existing future rows are exhausted, keep them as new generated rows.

Override-Preservation Rule

The first-cut override rule is explicit:

  • regeneration must not silently replace user-edited future rows
  • regeneration must not silently replace repair rows
  • candidate rows that would have occupied those preserved slots are discarded until a later explicit conflict-handling flow exists

This keeps v1 safe before the later conflict-resolution work in F249.

Deliberate Non-Goals For F238/F239

This checkpoint does not yet define:

  • operator-facing conflict queues when preserved overrides and new source rules diverge materially
  • bulk conflict resolution
  • per-field merge behavior between a user edit and a regenerated candidate

Those remain later follow-on work after the first preservation-safe regeneration path.