feat/energia-det
safe67d4f5c · incrementalPR #308reviewed 2026-07-21 19:41 UTC0H · 0M · 1L · 1I- Purpose
- P1 of the Energía detection engine: the trigger-agnostic core that detects billing anomalies across all 10 corpus-verified detectors and writes idempotently into utility_contract_findings.
- Goal
- Ship the pure-function detector suite, the findings ledger domain entity (FCIS), and a manual runner so nightly incremental sweeps (a separate infra PR) can wire in later.
- Sub-goals
- 10 corpus-verified pure detectors (estimated_reading, fp_recompute_mismatch, fp_regime_change, inactive_service_charges, vat_recompute, dap_present, consumption_yoy_spike, fp_chronic_penalty, demand_overage_risk, demand_oversized)
- finding FCIS entity: type, errors, decisions, queries, shells, mapper, type-check
- utility_contract_findings migration with RLS + contract-access-chain isolation
- detect-findings.ts runner with parameterized SQL (injection fix)
- Integration tests: idempotency, outbox atomicity, cross-org isolation, findByContract contract/RLS isolation
- Soft-launch toggle for the Energía module (per-org)
- What
- This incremental window adds: (1) the database migration for utility_contract_findings, (2) two new integration test suites (outbox event atomicity, findByContract contract+RLS isolation), (3) barrel exports for tax-regime types and ContractActiveChapterRaceError. The SQL injection fix in the runner was already in the previous review snapshot (confirmed correct). The branch was rebased onto the merged #300 findings ledger after the prior review.
- Why
- Address #308 review findings: parameterise runner SQL (SQL injection vector, even with DB-sourced ids), add missing test coverage for the outbox invariant and the findByContract query that had no integration-level pin.
- Areas
- domains/utility/src/finding+3299−0packages/database+174−0scripts/energia+181−0apps/platform+67−3domains/core/src/organization+1−1docs/specs+122−0
- Blast
- 28 files, +18410/-5. Contained to the new finding entity + migration + runner script. No changes to existing bill/contract write paths. Platform changes are UI-only (sidebar + energia page scaffold behind soft-launch toggle).
Findings · 2
correctness1
Rebase drift — lastReviewedSha not an ancestor of HEAD
The ledger's lastReviewedSha (40b0c87) is from the pre-rebase history. After rebasing onto the merged #300, the fix commit became 67d4f5ca with a different parent chain. The guard `git cat-file -e` passes (dangling commit still in reflog) but `git merge-base --is-ancestor` would fail. The incremental diff window crossed rebase history, causing detect-findings.ts to be excluded from REVIEW_FILES (its tree content was identical in both SHA trees — SQL injection fix was already in 40b0c87). The SQL fix was confirmed correct in the prior review and is unchanged here. Operational note only.
conventions1
Missing trailing newline in migration SQL
packages/database/drizzle/0062_sloppy_ma_gnuci.sql:41
The file ends without a trailing newline after the ucf_select_member policy. Minor style issue; no functional impact but inconsistent with every other migration file in the repo.