Operations

The Audit Trail You Cannot Produce

Six months later someone asks who gave the discount, who cancelled the invoice, and who released the payment. The records exist; the trail does not. What makes an action reconstructable rather than merely recorded.

Audit TrailData IntegrityRecordsNoxOrigin

Six months later somebody asks three questions. Who gave the discount on this invoice. Who cancelled the earlier one. Who released the payment. All three records exist. The invoices are there, the payment is there, the cancellation is there as a status on the record rather than a hole where a record used to be. And yet you cannot answer a single one of the three, because the records contain what happened and not who did it, and the questions are all about who.

This is the failure mode that looks least like a failure. Nothing is missing. Nothing is corrupt. The records are complete in content and silent in authorship, and completeness of content is exactly what a system advertises. What is missing is the trail: the thing that lets you reconstruct an action rather than merely observe that a value exists.

This is the second of four articles on data trust. The first was about the shared login that makes attribution impossible at source. This one is about what happens after you have fixed that and still cannot answer the question — because a named actor is not a trail. The other two cover the person who configured the system and then left, and the difference between a backup and a file you actually hold. All four are about the same thing: whether the record will still be legible to you when you need it to be.

The distinctionRecorded is not the same as reconstructable

A record is recorded when a system stores the fact of something happening. It is reconstructable when someone, months later and without access to anyone's memory, can work out what the situation was before, what was done, by whom, under what authority, and what the alternatives were. The first is a property of the schema. The second is a property of the schema plus the review habit plus the fact that the values before the change were kept.

Most systems clear the first bar and fail the second without meaning to, because storing the current value is easy and storing the previous one is a design decision somebody has to make deliberately. The gap between the two bars is where investigations die. You know the invoice is 1,06,200 today. You have no way to establish that it was ever anything else.

Illustrative: what a change event has to carry to be reconstructable. Constructed for this article.

Carried on the changeAnswers a questionMissing, the change is only recorded
WhoWhich named account made the change.You learn that something changed but not which person to ask, and with a shared login, not even that.
WhenThe moment the change was made, to the record rather than to a day.A date is not enough when three changes happened on the same day, which is exactly when you need the sequence.
The value beforeThe size and direction of the edit, and therefore whether it was material.The edit is invisible. A change from 90,000 to 12,000 looks identical to a change of nothing.
Why, in the actor's wordsWhether this was a correction of a typo or a deliberate commercial decision.A correction and a concession become indistinguishable, and only one of them is a problem.
What else changed at the same momentWhether this was a considered edit or a side effect of something else.A field edited as a side effect of another action is indistinguishable from a field edited on purpose.

The fourth row is the one that surprises people. When a value changes silently, it is almost never a considered decision about that value. It is a side effect: a recalculation, a copy from a related record, a partial save, a form that submitted a default over a corrected field. This is precisely why a silent change is more dangerous than a missing value.

Worked exampleA discount that looks completely normal now

The 18% GST figure in this section is used only to keep the arithmetic checkable so you can verify it by hand. It is not a statement about the rate that applies to your business and it is not tax advice. Confirm your rate, your place of supply, and your invoice treatment with your own chartered accountant.

A job is quoted and then invoiced. All figures in this example are constructed for this article.

The quote, Q-1180, carries a tax-exclusive value of 1,00,000. GST at 18 percent, used only to keep the arithmetic checkable, is 1,00,000 multiplied by 0.18, which is 18,000. Quoted total: 1,00,000 plus 18,000, which is 1,18,000.

The invoice, I-2241, is raised later. Suppose the taxable value on it is edited in place from 1,00,000 to 90,000, and nothing else is touched. The tax follows: 90,000 multiplied by 0.18, which is 16,200. The total becomes 90,000 plus 16,200, which is 1,06,200.

The gap between what was quoted and what was invoiced is 1,18,000 minus 1,06,200, which is 11,800. You can check it a second way: 90,000 is 1,00,000 less 10,000, so the discount was 10,000; the GST given up with it is 10,000 multiplied by 0.18, which is 1,800; 10,000 plus 1,800 is 11,800. The two routes agree.

Now put yourself in the position of the person asked about this invoice six months later. Open it. It reads: tax-exclusive 90,000, tax 16,200, total 1,06,200. The arithmetic is right. The fields are consistent with each other. The GST split on the invoice is exactly what the taxable value implies. Nothing about this record is malformed. It looks like every other invoice in the month.

And that is the problem. If the same discount had never been applied — if the invoice said 1,00,000 and the quote said 1,00,000, but the client believed there was a 10,000 concession — then the record would be fine and the dispute would be about a conversation. But if the discount was applied by editing the value in place, the record is now indistinguishable from an invoice where the discount was agreed, approved, and documented. The trail that would have told you which of those two worlds you were in has been consumed by the edit.

This is why a value that changed silently is worse than a value that was never captured. The uncaptured value leaves a hole. The silently changed value leaves a plausible-looking surface, and it does so at the exact moment you would be relying on the record to be your evidence.

The same question, three timesThree questions, three different records

The three questions in the opening are usually asked as if they are one question. They are not, and separating them is most of the work. They land on three different records, and each record has a different natural home for the answer.

Illustrative: where each of the three questions actually lands

Quote and invoice

Who gave the discount

Lands on the quote and the invoice together. The answer lives in the change to the invoice value, and only if that change carries an actor, a time, and the value it replaced.

Invoice status

Who cancelled the invoice

Lands on the invoice, as a status change rather than a deletion. The record should still be there; the question is whether the status change carries an actor and a time.

Payment record

Who released the payment

Lands on the payment record, not on the invoice. Recording a payment and allocating it are two separate acts, and only the second one changes what the invoice looks like.

The third of those deserves expanding, because it is where an invoice and a payment come apart. In NoxOrigin an invoice and a payment are different records. A payment is recorded in its own right, with its own amount, its own method, its own date, and its own author. It is then allocated to one or more invoices. Paid is not a field stored on the invoice; it is a projection of those allocations, computed rather than maintained. That design has a direct consequence for your audit question, and it is a good one: the moment a payment is released, the invoice does not change, and the change you can look at is the allocation.

A constructed example. A payment of 1,06,200 is recorded on 11 May against a method the counter recognises, and the figures here are constructed for this article. If it is allocated in full to the invoice raised after the cancellation, the projection on that invoice is settled, and the outstanding balance is 1,06,200 minus 1,06,200, which is zero. If the same payment had instead been allocated to the cancelled invoice, the projection on the cancelled invoice would appear settled while the live invoice still shows the whole amount outstanding. Both records are internally consistent. The difference is one allocation, and it is an act with an author.

That is why an audit trail for money is not really about invoices. It is about payments and allocations, because that is where the acts are. An invoice is a claim. A payment is an event. An allocation is a judgement. The judgement is the thing you will need to explain.

There is one more thing a trail needs that is easy to overlook, and it is not a field. It is sequence. Three changes to one invoice on one day, each with an actor and a time, are only reconstructable if the times are precise enough to order them. If the times are recorded to the day, you have three events and no order, and the causal story is unrecoverable: you cannot tell whether the discount caused the cancellation or the cancellation caused the discount. Precision of time is not a technical detail. It is what turns a list of events into a sequence.

The three fields that decide whether a trail exists

If you could add exactly three things to a system to make an action reconstructable rather than merely recorded, these are the three. The ordering matters — it is listed in the order in which the information is usually lost.

1. The value before. Without this, every change looks the same and every change looks small. It is also the field that protects you from the worst case, which is a value that changed silently into something that is arithmetically valid and commercially wrong. A silently changed value produces a record that passes every validation you have, because validation checks whether the parts agree with each other, not whether the answer was ever deliberately arrived at.

2. The time, at a resolution that orders events. A date tells you which day. A time tells you which came first. If two changes on the same day could have happened in either order, the causal question has no answer, and the causal question is usually the one being asked.

3. The reason, in the actor's own words, when the change is commercial. A typo correction and a deliberate concession produce identical database states. Nothing in the schema can tell them apart, and nothing downstream can recover the difference. A free-text reason is weak evidence — it can be written badly or written dishonestly — but its absence guarantees the distinction is lost, and in a dispute the absence is what you will be asked about.

Note what is not on this list: a description of the user interface, a screenshot, or a notification that something happened. None of those survive an investigation.

It is worth being honest that a trail is not a guarantee. A reason field can be filled in dishonestly, and someone with sufficient access can in principle construct a false trail. What the trail buys is that those two situations become distinguishable. A system with no trail cannot tell an honest mistake from a dishonest one. A system with a trail usually can, because an implausible reason on an implausible change stands out against everything else. That is the difference between prevention and detection, and it is the honest ceiling of what a record can do.

The practical consequence for a small business is a scope decision rather than a technical one. You do not need a trail on everything. You need it on the handful of actions where a silent change would cost you money you cannot recover and could not reconstruct from memory — a discount above the ceiling, a cancellation, an allocation of a payment, a change to a customer's phone number or address, and a merge decision on a duplicate record. Those are the actions worth a reason field and a precise time. Everything else can be recorded loosely, because nobody will ever ask.

Testing whether your own trail exists

  • Pick one invoice from three months ago. Write down the value it shows now, then try to establish what it showed before. If you cannot, the prior value is not being kept.
  • Pick one cancelled invoice. Confirm the number, the lines, and the history are all still there, and that the cancellation carries a name and a time rather than having removed the record.
  • Pick one payment. Trace it from the payment record to the allocation that made an invoice look settled. If the link between the money and the invoice is only a status field, the judgement is not attributable.
  • Check the time resolution on a day when two changes hit the same record. If you cannot order them, the causal question is unanswerable.
  • Check whether any action requires a written reason. If none does, then a typo and a concession are indistinguishable forever.
  • Write down the five actions in your business where a silent change would hurt most, and confirm each one has the three fields above. Five is enough to be worth doing and few enough to survive a busy week.

Three related failures in the same family — the record that cannot be exported, the knowledge that cannot be handed over, and the row that too many people can see — are treated separately. why a backup and an export are not the same thing what a handover actually has to transfer how visibility on a customer record is decided

Frequently asked questions

My system has an activity log. Is that not an audit trail already?

Usually it is a record of events rather than a trail, and the difference is the value before. A log that says this field changed at this time by this person tells you something happened. It does not tell you what it was, how big the change was, or whether the change was a correction or a decision. Those are the parts you need when the question is asked months later.

Why is a silently changed value worse than a value that was never captured?

Because a missing value leaves a visible inconsistency you can detect, while a silently changed value leaves a record that is internally consistent and arithmetically valid. The uncaptured value tells you something is wrong. The changed value tells you everything is fine, and does so at the moment you were relying on the record as evidence.

Do I need this on every record in the system?

No, and trying is why most attempts fail. You need it on the few actions where a silent change would cost you money you cannot recover — usually discounts, cancellations, payment allocations, changes to customer contact details, and duplicate-record merge decisions. Five is a workable number. Every record is not.

Does cancelling an invoice destroy it?

It should not, and in NoxOrigin a cancellation changes the invoice status while the number, the lines, and the history remain. If money moved against that invoice, the movement is represented by a credit note, which is a separate record. Deleting a cancelled invoice is the failure mode, not cancelling it.

Where does the question of who released a payment actually get answered?

On the payment record, not on the invoice. In NoxOrigin an invoice and a payment are different records, and paid is a projection of allocations rather than a stored field. So the change worth tracing is the allocation, which is a judgement with an author — and that is the act you will need to explain.

Can a reason field be relied on as evidence?

It can be written badly or dishonestly, so it is weak on its own. Its value is comparative: a plausible reason on an implausible change usually stands out against everything else, whereas its absence guarantees the distinction between a typo and a concession is lost permanently.

Sources and further reading

Continue reading

Looking for the rest of this topic? More in business operations →

OperationsAnatomy of a permissions system for owner, finance, and delivery staffRead guide →BillingWhy a ₹15,000 invoice and a ₹15,000 payment are not the same recordRead guide →ReportsOne payment, many invoices: the allocation waterfallRead guide →