The CRA
disagrees with
the CRA.
Every Canadian employer withholds income tax, CPP and EI from every paycheque using arithmetic the Canada Revenue Agency publishes as the T4127. Takehome implements it in one Rust engine and checks itself against the CRA's own calculator: 8,838 of 9,002 boundary cases agree, and all 164 disagreements are published. Building that check turned up a place where the calculator does not follow the formula it is meant to implement. Live: takehome.gautamkhosla.com. Code: takehome, Apache-2.0.
SEC. 01
The rules change twice a year, and one of the changes is wrong on purpose
When a province raises a tax rate backdated to January, employers have already withheld six months at the old rate. The CRA does not ask anyone to fix those six months. It publishes a prorated rate for July to December that averages out correctly across the whole year, and is incorrect for any other purpose.
On 1 July 2026 that happened to three provinces at once. A payroll engine holding a single dataset for the year cannot represent it. It is correct for one half and silently wrong for the other, and nothing in its answer tells you which half you asked about.
Nobody in this market publishes an error rate. Verifying a vendor means trusting a sales call.
SEC. 02
A schema decision made in the first hour
Every rule carries a validity interval rather than a year. Every call accepts an optional pay date and defaults to today, and every response names the rule set version that answered it.
The fourth key is the one that is easy to miss. The CRA publishes different values for the same jurisdiction on the same date depending on which of two calculation methods you use. Key a rule on three things and the second method is wrong for six months of any year with a mid-year change, without an error anywhere.
Rules are data, never literals. No rate, threshold or maximum appears in engine code, so when the CPP base rate falls from 4.95% to 4.75% on 1 January 2027, supporting it is adding a row. A preview of that rule set already ships, labelled proposed and not yet enacted, with the warning above the number rather than below it.
SEC. 03
No binary floating point in a money path
The type system makes IEEE-754 floats unreachable in anything that touches money, and a CI check fails the build if a float type appears in the engine at all. That is enforcement, not a review comment.
It matters more than it sounds, because the CRA specifies three different rounding behaviours. The CPP basic exemption truncates the third decimal where every other quantity rounds half up. 3,500 divided by 12 is $291.66, not $291.67. That figure sits in the suite as a canary, paired with its rounded twin, so the two code paths can never quietly merge.
SEC. 04
One engine, every runtime
A single Rust core compiles to WebAssembly and to native, with thin bindings for JavaScript and Python. The browser, the API and the command line all run the identical compiled artifact, and a test runs the same vectors through WASM and native and asserts byte-identical output.
The engine has no input, no output, no network and no clock. Give it a request and a rule set, get a response. Because the rule data is static and the engine is WASM, the calculator pages work with no network after the first load, and no salary figure ever leaves the visitor's device.
SEC. 05
The government's calculator as an oracle, not a competitor
The CRA runs its own Payroll Deductions Online Calculator. It is the authoritative answer and it has no API. So a grid generator produces cases densely clustered around every boundary that matters, bracket thresholds, pensionable earnings ceilings, credit phase-outs, surtax and health premium tiers, one cent either side of each. A rate-limited harness runs each unique case through the official calculator overnight and caches every result permanently.
The coverage gaps are published beside the number, in the same words. Quebec is not supported. Four of the fourteen legal pay frequencies cannot be captured because the official calculator does not expose them. And the interior of the grid is checked against invariants rather than against the oracle, so 750,000 self-checked cases are not folded into the headline.
A bug in the harness is a defect: fixed and removed. Identical inputs producing different outputs is a disagreement: published, even when the conclusion is unflattering.
SEC. 06
Finding one: the published constants make tax discontinuous
The CRA publishes a constant for each bracket, rounded to the whole dollar, that corrects for applying the top applicable rate to the entire income. Because those constants are rounded, annual federal tax jumps by up to a dollar as income crosses a threshold by a single cent.
That was not the goal. It came out of building the conformance grid, because a grid clustered one cent either side of every threshold is exactly the instrument that sees it. The measured jump at every threshold in every supported jurisdiction is published, so the behaviour is documented instead of surprising someone during a reconciliation.
SEC. 07
Finding two: the calculator does not follow the formula
The T4127 instructs a calculator to use the maximum base CPP contribution for the tax credit in the pay period where an employee first reaches the annual maximum. The official calculator does not do this. It uses the year-to-date figure instead.
I did not establish that by reading the document harder. I solved backward from the official calculator's published figure for the credit base it must have used, then compared that recovered number against each candidate interpretation. The formula's reading gives $3,519.45. The year-to-date reading gives $3,494.12. Only one matched, to the cent.
Takehome conforms to the calculator by default, because agreement with the calculator is what customers reconcile against. The document's literal reading stays selectable. Both are documented, with reproduction steps a reader can follow in five minutes.
SEC. 08
What broke, and what I would change
Three guards that read green while measuring nothing. A property test that was being skipped. A watchdog that only noticed the successful code path, so it fired during normal operation and stayed silent during a hang. A consistency check that compared two of four copies of the same list. The standing rule now is that a passing guard is not evidence until I have broken the thing it watches on purpose and watched it go red.
Quebec returns an error, not a number. It is administered separately under its own formulas and is roughly a fifth of Canadian employment. A Quebec request gets a typed error rather than federal tax with the provincial line zeroed, because a confident wrong number in the one province the engine does not calculate is worse than an outage. It also means no national employer can use this alone yet.
What I would change, or at least say louder: 98.2% is agreement with the official calculator, not correctness. By conforming to the calculator by default, Takehome inherits its departure from the formula on purpose, and the headline number is structurally unable to detect any error the oracle shares. That is the right product decision, because employers reconcile against the calculator. It is also a real limit of the instrument, and the conformance record should state it in its first paragraph rather than leaving a reader to work it out.