This is the engineering documentation for TaxChad. Every number here was read from the live database and the repository, not estimated. Five minutes gets you the shape of it. The five pages at the bottom go as deep as you want.
Everything is either code in one repository or a named service with a data processing agreement behind it. There is no second system and nothing undocumented between a bank line and a filed return.
There are two ways into the database and no third. The app reads your own rows straight from PostgreSQL, and row level security is what filters every one of them. Anything that needs a secret, touches HMRC or moves money goes through a server function instead, which is the only place a credential exists.
The only code that turns journal lines into a trial balance, a profit and loss or a VAT box. The screen your accountant reads and the return that goes to HMRC cannot show different numbers, because they are not two calculations.
a build gate fails if the two sides ever disagreeA database of 233 tables sounds like something nobody can hold in their head. It is not, because almost every link in it points at one of two places.
Two places hold the whole schema together. That is what lets a database this size stay something a person can reason about, and it is why one client's books cannot quietly become visible inside another's. The route between them does not exist.
Encrypted backup, ledger sweep, exchange rates, HMRC token expiry, Companies House, reminders, recurring invoices, receipt matching. Four of them exist purely to notice when nothing is happening.
Typecheck, lint ratchets, production build, the ledger invariants, real client books replayed, and two database tenant isolation suites. A skipped gate fails the build rather than passing quietly.
Every table, the login records and all documents, encrypted with a key whose private half has never existed inside the platform, into a separate cloud account.
Feed, CSV, OFX or PDF. Documents are read by text extraction and always shown to a person before anything posts.
Your rules, in a fixed order, first full match wins. Nothing is guessed. No match means it stays visible, not invented.
Tax rounded once, net is the remainder. Net plus VAT equals gross, to the penny, every time.
Double entry. The database refuses anything that does not balance, in both currencies, at the moment of saving.
Your accountant starts at the trial balance, not the shoebox, and signs what goes out.
Filed through the Making Tax Digital API with the required fraud prevention headers. Every call logged.
Five things are not true yet. Each is named here rather than left for you to find, next to the work that closes it. Four of the five are in progress now, and the fifth is sequenced on purpose.
Each of these is written up in full on the pages below rather than summarised away.
The nine things the database refuses to let anyone write, why some rules are deliberately warnings instead, multi-currency, and one chart of accounts across every entity type.
The two boundaries, what our isolation tests actually assert, what they do not catch, every audit trail, and the gaps we have not closed.
Five match types, a fixed order down to the tie-break, and the hard line between reading a document and making an accounting judgement.
HMRC and the fraud prevention header problem, open banking, payments, Companies House, exchange rates, and what happens when one of them breaks.
Thirteen gates on every push, real client books frozen and replayed, the change ledger, and how a backup is restored.
The plain-English security page: what we hold, what has been audited, what has not, and how to report a problem.