← all branches

feat/ui-impact

needs attentionviewing older commit
c3c5121 · incrementalpre-PRreviewed 2026-07-24 15:17 UTC2H · 1M · 5L · 4I
The branch
Purpose
Energia module — per-org energy consumption analysis platform with anomaly detection, findings ledger, and comparison views, built on real Grupo Axo production CFE bill data for demo readiness
Goal
Ship a demo-ready Energia UI: Comparativo view (like-for-like consumption comparison), Demanda alerts wired to real findings API, real Grupo Axo data from production Supabase with proper anonymization
Sub-goals
  • SG-1: Detection engine — 8 corpus-verified detectors + runner
  • SG-2: Findings ledger domain entity and API (ts-rest, energia-entitled)
  • SG-3: UI screens — Hallazgos, Resumen, Demanda, Comparativo wired to real findings API
  • SG-4: Demo interactivity — real RPU, attributed colors, FP framing
  • SG-5: Comparativo dataset rebuild from real production Supabase bills (this commit)
The changes (whole branch)
What
Extended MonthPoint with exact/ps/pe fields to carry real CFE billing period dates where available. Replaced the synthetic Comparativo dataset (28 stores) with real Grupo Axo production data (23 stores from Supabase). Updated the CFE view to show actual Inicio/Fin dates ('—' when missing) instead of derived Frecuencia. Changed default store from t26 (no longer exists) to t02.
Why
The previous dataset used estimated data without real period dates. Pulling from production Supabase gives the Comparativo view real billing precision and surfaces the ~50% period-date coverage honestly, which builds demo credibility with analyst users.
Areas
apps/platform/src+64991domains/utility/src+48241packages/api/src+1491packages/database/src+1330docs/specs/energia-module-pr1-pr2.md+1220scripts/energia+1810
Blast
69 files, +25290/-4 across the whole branch. This commit touches only 2 files (+71/-76 lines) in the Comparativo route — isolated to the demo dataset and its UI rendering.
TEMP soft-launch bypass must be reverted before merge to main Real customer name in client bundle (PII boundary risk)
typecheck· tsc not in PATH on this runner (node_modules not installed); could not verify locallyci· No open PR for this branch — no CI signal availablecoderabbit· No .coderabbit.yaml in repo

Findings · 12

correctness1

high

<th> alignment guard uses removed 'Frecuencia' instead of 'Inicio'/'Fin'

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/page.tsx:315

The <th> className condition is `h === 'Periodo' || h === 'Frecuencia'` — 'Frecuencia' was removed in this diff; CFE view now emits 'Inicio', 'Fin', 'Días'. The <td> isText guard on line 324 was correctly updated to include 'Inicio' and 'Fin', but the <th> guard was not. Result: in CFE mode the 'Inicio' and 'Fin' column headers render `text-right` while the cells below are left-aligned (`font-medium`) — a visible header/cell alignment mismatch. Fix: change <th> condition to `h === 'Periodo' || h === 'Inicio' || h === 'Fin'` to match the <td> isText guard.

security2

high

Real customer name 'Grupo Axo' ships in the 'use client' bundle via JSDoc comments

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/_lib/realConsumption.ts:2

The JSDoc block says 'REAL Grupo Axo consumption series' and 'Pulled from PRODUCTION Supabase (org "Grupo Axo", read-only)'. This file is a 'use client' module; its source text ships in the Next.js client bundle. Any authenticated user who opens DevTools → Sources can read the customer's real name, defeating the store-label anonymization ('Tienda CDMX 01' etc.). Recommendation: replace 'Grupo Axo' with a codename (e.g. 'the reference portfolio' or 'Grupo A') so the bundle carries only anonymous attribution.

medium

Energia module intentionally ungated (TEMP) — real production data reachable by all authenticated users

apps/platform/src/lib/soft-launch.ts:50

Two '// TEMP: energia live for preview demo — revert before merge' comments at lines 50 and 57 intentionally exclude /energia from the soft-launch gate. This means the Comparativo page with real Grupo Axo kWh+tariff+dates data is accessible to every authenticated platform user, not just entitled orgs. The TEMP markers indicate this is known and pre-merge. Flagging as a pre-merge checklist item: restore the energia gate before this branch lands in main.

conventions2

low

Block comment in realConsumption.ts partially duplicates MonthPoint field comments

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/_lib/realConsumption.ts:1

The 19-line block comment is justified (data provenance and PII compliance are non-obvious). However, lines 11–18 partially repeat what the MonthPoint interface field comments (lines 26–29) already say about exact/derived dias. Consider trimming the block comment to just the provenance/PII declaration and the top-level dias caveat, and letting the field comments carry the per-field detail.

low

diasCell() '~N' approximation marker is not i18n-safe

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/page.tsx:47

The tilde prefix (~) is hardcoded. All user-facing strings should come from messages/{locale}.json per ui-patterns.md. Acceptable as a demo-internal shortcut for now; flag for when the Comparativo surface goes to production.

tests4

low

diasCell() has no unit test — the ~N export format is unguarded

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/page.tsx:47

diasCell() is a one-liner but its output appears in both the on-screen table and the CSV export. A two-case unit test (exact: true → number; exact: false → string starting with '~') would cost nothing and guard against accidental format changes affecting the WYSIWYG export contract.

info

MonthPoint extension is additive and type-safe — no existing tests affected

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/_lib/realConsumption.ts:23

No __tests__ files reference MonthPoint, realConsumption, or the comparativo route. anomaly.ts only reads .kwh, .dias, .ym — the new fields are invisible to the existing analysis logic. Extension is safe.

info

Removed store IDs (t26, t27, t28) are not referenced in any test fixture or seeded data

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/_lib/realConsumption.ts:50

A codebase-wide grep finds no references to t26/t27/t28 outside the changed file. Dataset replacement is clean.

info

No e2e coverage for the Comparativo route — existing gap, not new

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/page.tsx:109

The entire energia module has no e2e tests. The default store change (t26 → t02) and new column names are not tested. This is a pre-existing gap for the whole module, not introduced by this commit.

improvement3

low

'Tuple' type alias is positional and not self-documenting

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/_lib/realConsumption.ts:37

type Tuple = [string, number, number, boolean, string | null, string | null] carries no domain signal. A reader scanning the data tuples must cross-reference the S() destructuring to know position 3 = exact, 4 = ps, 5 = pe. Minimal fix: rename to BillTuple or add a JSDoc comment `// [ym, kwh, dias, exact, ps, pe]` to the alias.

low

ps/pe abbreviations reduce external readability of the MonthPoint interface

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/_lib/realConsumption.ts:29

ps and pe for period_start/period_end are explained in field comments, but using the abbreviation in the exported interface forces every consumer (page.tsx, future callers) to look up the docs. Consider using periodStart/periodEnd in the MonthPoint interface and keeping the short names only as destructuring aliases inside S().

info

No dead code from freq() removal detected

apps/platform/src/app/[locale]/(dashboard)/energia/comparativo/

freq() was not in ded4e61c — it was already removed before this incremental window. No orphan references to freq, Bimestral, or Mensual remain.

History · 15 commits

  1. 96ca7d7needs attentionincremental0H · 9M · 12L2026-07-25 16:40
  2. 25516f7needs attentionincremental5H · 7M · 8L2026-07-25 03:29
  3. a7f8d64needs attentionincremental0H · 4M · 5L2026-07-25 01:56
  4. 7fc4ef0needs attentionincremental2H · 6M · 8L2026-07-24 21:04
  5. 027e5eaneeds attentionincremental4H · 9M · 8L2026-07-24 20:04
  6. 95a101eneeds attentionincremental3H · 6M · 5L2026-07-24 16:09
  7. 5d0d186needs attentionincremental1H · 3M · 5L2026-07-24 15:36
  8. c3c5121needs attentionincremental2H · 1M · 5L2026-07-24 15:17current
  9. ded4e61needs attentionincremental2H · 3M · 9L2026-07-24 14:22
  10. 312a1f4needs attentionincremental1H · 4M · 4L2026-07-24 04:01
  11. b48af56needs attentionincremental1H · 6M · 6L2026-07-24 03:14
  12. 6d07cc8needs attentionincremental2H · 4M · 5L2026-07-24 00:50
  13. 261b55eneeds attentionincremental5H · 11M · 6L2026-07-24 00:38
  14. 5b8a252needs attentionincremental3H · 6M · 9L2026-07-24 00:19
  15. f29cc5bneeds attentionfull9H · 17M · 11L2026-07-23 23:07