Overview
Every audit row is hash-chained to the row before it, so altering or deleting a historical row is detectable when the chain is verified. The chain is written automatically; no one has to remember to record anything.
How the chain works
Each new audit row stores the hash of the row before it. Verifying the chain recomputes every link and reports the first row that no longer matches. The database also blocks updates and deletes on the audit table outright through two triggers.
What it detects
The triggers block ordinary UPDATE and DELETE statements. The chain is the detection layer for a change made with those triggers disabled: a single edited row is reported broken at its chain position, and restoring the original value makes it verify again.
What it does not detect
A coordinated rewrite that also replaces the newest row's hash is not detected by this chain alone. Rows written before the chain existed are not covered; the verify report states how many such rows exist rather than pretending they are protected.
How concurrency is handled
Concurrent writers serialise on a database advisory lock so two transactions cannot fork the chain. Load-testing with four writers at once produced a single unbroken sequence.