Saudi corporate filings — Zakat and income tax at the core, ten shipped engines in all: statements, verification, transfer pricing, withholding, VAT, RETT, excise, UBO — computed from ledgers into submission-ready declarations, with the proof attached. Models are used heavily. The arithmetic is untouchable. That boundary is not a policy; it is the architecture.
The computation core is a pure function: no network, no database, no import path to a model client — verified across the full transitive import graph, not promised in a README. The last model influence is a mapping suggestion a person approved; the engine’s parameter is literally named approved_mappings.
Every input freezes into a versioned checkpoint before the engine runs; replay is asserted bit-identical, and expected values are hand-derived from the regulation before the code exists. Inputs are stored, not conclusions — a corrected rule should change the answer; what you need is to know that it did.
Twenty-one controls in a flat sequence with no short-circuits — twelve blocking. Some re-derive the arithmetic from the raw inputs by an independent route and compare; others surface the engine’s own identity checks as first-class, auditable results. One gate has teeth: a filing with failing blockers cannot be exported. All math in fixed-precision decimal, converted at the boundary so nothing inherits float imprecision at birth.
Ingestion tries the cheapest thing first: known vendor formats, deterministic column maps, a cached layout fingerprint — a familiar file is processed with zero model tokens, and learned layouts are shared across tenants as structure only, never values: the tenth user of an ERP format pays what the first nine already taught. Eleven model call sites in total, all behind one wrapper with retries, a circuit breaker and a hard budget abort.
“A control that is right most of the time is not a control.”
Schema strictness tracks consequence: where a model’s output becomes a number a person will approve into a filing, it is forced through a schema and rejected on mismatch; where it is a suggestion a person will read, lighter validation is proportionate. Where a rule exists but isn’t implemented — earlier regulatory regimes, sectors with unimplemented brackets — the system refuses at the boundary before the engine is ever called: a pre-flight rejection is a support ticket, an approximate filing is an assessment. And the bug that proves the thesis: an extraction once silently returned 52 of 54 rows, and every ratio-based plausibility check passed — the fix was a set difference against the source, row by row, by identity, not a better prompt. Every figure with source coverage opens an evidence drawer in the product: line → contributing accounts → sheet and row → a highlighted excerpt of the original upload. Known gaps, stated plainly: the newer per-return engines each stamp their version onto the persisted return, the Form-10 core does not yet — so “recompute everything affected by this correction” is not yet a first-class query there; and the core’s purity is audit-verified and convention-enforced, not yet pinned by an import-graph test. Both are named next pieces of work.