Home · Methodology

Methodology

TaxMetria is built around a deterministic calculation engine, versioned data records, and a structured audit trail for every result. The engine is open, the tests are public, and every material number ties back to a primary source.

The calculation engine

The engine is written in TypeScript and uses decimal.js for all monetary arithmetic. We deliberately avoid IEEE-754 binary floating-point: tax math is exact or it is wrong, and a 0.0000001 difference at scale becomes a real sum of money.

For every calculation the engine returns a structured result:

  • gross_income, taxable_income, net_annual, net_monthly
  • income_tax, total_employee_contributions, total_surtaxes
  • effective_tax_rate (numeric) and marginal_rate_pct
  • trace — every step with its rule, source fact ID, and amount

On invalid input, the engine returns a discriminated-union rejected result with a reason and field. It does not silently approximate.

Progressive brackets

Brackets are walked explicitly: each band contributes (slice × marginal rate) to the running total. Top bands are open-ended. The engine rejects brackets that don't start at zero or whose ceilings are out of order.

Allowances and credits

Deductions (applies_to: taxable_income) reduce the income that bands are applied to. Credits (applies_to: tax_liability) reduce the tax after bands have been applied, but never below zero. Exemptions behave like deductions in v1.

Employee contributions

Mandatory employee-side contributions are modeled as separate lines, each with a base, rate, optional cap, and optional floor. The engine handles "8% between £12,570 and £50,270" by setting floor: £12,570 and cap: £50,270; the slice the rate applies to is computed against the gross-income axis.

Rounding

By default, contributions, income tax, and net are rounded to the nearest minor unit (0.01) using banker's rounding. We keep the unrounded value internally and only round at display time.

Data architecture

Every material tax fact lives in a versioned structured record. The shape:

FieldPurpose
fact_idPermanent identifier used in traces, change logs, and references.
jurisdiction_codeISO or internal jurisdiction identifier.
tax_yearTax year the fact applies to.
effective_from / effective_toActual effective period.
filing_statusSupported taxpayer scenario.
income_typeEmployment, self-employment, etc.
rule_typeBracket, allowance, credit, contribution, cap, surcharge, or rounding.
threshold / rate / capMachine-readable rule values.
currencyISO 4217 currency code of the values.
source_urlDirect official source URL.
source_titleHuman-readable source name.
reviewed_atRetrieval date for the fact.
reviewerAccountable human reviewer.
release_versionImmutable data release containing the fact.

The page prose, the worked examples, the JSON-LD structured data, and the calculator all read from the same registry. They cannot disagree because they read from the same place.

Source policy

Preferred evidence order:

  1. Tax authority or finance ministry legislation, tables, and official guidance.
  2. Official social-insurance authority.
  3. Official gazette or enacted legislation.
  4. Official regional/state/provincial authority.
  5. A qualified professional source only to interpret ambiguity — never to replace an available official fact.

Search snippets, blog posts, and AI-generated answers can flag problems but never set a number. See the source registry for the per-jurisdiction list.

Test approach

The engine and data records are tested in five ways:

  • Unit tests — each rule and validation path.
  • Boundary tests — one unit below, at, and above every threshold, cap, and floor.
  • Golden tests — verified expected values computed directly from the official rate tables.
  • Property tests — invariants that must hold across all valid inputs (net ≤ gross; marginal rate monotonic after band crossings; credits never make tax negative).
  • Cross-surface tests — calculator output, page table, worked example, and JSON-LD all agree.

Run npm run test:all to execute the suite. Each test name documents the property it pins.

Releases and versioning

Each jurisdiction has an immutable release identifier, e.g. us-fed-2026.1. Releases are never silently overwritten. When a fact changes (e.g., new IRS Rev. Proc. published), a new release is published and the change log shows the diff.

Audit trail

Every result the engine produces carries a trace with one entry per band, allowance, and contribution. Each entry has the rule applied, the source fact ID, and the amount. The calculator UI exposes this trail in the result panel; the JSON serialisation is available via the Web Share API result link.

See sources and assumptions for the broader trust picture.