Assurance — what we verify, and what we cannot
The claim
Statbook never claims to be “100% accurate.” The claim is: traceable, corroborated, re-verified, versioned, signed — and when wrong, detectably and briefly wrong, with a published correction trail. No indemnity is offered at any tier.
How a value earns “corroborated”
Every figure declares which legal instrument governs it (Source A,
legislation.gov.uk) and which official guidance page states it (Source B,
gov.uk). The two are fetched and extracted by isolated passes that share
no state; only when both extractions match can a value carry the
corroborated status — the build system is physically unable
to emit it otherwise. Mismatches ship as disputed or not at
all.
The pipeline, in order
- Fetch — both official sources per figure; raw snapshots stored with content hashes.
- Extract — two isolated passes that share no state, one per source.
- Gate 1 · corroboration — A must equal B;
mismatches ship as
disputedor not at all. - Gate 2 · invariants — cross-figure identities and date-range checks; any failure fails the whole build.
- Gate 3 · human diff review — every value change reviewed against source excerpts before release.
- Sign & publish — manifest with per-record hashes, minisign-signed, committed to the public releases repository.
Source independence — the honest statement
Source B is HMG's own interpretation of the legislation, produced downstream of it. Corroboration therefore catches our extraction errors, staleness, and drift — it does not catch an error both sources share, nor resolve genuine ambiguity in the instrument itself. A-vs-B mismatch most commonly means gov.uk hasn't updated yet (early April) — exactly what the gate must catch.
In plain terms: corroboration is a strong net for our mistakes, not a guarantee the government's own documents are right. An error shared by both sources, or genuine ambiguity in the instrument itself, passes through by design and is caught only by the corrections protocol when surfaced.
Assurance by source type
The promise “every figure traceable to primary legislation” is scoped
to act/si source types. Other types are
published with their assurance level explicit — honesty as a feature,
not a broken promise.
| source_type | Examples | Two-source gate | Assurance level published |
|---|---|---|---|
act | AMAP rates (ITEPA 2003 s.230(2)) | Yes | Full |
si | Increase of Limits Orders, NMW regs, uprating orders | Yes | Full |
presidential_guidance | Vento bands (no SI exists; judiciary.uk PDF, URL rotates yearly — each snapshot archived; Crown/OGL via site-wide notice) | Degraded (sole publisher + reproductions) | Labelled |
resolution | Scottish and Welsh income tax rates (a rate resolution of the Scottish Parliament or the Senedd — primary law for the rates, published as an agreed motion and never on legislation.gov.uk) | Yes — the motion as agreed, against the devolved government's rates page | Full |
administrative | HMRC Advisory Fuel Rates and National Insurance category letters (HMRC's own creation; no instrument prints them, and the page is overwritten quarterly) | Where a second official page prints the same table; otherwise no — single source, honestly labelled | Labelled |
statistical | The RPI All Items Index (ONS series CHAW) that SI 2009/470 reg 3(1) names by title and the student-loan repayment thresholds are computed from — the statute states the formula and can never state the index | No — one publisher, named in the instrument; a second page printing the same index is a copy of it, not an independent reading | Labelled |
computed | Late-payment interest (SI formula × live BoE base rate) | Formula yes; value computed | Labelled + formula shown |
derived | Max redundancy payment (20 × 1.5 × cap) | Derivation from corroborated inputs | Labelled + derivation shown |
April and Budget weeks — “guidance confirmation pending” is the system working
On the day a new instrument is made, gov.uk typically hasn't updated yet. The headline new figures therefore cannot pass corroboration on day one — and the gate refuses to claim corroboration it doesn't have. Promoted figures publish as Primary source only with guidance confirmation pending, and nightly re-verification auto-promotes each one to Corroborated the day gov.uk catches up — leaving a public, dated promotion trail. If you see that badge in early April, you are watching the gate work in public.
Re-verification and corrections
- Every current value's machine-readable sources are re-fetched and
hash-compared on a nightly schedule, and
last_verifiedon every record and API response dates the last check that succeeded — a missed night shows as an older date, never as a claim. One figure's source is not machine-readable — the Vento bands are published only as a PDF (see the source-type table) — so its date advances when a person re-reads the addendum, and the record shows that older date rather than borrowing the corpus's. - That date is per source, and the published one is the oldest: a figure is only as fresh as the stalest thing behind it, so where the statute and the guidance were last checked are shown and dated separately and a value whose statute has been unreachable for a fortnight says so instead of borrowing the other side's freshness.
- Source drift that removes a value auto-flips its status to
disputedwithin 24 hours, before any human review. - Wrong values are never deleted: they stay in history marked
corrected, with a numbered advisory in the public corrections log.
Verify a record yourself — no trust in us required
- Take any record from the API, e.g.
/v1/figures/employment.redundancy.weekly_pay_cap.json— thereceipt.record_hashfield states its SHA-256. - Recompute it: serialize the
figureobject as UTF-8 JSON (2-space indent, non-ASCII preserved, trailing newline) and hash it. - Check the same hash appears in the
release manifest
under
record_hashes. - Verify the manifest's minisign signature against the published public
key, and compare the manifest with the copy in the public
statbook-releasesgit repository — history rewrites there are detectable by any cloner. - Follow the per-source citations: every
uriis the document its role names — the official publisher's, except asecondarysource, which is an independent reproduction used only to corroborate a figure whose publisher is the sole one (see the source-type table below) and is labelled as such on the record.content_hashpins the exact bytes we extracted or verified from. Where those bytes are a different representation than the cited page — legislation citations point at the human-readable page while extraction reads the as-madedata.xml—content_hash_ofnames the exact URL the hash pins. Sources whose documents we have not yet archived carrycontent_hash: nullrather than a hash we couldn't back.
A self-contained reference implementation is published at
/tools/verify_receipt.py
— a single stdlib-only Python file you can download, read and vendor.
The signing key
Every release manifest is signed with this minisign public key
(key ID 12D5059844B2CD8F). The same key is
published in every API response under meta.signing and in the
statbook-releases repository README — cross-check all three so
no single source can substitute a key of its own.
Save it as minisign.pub and verify any manifest offline:
untrusted comment: minisign public key 12D5059844B2CD8F
RWSPzbJEmAXVEvTqYZ8O9iHuOcOUii5lCNZM5t9bdoQh4ZnwKsxk/+bd
minisign -Vm manifest.json -p minisign.pub