PerspectiveData integrity

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.