TaxChad Technical Architecture ยท Build and run
01 Build and run

A wrong number still looks like a number.

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.

4,042
Tests, across 358 files
13
Gates on every push
6
Lint-time ratchets
13
Consecutive successful nightly backups
Delivery01 / 07
02 The pipeline

Thirteen gates, in this order, on every push and pull request.

#GateWhat it stops
01TypecheckThe cheap failures, first
02Lint, carrying six ratchetsStructural drift. Deliberately early, so a memory failure later in the run can never be the reason the ratchets did not execute
03Production buildAnything that compiles in development but not for release
04Ledger invariants against seeded multi-currency scenariosSilent accounting drift, proven against books built to contain combinations no real client has produced yet
05Security.txt format checkA malformed vulnerability disclosure file, checked against the published standard
06Security.txt served correctlyThe file being right in the repository but wrong over HTTP
07Golden fixture sign-off gateReal client figures changing without a recorded, signed-off reason
08Commit message quality on accounting codeA change to ledger, VAT, HMRC, tax, FX or payroll code landing with an empty message
09Accounting change ledger entry requiredThe same change landing without an entry explaining what moved and why
10Full test suiteEverything else
11Database gate configuration checkA skipped isolation gate reading as a green build. This step fails deliberately if the database credential is missing
12Tenant isolation gateA tenant boundary moving. Runs against a real database, in a transaction that is always rolled back
13Privileged function isolation gateAn elevated database function being pointable at another tenant
The detail we are most pleased with

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.

Pipeline02 / 07
03 The ratchets

Six checks that stop the codebase sliding back.

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.

01

Library boundary

Domain code must live in a named domain folder. The root is closed, with an allowlist that can only shrink.

02

Discarded writes

Catches database writes whose result is thrown away, the shape of bug where a save silently does nothing.

03

No secrets in the repository

Scans for credential-shaped values before they can be committed.

04

Golden sign-off

Frozen client figures cannot change without a recorded sign-off.

05

Icon button labels

An accessibility ratchet: an icon-only control must carry a label.

06

House style

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.

Ratchets03 / 07
04 Golden fixtures

Real books, frozen, replayed on every push.

What they are

Captured client ledgers

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.

Why they cannot be touched

Rebaselining is forbidden

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.

The other half

Built scenarios

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.

Proving the tests work

Deliberate corruption

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.

Fixtures04 / 07
05 Backups and recovery

Encrypted, off-site, in an account the platform cannot reach.

Scope
Every table in the application schema, the authentication users and their identities, and every object in all eight private storage buckets. The migration set is recorded in the manifest so a restore rebuilds the schema before loading a row.Session tokens and multi-factor enrolments are deliberately excluded. Restoring live sessions is not recovery, it is a security problem.
Cadence
Nightly at 02:00 London, all year, using two time-guarded schedules so the hour does not drift with the clocks. On demand from the firm dashboard as well.
Encryption
Each segment gets a fresh authenticated encryption key. Content is compressed, split into frames, and each frame is bound to its snapshot and its position, so frames cannot be reordered, dropped, or moved between snapshots without detection.Segment keys are wrapped with a 4096-bit public key. The private half was generated on the founder's own machine and has never existed inside the platform. If the platform is compromised, the attacker gets ciphertext.
Fails closed
With no public key configured, the job refuses to run rather than writing an unencrypted snapshot. If the off-site credentials are missing it falls back to platform storage and flags itself as not off-site rather than reporting success.
Destination
Object storage in a separate cloud account from production, in the London region, created specifically for this purpose with multi-factor authentication on the root account and a write-only access key.
Efficiency and retention
Unchanged documents are stored as references to the parent snapshot, with a forced full snapshot after six links. Thirty nightly snapshots are kept plus the first successful run of each of the last twelve months, and the newest successful snapshot is never deleted, nor any parent a kept snapshot still depends on.
Restore
A documented script unwraps the keys, verifies every frame's integrity tag and aborts on tampering, reassembles the archive, replays the migrations, loads tables in manifest order with referential checks suspended, restores the authentication records, recreates the buckets, re-uploads the objects, and then verifies row counts against the manifest.
Proven, and not
Proven: thirteen consecutive successful nightly runs since 7 September 2026, all landing off-site, verified by decryption, integrity checking and row counts against the manifest.Not proven: a full load into a clean scratch database. That needs a throwaway database and the private key brought together, which is being arranged. Until it has happened we describe the restore as documented and partially verified, not as tested.
Recovery05 / 07
06 Running it

What the operator looks at, and what looks at itself.

Ledger health

Is every client's book sound

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.

Guard log

What the guards refused

Insert-only, per firm, with application-side and database-side rejections grouped under the same rule code.

Errors

Captured, digested, reviewed

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.

Backups card

Owner-gated, honest

Shows the last run, its destination, and whether it actually went off-site. A fallback run displays as a warning, not a tick.

Metering

Usage per client

Document extraction and other usage-sensitive costs are metered per client, so unit economics are measured rather than assumed.

Data access log

Shown to the client

Who read what, and when, across four underlying logs, behind a single gated function with no operator override.

Incident response

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.

Operations06 / 07
07 What comes next

The engineering roadmap.

PriorityWhy it is next
HMRC recognition in TaxChad's own nameThe 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 volumeIntegration is built. Moving it from integrated to carrying real customer volume is what makes the bookkeeping product self-serve rather than assisted.
A second engineerAs 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 testNamed on our security page as not done. It stays named until it is.
Accounts production integrationToday 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 historyStamping 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.
Everything on this page was built by one person, inside a working accountancy practice, against real client books. The interesting question was never whether it could be built. It is what it takes to stop it depending on one person.
Back

Pricing

What the software costs, and what the accountant tiers add on top.

Up

Architecture overview

The system diagram, the stack and the life of a transaction.

Roadmap07 / 07
TaxChad is built and operated by TaxChad Ltd, company number 17346680, registered in England and Wales. This page describes the platform as built on 19 September 2026. Counts of tables, migrations, tests and lines of code were read from the live database and the repository on that date and move as the product does. Anything described as in build or planned is a statement of intent rather than a commitment. Regulated accountancy services are provided by PowerStone Accountants Ltd, a separate company, under its own licence and insurance. Nothing here is tax, legal or investment advice.