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, email delivered, email bounced, link fetched, opened in the recipient's account, 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.
Each entry also records which surface wrote it — an assistant, the account portal, the emailed link, an email reply, or the mail provider reporting on its own work — and, for an assistant, which application it was. That half of the record is for whoever runs the service, answering questions the events alone cannot: which surfaces people actually use, and which assistants they connect. None of it reaches the sender. Which assistant somebody reads their mail with is a fact about them, not about their correspondent.
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 — with one further condition on the first: the pull is shown only if the recipient shares read receipts with that sender. Off, account-wide or for that one sender, the summary reads read receipts not shared instead, whether or not the pull happened, because the two have to be indistinguishable or the setting would leak the fact it exists to withhold. The reply and the acknowledgement carry no such condition — they are acts the recipient chose to make visible, not a passive trace of an assistant's own work.
Two entries are in the record and drive nothing. The link fetch is the older of them, 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 second is a package being opened in the recipient's own account, in a browser. It is a person rather than a scanner, which makes it more informative than a fetch and still not a read receipt: a page was rendered, and the reader may have glanced at the subject and closed the tab. So it is recorded, it tells whoever runs the service that the portal is used, and it changes nothing a sender sees. Acknowledged remains the only entry that means a person decided to say so.
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: the provider taking a message says only that it took it. Two later entries close that loop when the provider reports back — delivered, when the receiving mail server accepted it, and bounced, when it refused. They arrive minutes or hours after the send, from a webhook rather than from the send itself, which is why a trail can sit at accepted for a while and why a wall of rows stuck there means the webhook rather than the mail.
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.