feat(lib): pricing utility (RMP comparison subject) #6
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "test/rmp-compare-findings"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A small utility with genuine review issues, used as the A/B comparison subject for the quorum modules (exercises the arbiter/divergence + heterogeneous-leg paths). Throwaway — close after the comparison.
hib-pr-reviewer review — PR #6 (hib/hib-pr-reviewer)
Round 1 — head
0e8be4592a44, basemain, triggeropenedTL;DR: NEEDS_WORK — kept all 5 agreed findings (3 major, 2 minor) across four new exported functions; corrected one off-by-one line citation from reviewer B (line 27 → 28 for pickFirst return); no findings dropped.
Summary
All 5 findings verified against
/var/lib/pr-reviewer/repos/hib/hib-pr-reviewer/1527/src/lib/pricing.ts. Both reviewers agree on all five issues across the four exported functions. Line numbers confirmed:applyDiscountreturn at line 8,parseQuantityreturn at line 14,loadConfigfetch/json at lines 21-22,pickFirstreturn at line 28 (B cited line 27 — that is the comment line; corrected to 28). The14-resilience-and-config.mdrule on mandatory timeouts is confirmed in the checkout, substantiating theloadConfigmajor finding. Kept 5 agreed findings, corrected 1 line-number discrepancy, dropped nothing.Blast Radius
The diff is confined to a single new file (
src/lib/pricing.ts) with four exported functions. Because the functions are exported they form a new public API surface that any downstream module can import. The billing-correctness bugs (applyDiscountclamping,parseQuantityNaN) and the resilience violation (loadConfig) carry proportionally higher impact if callers are added before the issues are fixed.BLAST_SCORE: 4/10
Risk Indicators
loadConfig,applyDiscountCI status (head
0e8be4592a44)Overall: ✓ success
3 checks: 3 pending
Findings (5)
[MAJOR] applyDiscount: unclamped percentOff allows negative prices and silent price inflation
src/lib/pricing.ts:8
Line 8:
return priceCents - (priceCents * percentOff) / 100;percentOffis never validated before use:percentOff > 100yields a negative price (e.g.applyDiscount(500, 150)→-250).percentOffsilently raises the price rather than discounting it.Both are billing-correctness regressions in any production pricing context.
Fix:
[MINOR] applyDiscount: returns fractional cents due to floating-point arithmetic
src/lib/pricing.ts:8
Line 8:
return priceCents - (priceCents * percentOff) / 100;Floating-point arithmetic on integer cent values (e.g.
applyDiscount(999, 33)) returns669.33, not an integer. Monetary cent values must be integers; fractional values silently corrupt downstream arithmetic and integer database columns.Fix: Wrap the return value in
Math.round(…)(orMath.floorto always favour the merchant). The clamping fix above already incorporates this.[MAJOR] parseQuantity: missing radix and no NaN guard allow silent NaN propagation
src/lib/pricing.ts:14
Line 14:
return parseInt(raw);Two problems:
parseInt('010')can return8in engines that honour legacy octal notation; every major linter (and MDN) requires an explicit radix.parseInt('abc', 10)returnsNaNtyped asnumber, which propagates silently through all downstream arithmetic and comparisons.Fix:
Alternatively change the return type to
number | nulland let callers decide.[MAJOR] loadConfig: no response.ok check, no timeout, no try/catch — violates resilience rule
src/lib/pricing.ts:21
Lines 21-22:
14-resilience-and-config.mdexplicitly requires every external call to have a timeout. Three violations:response.okcheck — a 4xx/5xx response with a JSON body is silently cast and treated as valid config.Fix:
[MAJOR] pickFirst: empty array returns undefined typed as T — type-system lie
src/lib/pricing.ts:28
Line 28:
return items[0];When
itemsis empty,items[0]isundefinedat runtime, but the declared return type isT. TypeScript does not warn callers; they will dereferenceundefinedwithout a null-check and crash or corrupt state.Fix — Option A (throw on empty, empty is always a bug):
Fix — Option B (widen the return type, let callers decide):
Verdict
NEEDS_WORK
hib-pr-reviewer • round 1 • 5 findings (4M/1m) • 2026-06-03T06:49:50.684Z → 2026-06-03T06:50:38.960Z • posted-as: pr-reviewer-bot • model: auto
Pull request closed