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
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
5.0 KiB
5.0 KiB
Scratchpad — Contract Template Normalization
- Plan slug:
contract-template-normalization - Created:
2026-03-16
What This Is
Keep a lightweight, continuously-updated log of discoveries and decisions made while implementing this plan.
Prefer short bullets. Append new entries as you learn things, and also update earlier notes when a decision changes or an open question is resolved.
Decisions
- (2026-03-16) Treat this as a new standalone ALGA plan rather than appending to
2026-03-16-client-owned-contracts-simplification. The earlier plan is implementation-specific and already largely shipped; this work is a broader normalization/cutover effort. - (2026-03-16) Sequence the work as runtime cutover first, API/UI separation second, schema cleanup last. Deleting legacy columns/rows before removing runtime fallback is unsafe.
- (2026-03-16) Treat template instantiation as the only legal transfer boundary between authoring data and runtime data. Existing contracts must be self-contained after instantiation, with no reverse sync from templates.
Discoveries / Constraints
- (2026-03-16)
packages/billing/src/lib/billing/billingEngine.tsstill resolves live contract lines throughcoalesce(cc.template_contract_id, cc.contract_id)and discount joins still usetemplate_contract_id OR contract_id. This is the primary runtime coupling to remove. - (2026-03-16)
shared/billingClients/templateClone.tsis already close to the target shape: it readscontract_template*tables and writescontract_*tables. The remaining question is whether template provenance should survive only as metadata. - (2026-03-16)
packages/billing/src/actions/contractActions.tsstill maps template rows intoIContract-shaped responses and falls back from contract lookup to template lookup. - (2026-03-16)
packages/billing/src/models/contractTemplate.tstemplate deletion still deletes from instantiated contract tables (contract_lines,contract_line_service_*,contract_line_services,contract_line_service_defaults). This is a hard coupling and a cleanup blocker. - (2026-03-16) The strongest framing for this plan is not just “remove legacy template flags,” but “make templates authoring-only assets and instantiated contracts self-contained runtime facts.”
- (2026-03-16)
server/scripts/verify-template-migration.tscurrently validates parity between legacy template rows incontractsand canonical rows incontract_templates, which means the operational model still assumes duplicated storage exists. - (2026-03-16)
server/scripts/contract-template-decoupling.tsstill preserves hybrid semantics by backfilling or relying ontemplate_contract_id. - (2026-03-16) Schema artifacts still present from the mixed model:
contracts.is_templatecontract_lines.is_templateclient_contracts.template_contract_id
- (2026-03-16) Citus / distributed-FK constraints are part of the sequencing risk. Some migrations intentionally avoided strict FKs, so application/runtime cleanup cannot assume the database enforces the final invariant today.
Commands / Runbooks
- (2026-03-16) Recon:
rg -n "is_template|template_contract_id|contract_templates|mapTemplateToContract|isTemplateContract\\(" packages/billing packages/clients server sharedsed -n '520,590p' packages/billing/src/lib/billing/billingEngine.tssed -n '1,220p' server/scripts/verify-template-migration.tssed -n '1,240p' packages/billing/src/actions/contractActions.tssed -n '120,210p' packages/billing/src/models/contractTemplate.ts
- (2026-03-16) Plan validation:
python3 /Users/roberisaacs/.codex/skills/alga-plan/scripts/validate_plan.py ee/docs/plans/2026-03-16-contract-template-normalization
Links / References
- Prior related plan:
ee/docs/plans/2026-03-16-client-owned-contracts-simplification/
- Key runtime files:
packages/billing/src/lib/billing/billingEngine.tsshared/billingClients/templateClone.tspackages/billing/src/actions/contractActions.tspackages/billing/src/models/contract.tspackages/billing/src/models/contractTemplate.tspackages/billing/src/repositories/contractLineRepository.ts
- Key migration / ops files:
server/migrations/20251020090000_contract_templates_phase1.cjsserver/migrations/20251020164500_backfill_contract_template_tables.cjsserver/migrations/20251020180500_update_client_contract_template_foreign_keys.cjsserver/migrations/20251028090000_remove_contract_line_mappings.cjsserver/scripts/verify-template-migration.tsserver/scripts/contract-template-decoupling.ts
Open Questions
- Should
client_contracts.template_contract_idremain as immutable provenance metadata, or should provenance move to a different field/table before full removal? - Are there production-only support or ops workflows still depending on legacy template rows living in
contracts? - Is there any externally consumed contract API that currently depends on template rows being presented as
IContractand needs a transition path?