Skip to content

Numeric Input Limits

Requirement (2026-06): every numeric value sent from a client (FE/POS/BO) to a backend API is bounded. Out-of-bounds input is rejected with a clean HTTP 422 validation error — it must never reach the database (no numeric overflow 500s).

1. The Limits

KindApplies toMaxDecimalsDB equivalent
Monetary / valueamount, price, total, fee, discount value, balance, revenue, cost99,999,999,999.99994numeric(15,4)
Quantity / volumequantity, qty, volume, stock count, uom conversion9,999.99994numeric(8,4)

Rules:

RuleBehavior
Above max422 with field-level error message
More than 4 decimal places422 (input is rejected, not silently rounded)
Negative422 — all monetary/quantity inputs are non-negative unless the field explicitly documents otherwise
NaN / Infinity / non-numeric422
Exchange-rate fieldsKeep their dedicated precision (numeric(12,6) / numeric(19,6)) but are bounded at the validation layer the same way

2. Scope — where bounds are enforced

Bounds live in the Zod validation layer, via shared schemas in @nx/core (single source of truth — never re-declare per package). DB column precision is unchanged by this requirement.

Two input surfaces are covered — both must be swept per package:

  1. Explicit request schemasz.number() fields in models/requests/ and controller definitions.ts.
  2. CRUD-generated schemas — entities with decimal/numeric columns (and numeric fields inside jsonb) exposed through generic CRUD controllers; the generated insert/update schema accepts unbounded values unless overridden.

3. Rollout by package

PackageSurfacesStatus
coreshared schemas + jsonb numeric constants (sale-item discount, ledger book schemas)WK25
commerce18 CRUD controllers, lowStockThreshold, uom conversion ratiosWK25
saleshift cash fields, order quantity, 14 CRUD controllersWK25
inventorypurchase-order/voucher quantity & unit price (15 CRUD controllers)WK25
pricingfare/cost/tax/promotion-method amounts & quantities (9 CRUD controllers)WK25
financevoucher amount/exchangeRate, 5 CRUD controllersWK25
invoiceinvoice line quantity/price/amount/taxAmountWK25
ledgertax-tier revenueMin/Max, declaredAnnualRevenueWK25
taxationtax-group-item value (5 CRUD controllers)WK25
helpdeskcompensation.amountPending — package build is broken; item created when repaired
identity / signal / search / outreach / payment / asset / licensingpriority/pagination/count only — no monetary or quantity FE input found (audited 2026-06)No action

4. Boundary test matrix (for QA)

Run per endpoint that accepts a monetary or quantity field:

#InputExpected
1exactly 99999999999.9999 (money) / 9999.9999 (quantity)202/200 accepted
2max + 0.0001422, field named in error
3value with 4 decimal places (e.g. 12.3456)accepted
4value with 5 decimal places (e.g. 12.34567)422
5-1422 (unless field documents negative support)
60accepted (unless field requires positive, e.g. voucher amount)
7string "abc", null on required, 1e30422

A DB error / HTTP 500 on any of these = bug — the bound is missing at the validation layer.

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.