How we check ourselves

Don’t take our word for it. We didn’t.

Software that calculates pay asks for a lot of trust, and the usual answer to that is a badge and a promise. Momiji is built to be checked instead: against the CRA’s own calculator rather than our test suite, against your pay stub rather than one we chose, against the production database rather than a copy of it. This page is those checks, and what they found when we pointed them at our own work.

The engine is checked against the CRA, not against our own tests.

A test suite written by the people who wrote the engine can only confirm that the code does what they meant. It cannot tell them the meaning was wrong. So the payroll engine is replayed against figures Momiji did not produce: 46 cases and 303 fields, 220 of them anchored to numbers the CRA either published or returned, with 0 mismatches. The anchors are the worked calculations printed in the CRA’s payroll guides and captures taken from the CRA’s live Payroll Deductions Online Calculator.

A required step of the same gate that produces the build.

What the check found

A rounding bug in our own engine.

The federal basic personal amount is not one number. Above a threshold it tapers, from $16,452 down to $14,829, across net income between $181,440 and $258,482. At exactly 100 income levels inside that band the correct amount lands on a half-cent, and a half-cent cannot be represented exactly in binary. So the engine was rounding on floating-point noise: the same calculation could go down at one income and up at the next, and nothing in the code decided which.

Fourteen of those incomes were put through the CRA’s own calculator, across three pay frequencies. It returned the rounded-down figure all fourteen times, which is the opposite of the rounding rule the CRA prints in its own formulas guide. We changed the engine to match what the CRA actually returns, in exact integer arithmetic. We did not change the check to match the engine.

The amount involved is about $0.0014 a year, and no customer was affected. We are not going to present that as a near miss, because it was not one. It mattered for a narrower reason: a payroll figure that depends on floating-point noise cannot be reconciled. The same input has to give the same answer every time, or a tie-out against it proves nothing. We would rather find that ourselves than have your auditor find it.

A guard now runs on every build. It sweeps 121,245 incomes across 149 checks and replays 26 anchor points computed by the CRA against two independent re-derivations of the formula, one from the Income Tax Act and one from the CRA’s own TD1 worksheet. Neither re-derivation shares any code with the engine, so agreement between the three is evidence rather than a tautology.

The guard is a script called verify-bpaf-taper, wired into the build gate as a required step. The fix is a single commit. We will walk you through either one.

  • 100

    half-cent income levels

  • 14

    answers taken from the CRA

  • 149

    checks in the standing guard

  • 0

    failures

The rest of the checks

The same standard, applied to everything else.

Each of these exists because the alternative was to assert something and hope. They are written to the same rule as the defect above, which is why the limits are in here with them.

  • 01

    Your stub is the test case

    Before a first live run, Momiji recomputes a period your current provider already paid and shows every figure beside theirs. You bring the stub, so we do not get to pick the case that gets checked. If it does not tie to the cent, you do not go live. Manitoba we will not tie out at all yet, because the CRA has published no worked example inside the range its basic personal amount needs, and we block live runs there for the same reason.

  • 02

    We publish what we cannot do

    Momiji holds no SOC 2 report and has had no external penetration test. Two-factor authentication is available and nobody is forced onto it, so we do not claim enforced MFA. Receipts and generated T4 slips are deliberately permanent, which means a document filed in error cannot be deleted through the product today. All of it is set out on the security page in our own words, rather than left for a reviewer to find.

  • 03

    The backup was restored, not asserted

    A backup nobody has restored is an assumption. So a real file was deleted from storage and recovered from the backup with an identical sha256 fingerprint, and the database row pointing at it resolved again. A copy corrupted on purpose was caught by the verifier, and the restore refused to write it over the good file.

  • 04

    The tests run against the production schema

    66 suites run against the production database itself rather than a copy, each inside a transaction that is rolled back, so nothing is written. They re-prove tenant isolation and confidential-record containment. The runner also fails any suite that plans more assertions than it actually runs, because a short plan otherwise reports zero failures and reads as a pass.

A check has to come from outside the thing being checked.

Ask for the one behind any line

Every figure on this page comes from a script, a test suite, or a commit, and each one is something we can walk you through. If you are running a review, or your auditor is, write to hello@mymomiji.com and name the line. If the honest answer is that something is not built, that is the answer you will get.

The payroll evidence, including the tie-out, sits under Payroll. The database, subprocessor, and limit detail sits under Security.