Catalogue management

Reading the audit log, and why retention can only ever go up

Every staff view of a resident's personal data is already recorded — this screen is how anyone reads that ledger back, and reading it is itself an audited act.

By The Kav team Published 2 min read

The backend has written every staff view of a resident's personal data to the audit ledger since before this screen existed. What was missing wasn't the recording — it was a way for anyone to read it back, and an audit trail nobody can browse isn't functioning as one no matter how faithfully it writes.

Opening the log is itself an audited act

Before the table of records ever loads, you're asked to declare a purpose — regulatory audit, an incident investigation, whatever the real reason is — and an optional free-text detail. Nothing is fetched until you confirm it. That's not friction for its own sake: reading personal-data access records is itself a personal-data-adjacent act, and this screen holds itself to the same standard it exists to enforce on everyone else. The confirmation writes its own record before your query is answered.

The purpose picker isn't decoration you can click through absent-mindedly — pick the one that's actually true. Reading this log with a routine placeholder purpose defeats the reason it asks at all.

What one row tells you

Each record carries when it happened, who the actor was, what the action was (a raw, technical action code — the log stays honest about exactly what it knows rather than paraphrasing), what subject it touched, the declared purpose, the data class involved, and whether the access succeeded, was denied, or hit some other outcome. Denied attempts show up here too — a refusal is exactly as much a security-relevant event as a successful read.

Retention: extend-only, by construction

Below the log itself, if you hold the read permission, sits a table of retention policies — one row per data class, from Public up through SpecialCategory — each with a day count and a justification. If you also hold the write permission, you can extend any of them, but never shorten one: the domain aggregate behind this screen (AuditRetentionPolicy.Extend) throws outright if the new value is below the current one, and the form disables the save button on the same condition rather than letting the server refuse it silently after the fact.

This isn't a UI restriction you can route around — the floor is enforced server-side regardless of what any screen shows. A configuration surface that could shorten a municipality's own accountability trail with no deploy and no review is exactly the failure mode this design exists to close off.

Why the two live on one screen

The log and its retention policy answer the same underlying question from two directions — what's being kept, and for how long — and putting the extend-only editor directly beside the records it governs is what makes a longer retention window a visible, deliberate choice rather than a setting buried somewhere unrelated to the data it protects.