HMAC-chained audit log
Privileged actions, signed and chained.
Privileged actions write an audit row. Per-row HMAC-SHA256 signed with Z4J_AUDIT_CHAIN_SECRET, a dedicated key separate from the application secret and required outside development, plus prev_row_hmac so consecutive rows form a chain, and a separately authenticated head and row count. An edit or a deletion that does not come from the audit service leaves the two out of agreement, which verification reports. This covers application bugs, a downgraded adapter and an operator mistake; it does not cover a role holding write access to the database itself, and the threat model says so plainly.
The related dashboard view, captured with sample project data. Open the live demo to try it.
Ships with
- Per-row HMAC (detects modification)
- Chain anchor plus an authenticated head and row count (detects deletion)
- Signed with a dedicated key, so an auditor can verify without holding the session key
- z4j audit verify walks the chain on demand, or on a schedule via an opt-in worker
- Row id folded into HMAC input (prevents row cloning)
- Verifiable against a head exported off-box, which is what covers the database-role case
Related