Free learning / 50-minute financial amount-contract lab
Preserve the amount across a money contract
Execute unit and currency mismatches, actual JSON precision loss and explicit rounding policies. Give a receiving engineer exact amount evidence and the business rule still needing agreement.
No account needed. Use your own copy for writing and keep the original as a reference.
Engineering lab library / Run locally
Choose your next agent lab.
Start with the durable workflow reference, then choose the boundary you want to test. Open its walkthrough for setup, commands and expected observations.
Synthetic records. No provider key or model inference. Runs locally with the standard library.
Start here / Node.js 24 · Offline exercise
Exact money units, JSON and rounding contracts
Reproduce equal-number false matches, one lost JSON integer unit and mode/scope changes over unchanged calculation inputs.
Node.js 24 · Standard library · Synthetic nonnegative amounts · No financial writes or network
Original LockedIn Labs instruction · 50-minute financial data-contract lab · reviewed 27 October 2026.
Two systems send 12500. Do they agree? One means USD 125.00 in minor units; the other means USD 12,500 in major units. A numeric equality check passes while the business amount differs by a factor of one hundred. You will reproduce this failure, an actual JSON precision loss and four explicit rounding policies.
This is a read-only engineering workshop using synthetic nonnegative amounts. It creates no account, fee, posting or financial transaction. You need Node.js 24 and its standard library; no packages, credentials, database or network. Start with financial reconciliation if case, posting and credit meaning are new.
1. Name the amount before comparing it
An amount needs a currency, unit and exact representation. A major unit is the named currency unit; a minor unit is the scale used by the agreed currency contract. Scale is the number of decimal places represented. It is separate from a software number type's precision and the business policy for rounding.
| Payload meaning | Equivalent value in this fixture | Required context |
|---|---|---|
USD major 125.00 | USD minor 12500 | Currency USD, scale 2 |
JPY major 125 | JPY minor 125 | Currency JPY, scale 0 |
KWD major 1.234 | KWD minor 1234 | Currency KWD, scale 3 |
These three minor-unit facts were checked against SIX's ISO 4217 List One, published 17 September 2026. They are a bounded authored snapshot, not a complete or automatically updated currency service. Provider APIs and product contracts may impose additional scale or settlement rules. Never infer a universal “multiply by one hundred” rule or perform an implicit currency conversion.
The runner accepts exactly amount, currency and unit. The amount is a canonical decimal string; the unit is explicitly major or minor. Minor-unit strings must be integers. This fixture rejects signs, exponent notation, commas, leading zeros, unsupported currency and excess fractional places. Those choices are its interface contract, not the grammar of every financial API.
2. Follow representation and policy separately
For ordinary bounded integers, JavaScript Number can be exact. Its binary floating-point representation does not exactly represent every decimal fraction, and integers above its safe range can become indistinguishable. An exact decimal string can preserve the original digits at an API boundary; a parser still needs bounds, currency, scale and validation before it can use them.
The lab converts validated strings into BigInt minor units. BigInt performs integer arithmetic; it does not invent currency meaning, decimal policy, authorization or a financial ledger. Do not convert an already-rounded Number to a string and assume its lost digits returned.
The visual has six original frames grounded in actual Node.js results. The browser explains those observations; download the program to execute them. The written ledger below keeps the same distinctions available without the map.
UNDERSTAND THE SYSTEM
A matching number can carry a different amount
Six original frames explain actual Node.js parser and arithmetic observations. The browser does not execute the downloadable money lab or select a real financial policy.
Watch one example, step by step.
Read the full worked example
- 011 · Currency scale is part of the data
Actual normalization maps USD 125.00 to 12500 minor units, JPY 125 to 125 and KWD 1.234 to 1234. The checked scales are 2, 0 and 3. USD 0.005 is refused by the amount-field contract rather than silently rounded.
EXPLICIT CURRENCY SCALE: USD 2 · JPY 0 · KWD 3 · excess fractional digits refused
- 022 · Equal raw digits can mean unequal money
Both raw inputs say 12500, so a Number-only equality test passes. USD minor means 125.00; USD major means 12500.00 and normalizes to 1250000 minor units. The guarded comparison reports amount_mismatch.
UNIT MISMATCH: 12500 minor ≠ 1250000 minor under USD
- 033 · Equal units do not exchange currency
USD minor 12500 and JPY minor 12500 also pass raw numeric equality. The guarded result is currency_mismatch. No exchange rate or conversion policy is invented from matching integer counts.
CURRENCY MISMATCH: Equal raw count · different currency identity
- 044 · Exact digits can be lost before validation
The actual Number sum is 0.30000000000000004; exact string normalization yields 30 USD minor units. Separately, JSON's numeric 9007199254740993 parses as 9007199254740992. Wrapping that Number in a string or BigInt preserves the loss, while the original string keeps its digits.
ACTUAL RUNTIME PRECISION: One minor unit lost in the numeric JSON path
- 055 · Rounding has more than one decision
Three intermediate USD 0.005 values produce three cents with half-up per line, but two cents with half-up after totaling. Half-even per line produces zero cents; half-even after totaling produces two. The fixture computes each policy without choosing one for a real fee.
DECLARED MODE AND SCOPE: half-up line 3 · total 2 · half-even line 0 · total 2
- 066 · Change one policy and preserve the rest
Change only --rounding-mode to half-even: the selected line result becomes 0 rather than 3 minor units. From the original, change only --rounding-scope to total: it becomes 2. Other five cases remain unchanged. Retain original and changed outputs for the receiving engineer.
CONTROLLED POLICY CHANGE: Exact arithmetic still needs agreed financial meaning
Read the connections in plain English
- 01Original amount bytes → Currency + unit
Currency and unit give the original digits their amount meaning.
- 02Currency + unit → Exact normalized amount
Normalization follows the declared currency scale and unit.
- 03Original amount bytes → Number observation
This deliberately unsafe branch executes real Number parsing and arithmetic.
- 04Number observation → Receiving contract review
An exact integer wrapper after loss still contains wrong source digits.
- 05Exact normalized amount → Declared rounding policy
Higher-precision intermediates need a separately declared rounding contract.
- 06Declared rounding policy → Receiving contract review
The receiving owner must agree mode and scope; output convenience is not authority.
- 07Exact normalized amount → Receiving contract review
Keep both currency identity and exact normalized minor units.
Check your understanding: Does switching a parsed Number to BigInt restore the original JSON integer?
No. The numeric JSON token 9007199254740993 already became 9007199254740992. Conversion afterward retains that wrong value. Preserve the original exact representation through the producer and consumer contract, then validate currency, unit, bounds and any explicit rounding policy.
3. Run six amount-contract comparisons
Download the money-contract runner. Keep original and changed reports separately:
node --version
node fde-money-contracts.mjs > money-original.json
node fde-money-contracts.mjs --rounding-mode half-even > money-even.json
node fde-money-contracts.mjs --rounding-scope total > money-total.jsonThe runner uses actual JSON.parse, Number operations and BigInt arithmetic. It is a bounded teaching parser for nonnegative inputs, not a production money library. node_version records the runtime. All exact integer results in the report are serialized as strings so reporting does not reintroduce Number loss.
The written ledger
| Case | Deliberately unsafe observation | Guarded or explicit-policy observation |
|---|---|---|
currency-scale | Assuming every currency has two decimal places loses meaning | USD 125.00 → 12500; JPY 125 → 125; KWD 1.234 → 1234 |
unit-mismatch | Raw Number values both equal 12500 | USD minor 12500 differs from USD major 12500, which is minor 1250000 |
currency-mismatch | Raw Number values again match | USD and JPY remain different currencies; no FX conversion occurs |
binary-arithmetic | 0.1 + 0.2 produces 0.30000000000000004, unequal to 0.3 | Exact string inputs become 10 + 20 = 30 minor units, USD 0.30 |
json-integer | Numeric token 9007199254740993 parses as 9007199254740992 | Original string preserves 9007199254740993; one minor unit was lost on the Number path |
rounding-policy | “Round the fee” omits mode and aggregation scope | Three intermediate USD 0.005 values yield different explicitly calculated policies |
Inspect json-integer.numeric_wire, parsed_number_text and converting_after_loss. The strict interface refuses the Number input, but converting that rounded value to a string afterward still supplies the wrong digits. Validation cannot reconstruct source information already discarded. The original string must survive the producer, transport, parser and storage contract together.
A USD major amount of 0.005 exceeds this currency-scale contract. It is refused rather than silently rounded. The separate rounding exercise explicitly declares higher-precision intermediate values and a policy for producing final minor units. Distinguish an invalid amount field from an authorized calculation input.
4. Make rounding mode and scope reviewable
The fictional calculation has three nonnegative intermediate values, each USD 0.005. They use scale 3 until conversion to scale-2 USD cents. No real fee rule, regulatory interpretation or recommendation is supplied.
Half-up rounds a nonnegative exact halfway value upward. Half-even rounds a halfway value toward an even retained integer. Line scope rounds each input first and then adds the minor units. Total scope adds the exact intermediates first and rounds once. Both choices must come from the responsible business contract; the smaller or more convenient result is not automatically correct.
| Mode | Scope | Actual selected minor units | USD display |
|---|---|---|---|
| half-up | line | 3 | 0.03 |
| half-up | total | 2 | 0.02 |
| half-even | line | 0 | 0.00 |
| half-even | total | 2 | 0.02 |
The default selects half-up/line. Change only the mode and predict 0 rather than 3; change only the scope from the original and predict 2. All other five cases retain their inputs and results. alternatives calculates all four policies for comparison. line_minor_if_rounded is a hypothetical per-line view; for total scope, those values are not added to produce the selected amount.
The rounder handles only nonnegative thousandths-to-cents in this exercise. Negative adjustments, reversals, tax, FX, cash rounding and residual allocation require their own agreed rules and tests. A display formatter must not silently become the accounting calculation.
5. Receive the amount contract as an enterprise pod
Use builder, application/ledger owner and receiving engineer roles. Combine roles explicitly for smaller groups; label solo work self-review. The receiver chooses one changed policy, makes a prediction first and reproduces it without author takeover. Each person retains their own evidence and assistance.
| Role | Receiving responsibility |
|---|---|
| Builder | Locate exact input bytes, parser version, normalized units and the earliest point where precision could be lost |
| Application/ledger owner | Agree currency metadata, amount sign/direction, units, precision, rounding mode/scope and treatment of unresolved differences |
| Receiving engineer | Reproduce one mismatch and one controlled policy change, then return an observation with its remaining contract question |
| Platform/integration owner | Verify actual serializers, database types, consumers, limits and deployed source/version coverage before adoption |
My role / exact runner and command:
Prediction before the comparison:
Original wire digits / type / currency / unit:
Normalized minor units / source scale and version:
Observed mismatch or actual selected rounding policy:
One changed condition / prediction before that run:
Changed observation kept separately:
Receiving action actually attempted / assistance:
Unresolved contract / next accountable role and bounded action:Matching amounts do not prove the same transaction, posting state, credit kind or case outcome. Carry the amount evidence into the existing reconciliation contract; retain any exception for its authorized owner. A local run is not an independent review, qualification, client placement decision or permission to post money.
6. Defend the boundary in an interview
Why can 12500 === 12500 be a false business match? Why can converting Number to BigInt after JSON parsing preserve the wrong integer? Why does exact integer arithmetic still need currency and rounding rules? Which consumer or storage change would invalidate your proof? Answer using the recorded inputs and results.
Primary references checked 27 October 2026:
- SIX ISO 4217 currency metadata and current lists, including List One XML.
- ECMAScript Number safe-integer behavior.
- RFC 8259 number interoperability.
The parser, fixture policies and examples are original LockedIn Labs instruction. Continue with financial reconciliation and its protected Academy lesson under existing training access.