Enterprise feature
Audit log
Hash-chained, tamper-evident log of every sign-off, repair, waiver, gateway upload and role change. Each event references the previous event's hash — any tampering breaks the chain.
Enterprise
Events
10
Chain integrity (API)
Valid
Re-verified in browser
Match
chain links re-verified locally (sha256 / legacy fnv1a)
Latest eventsshowing 10 of 10
Newest first.
| Seq | Action | Target | Actor | When | Hash |
|---|---|---|---|---|---|
| 1 | system.boot | api | system | 01/05/2026, 08:00:00 | a1b2c3d4e5f6… |
| 2 | audit.run | audit-run/aud-2026-01 | data.steward@fhe.ac.uk | 04/05/2026, 10:12:00 | b2c3d4e5f607… |
| 3 | submission.create | hesa/Student/2026 | registrar@fhe.ac.uk | 08/05/2026, 09:30:00 | c3d4e5f60718… |
| 4 | submission.sign-off | hesa/Student/2026 | head.of.planning@fhe.ac.uk | 12/05/2026, 14:00:00 | d4e5f6071829… |
| 5 | drift.report | tables/student | system | 20/05/2026, 02:00:00 | e5f60718293a… |
| 6 | waiver.create | F12-SCJ-without-RDM:HUSID2026100119 | registrar@fhe.ac.uk | 12/05/2026, 10:30:00 | f60718293a4b… |
| 7 | repair.applied | rep-004 | finance.lead@fhe.ac.uk | 28/05/2026, 16:20:00 | 0718293a4b5c… |
| 8 | role.change | principal:sub=abc tier:pro→enterprise | stripe-webhook | 01/06/2026, 09:00:00 | 18293a4b5c6d… |
| 9 | drift.capture | tables/programme | drift-worker | 02/06/2026, 02:00:00 | 293a4b5c6d7e… |
| 10 | submission.create | hesa/Provider/2026 | registrar@fhe.ac.uk | 03/06/2026, 10:00:00 | 3a4b5c6d7e8f… |
What does a tampered chain look like?
Three deliberately-broken fixtures so the integrity story above is falsifiable. Each mode mutates a clean baseline in one specific way; the same
verifyChain() the live log uses rejects all three.Event 2's metadata was rewritten in-place. The stored hash still matches the original content, so recomputing it now yields a mismatch — the verifier rejects with "content hash mismatch".
Verifier rejected
broke at seq 2
— content hash mismatch at seq 2See the 3 events
[
{
"seq": 1,
"tenantId": "demo",
"actor": "service:audit-runner",
"action": "rule.run",
"target": "run:2026-06-28T08:00:00Z",
"at": "2026-06-28T08:00:00.000Z",
"prevHash": "",
"metadata": {
"ruleId": "F03.04",
"findings": 12
},
"algorithm": "sha256",
"hash": "ff13d89210845c6734c3d8582642a01c9dcc40bca13d33333fd4f53606ea4c84"
},
{
"seq": 2,
"tenantId": "demo",
"actor": "analyst@demo",
"action": "finding.waive",
"target": "finding:HUSID.FORMAT/0042",
"at": "2026-06-28T08:05:13.000Z",
"prevHash": "ff13d89210845c6734c3d8582642a01c9dcc40bca13d33333fd4f53606ea4c84",
"metadata": {
"reason": "tampered — actual reason was a known false positive"
},
"algorithm": "sha256",
"hash": "5232966c3122506c09d75727a2cefb4eb04155067b5b86f9a412cf266065f007"
},
{
"seq": 3,
"tenantId": "demo",
"actor": "registrar@demo",
"action": "return.signoff",
"target": "submission:hesa-student-2024-25",
"at": "2026-06-28T08:09:42.000Z",
"prevHash": "5232966c3122506c09d75727a2cefb4eb04155067b5b86f9a412cf266065f007",
"metadata": {
"stream": "Student",
"checksum": "sha256:abc…"
},
"algorithm": "sha256",
"hash": "24d1fb2f3f68e0b4da6566ecebf071b9dd840bf1e3bff634313a2567f333eea5"
}
]