What is an audit trail?

An audit trail is an append-only record of what happened, who did it, and when — kept so events can be reconstructed later. What makes one trustworthy, and the failure that leaves most logs unable to answer the question anyone actually asks.

6 min read

14:02 — status changed to approved.

Nobody has ever wanted to know that. The questions are who approved it and on what basis, and the line answers neither. It is a log entry with the audit taken out.

An audit trail answers three questions

An audit trail is an append-only record of what happened, who did it, and when, kept so events can be reconstructed afterwards by someone who was not there. Three fields, and dropping any one costs most of the value of the other two.

  • What happened, specifically enough to be unambiguous. "Updated" is not an event. "Changed the delivery date from the 3rd to the 17th" is.
  • Who did it — an actor, not a subsystem. "The scheduler ran" names the mechanism; something set the mechanism going, and that is the entry worth having.
  • When, on a clock the other entries share, so that ordering means something.

Append-only does quiet work in that definition. A record that can be revised is not a record of what happened. It is a record of what someone currently prefers to have happened.

What makes a trail trustworthy

Four properties, in rough order of how often they turn out to be missing.

Completeness with visible edges. No trail records everything. What matters is that the boundary is stated — this trail covers these events and not those. A trail that silently stops covering a class of event is worse than one that never covered it, because readers treat absence as evidence of absence.

Attribution on every entry. The actor belongs on the line itself, not inferable from three tables and a join. If working out who did something needs a second investigation, the trail has deferred the only hard part.

One clock, one representation. Times in mixed local zones cannot be ordered by reading them, and a reader who does not notice will order them wrong with complete confidence. Worth separating too: when the event happened versus when it was recorded. Retries and queues pull those apart.

No edit path. At minimum nothing in the system rewrites an entry; better, the record lives where the people it describes cannot reach it. That is a property of the system, never something an entry can assert about itself — a line reading "this record has not been tampered with" is worth nothing, for the same reason a process record is not a proof.

A fifth property is usually absent and usually the one you want: the reason. Trails record outcomes and lose intent, because no field ever existed to hold it. Long after the fact, why beats who.

The common failure is outcome without actor

The usual defect is not a missing log. It is a log full of outcomes.

Systems record state transitions because state transitions are what the code is holding at the moment it writes. The actor sits upstream — a person clicked something, an automation fired on a schedule, a request arrived carrying a token — and by then that context is several layers back. The result reads as a complete history and answers nothing anyone asks of it.

The tell is simple. Read the trail end to end and try to answer who did this. If you cannot, the trail records the system's behaviour rather than anyone's conduct, and every consultation of it ends in an interview anyway.

The assistant-era version is worse than a missing actor, because it is a present and ambiguous one. An entry attributed to a person may mean that person acted, or that software acting on their behalf did. Both are accurate statements about the account. Only one is a statement about the human.

An entry records what tripped the instrument

This part generalises past any one system: a trail records events as its instrumentation defines them, and instrumentation attributes to whatever tripped it.

RelayLink keeps a small fixed vocabulary of delivery events per package — sent, email send attempted, email accepted, email failed, link fetched, pulled by the recipient's assistant, replied to, acknowledged. That is the entire set, and it is deliberately split in two halves that are not equal.

Three of those events are allowed to mean something to a sender: the assistant pull, the reply, and the acknowledgement. Each requires either that an assistant ingested the briefing or that a human pressed a button on purpose. Those three, and only those three, are what a sender sees summarised as they have seen it.

The link fetch is in the record and drives nothing, and the reason is the whole lesson of this section. It is written when the package's link is fetched, and a mail scanner that prefetches links will fetch it — corporate scanners detonate every URL in an inbound message as a matter of policy. So the entry truthfully records a fetch and says nothing whatsoever about a human. It was originally wired into they have seen it, on the reasonable-sounding theory that a fetch approximates a read. It does not: the theory let a scanner tell a sender their recipient had read something nobody had opened, and let the same prefetch mark a package handled so the recipient's own assistant stopped surfacing it. The event stayed; everything built on top of it was taken away.

The send-attempted entry is instructive in a different way. It is written before the message is handed to the mail provider, so on its own it records only that the system tried. Two more entries close that loop: accepted, when the provider took the message, and failed, when the call did not succeed. Accepted is not delivered, and the distinction is the whole point — there is no delivered event in the vocabulary, no bounce and no complaint, so a message the provider accepted and then could not deliver leaves a trail indistinguishable from one that arrived, until a reply lands or doesn't.

Neither problem is peculiar to one product. Every read receipt ever built has the first, and every send pipeline has some version of the second. The response that works is writing down what an entry means beside the entry, rather than strengthening the wording until it sounds like knowledge.

One limit worth stating plainly: RelayLink is not an audit or compliance product and does not offer itself as one. The events exist in storage and nothing deletes them, but no tool hands anyone a browsable event log. A sender sees a single seen-or-not flag on the most recent message in a thread — no timestamp, no count, no history.

A thread qualifies only if entries name who is behind them

Correspondence gets two of the three fields for free. What happened is the message. When is the timestamp. Who is the field that quietly broke when assistants started drafting on people's behalf.

A sender name is an account, and an account is not an author. Filling the actor field back in is what per-field provenance labelling does — recording, per message, whether the words were typed by the person, drafted by their assistant and approved unchanged, or typed into a link-authenticated reply form. That distinction is what turns a scroll of text into something you can reason about later, and it is the argument for keeping the correspondence at all.

The best entries in any trail are written by someone assuming a stranger will read them cold, months later, unable to ask a follow-up question — the same discipline behind a decision record. It costs a sentence at the time and saves an afternoon later.

To see what an actor field looks like when the system fills it in rather than the sender, connect your assistant and read a message from the receiving end.

Frequently asked questions

What is the difference between a log and an audit trail?
A log is written for whoever operates a system and records whatever happened to be useful while building it. An audit trail is written for someone reconstructing events afterwards, which means each entry has to name the actor, the time and the thing acted on, and no entry may be altered or quietly removed once written. Most logs fail that second requirement without anyone noticing, because trimming old lines counts as ordinary housekeeping.
What makes an audit trail trustworthy?
Four things, roughly. It is complete enough that a gap is visible rather than silent. Each entry attributes the action to an actor rather than to a subsystem. Times come from one consistent clock, so entries can be ordered against each other. And entries cannot be rewritten after the fact by the people whose actions they record.
Does a message thread count as an audit trail?
Only if each entry says who is behind it. A thread is a record of text, and once assistants draft on people's behalf, the sender name on a message no longer tells you whether that person composed the words or approved somebody else's draft of them. Without that distinction recorded per entry, a thread preserves what was said and loses who said it.