Dimensional validation (VALIDATE)
This is the step that makes "Physical Type-Safety" more than a slogan. It is implemented in
shared/api-core/src/lib/dimensions.ts, and it closes a specific, dangerous failure mode:
sending {"temperature": 300} to a quantum-box operator and getting back a confident energy
computed entirely from default inputs — a right-looking answer to a question never asked.
After Step 3, that cannot happen. A compute whose supplied inputs do not dimensionally engage the selected solver is rejected before it runs.
Two checks
VALIDATE runs two checks in sequence.
Range sanity (validateInputs) repairs or clamps physically impossible inputs: non-finite
values become 0, negative mass is taken absolute, a velocity above c is clamped to 0.999c,
a temperature below 0 K is clamped to 0, a non-positive radius is set to a safe default. Each
repair is recorded as a warning.
Dimensional engagement (checkDimensionalEngagement) is the important one, and the rest of
this page is about it.
A real SI dimension algebra
The framework carries a genuine dimensional algebra. Every physical quantity is a vector of seven exponents over the SI base dimensions:
[M, L, T, I, Θ, N, J]
mass, length, time, current, temperature, amount, luminous intensity
So velocity is [0, 1, −1] (L·T⁻¹), force is [1, 1, −2] (M·L·T⁻²), energy is [1, 2, −2]
(M·L²·T⁻²), pressure is [1, −1, −2], and a dimensionless count is [0,0,0,0,0,0,0]. The
module defines these as named constants (VELOCITY, FORCE, ENERGY, PRESSURE, …) and can
format any vector for a human: fmtDim(ENERGY) → "M·L²·T⁻²".
Per-solver input signatures
Each solver declares which input names it reads, and what dimension each one carries. These
signatures are derived from the actual inputs.<name> reads in zeqSolvers.ts — a drift-lock
test re-scans the solver source and fails the build if a solver gains an input the signatures
don't cover. A few examples:
GR: { M: MASS, mass: MASS, r: LENGTH, radius: LENGTH },
CM: { m: MASS, a: ACCEL, v: VELOCITY, r: LENGTH, m1: MASS, m2: MASS, … },
TD: { T: TEMP, V: VOLUME, n: AMOUNT },
EM: { q: CHARGE, r: LENGTH, E: EFIELD, B: BFIELD, v: VELOCITY },
WP: { f: FREQ, lambda: LENGTH, v: VELOCITY },
Names are solver-local on purpose: A is a dimensionless mass-number in the nuclear solver but
an area in the structural solver. The signature knows the difference.
The rejection rule
The verdict is reject only when the caller actively supplied inputs and none of them
appears in the selected solver's signature — i.e. the solver would compute its whole answer
from defaults while appearing to answer your question. If even one input engages, the compute
proceeds (extra inputs are noted as ignored, not fatal). An empty input set — the demo /
defaults path — is always allowed.
When it rejects, the error names what was required versus what was supplied:
DIMENSIONAL_MISMATCH — None of the supplied inputs (temperature [Θ]) engages the QM
solver — it would answer entirely from defaults. Accepted inputs: n [1], L [L], m [M].
The routes surface this as HTTP 400, and nothing downstream of VALIDATE runs. The result's
verification is never verified for a rejected compute.
One deliberate exemption
The seeded equation-generation path — the tokens + seedHex credential flow used when a new
user's account equation is minted — is exempt from dimensional engagement. Its inputs are
synthetic token entropy (tok_0_…), not a physical claim; they carry no verified status and
never enter the recompute contract. Gating them once broke account creation for every new user,
so the exemption is explicit and narrow: credential equations are not physical §3 claims.
Why this is rare and valuable
Almost no scientific API checks that your inputs mean the right thing before computing. Most
will happily accept a temperature where a length belongs and return a number. Zeq treats a
dimensional mismatch the way a typed language treats a type error: it fails early, loudly, and
with a message that tells you the expected shape. That is what lets a downstream consumer trust
that a verified result actually answered the question that was asked.
Read next
- The solvers — Step 4: what runs once the inputs are validated
- Precision & proof — the
verified / unverifiable / disputedverdict - The pipeline — where VALIDATE sits
Dimensionally-incoherent computes fail before compute, loudly. That is the type-safety.