That sentence is written at the top of the continuous integration configuration, and it is the reason the pipeline is shaped the way it is. An accounting regression does not crash. It produces a plausible figure that somebody files. Everything below exists to make that class of failure stop at the build rather than at the client.
| # | Gate | What it stops |
|---|---|---|
| 01 | Typecheck | The cheap failures, first |
| 02 | Lint, carrying six ratchets | Structural drift. Deliberately early, so a memory failure later in the run can never be the reason the ratchets did not execute |
| 03 | Production build | Anything that compiles in development but not for release |
| 04 | Ledger invariants against seeded multi-currency scenarios | Silent accounting drift, proven against books built to contain combinations no real client has produced yet |
| 05 | Security.txt format check | A malformed vulnerability disclosure file, checked against the published standard |
| 06 | Security.txt served correctly | The file being right in the repository but wrong over HTTP |
| 07 | Golden fixture sign-off gate | Real client figures changing without a recorded, signed-off reason |
| 08 | Commit message quality on accounting code | A change to ledger, VAT, HMRC, tax, FX or payroll code landing with an empty message |
| 09 | Accounting change ledger entry required | The same change landing without an entry explaining what moved and why |
| 10 | Full test suite | Everything else |
| 11 | Database gate configuration check | A skipped isolation gate reading as a green build. This step fails deliberately if the database credential is missing |
| 12 | Tenant isolation gate | A tenant boundary moving. Runs against a real database, in a transaction that is always rolled back |
| 13 | Privileged function isolation gate | An elevated database function being pointable at another tenant |
Gate eleven exists because the two database gates are conditional on a credential being present, and a conditional gate that silently skips is worse than no gate at all: it produces a green build that means nothing. So the pipeline fails if the credential is missing. A skipped safety check must never look like a passed one.
A ratchet is a check that allows what already exists and refuses anything new of the same kind. It is how a single operator keeps a 338,000 line codebase from decaying, and every one of these was added after a specific problem, not in advance of an imagined one.
Domain code must live in a named domain folder. The root is closed, with an allowlist that can only shrink.
Catches database writes whose result is thrown away, the shape of bug where a save silently does nothing.
Scans for credential-shaped values before they can be committed.
Frozen client figures cannot change without a recorded sign-off.
An accessibility ratchet: an icon-only control must carry a label.
A typographic rule enforced at build time. Small, but it is the same principle: decide once, then let the machine hold the line.
Two further rules are enforced in the linter itself rather than as scripts: category pickers must use the component that also offers "create a new nominal", because forms repeatedly shipped without one and trapped users; and native browser dialogs are banned outright in favour of in-application confirmations.
Real client books, captured as fixtures and replayed through the live reporting core. The suite asserts no penny leakage in any VAT split, that each client's trial balance difference matches its recorded figure exactly, that retained earnings appear exactly once when there is prior activity, that no nominal code is duplicated on a report, and that every reported figure is whole pence.
Regenerating a fixture to make a failing test pass would convert the safety net into a rubber stamp. It is banned in writing, enforced by a sign-off manifest and checked in continuous integration. If a figure legitimately changes, a human signs it off and records why.
Fixtures freeze what clients have produced. Seeded scenarios cover what they have not: a sterling-home client with dollar and euro accounts and a dollar gateway, a euro-home client, registered and unregistered for VAT. The rule is to add a scenario whenever a new currency, gateway or VAT shape ships.
Each scenario is also corrupted on purpose so that every invariant is observed to fire. A test that has never failed has not been shown to work.
Per-client trial balance difference, uncategorised items, control account state. The nightly sweep populates it; the invariant is that any difference is pinned and explainable, never hidden.
Insert-only, per firm, with application-side and database-side rejections grouped under the same rule code.
Application errors and browser policy violations land in tables rather than a log file nobody reads, with a digest job so a new class of failure surfaces without anyone remembering to look.
Shows the last run, its destination, and whether it actually went off-site. A fallback run displays as a warning, not a tick.
Document extraction and other usage-sensitive costs are metered per client, so unit economics are measured rather than assumed.
Who read what, and when, across four underlying logs, behind a single gated function with no operator override.
A published vulnerability disclosure address, with the file itself format-checked and served-correctly-checked in continuous integration. A personal data breach is notifiable to the Information Commissioner within the statutory seventy-two hours. The commitment made to clients specifically includes telling them which returns and which periods are in scope, because for an accounting platform that is the question that actually matters.
| Priority | Why it is next |
|---|---|
| HMRC recognition in TaxChad's own name | The single largest unlock. It turns the filing layer from something delivered through the practice into a product capability, and it is a prerequisite for the sole trader and landlord market that Making Tax Digital is about to create. |
| Open banking feeds at live volume | Integration is built. Moving it from integrated to carrying real customer volume is what makes the bookkeeping product self-serve rather than assisted. |
| A second engineer | As much a risk control as a capacity increase. It ends the single-reviewer position on authorisation changes and halves the key person exposure this page is candid about. |
| Third-party penetration test | Named on our security page as not done. It stays named until it is. |
| Accounts production integration | Today the accountant prepares accounts in a separate tool from the trial balance. Closing that seam is the largest remaining efficiency in the regulated layer, and the regulated layer is the real margin constraint. |
| Rule provenance and rule history | Stamping the deciding rule on the transaction and versioning rules so a prior year replays exactly as it stood. Named as a gap on the engine page; this is when it closes. |