Building an audit trail you would actually show a regulator

How we designed immutable provenance records on top of Postgres, and the tradeoffs we made for Part 11.

Engineering · 2026-03-28 · 12 min read

Every AI product in regulated industries claims an audit trail. Most of them mean a log table with a timestamp column. A regulatory reviewer knows the difference, and increasingly, they will ask.

This is what 21 CFR Part 11 actually requires for AI-generated clinical data artifacts — and the specific design choices we made to meet it in TrialNexus.

What Part 11 actually requires

21 CFR Part 11 was written in 1997 for electronic records and signatures. It was not written for AI. But its requirements map cleanly onto AI-assisted systems if you read them carefully.

The relevant sections for AI output are: (a) audit trails that are computer-generated and capture who did what and when, in a way that is not modifiable by the user; (b) the ability to reconstruct any record as it existed at any point in time; and (c) attribution — every record must be linkable to the individual who created, modified, or approved it.

For a traditional EDC, this is straightforward. A DM changes a value; the old value is logged with the DM's credential and a timestamp. The regulator can see the full history of the field.

For an AI system, the equivalent question is: who proposed this mapping, why, with what confidence, and who approved it? The "who proposed" is the agent. The "why" is the reasoning chain — the source passages from the protocol, the CDISC controlled terminology it matched, the rules it applied. The "who approved" is the DM lead who clicked Approve in the Decision Queue. All of that must be logged, immutably, in a way that survives the DM lead leaving the company and the agent model being updated.

Append-only design

The core architectural choice is append-only storage. No record in the TrialNexus audit schema is ever updated or deleted. When a DM lead revises an agent proposal, we do not update the proposal row — we create a new row representing the revision, with a pointer to the row being revised. When the approval comes, we create a third row representing the approval event, with the approver's identity, the credential they authenticated with, and the exact timestamp.

The practical effect is that the full history of any artifact is recoverable by reading the append log in sequence. If an inspector wants to know exactly what the SDTM mapper proposed for a specific AE term on a specific date, we can produce that record with its full reasoning chain, before and after any human revision, and the identity of the person who approved the final version.

We use Postgres with a trigger-based immutability enforcement layer — any UPDATE or DELETE on audit tables raises an exception. The schema is deployed with restricted database-level permissions so that no application user can bypass it. The exception is vacuum operations on expired partitions, which are logged separately.

What gets logged

Every agent inference call produces a structured log entry containing: the agent ID and version, the model identifier (including the specific model version, not just the family), the tenant and study context, the full input context passed to the model, the full output, a confidence score produced by the agent's scoring function, and a wall-clock timestamp.

The Decision Queue records the human interaction: which proposal was presented, which action the user took (Approve / Revise / Reject), the revised text if applicable, the user's authenticated identity, the authentication method, and the timestamp.

Source attribution is stored as a separate linked record: for each agent output, the source passages from the protocol that contributed to the output, with character-level offsets so the exact text is reproducible even if the source document is later revised.

The hard part: model versioning

The trickiest compliance requirement is reproducibility across model updates. If we update the underlying LLM from one version to another, an inspector reviewing a study that ran on the old model needs to know that the outputs they are looking at were produced by a specific model version, not whatever model is running today.

Our approach is to log the full model identifier — provider, model family, and version — as part of every inference record. We do not overwrite historical inference calls when models are updated; the record reflects what was actually used. We also maintain a read-only archive of older model versions for the audit replay period required by the study's regulatory jurisdiction — typically the study duration plus five years.

The operational cost of this is non-trivial. Model archives take storage. The compliance benefit is that any output produced by TrialNexus can be attributed to a specific model version and, theoretically, reproduced by running the same input through the same version — though we note in our validation documentation that LLM outputs are stochastic and reproduction is best-effort rather than guaranteed.

What an inspector actually sees

When a sponsor's QA team conducts an audit of a TrialNexus-managed study, we produce an Audit Report — a human-readable document generated from the append log that shows, for each decision point in the pipeline: what the agent proposed, the confidence score and the sources it cited, whether a human revised the proposal and what the revision was, who approved the final output and when.

The format mirrors a traditional audit trail report from an EDC — it is designed to be familiar to an inspector who has never seen an AI-assisted DM process before. Every row links to the underlying log records. Nothing is summarized in a way that obscures the underlying data.

We have not had an FDA inspection of a TrialNexus-managed study yet. We have reviewed our design with two regulatory consultants and one former FDA reviewer. The consistent feedback has been that our approach meets the letter and intent of Part 11 for AI-assisted systems, with one caveat: the regulatory guidance on AI in clinical trials is still evolving, and what satisfies an inspector today may be exceeded by guidance issued next year. We are monitoring the FDA's AI framework process and will update the validation package when new guidance clarifies requirements.

The tradeoff we made

Append-only, immutable, fully-attributed logging is not free. It adds overhead to every agent call. It inflates storage costs. It makes schema migrations harder — you cannot retroactively add a column to a historical log record without careful migration planning.

We made this tradeoff deliberately. The alternative — a lighter audit system that is easier to build and cheaper to operate — would produce an audit trail that satisfied no experienced inspector. In a regulated trial, the audit trail is not a nice-to-have. It is the thing your DM lead and your sponsor's QA team will be asked to defend. We built for that conversation, not for the easier one.