← all branches

feat/smarter-mrr

needs attentionviewing older commit
a4fbc2b · incrementalpre-PRreviewed 2026-08-08 00:42 UTC7H · 11M · 5L
The branch
Purpose
Measure Smarter (Energía Real) MRR accurately with an event-sourced pipeline instead of hardcoded Terraform locals.
Goal
Replace Phase 1 hardcoded $20/report rate and static FX with a Supabase-sourced rate + live FX snapshot, emitting revenue.smarter_mrr_snapshot events to PostHog.
Sub-goals
  • SG-1: custom-smarter plan as rate SOT in Supabase (unbound, never charged)
  • SG-2: live USD→MXN FX via open.er-api.com with frankfurter.app fallback
  • SG-3: shell-verified calculated bill count query (findCalculatedBillCountsByOrg)
  • SG-4: manual monthly refresh script (billing:smarter-mrr-refresh)
  • SG-5: daily mark in mrr-sync Lambda (section 10)
  • SG-6: event-sourced PostHog insights (smarter_mrr + smarter_mrr_calc_log)
The changes (whole branch)
What
Adds packages/billing/src/fx.ts (FX fetcher), smarter-mrr.ts (pure computation), database seed-smarter-rate.ts, manual refresh script, mrr-sync handler section 10, bill.queries.ts aggregate query, and PostHog Terraform insights/dashboard updates.
Why
Phase 1 hardcoded rate and FX in Terraform; a rate change required a TF apply. Event-sourced approach stores rate in Supabase (SOT), snapshots live FX at calculation time, and emits PostHog events so MRR is attributable to a specific rate+FX moment.
Areas
packages/billing+1190packages/database+990scripts/billing+1360services/billing+831domains/utility+420infra/posthog+1010packages/analytics+360
Blast
7 areas, +617/-1 lines. No DB migrations, no public API changes, no RLS changes. Lambda handler gains a new try/catch section that never fails the sync. Measurement-only.
billing external-api no-tests
CI· No CI checks available for pre-PR branchcorrectness· 2 high, 2 mediumsecurity· 3 medium, 1 lowconventions· 1 high, 2 mediumtests· 3 high, 2 mediumimprovement· 1 high, 2 medium, 1 lowseo· No apps/web files — self-skipped

Findings · 17

correctness4

high

COUNT(DISTINCT contract) semantics — assumes one bill per contract per month

domains/utility/src/bill/bill.queries.ts:2906

count(DISTINCT utilityContractId) counts unique contracts, not bills. Docstring says dedupe is delete+replace at (contract, period) so this should be invariant — but if that breaks, under-count is silent.

high

yearMonth derived from UTC — mismatch with Mexico-local CFE billing periods

scripts/billing/smarter-mrr-refresh.ts:27

currentYearMonth() uses getUTCFullYear/Month. Bills store Mexico-local month strings. At UTC midnight on month boundary these diverge. Same bug in mrr-sync.handler.ts.

medium

Double drizzle instance on same connection

scripts/billing/smarter-mrr-refresh.ts:42

drizzle(connection) called twice — once as `db` (unused) and once inline. Use one ORM instance.

medium

fetchUsdMxnRate has no timeout — can block Lambda indefinitely

packages/billing/src/fx.ts:13

Neither fetch call uses AbortSignal.timeout(). Hung external call consumes full Lambda invocation timeout.

security3

medium

No timeout + no rate sanity check on external FX fetch

packages/billing/src/fx.ts:6

Add AbortSignal.timeout(5000) and sanity range (5 < rate < 100 for USD/MXN).

medium

org_name emitted verbatim to PostHog — PII / confidential data leakage

scripts/billing/smarter-mrr-refresh.ts:90

Customer org name in PostHog event. Prefer emitting org_id only; resolve display name via group properties.

medium

Service-role all-orgs query without active/billable filter

services/billing/src/handlers/mrr-sync.handler.ts:445

findCalculatedBillCountsByOrg aggregates across every org. Add active org filter.

conventions2

high

Section 10 silently swallows errors — FCIS violation

services/billing/src/handlers/mrr-sync.handler.ts:438

Bare try/catch only logs to console.error. FCIS requires discriminated-union errors, not swallowed exceptions.

medium

fetchUsdMxnRate throws plain Error instead of Result<T, E>

packages/billing/src/fx.ts:1

ADR-016 FCIS requires discriminated-union errors. Return Result<UsdMxnRate, FxError>.

tests5

high

No tests for computeSmarterMrr pure function

packages/billing/src/smarter-mrr.ts:1

Pure function with boundary cases — zero tests added.

high

No tests for readSmarterUsdRate metadata parsing

packages/billing/src/smarter-mrr.ts:1

Parses unknown JSONB blob. All paths (null, wrong keys, happy path) untested.

high

No tests for fetchUsdMxnRate — injectable fetch unused

packages/billing/src/fx.ts:1

fetchImpl injectable for testing but no test exercises it. Primary, fallback, and both-fail paths all untested.

medium

No integration test for findCalculatedBillCountsByOrg

domains/utility/src/bill/bill.queries.ts:1

COUNT(DISTINCT contract) invariant needs a DB integration test.

medium

Section 10 has no test coverage for skip and FX-fail paths

services/billing/src/handlers/mrr-sync.handler.ts:438

No rate plan → skip; FX throws → swallowed. Both untested.

improvement3

high

No timeout on FX HTTP calls

packages/billing/src/fx.ts:1

Use AbortSignal.timeout(5000) on both fetch calls.

medium

yearMonth validation missing at query boundary

domains/utility/src/bill/bill.queries.ts:1

Add regex guard at entry so malformed values throw instead of silently returning 0 rows.

medium

Fallback FX error discards upstream cause

packages/billing/src/fx.ts:1

Include response body (first 200 chars) in error for faster production debugging.

History · 4 commits

  1. 37de5d2safeincremental0H · 0M · 2L2026-08-10 19:05
  2. af89f54needs attentionincremental1H · 2M · 9L2026-08-10 17:36
  3. a4fbc2bneeds attentionincremental7H · 11M · 5L2026-08-08 00:42current
  4. 4d95793needs attentionfull0H · 0M · 4L2026-08-07 19:28