Editorial methodology

How we keep the VAT numbers right

Every rate, threshold and rule VATLY shows comes from a typed row in a maintained rules engine. Each row records an HMRC source URL, the date the figure first applied, and the date a human reviewer last verified it. A daily background job flags any row not reviewed in 90 days. This page documents that process in full.

1. Source provenance — every figure is traceable

Each rate row in packages/rules-engine is a typed record with the following fields:

  • value — the rate or threshold itself, stored as an integer (basis points for rates, pence for cash).
  • source_url — a single canonical HMRC page (usually gov.uk) that defines the figure.
  • applies_from — UK tax-year-aware effective date (e.g. 2025-04-06).
  • applies_to — null when current; populated when superseded.
  • last_reviewed_at — the last time a human reviewer verified the row against the source.
  • reviewer_id — who did the review.
  • notes — exceptions, caveats, or HMRC's own wording where it materially clarifies.

When a calculator renders a rate, the source URL and "last reviewed" date are shown inline. Compare this with the typical UK VAT calculator, which usually shows a single static rate with no source link at all.

2. Editorial review cadence — 90-day stale-rule audit

A daily cron runs at 06:00 UTC. It scans the rules-engine seed and writes an audit_log entry with severity governance.stale_rule for any row whose last_reviewed_at is older than 90 days. Those entries land in an editor's queue. The corresponding fix is either:

  • Re-verify the figure against the source URL and bump last_reviewed_at; or
  • Update the figure (and the source URL if HMRC has moved the page) and bump last_reviewed_at; or
  • Supersede the row by setting applies_to and inserting a new row with the updated value.

Code-only changes never bump last_reviewed_at. Bots can tell the difference between an editorial change and a refactor; trust degrades fast if the date lies. This is policed by a unit test in the rules-engine package.

3. Severity ladder — what gets reviewed when

Not every audit-log entry needs the same response time. The severity values are defined in docs/EDITORIAL_WORKFLOW.md:

  • governance.stale_rule — review within 14 days.
  • governance.missing_provenance — a row is missing one or more of the mandatory fields. Fix within 7 days.
  • governance.value_disputed — a user-reported correction or an internal find. Fix within 48 hours.
  • governance.figure_changed_at_source — HMRC has updated the underlying figure. Same-day update.

4. Rounding policy — integer pence, banker's rounding

All money on VATLY is stored and computed as integer pence. Display formatting uses a typed Pence brand to make it impossible to add pounds and pence by accident. Where a rounding decision is required, the calculator uses banker's rounding (round-half-to-even) — the same convention HMRC uses in its own published examples for VAT amounts.

The full money policy, including overflow guards, parse rules, and the thin-space pound-symbol formatting, lives in docs/MONEY_POLICY.md.

5. Tax-year boundary — Europe/London, not UTC

UK tax years run 6 April to 5 April. To decide which tax year applies to a given calculation, VATLY converts to a London-local date before comparing against rule applies_from / applies_to. Without this, the tax year would flip an hour late during BST. This is tested explicitly with cases like "23:30 UTC on 5 April during BST" to lock the behaviour.

6. Testing — golden cases against HMRC examples

The @vatly/calculations package ships 33 hand-verified golden tests sourced from HMRC's own published worked examples. They include:

  • 9 UK VAT cases (Standard Scheme + Flat Rate Scheme + reverse VAT)
  • 6 PAYE/income-tax cases (UK and Scotland rates, with personal-allowance taper)
  • 4 NHS pension tier lookups
  • Property-style sweeps for net + VAT = gross over £0–£200,000
  • Threshold-status monotonicity tests

New calculators ship with a minimum of five hand-verified goldens before going live. Tests run on every push and block deploys on failure.

7. Public correction path

If you spot a figure you believe is wrong, email hello@vatly.uk with the calculator URL, the figure you saw, what you believe the correct value should be, and (ideally) an HMRC link. Disputed values are logged as governance.value_disputed with a 48-hour SLA. We will reply with the resolution, including a link to the audit-log entry.

8. What we will not do

For trust reasons we deliberately avoid:

  • Pseudo-precision claims like "save £332/year" without transparent methodology.
  • SEO listicles ("13 mistakes that cost thousands") on product pages — useful as content, dishonest framing on a calculator.
  • Embedding third-party analytics on calculator pages (PostHog is opt-in and only inside the signed-in app, never on the public calculators).
  • Stale third-party content libraries — every figure on VATLY is maintained by us against an HMRC source, not bought in.