The audit trail your forms should keep (and the one they shouldn’t)
A parent called the clinic, upset. She had submitted the intake form on Tuesday. The clinic had no record of it. She was sure she had submitted it because she remembered the confirmation page. The clinic was sure they had not received it because nothing matching her name was in the system. Both were right. The form had been submitted. The form vendor had logged the submission and then, due to a webhook misconfiguration that nobody had caught, had failed to forward it to the clinic. There was no record on the clinic’s side that anything had ever happened. A proper form audit trail is the difference between knowing a submission arrived and hoping it did.
The conversation took 25 minutes. The parent left frustrated. The clinic spent another two hours over the week figuring out what had gone wrong. None of this had to happen, because every piece of information needed to resolve it should have been in an audit trail that nobody had built.
What a form audit trail is, and is not
An audit trail is a tamper-evident log of every meaningful event in the form’s lifecycle. Not what a parent typed. Not the contents of the submission. The events around it: when it was started, when it was submitted, when it was viewed, by whom, and what happened to it next.
The distinction matters. A good audit trail can answer the question “did this submission happen and what happened after” without exposing the PHI inside the submission. That is exactly the property you want under HIPAA, and exactly the property that lets the front desk resolve a dispute without opening the encrypted record.
The events worth logging
A useful audit trail for a clinic intake form captures these events at minimum:
- Form started: timestamp, anonymous session ID, page URL.
- Form abandoned: timestamp, session ID, last field touched. No field contents.
- Form submitted: timestamp, session ID, submission UUID, IP address (hashed for storage, retrievable on subpoena), browser fingerprint.
- Notification sent: timestamp, recipient address, delivery status, retry attempts.
- Webhook delivered: timestamp, endpoint URL, HTTP status code, retry attempts. This is the one the clinic above did not have.
- Record viewed: timestamp, authenticated user ID, submission UUID. This is the one that matters for the HIPAA access log.
- Record exported: timestamp, authenticated user ID, destination (downloaded, emailed, forwarded to PMS).
- Record deleted: timestamp, reason, authenticated user ID. Or, for automated purges, the policy that triggered it.
Eight events. None of them contain PHI. All of them are necessary for both operational debugging and compliance.
The audit trail you should not keep
What I have seen built more often is the wrong audit trail. Specifically:
- Field-level change tracking that captures what the user typed before they corrected it.
- Full DOM event streams (the territory of session replay, see the separate post on that).
- Email logs that include the body of the notification email, which often includes PHI even when it should not.
- Application server logs that print the form payload at INFO level.
- Database transaction logs that capture every insert with all column values.
These are all audit-adjacent things. They are useful in narrow contexts. They are also liabilities, because each of them creates a second copy of PHI in a place that may not be encrypted, may not be access-controlled, and may not be retention-managed. The audit trail should be lean. PHI lives in one place. Events about PHI live somewhere else.
The tamper-evident requirement
An audit trail that anyone can edit is not an audit trail. It is a log file. The distinction matters when somebody asks the clinic, six months after an incident, to prove what happened.
Tamper-evident does not mean cryptographically signed blockchain. For a small clinic, it means three practical things: the audit trail is append-only at the application layer, the underlying storage has write protections that exceed normal user access, and there is at least one out-of-band copy (a daily export to a separate system) that would catch wholesale tampering after the fact.
A WordPress site that logs to a custom table accessible to any plugin admin is not tamper-evident. A WordPress site that logs to a separate database, behind a service account with restricted credentials, with daily snapshots to encrypted offsite storage, is meaningfully closer.
The retention question
How long to keep the audit trail is a separate question from how long to keep the form submission itself. The submission can be purged on a 14 or 30 day schedule. The audit trail, in most clinical settings, needs to be kept for six years. That is the HIPAA documentation retention requirement for access logs and security incident records.
This is one of the reasons it matters that the audit trail does not contain PHI. Keeping PHI for six years would be a problem. Keeping six years of “submission UUID 4f8a-… was viewed by user 12 on March 8 2023” is not a problem.
Using the audit trail
The audit trail’s job is to answer questions the clinic actually asks. The common ones:
- “This parent says they submitted a form on Tuesday. Did they?” Pull the submission log for Tuesday by IP or by session ID. If the form was submitted, it is there. If the webhook failed, the webhook log shows it.
- “Who looked at this patient’s intake last week?” Filter the view log by submission UUID. Three timestamps, three user IDs.
- “How many intake forms got abandoned in March, and at what step?” Aggregate the abandonment events. No PHI required.
- “Did the PMS receive the submission for the appointment that did not show up?” Check the webhook delivery log for that submission UUID.
- “We just terminated an employee. Show me everything they viewed in the last 90 days.” Filter by user ID across the view log.
Each of these questions is operational, frequent, and impossible to answer without the audit trail. Each of them is easy to answer with it. The investment is small and pays back the first time the clinic gets a phone call from an upset parent who is sure they did everything right.
What we build into our forms
The forms we build for medical practices log the eight events above to a separate audit database. The PHI lives in encrypted columns in the primary database. The audit trail lives in a different database with restricted write permissions. Daily snapshots go to encrypted offsite storage with a six-year retention. The front desk can pull a submission’s full history with a single query that returns no PHI.
Almost no off-the-shelf form vendor does this. Most log either too little (to claim minimal data retention) or too much (collapsing logs and PHI into the same table). The right architecture is in the middle, and it requires thinking about logs and PHI as two separate problems with two separate retention schedules.
If your current form vendor cannot answer the parent-on-Tuesday question, you have an audit trail problem. See the related post on quiet booking failures for the same pattern in a different system, and our plans for how we structure form work to avoid this category of issue.
