How an AI bookkeeping audit trail is produced
Two records, produced differently. The journal is append-only, so a correction is a reversal that sits beside the original rather than replacing it. The audit log is written by the dispatcher from the call it actually executed, in its own transaction, so it survives the failure of the operation it describes.
An audit trail an agent writes about itself is a statement of intent, not evidence. If the same code path that performs an action also reports it, the report is only as reliable as the code, and a bug that skips the action can skip the report with it.
So both records here are produced by something other than the thing being recorded.
What is actually enforced
- Journal entries and journal lines reject UPDATE, DELETE and TRUNCATE for every caller.
- The only correction mechanism is a reversal, which stays on the record beside the original.
- A reversal returns the transaction ids it released, so the underlying transaction can be re-categorized.
- The audit log is written by the dispatcher from the call it actually executed, not from a self-report.
- Audit rows are written in their own transaction, so a failed operation still leaves a record it was attempted.
- The audit log is append-only.
The journal: corrections sit beside mistakes
Journal entries and journal lines refuse updates and deletes at the database level. There is no path that edits history — not through the tools, not through the service layer, not through raw SQL from the application role.
The only correction mechanism is a reversal: a new entry that undoes the original and stays on the record beside it. A reversal must belong to the same book as the entry it reverses, and a reversal cannot itself be reversed, so the chain cannot become circular.
Reversing also returns the identifiers of the transactions it released, so the bank transaction underneath becomes categorizable again. The correction is a first-class operation rather than a cleanup step someone has to remember.
The audit log: evidence, not self-report
Every tool call arrives through one dispatcher, and that dispatcher writes the audit row from the call it actually executed — the tool name, the outcome, when it ran. Nothing reports on itself.
The row is written in its own transaction, separate from the operation. So a tool call that fails and rolls back still leaves a record that it was attempted, which is exactly the case where a log written inside the same transaction would vanish along with the thing worth knowing about.
The log is append-only. It cannot be edited or deleted through any path the application exposes.
The honest weakness
The completeness of the audit log rests on one property: the route handler is its only producer. A second entry point into the dispatcher would work perfectly and log nothing, and no test would fail.
That is a real fragility and it is worth stating plainly rather than describing the log as complete. It is the reason there is exactly one door.
What this does not cover
- The audit log is complete only because the route handler is its sole producer. A second entry point would silently produce no rows.
- The log records what ran, not why. It cannot tell you whether a categorization was a good judgement.
- Two valid entries recording one real movement — the transfer case — look correct in both records.
Common questions
- Can I see everything the AI has done?
- Yes. Every tool call is in the audit log, and every entry it posted is in the journal, including anything it later reversed.
- Can the audit log be edited?
- Not through any path the application exposes. It is append-only, like the journal.
- What does a correction look like afterwards?
- Two entries: the original and its reversal, both visible, with the reversal identifying what it reverses. The net effect on your reports is zero, and the history of what happened is intact.
- Is this enough for an accountant?
- It gives an accountant what they usually ask for first — an unbroken journal, corrections that are visible rather than silent, and a record of every action. What it does not give them is multi-client access or the ability to work in your books alongside you.
Checked against the implementation on 2026-08-09.