Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
14 KiB
PRD — System-Managed Default Contract Cutover
- Slug:
system-managed-default-contract-cutover - Date:
2026-03-21 - Status: Draft
Summary
Replace unmatched/non-contract billing fallback behavior with a first-class, system-managed Default Contract per client. The default contract is created on-demand when billing configuration exists/gets created, but it no longer behaves like a user-authored recurring contract. Instead, it becomes a non-authorable attribution shell for unmatched time/usage, while billing windows come from the client billing schedule and pricing comes from default/service-catalog pricing. Client billing setup gains an optional historical bootstrap date so MSPs can backfill client billing cycles for back-dated billable work without corrupting invoiced history.
Problem
Today, unmatched work is represented as non-contract/fallback behavior across time-entry save paths, usage save paths, due-work collection, and invoice generation. That causes:
- inconsistent assignment outcomes across UI/save/invoice paths,
- ambiguous UX language (
non-contract,default rates) that does not match target business model, - fragile edge cases after multi-contract-per-client changes,
- complexity debt from fallback paths that should no longer be primary behavior,
- overloaded semantics where a system-managed default contract still looks like a recurring contract with start dates, cadence, and line authoring,
- unresolved back-dated billing gaps when a client receives billing configuration after historical work already exists and no historical client billing cycles have been established.
Goals
- Establish a single default-contract model for unmatched billable work.
- Make default contract creation deterministic and on-demand.
- Remove runtime non-contract fallback paths from normal billing flow.
- Make system-managed default contracts non-authorable, non-recurring attribution shells rather than quasi-normal recurring contracts.
- Bill unmatched default-contract work on the client billing schedule, not on default-contract cadence semantics.
- Support optional historical client billing-cycle bootstrap/backfill from a user-chosen date while preserving invoiced history.
- Keep behavior safe under multi-contract-per-client, date-effective resolution, and concurrent writes.
- Make UI language and controls explicit for system-managed default behavior.
Non-goals
- No redesign of contract pricing model itself.
- No new contract authoring UX beyond minimum surfaces needed for visibility/read-only constraints and historical client-cycle bootstrap.
- No broad billing overhaul unrelated to default-contract routing and client-schedule backfill for unmatched work.
- No attempt to make the system-managed default contract support recurring fees, contract cadence, or custom line authoring.
Users and Primary Flows
- Billing admin configures/updates client billing settings.
- Technician enters billable time or usage.
- System auto-resolves work to explicit contract line or system-managed default contract path.
- If the client has no historical billing cycles for back-dated work, billing admin optionally establishes a historical client billing bootstrap date from the client billing schedule UI.
- Billing admin generates invoices for unmatched work on the client billing schedule without manual non-contract fallback reconciliation.
UX / UI Notes
- Contract lists/detail surfaces show
System-managed defaultbadge and helper copy. - Destructive/manual lifecycle actions for system-managed default contracts are constrained, and authoring surfaces that would make them behave like normal contracts are hidden/disabled.
- System-managed default contracts do not expose recurring cadence, start/end date, contract-line authoring, pricing-schedule authoring, or service-period management as meaningful editable controls.
- Time-entry/usage copy uses
system-managed default contractlanguage instead ofnon-contract/default rates. - Automatic invoicing grouped rows distinguish explicit contract work from default-contract work using business labels.
- Client billing schedule UI may optionally collect a
Billing history start dateon first setup (and controlled edits before invoiced history) to backfill client billing cycles. - If required attribution metadata is missing for grouped generation, hard block generation for affected rows.
Requirements
Functional Requirements
- Introduce a system-managed default contract concept with deterministic identity per client+tenant.
- Create default contract on-demand when billing settings are first ensured/inserted for a client.
- Support idempotent default contract ensure under concurrent requests.
- Route unmatched billable time and usage to default contract resolution path.
- Default resolution must be effective-date aware (work date / usage date), not current-time-only.
- Shared eligibility resolver must be used by save-path assignment, UI default display, and billing engine reconciliation.
- Billing engine unresolved-path reconciliation must persist deterministic single-match assignment back to source records.
- Automatic due-work candidate generation should include only truly unresolved records (none/ambiguous), not resolvable single-match records.
- Invoice generation selection key logic removes non-contract fallback semantics and uses default-contract-aware selection semantics.
- Existing clients with billing settings but no default contract should get it lazily at first qualifying touchpoint.
- Deletion/cleanup rules remove default contract assignment artifacts when client lifecycle deletes billing configuration/client.
- Contract deletion/archival guards remain intact for already-invoiced paths.
- API/controller paths that bypass package-level cleanup must be reconciled so default-contract cleanup is not skipped.
- Schedule/settings updates that intentionally delete overrides (
nullsettings) must not accidentally recreate default contracts unless required by active billing configuration policy. - Add clear business-safe labels in UI for default-contract and unmatched work semantics.
- Preserve multi-contract-per-client behavior without reintroducing single-contract constraints.
- System-managed default contracts must not participate in recurring cadence/service-period generation.
- System-managed default contracts must not allow contract-line authoring, recurring cadence edits, pricing-schedule authoring, or user-managed assignment date edits.
- Runtime billing for unmatched default-contract work must use the client billing schedule for invoice-window timing.
- Runtime billing for unmatched default-contract work must use default/service-catalog pricing semantics rather than default-contract-authored recurring lines.
- Client billing schedule setup must support an optional historical bootstrap date used to generate historical
client_billing_cyclesfrom the containing billing-cycle boundary through the present. - Historical bootstrap date must normalize to the containing client billing-cycle boundary rather than trusting the raw user-entered date as the exact period start.
- Historical bootstrap/backfill must remain safe under invoiced-history constraints: uninvoiced historical cycles may be rebuilt, but invoiced cycles define the earliest locked boundary.
- If client billing cycles already exist and none are invoiced, moving the bootstrap earlier must regenerate historical cycles from the newly normalized boundary.
- If invoiced client cycles already exist, moving the bootstrap earlier than the earliest invoiced cycle start must be blocked with clear UI copy.
- Manual creation/bootstrap flows and automatic first-time billing-schedule setup must converge on the same cycle-generation rules so client-schedule history stays deterministic.
- Default-contract invoice history and UI attribution must remain meaningful even though the default contract no longer carries recurrence semantics.
Non-functional Requirements
- Deterministic behavior under concurrent write paths (no duplicate default contracts).
- No cross-tenant leakage.
- Backward-compatible migration path with nullable new pointers/flags where needed.
- Idempotent reconciliation jobs/actions.
- Clear observability logs for ensure/reconcile/route decisions.
- Historical client billing-cycle bootstrap must be deterministic for the same client/schedule/date inputs.
Data / API / Integrations
- Use existing
contracts+client_contractslifecycle as minimum durable footprint for default contracts. - Add schema support (if needed) for explicit system-managed marker and/or pointer from billing settings to default contract assignment.
- Enforce uniqueness constraint/index for one default contract per client+tenant lifecycle domain.
- Ensure existing migration conventions are followed with idempotent guards.
- Audit create/delete pathways:
- package actions,
- shared helper paths,
- API service/controller paths,
- integration-import create paths.
- Decide whether historical bootstrap date lives in
client_billing_settings, is derived ad hoc during setup, or is stored only as operational metadata after cycle creation. - Ensure client billing-cycle bootstrap uses the same anchor normalization helpers as normal cycle creation so historical cycles and future cycles stay continuous.
Security / Permissions
- Only authorized billing/contract roles can view/manage default contract details.
- System-managed fields are read-only where user edits could break invariants.
- No privilege escalation through API bypass flows.
- Historical bootstrap/backfill actions are restricted to billing-schedule management permissions.
Observability
- Structured logs for default contract ensure, resolution, and reconciliation outcomes.
- Metrics/counters (or equivalent trace markers) for:
- default contract created,
- default contract reused,
- unmatched resolved deterministically,
- unresolved ambiguous still requiring human action.
- Historical cycle bootstrap/backfill should emit structured markers for:
- bootstrap requested,
- normalized bootstrap boundary chosen,
- historical cycles created/regenerated,
- bootstrap blocked by invoiced-history boundary.
Rollout / Migration
- Hard cutover objective: remove fallback complexity in primary path.
- Schema/runtime shift: default contract becomes attribution shell, not a recurring contract authority.
- Schema migration first (nullable-safe) for any new client billing settings bootstrap metadata if persisted.
- Runtime on-demand ensure enabled behind migration-complete assumption.
- Reconciliation pass for existing null
contract_line_idrecords that have deterministic single match. - Clean up UI/API terminology and selection-key parsing after routing cutover is in place.
- Remove/gate obsolete default-contract recurring/service-period code paths after validation.
- Roll out historical client-cycle bootstrap behind deterministic invoiced-history guards.
Execution Order
- Finalize data/runtime model: system-managed default contract is an attribution shell with no recurrence authority.
- Implement shared default-contract ensure primitive (idempotent + concurrency-safe).
- Hook ensure primitive into all billing settings/schedule/cycle-anchor ensure/insert paths.
- Add client billing-schedule historical bootstrap model and deterministic boundary-normalization rules.
- Implement historical
client_billing_cyclesbootstrap/regeneration with invoiced-history guardrails. - Align resolver contract (
effectiveDate) and update all save/UI callers. - Remove default-contract participation from recurring cadence/service-period generation and authoring flows.
- Update unmatched-work invoice timing to consume client billing schedule windows plus default/service pricing semantics.
- Implement billing engine reconciliation write-back for deterministic single-match records.
- Update due-work collection and invoice generation to consume reconciled/default-contract-aware semantics.
- Update UI copy/constraints across contract list/detail, time entry banner, automatic invoicing rows, and client billing schedule.
- Implement deletion and orphan cleanup consistency across package actions + API service paths.
- Add migrations/tests, run high-impact integration suite, then remove obsolete fallback and default-contract-recurring code paths.
Open Questions
- Should default contract creation trigger on every billing-settings ensure event or only on explicit non-null billing configuration states?
- Should API generic delete be replaced with domain delete orchestration for clients, or should it call the same cleanup primitive?
- Do we store default-contract pointer on
client_billing_settingsdirectly, or infer by deterministic query each time? - Should historical bootstrap date be persisted as durable client billing metadata, or treated as an operational input that only shapes
client_billing_cyclescreation/regeneration? - Should unmatched default-contract work use only service-catalog default pricing, or can other tenant-wide default-pricing rules participate?
Acceptance Criteria (Definition of Done)
- For any client with active billing configuration, system can ensure exactly one default contract identity.
- System-managed default contracts do not act as recurring cadence/service-period authorities and do not expose normal contract authoring flows.
- New/updated billable time and usage resolve through effective-date-aware resolver, with deterministic assignment when possible.
- Unmatched default-contract work bills on client billing schedule windows rather than default-contract cadence.
- Billing admins can optionally define a historical bootstrap date on client billing schedule setup to create historical client billing cycles from the containing boundary through today.
- Historical bootstrap can be moved earlier only while preserving invoiced-history boundaries; unsafe backward moves are blocked clearly.
- Invoice due-work no longer surfaces deterministic single-match work as non-contract.
- Automatic invoicing flow does not depend on legacy non-contract fallback keys for normal operation.
- UI labels and action constraints reflect system-managed default contract semantics clearly.
- Client deletion and billing-config cleanup do not leave orphaned default contract assignment artifacts.
- Test suite covers core creation/routing/reconciliation/cleanup/bootstrap behavior with high-confidence scenarios.