Integrity should not depend on application code behaving
Every EDC promises an audit trail. The question an inspector actually asks is: what happens when the application has a bug? Our answer: the database refuses.
Most systems implement their audit trail in application code: the code that writes your data is also the code that promises to log it. When that code has a bug — or a future developer adds a new table and forgets the logging — coverage silently drifts. Nobody notices until an inspection.
Push the promises down a layer
- The audit engine is a database trigger that writes an immutable row for every insert, update and delete — and attaches itself automatically to every new table. Coverage cannot drift, because it is not optional.
- The audit log is physically append-only. UPDATE, DELETE and TRUNCATE are revoked; a second trigger rejects them even for privileged mistakes.
- Change reasons are demanded by the database. Editing a saved clinical value without a reason is not rejected by a form — it is rejected by PostgreSQL.
- Signed records are frozen by a trigger. After e-signature, no code path — including ours — can modify the record.
- Tenants are isolated by row-level security. A connection without a tenant context reads nothing.
Consistency comes from one engine, not two
The same validation engine runs in the browser and on the server — one implementation, shared verbatim. What the site sees at entry is exactly what the reviewer sees in data review and exactly what lands in the export. Explicitly-missing values keep a coded reason everywhere, so datasets stay consistent from first keystroke to SDTM domain.
And when the bar is even higher
Signatures carry a content hash that can be re-verified outside the application. For audit programmes that demand third-party proof, those hashes can optionally be anchored to a public blockchain — only hashes leave the system, never data, which keeps it GDPR-safe.
ALCOA+ is easy to claim. It is harder to show. Ask us to demonstrate any of the above in the running product.