Audit and privacy
A record that can be checked without trusting the system that wrote it
Audit events form a per-tenant hash chain, written in the same transaction as the change they describe. The integrity check recomputes the chain on request rather than reading a stored verdict, and an auditor can verify the whole thing offline against a restored backup with no network and no access to this application.
Retention, legal holds and erasure are governed rather than automatic. Five years is the enforced floor, no purge capability is implemented or claimed, and an active hold refuses a reduction rather than warning about one.
The problem
An audit log is only evidence if it can survive the system it lives in
Most application audit logs are a table the application can write to, update and delete. That is a diary, not a control, and an examiner who understands the difference will ask.
A log the application can edit
If the same database role that writes business records can also update or delete audit rows, then every audit assertion depends on nobody having done so. An institution cannot evidence a negative like that, and a compromise of the application is a compromise of the record of the compromise.A cached integrity flag
A stored “chain valid” boolean is exactly what an attacker with database access would set. Reading it back proves that somebody once wrote true into a column, which is a strictly weaker claim than the one being made.Erasure that erases the case
Deleting a subject to satisfy a data-protection request also destroys the AML record the institution is legally required to keep for five years. The two obligations are both real, and a system that satisfies one by breaking the other has not solved anything.
How it works
Chain the record, anchor it outside, and govern what may be reduced
The audit chain and the privacy controls are one capability because they answer the same question from two directions: what has to be kept, and what is allowed to go.
Platform
The audit row commits with the change it describes
Actor-initiated actions, configuration changes, approvals and sensitive data access are written into the chain inside the same database transaction as the change itself. Any other arrangement permits a state where the change committed and the record of it did not. Transactions and alerts are deliberately not audit events — they are domain records with their own immutability — which is what keeps the chain bounded by human throughput rather than by payment-rail throughput.Auditor
Verification recomputes, and reports where it broke
The integrity check recomputes the chain from genesis and verifies the anchors, reporting the chain head, how many events were recomputed and how many anchors were checked. A divergence names the sequence number and the reason — and says what it means: the application cannot produce that state, because it holds no update or delete grant on those tables, so a broken chain is evidence of direct database access rather than an application bug.Auditor
The same check runs without this application at all
Chain verification is available as a standalone run mode of the same binary, executed against a restored backup with no network access, and the canonical serialisation is specified precisely enough for a third party to reimplement independently. Digests are shown in full and selectable on screen, because a value that cannot be copied out cannot be checked against a second implementation.Platform
Sensitive reads are events, recorded as metadata
Revealing an identifier, loading an application review, downloading document or case evidence and decrypting a case note each write a sensitive-access event into the same chain, attributed to the actor who caused it. They record what was accessed and by whom as metadata — never the URL, the query string or the value — so that the audit trail does not quietly become a second copy of the customer database with none of its controls.MLRO or compliance administrator
Retention is proposed, approved and version-tracked per evidence family
Ten evidence families — alerts, audit events, cases, configuration history, customers, onboarding evidence, privacy and authority records, regulatory reports, screening records and transactions — each carry their own policy. Coverage is reported as compliant, held or non-compliant, and a family with no policy is reported as missing rather than treated as a five-year default. A change is a digest-bound proposal that a different authorised person approves, and the applied history is immutable.Legal and compliance
A hold refuses a reduction rather than warning about one
An authority request records neutral intake — the authority, its reference, the legal basis, the deadline and the period in scope — and proposes one hold per linked subject, each activated through approval. While any hold is active or awaiting release, reductions fail closed; increases are still allowed. Releasing a hold is itself a proposal that a different person approves.MLRO and legal
Erasure destroys a key; it does not delete the AML record
An erasure request restricts the subject immediately and destroys nothing until it has been approved and then explicitly executed. Execution destroys that subject’s data-encryption key and redacts the mutable onboarding personal data, leaving the retained AML skeletons and the audit chain intact — the only mechanism that answers a data-protection erasure right and a five-year retention floor at the same time. It fails closed while the subject is held, and it is idempotent after success.Auditor or legal
An authority response is a hashed inventory, not a transmission
A response export produces a retained, neutral JSON inventory: the evidence categories in scope, the record counts, the provenance and a digest per category plus one for the package. It is explicitly not an authority-specific schema and not a submission receipt, and generating it sends nothing anywhere.
In the product
The audit trail and the integrity panel
The screen an internal auditor spends their time in, and the one an external examiner asks to be shown.
Placeholder — TODO: capture the audit trail with chain integrity screen (/audit) from a seeded demonstration tenant — no screenshot of it exists yet. Replace with sourced, approved content before this page is made public.
/auditaudit trail with chain integrity
Screenshot slot. Capture from a seeded demonstration tenant with synthetic data and replace this frame. Do not substitute a mock-up of the interface.
What the capture must show
- Chain integrity panelRecomputed on request: the chain head, how many events were recomputed, how many anchors verified, and when the chain was last notarised.
- The event rowSequence, time, action, actor, resource, outcome and a truncated digest — with outcome restricted to success, failure or denied so a refusal is as visible as a success.
- Digests in fullThe row detail shows the previous digest and this digest complete and selectable, alongside the request identifier and the before and after states.
- Denied attempts are in the trailAn access that was refused is recorded, which is what makes a permission model auditable rather than merely configured.
- Independent verification guidanceOn the page itself: how to run the same check offline against a restored backup, and why the anchors cannot be forged from inside the database.
- Honest pagingCursor navigation with an explicit statement when older events exist behind the current page, and when the end of the trail has been reached.
Controls
What makes the record hold
Each of these is checkable by someone who does not trust the application, which is the only standard that matters here.
No update, no delete, three times over
The grants are revoked, a trigger raises unconditionally on either operation so a future grant cannot silently reopen them, and the digest chain makes an undetected edit require rewriting everything after it.Anchors keyed outside the database
An attacker with full database access can make a rewritten chain internally consistent. They cannot forge the anchors, because the key material that produces them is never in the database they hold.Access is audited as metadata, never as content
Sensitive reads record who, what and when. They do not record the value, the URL or the query string, so investigating an access does not require exposing the data the access concerned.Crypto-shredding built before it was needed
Per-subject data-encryption keys were built before any personal data existed, because the mechanism cannot be retrofitted onto data already encrypted under a shared key. Destroying one subject's key is the erasure; nothing has to be found and deleted.Holds are reconciled and fail closed
Hold state is a conservative tenant-level summary for subject-scoped evidence: it refuses reductions while any hold is active or awaiting release rather than asserting that every affected row belongs to that subject.Missing policy is reported as missing
An evidence family with no approved retention policy is shown as uncovered rather than silently inheriting the statutory floor. A default that looks like a decision is how a gap survives an internal audit.
Where the edges are
Technical controls are built. Two decisions are not ours to make.
And one screen the control documentation describes does not exist yet, which is worth saying here rather than discovering during an evaluation.
In the product today
- Per-tenant append-only hash-chained audit with anchors, on-demand recomputation from genesis, full digests on screen and an offline verification mode of the same binary.
- Sensitive-access events for identifier reveal, application review, evidence download and case-note decryption, written into the same chain as metadata.
- Retention policy across ten evidence families with a five-year floor, digest-bound proposals, four-eyes application and immutable applied history.
- Authority request intake, per-subject legal holds that fail closed, four-eyes hold activation and release, and a retained hashed evidence manifest.
- Erasure by destruction of the subject key with mutable onboarding personal data redacted, refused while a hold is in force and idempotent once executed.
Not claimed here
- A legal determination. The platform records the institution's decisions; whether erasure is permitted against the AML retention obligation, and what the acceptance and release rules for an authority hold are, remain questions for your compliance and legal advisers. The product carries that caveat on the screen rather than in a footnote.
- A retention purge. Nothing in this build destroys records at the end of a retention period. A purge must be a separately authorised, hold-aware capability that records what it destroyed, and none is claimed.
- A dedicated sensitive-access review screen. Those events are in the audit chain and readable in the audit trail, but the trail has cursor navigation only — no filter by action, actor, resource or date — so an access review today is an export and an analysis rather than a screen. The control documentation describes a review surface the build does not yet have.
- Physical retirement of an old root key. Key rotation rewraps subject keys under a maker-checker, resumable lifecycle, but historic blind indexes and audit anchors may still require the previous root, and there is no hardware security module or cloud key-management integration.
- Certification of any kind. Nothing here is an attestation, a standards certification or an independent audit opinion; it is a set of controls and the evidence they produce.
Keep reading
Related capabilities
The architecture the chain depends on, and the two capabilities that produce most of what it records.
Bring your internal auditor
Let them try to break the chain
The most useful session we run is with the people who will have to rely on this: verify the chain, read a denied attempt, follow a sensitive-access event to its subject, and check a digest against an independent implementation.