Platform
One kernel, three places to run it
Every engine stands on the same small core of arithmetic, receipts and checks. The core runs in a browser, at the edge and inside your own estate, and returns the same answer to the last bit in each.
Kernel
A kernel small enough to read
Everything regulatory sits on 23 files. 10 are arithmetic and bookkeeping that every engine needs, and 13 carry a regime. A reviewer can read the foundation in an afternoon, and that is the point.
- Foundation, 10 files
- Market risk and margin
- Insurance and reinsurance
- Investor disclosure
- Environment and mobility
- Cryptographic assurance
23 files, 8,058 lines. The area of a block is the length of its file.
-
Only the four operations
IEEE 754 fixes the result of add, subtract, multiply and divide to the last bit, on every machine. It does not fix exp or ln, so a browser and a server can disagree in the last digit. The kernel builds its own from the four operations that are exact.
-
Sums run in order
Adding floating point numbers in a different order gives a different answer. Every sum in the kernel runs from the first input to the last, so the same inputs always meet the same rounding.
-
Nothing outside the inputs
No clock, no network, no storage, no unseeded randomness. A test reads every file and fails if one of them reaches for any of these. A calculation that cannot look outside itself cannot be changed from outside.
-
Exact where it is cheap
Whether a correlation matrix is valid is a yes or no question, and rounding can flip it. The kernel checks it with exact fractions, from a certificate that a faster program produced and a short program verifies.
Read what every file does Hide the files
| File | What it does | Lines |
|---|---|---|
| Foundation Arithmetic and bookkeeping that every engine uses. 10 files, 1,093 lines. | ||
dmath.ts | exp, ln, cube root and sine and cosine in degrees, built from add, subtract, multiply and divide alone, so that every engine returns the same bits. | 157 |
rational.ts | Exact fractions on big integers, for checks that cannot afford a rounding error. | 116 |
linalg.ts | Vectors, matrices and an eigenvalue solver. Every sum runs from left to right. | 123 |
rng.ts | Random streams that start from a seed and replay exactly. | 83 |
receipt.ts | The canonical text of a result, with numbers as bit patterns, and its SHA-256. | 35 |
trace.ts | A calculation that returns its own provenance: a value, an exact share and a clause at every node. | 41 |
apportion.ts | Rounds a column of figures so that it adds up to its total. | 36 |
aggregate.ts | The correlation rule behind most capital, the square root of c transposed R c, with exact additive shares. | 43 |
certify.ts | Checks that a matrix is positive definite, in exact arithmetic, from a certificate a producer hands over. | 69 |
parity.ts | The fixtures that every engine runs, so their receipts can be compared. | 390 |
| Regimes One file for each regime that the kernel carries. 13 files, 6,965 lines. | ||
frtb.ts | FRTB standardised approach, GIRR delta, with an exact allocation to each risk factor. | 376 |
priips.ts | PRIIPs market risk: the VEV from a Cornish-Fisher expansion and the MRM class. | 202 |
solvency.ts | Solvency II standard formula at the top level: the basic SCR from five modules, then the SCR. | 143 |
entropy.ts | Health tests and the min-entropy estimate for a noise source, in the style of NIST SP 800-90B. | 231 |
pqc.ts | Key and signature sizes from the formulas of FIPS 203, 204 and 205, and a migration plan that orders uses by the latest year each can start. | 876 |
aermod.ts | A textbook plume, five years of illustrative hourly weather, and the forms of four standards of 40 CFR Part 50 that turn hours of concentration into a design value. It is not AERMOD, which the product runs. | 973 |
reserving.ts | The chain ladder on a run-off triangle and the standard error that Mack derived from it, with a reader for a triangle pasted from a sheet. | 279 |
curve.ts | The risk-free curve of EIOPA: the Smith-Wilson fit that built it until the framework changes, the closed form from the first smoothing point that builds it after, the bootstrap of swap rates, and the ultimate forward rate of the year. | 790 |
sacva.ts | The standardised approach to credit valuation adjustment risk of MAR50: weighted sensitivities, the capital of a bucket with the hedging disallowance, the capital of a class across buckets, and the part of the capital that rests on each risk factor. | 515 |
ics.ts | The standard method of the Insurance Capital Standard: the charges of the risks put together in three levels, the operational charge, the tax effect, the non-insurance charge, and the limits on the capital resources that count. | 840 |
simm.ts | The delta margin of the ISDA standard initial margin model on a calibration of our own: net sensitivities, risk weights, concentration factors, buckets, risk classes and product classes, the part of the margin that rests on each risk factor and each trade, and the comparison of two portfolios line by line. | 1,106 |
wltp.ts | WLTP cycle energy, road load, CO2 interpolation and the declared figure. | 496 |
wltc.ts | The class 3b test cycle, second by second, with the checksums that prove it was copied right. | 138 |
Receipts
Every number comes with a receipt
A receipt is the SHA-256 of a canonical text of the inputs, the rules and the result. Two runs agree if and only if they agree on every bit. You do not have to take our word for that. The panel below builds one, and lets you break it.
Fig. 1 A receipt, taken apart
Verifying receipt
1 What went in
Present value
1148.0803695672707
The first 15 digits are where most programs stop. The stored number has more, and the receipt covers all of it.
2 What is hashed
The inputs and the result, written the same way on every machine. Keys are sorted. Each number becomes the 16 hex digits of its IEEE 754 bit pattern, so no engine's number formatting can change the text.
{"inputs":{"cashflows":[f64:4059000000000000, f64:4059000000000000, f64:4091300000000000], "ratePercent":f64:4012000000000000, "years":[f64:3ff0000000000000, f64:4000000000000000, f64:4008000000000000]}, "kind":"present-value", "result":f64:4091f0524c665c16}Result as stored: 4091f0524c665c16
3 What comes out
The SHA-256 of that text. Change anything, even one bit, and the digest is unrecognisable.
01cb05ef1a8b46f414173d0a332e117258339dfa6b1b2c48ec9e97bc3c95c5a5
This is the receipt that was made when the page was built.
Each square is one bit of the 256. A lit square differs from the receipt made when the page was built.
-
It is not a signature
A receipt shows that a calculation reproduces. It does not say who ran it, or when. It is evidence about arithmetic and nothing more.
-
It does not vouch for the inputs
Wrong inputs give the same wrong answer every time. What a receipt removes is the question of whether two machines did the same arithmetic.
-
The rules travel with it
The prescribed parameters are part of the text that is hashed. When a standard changes a number, the receipt for the same inputs changes too, and an earlier release still reproduces the earlier one.
Parity
The same bits on every engine
Each run of the parity check feeds the same 24 fixtures to 5 JavaScript engines and compares their digests. A single differing bit fails it. We run it before every release, and the table is what the last run measured.
| Engine | Version | Receipt (first 24 of 64 hex digits) |
|---|---|---|
| Node.js | 25.2.1 | 127dcc3b f60e7fee 1f72740e |
| workerd (Cloudflare Workers) | 1.20261023.1 | 127dcc3b f60e7fee 1f72740e |
| Chromium | 156.0.8078.4 | 127dcc3b f60e7fee 1f72740e |
| Firefox | 157.0 | 127dcc3b f60e7fee 1f72740e |
| WebKit | 27.2 | 127dcc3b f60e7fee 1f72740e |
| Engine | exp | log | sin | tan |
|---|---|---|---|---|
| Node.js | reference | |||
| workerd | 189 | 32 | 60 | 56 |
| Chromium | 189 | 32 | 60 | 56 |
| Firefox | 2 | 2 | 15 | 30 |
| WebKit | 185 | 32 | 90 | 781 |
Commit 71716b4f. Regenerate with npm run parity.
The second table is why the kernel brings its own exp and ln. On the same inputs the platform's functions return a different last digit from Node's on some engines, and a receipt cannot tolerate that.
Delivery
Runs where your data lives
The choice between the three is about where your figures may go. It never changes what they are.
-
On the device
- Where do your figures go?
- Stays on the machine. Nothing is sent.
- Who runs it?
- You do, in the browser or an application.
- Works offline?
- Yes, once the page or application has loaded.
- How does it update?
- When you open a newer version.
- What it suits
- A trader trying a position. A validator reproducing a figure.
-
At the edge
- Where do your figures go?
- Goes to our endpoint over TLS, is worked on in memory and is not stored.
- Who runs it?
- We do, on Cloudflare Workers, near the user.
- Works offline?
- No.
- How does it update?
- Continuously. Each release is a new deployment.
- What it suits
- Report generation. Integrations through the API. Checking a receipt.
-
In your estate
- Where do your figures go?
- Stays inside your network, including a network with no way out.
- Who runs it?
- You do, from a signed container image or a package.
- Works offline?
- Yes.
- How does it update?
- When you pull a signed release and choose to apply it.
- What it suits
- Production batch runs. Regulated filings. Air-gapped sites.
Measured on every build
- Browser The kernel runs in the page. Inputs stay on the device.
- Edge Cloudflare Workers, close to the user, with D1 and R2 for state and artifacts.
- Node.js Servers, batch jobs and test harnesses.
Ship when they reproduce every fixture
- Python A package for notebooks and research pipelines.
- JVM For the risk platforms that already run there.
- .NET For the desktop and server estates that run on Windows.
- Excel An add-in that returns the number and the derivation.
- Command line Scriptable runs that emit a receipt next to the result.
- Container A signed image for your own cloud or an air-gapped site.
Standards
Standards change. The kernel is told
A regulation is a moving target. Keeping up is a process with a fixed order, and each step leaves a record you can read in the specification feed.
-
A standard setter publishes
The feed picks it up from the setter’s own channel and files it against the regimes it touches.
-
The change is mapped to clauses
A methodologist reads the text and lists the rules that move, each against the function that carries it.
-
A test fails first
The new rule is written as a test before the code, so the old behaviour cannot pass it by accident.
-
The engine is released
Every release says which publication it answers. The proofs, the parity check and the suite run again.
-
Old receipts keep verifying
A receipt holds the rule parameters it was computed with, so the earlier release still reproduces it.