Auditing the Event Store
This guide explains how to audit the integrity of events stored in EventSourcingDB. Using the audit endpoint, you can verify that the event chain has remained unchanged, ensuring tamper-proof compliance and reliable historical data integrity.
How Event Chain Auditing Works#
EventSourcingDB stores events in an immutable, append-only log. Each event contains a cryptographic hash referencing its predecessor, forming a secure, verifiable chain similar to a blockchain.
When performing an audit, EventSourcingDB:
- Calculates the cryptographic hash for each event.
- Verifies that each event's hash matches the predecessor hash stored in the subsequent event.
- If provided, checks that a previously audited event's ID and hash match exactly, ensuring that no past events were tampered.
This mechanism enables external auditors to regularly confirm the integrity of stored events, reducing the audit scope to newly added events since the last verification.
For detailed information on event storage and consistency, see Consistency Guarantees.
Performing an Audit#
Changed in 1.3To audit the event store, send an HTTP POST request to the /api/v1/audit-history endpoint.
Initial Audit#
When performing an audit for the first time, no request body is required:
curl \
-i \
-X POST \
-H "Authorization: Bearer <API_TOKEN>" \
http://localhost:3000/api/v1/audit-history
Subsequent Audits#
If you previously audited the store, include the latestEventId and latestEventHash from the last successful audit. EventSourcingDB will verify the integrity starting from the first event up to and including the given event ID, and continue with all subsequent events:
curl \
-i \
-X POST \
-H "Authorization: Bearer <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"latestEventId": "<PREVIOUS_EVENT_ID>",
"latestEventHash": "<PREVIOUS_EVENT_HASH>"
}' \
http://localhost:3000/api/v1/audit-history
Replace <PREVIOUS_EVENT_ID> and <PREVIOUS_EVENT_HASH> with the actual values from your last audit.
Interpreting Audit Results#
Changed in 1.3The server responds with a stream of newline-delimited JSON. While the audit is still running, the server sends heartbeat lines to keep the connection open; the final line carries the result.
If the audit succeeds, the result holds the ID and hash of the latest event audited, confirming the integrity of the entire event chain up to this point:
{"type":"result","payload":{"latestEventId":"...","latestEventHash":"..."}}
Changed in 1.3Writes wait while the audit runs, until it has finished, and so do reads that arrive after a waiting write.
Changed in 1.3If the store is empty, the payload is an empty object {}.
If the provided event ID or hash does not match, or if the event chain has been tampered with, the stream ends with an error line instead, whose message describes the issue:
{"type":"error","payload":{"error":"..."}}
The stream also ends with an error line if the audit itself cannot run to completion. The status code is already 200 by the time the first line goes out, so the last line is what tells you whether the audit succeeded. Treat an error line as a failed audit, not as a clean one.
Removed in 1.3Broken in 1.1, fixed in 1.3An event that is older than the event before it fails the audit as well, as a chain that has been tampered with does. Such an event comes about when the clock of the server goes back while it writes, for example when NTP corrects it, and the audit fails from it on.
If the audit found a mismatch or a tampered chain, further investigation is required. Review logs, check the last known good state, and consider running a full store verification as described in Verifying Store Integrity.
Typical Use Cases#
Auditing the event store is crucial whenever strong guarantees about historical integrity are required. Typical scenarios include external compliance audits, where auditors must independently verify that no historical data was tampered. Regular audits are also useful in internal governance processes to maintain trustworthiness of data over time.
In industries like finance, healthcare, or public services, audit trails are often a legal requirement, and the ability to efficiently validate the event history is essential. Additionally, audits provide a valuable tool in dispute resolution, enabling teams to prove that critical business events have not been manipulated after the fact.
Best Practices#
Changed in 1.3It is recommended to perform audits regularly and securely archive the latestEventId and latestEventHash values returned from each successful audit. This allows subsequent audits to be incremental, focusing only on the newly added events.
Automating the audit process, for example as part of scheduled maintenance routines, helps ensure consistent verification without manual overhead.
Whenever an audit fails, immediate investigation should be triggered, as any detected tampering could indicate a serious security incident or systemic issue. For comprehensive data integrity management, it is advisable to combine regular auditing with full store verifications as described in Verifying Store Integrity.
Auditing provides a lightweight but powerful mechanism to protect the long-term trustworthiness of event-sourced data and to demonstrate compliance with security, legal, and operational standards.