← all branches

feat/tax-regime

needs attention
a1f0898 · incrementalPR #302reviewed 2026-07-13 20:37 UTC1H · 1M · 4L · 5I
The branch
Purpose
Per-contract IVA tax regime for calculated bills — fixes northern-border sites being overtaxed at 16% instead of the correct 8% (IVA Frontera Norte).
Goal
Wire a data-driven tax_rates table and per-contract taxRegime column through the billing pipeline so THOR and CFE baseline/grid calculated bills apply the correct IVA rate.
Sub-goals
  • SG-1: Add tax_rates table + TAX_REGIMES/TAX_REGIME_RATES constants; seed iva=0.16, iva_frontera=0.08
  • SG-2: Thread taxRegime through utility-contract type, mapper, CreateContractCommand, insert
  • SG-3: NaN-proof resolveTaxRate + findRateByCode; integrate into computeBillShell + persistBillForContract
  • SG-4 (this commit): NaN parity for findAllRates + DB CHECK constraint rate∈[0,1]
The changes (whole branch)
What
findAllRates now filters non-finite rates (matching findRateByCode's existing guard). New Drizzle CHECK constraint `tax_rates_rate_range` enforces rate ∈ [0,1] at the DB layer. JSDoc and test comment updated for clarity.
Why
Loop-review prior pass flagged that findAllRates lacked the isFinite guard present in findRateByCode, creating a parity gap where a bulk-pricing caller could silently get NaN rates. The CHECK constraint closes the DB-level gap that the app-layer guard was masking.
Areas
domains/utility/src/tax-rate+653domains/utility/src/utility-contract+553domains/cross-domain+534packages/database/src/schema+581packages/database/drizzle (migrations)+130packages/database/src/seed-tax-rates.ts+390packages/api+72
Blast
Billing correctness for northern-border sites (calculated bills only — scraped CFE recibos read real IVA from bill XML and are unaffected). 14 code files across utility-domain, cross-domain, database, and api packages; drizzle snapshots dominate the line count.
financial-correctness migration-deploy-risk
CI· No CI checks registered on PR 302coderabbit· No .coderabbit.yaml present

Findings · 11

correctness3

low

CHECK constraint will fail migration if existing rows have out-of-range rates

packages/database/drizzle/0060_needy_menace.sql:1

ALTER TABLE … ADD CONSTRAINT validates all existing rows at migration time. If any row has a rate stored as a percentage (e.g. 16 instead of 0.16), the migration fails. This surfaces a latent data bug, which is desirable, but is a deploy risk that should be confirmed against staging data before prod.

info

findAllRates silently drops non-finite rows with no observability

domains/utility/src/tax-rate/tax-rate.queries.ts:30

A seed or admin error inserting a non-numeric rate will silently cause that regime to fall back to 16% on all bills with no log or alert. The CHECK constraint makes this structurally impossible going forward, but a console.warn or structured log for dropped rows would aid debugging during migrations.

info

Migration file missing newline at EOF

packages/database/drizzle/0060_needy_menace.sql:1

Diff shows '\No newline at end of file'. Cosmetic; does not affect SQL execution or migration runners.

security1

low

source:'default' fallback — confirm caller surfaces over-taxation to user

domains/utility/src/tax-rate/tax-rate.decisions.ts:24

When a code is absent from both the DB table and TAX_REGIME_RATES, resolveTaxRate returns source:'default' (16%). If the caller does not act on this flag before issuing a calculated bill, a border-rate site could be silently overtaxed. Confirm the calling shell checks source:'default' and rejects or flags the bill.

conventions2

low

Stale describe block title still references bare '0.16'

domains/utility/src/tax-rate/__tests__/tax-rate.decisions.test.ts:9

The describe string 'resolveTaxRate — table → constant → 0.16' hard-codes the default rate. The JSDoc was updated to say 'TAX_REGIME_RATES.iva (the standard-16% default)'; the test title should follow to avoid divergence if the constant changes.

info

NaN-filter in query layer is a convention smell — belongs in decision/shell

domains/utility/src/tax-rate/tax-rate.queries.ts:25

FCIS convention: thin query wrappers surface data faithfully; guard logic (treat-as-miss) belongs in the decision layer or shell. The CHECK constraint makes non-finite DB rows impossible going forward, so this filter is purely defensive. Acceptable here given the safety motivation, but worth noting the pattern deviation.

tests3

high

findAllRates NaN-filter has no test coverage

domains/utility/src/tax-rate/tax-rate.queries.ts:27

The isFinite guard added to findAllRates is the primary behavioral change in this commit, but no test — unit or integration — exercises it. A test should inject rows containing non-finite numeric strings ('NaN', '', null-coerced) and assert they are dropped from the returned map while finite rows survive. Without this the guard can be silently removed with no regression signal.

medium

No integration test for findAllRates happy path

domains/utility/src/tax-rate/__tests__/tax-rate.queries.test.ts

findAllRates has no integration test for the happy path. A DB-level test seeding two valid rows and asserting the returned Record matches expected code→rate pairs would document expected behaviour and provide a regression harness for future schema changes.

low

Comment-only test change adds no executable assertion

domains/utility/src/tax-rate/__tests__/tax-rate.decisions.test.ts:11

The added comment claims the behavior holds for 'any code with a row, including a hypothetical exempt (0%) code not in TAX_REGIMES'. A second expect with an arbitrary unknown code + finite DB row would make this a proven invariant instead of prose.

improvement2

low

map+filter two-pass could be a single reduce

domains/utility/src/tax-rate/tax-rate.queries.ts:25

rows.map(...).filter(...) iterates twice. A reduce combines them and eliminates the 'as const' cast: rows.reduce<Record<string,number>>((acc,r)=>{ const n=Number(r.rate); if(Number.isFinite(n)) acc[r.code]=n; return acc; },{}). At 2-10 rows this is cosmetic, but the intent reads more directly.

info

Inline test comment is implementation-level, not intent-level

domains/utility/src/tax-rate/__tests__/tax-rate.decisions.test.ts:10

The comment explains internal dispatch logic rather than observable caller behavior. Reframing as: 'a code absent from TAX_REGIMES but present in the DB still resolves via table — forward-compatible with new regime codes' would be more useful to a future reader.

History · 6 commits

  1. a1f0898needs attentionincremental1H · 1M · 4L2026-07-13 20:37current
  2. a72b534safeincremental0H · 0M · 0L2026-07-13 19:28
  3. 92e5afaneeds attentionincremental1H · 1M · 8L2026-07-13 16:47
  4. 7f40d56needs attentionincremental1H · 4M · 5L2026-07-13 16:38
  5. 5088e00needs attentionincremental3H · 4M · 4L2026-07-13 02:47
  6. 1bda877blockedfull12H · 12M · 9L2026-07-13 02:30