The audit log is the practice's event register: who did what, to what, and when. It is the basis of accountability under Article 5(2) GDPR and the first document reached for during an inspection or a suspected abuse.
Entries are created automatically, in a middleware layer between the request and the database — they do not depend on whether the author of the code remembered them. The app has no path that changes or deletes a single entry; the only deletion mechanism is the scheduled job described below.
What gets recorded
Every entry carries:
- who — the user identifier,
- in which practice — the tenant-separating field, always present,
- which action — from a closed vocabulary of several hundred entries; the interface shows their names, for example Created, Viewed, Exported, Submitted to KSeF, AI Scribe session started,
- on what — the object type and its identifier,
- whose data was viewed — a separate column pointing at the patient, including when the action concerned a note or an appointment,
- details — a JSON attachment, put through redaction so that a PESEL number or an e-mail address does not leak into the register,
- a network fingerprint and a client fingerprint — cryptographic digests of the place the request came from and of the browser that sent it,
- a timestamp.
Read events are recorded in batches and without the IP address and browser identifier — we collect those only on changes, so as not to weigh reads down. Changes are written immediately, so that a process failure cannot cut the trail short.
How to do it
The log opens at /audit, in the navigation as Audit Log. The filters: Date range (with ready-made ranges from Today to Last 90 days), User, Action type, Entity type and record ID. Clicking a row expands the details.
The Export button returns the result as CSV or JSON — honouring the filters that are set. The export is itself an event and leaves an entry in the log.
When something does not work
Only clinic owners and admins can view the audit log.
What this means: The signed-in person holds neither the owner nor the admin role in this practice.
No audit events match the selected filters
What this means: The date range, the user or the action type narrows the result to zero.
No records to export
What this means: The export inherits the filters from the view, and those return no rows.
Who has access
Only the practice owner and administrator read the log. There is no "audit-log read-only" role today for an external auditor — the auditor is given an export.
The register is one shared table for all practices, but every query from the application layer is narrowed to the active practice, and membership in it is checked before the procedure runs. A person working in two practices sees only that practice's events in each. The boundary is guarded by a dedicated lint rule and several ratchets that run on every code change.
How long entries live
A daily job deletes entries older than the period set in Settings → GDPR & Privacy → Audit-log retention (20 years by default). That setting governs the log only — not medical records and not patient data; automatic deletion of patient data is not enabled in Heltio. Until 2026-08-24 the label in the interface said otherwise. Billing, financial and patient-rights entries are excluded from it and stay regardless of the setting. The full list of exclusions: Retention policy.