fix/job-active
needs attentionviewing older commitdf0ef09 · incrementalPR #314reviewed 2026-07-16 00:23 UTC0H · 2M · 3L · 2I- Purpose
- Live incident fix (Solfium, RPU 077120901845): status-blind LIMIT 1 query picked a terminated history row over the active contract, minting a junk site. This PR implements the RPU-agreements model: one active regime per RPU, contracts are immutable history chapters, and evidence-driven reactivation self-heals tariff-change inversions within one billing cycle.
- Goal
- Active-first RPU resolution everywhere + terminated-only RPU skip + evidence-driven reactivation swap with deduped attachment re-pointing (SUC + monitoring-sub + payment-sub).
- Sub-goals
- SG-1: findByContractNumberActiveFirst query adopted by job-intent shell (single + batch), cfe-jobs handler, wizard PATH-2, payment-status fallbacks
- SG-2: Terminated-only RPUs mint no site/SUC/subscriptions (evidence-driven, not intent-driven)
- SG-3: ReactivateContract decision + ensureContractFromBillsShell reactivation path with demotion + deduped attachment transfer
- SG-4: reassignContractIdDeduped on SUC + both subscription tables
- SG-5 (this commit): Guard demotion updateWithVersion return + close round-1 test gaps
- What
- Incremental (d4a8d845..df0ef093): one production guard in utility-contract.shells.ts (null-check on demotion updateWithVersion return), service_tariffs junction inserts in cfe-job-intent test beforeAll, four new integration test cases (payment-sub dedup, active-first terminated fallback, batch terminated-only skip, full shell reactivation swap), and two new findNewestXmlPeriodEndForRpu tests.
- Why
- Round-1 review identified: the demotion write could silently no-op on an OCC conflict, leaving two active contracts; service_tariff junctions were missing in the integration test setup causing tariff resolution to fail; key scenarios (batch skip, full swap with both sub kinds) lacked end-to-end coverage.
- Areas
- domains/utility/src/utility-contract+200−6domains/cross-domain/src/__tests__+143−2
- Blast
- 3 files, +348/-8 incremental. All test-file additions except one 8-line production guard. Zero API surface, zero schema, zero handler changes.
Findings · 7
correctness2
updateWithVersion WHERE clause omits version — OCC is unenforced
domains/utility/src/utility-contract/utility-contract.queries.ts:383
The WHERE clause is `WHERE id = $id` only. `currentVersion` is used in the SET clause (`version: currentVersion + 1`) but NOT in the WHERE filter. The guard added in this diff — `if (!demotedRow) return err(...)` — can therefore only fire if the row is hard-deleted mid-transaction, which never occurs in normal pipeline flow. It cannot detect a concurrent version bump. To make OCC work as described, add `.where(and(eq(utilityContracts.id, id), eq(utilityContracts.version, currentVersion)))` to the UPDATE. Pre-existing bug, but the new comment ('a silent null here would commit BOTH rows active') is misleading without this fix.
TerminateAndReplace demotion write lacks the same null guard
domains/utility/src/utility-contract/utility-contract.shells.ts
The TerminateAndReplace branch calls `await contractQueries.updateWithVersion(tx, oldContract.id, { status: 'terminated' }, oldContract.version)` and discards the return value without a null check (line ~924). If this update returns null, the new contract is still inserted while the old one remains active — the same two-active corruption the Reactivate branch guard is meant to prevent. The fix was applied selectively; the sibling branch has the same gap.
conventions2
databaseError('update') wrong semantic for an OCC / version-conflict case
domains/utility/src/utility-contract/utility-contract.shells.ts:873
When updateWithVersion returns null the correct cause is an OCC conflict or row-gone, not a database infrastructure failure. `ContractErrors.databaseError('update')` maps to statusCode 500 and `_tag: ContractDatabaseError`, but `ContractErrors.versionConflict(...)` (409) is the right type. This mislabels a business-level conflict as an infra error and will mislead handlers and on-call engineers reading logs. Pre-existing pattern elsewhere in the file, but the diff doubles down on it — if OCC is going to be enforced here, the error type should be corrected too.
Comment block is longer than convention requires
domains/utility/src/utility-contract/utility-contract.shells.ts:865
The four-line comment narrates what the code does and restates the PR's motivation. Project convention: only add a comment when the WHY is non-obvious, one short line max. The invariant being protected ('demotion null-check prevents two-active') could be a single line, or omitted entirely since the guard matches the pattern already established for the reactivation write above it.
tests2
OCC failure path on demotion write has no test coverage
domains/utility/src/utility-contract/__tests__/ensure-contract-evidence.integration.test.ts
The `if (!demotedRow)` branch in ensureContractFromBillsShell is never exercised. No test forces updateWithVersion to return null on the demotion call, so the transaction-rollback invariant (reactivation is also undone when demotion fails) is unverified. Once the WHERE clause is fixed to enforce OCC, a test should inject a version conflict on the demoted row to prove the atomic rollback.
uniq('TAR') in test body comment could mislead future readers
domains/cross-domain/src/__tests__/cfe-job-intent.integration.test.ts
Line `tariffCode: uniq('TAR'), // tariff 1's code — the terminated row's regime` is correct (uniq() appends the shared testTimestamp, so the string is identical to the one used in beforeAll). A reader unfamiliar with uniq()'s determinism might think a random new code is being generated. A note like '// same as beforeAll tariff1.code — uniq() uses fixed testTimestamp' would remove the ambiguity.
improvement1
demotedRow captured but value never consumed after null check
domains/utility/src/utility-contract/utility-contract.shells.ts:869
const demotedRow = await contractQueries.updateWithVersion(...) captures the returned entity, but the value is never used after the null guard — all downstream code uses the pre-fetched `demoted` object. Using `if (!await contractQueries.updateWithVersion(...)) { ... }` directly (or prefixing with `void`) would signal intentionally that the returned value is not needed.
History · 6 commits
- 3e1361aneeds attentionincremental0H · 1M · 0L2026-07-16 01:14
- c7b4e31needs attentionincremental0H · 1M · 5L2026-07-16 01:03
- 2099ea7needs attentionincremental0H · 3M · 5L2026-07-16 00:53
- ce2dc3eneeds attentionincremental0H · 1M · 1L2026-07-16 00:44
- df0ef09needs attentionincremental0H · 2M · 3L2026-07-16 00:23current
- d4a8d84needs attentionfull0H · 3M · 5L2026-07-16 00:04