Audit log
The audit log is the answer to “who changed this, and when?”. Every meaningful action taken in your organization — a role granted, a person suspended, a program published, a grade changed, a key rotated — is written to an append-only record with the person who did it, the time, and what changed. It is the evidence you reach for during an incident, an internal review, or an external audit.
It works the same whether you run corporate training, a customer academy, a university department, or a school.
What this does
Section titled “What this does”The log records one entry per action, scoped to the organization you have active. Entries cannot be edited or deleted from the app — not by you, not by an administrator, not by Lurno support. You can read, filter, save questions, and export. That’s deliberate: a record you can alter is not evidence.
Before you start
Section titled “Before you start”- You need permission to view the audit log on the organization whose entries you want to read.
- Pick the right organization first. The log shows the active organization’s entries; switching organizations switches the log.
- To read a sub-organization’s log, you need audit access granted directly on that sub-organization.
Reading the log
Section titled “Reading the log”The table lists the most recent entries first, 50 at a time, with Load more at the bottom.
| Column | What it shows |
|---|---|
| When | Date and time in your locale’s format |
| Actor | Who did it — resolved to a name where possible, otherwise a short id. Scheduled jobs show as system |
| Action | The action name, e.g. role.assigned, user.suspended, program.published |
| Resource | The kind of thing affected, and a short id |
| Org | The organization the entry belongs to |
Click any row to expand it.
What an entry contains
Section titled “What an entry contains”The expanded entry opens a detail card with a plain-language title and one-line summary (“Alice Smith granted instructor on organization to Jordan Lee”), followed by:
- When, Request ID, IP, User agent — the technical fingerprint of the call.
- On behalf of — set when someone acted for another person.
- Authorizing assignment — the specific role grant that permitted the action.
- Reason — free text supplied at the time, where the action asks for one.
- Actor roles at time of action — a snapshot of the roles the person held then, not now. Revoking someone’s role later does not rewrite history.
- What changed — a before → after table for the fields that moved.
- View raw payload — the full before/after record, for when the summary isn’t enough.
Payloads carry identifiers, state changes, and counts. They deliberately do not carry sensitive free text: wellbeing entries, for example, record that a case moved state and who moved it, never the content of the case. Because entries are permanent, anything written here could never be redacted later — so it isn’t written in the first place.
Filtering and time ranges
Section titled “Filtering and time ranges”Open Advanced filters above the table:
- Action — an exact action name, such as
role.assigned. Partial names do not match. - Resource type — e.g.
user,program,breach_incident. - Actor — pick a person from your organization.
- Time range — last 24 hours, last 7 days, last 30 days, or all time. Default is 7 days.
Reset clears everything back to the last 7 days. Filters are applied on the server, so paging past the first page keeps them.
Questions and saved filters
Section titled “Questions and saved filters”The Questions rail beside the table turns filters into reusable questions.
- Built-in — four seeded shortcuts: “Who changed roles last week?”, “All deletions in the last 30 days”, “Logins in the last 24 hours”, “Permission grants this quarter”. Treat these as starting points rather than finished reports. The action filter behind them is exact-match; three are written as name prefixes and the fourth targets a sign-in action the log doesn’t currently carry, so all four come back empty today. Open Advanced filters after clicking one and swap the action for a full name — or clear it and filter by resource type instead.
- Assessments — seven presets for assessment work: published assessments this week, accommodations applied, result status transitions, bulk grading, grading-policy changes, regrades, appeals. Each targets one exact action name, so these match real entries whenever the underlying activity has happened.
- Your saved questions — anything you save yourself.
- Shared with the org — questions someone else promoted for everyone.
To save the current view: click Save current as…, give it a name (unique per person per organization), and optionally tick Share with everyone in the organization — that tick only appears if you have permission to manage audit queries. Deleting a saved question removes the filter only; the history behind it is untouched.
Exporting
Section titled “Exporting”Export CSV downloads the entries currently loaded on screen as audit-log-<date>.csv, with columns: When, Actor ID, Actor Name, Action, Resource Type, Resource ID, Org ID, Request ID, IP. Load more pages first if you need a longer window.
The audit log and assistant receipts are not the same thing
Section titled “The audit log and assistant receipts are not the same thing”Changes made through the AI assistant also produce receipts — cards on the assistant’s own pages showing what it did and offering Undo. They are a convenience, not evidence:
| Audit log | Assistant receipts | |
|---|---|---|
| Written by | The server, in a hash chain | The browser that ran the action |
| Covers | Every meaningful action anywhere in the product | Only changes made through the assistant |
| Can be relied on as evidence | Yes | No — use the audit log |
| Undo | No | Yes, by the person who made the change, for 24 hours |
| Retention | See below | 180 days |
An action taken through the assistant appears in both. Where they disagree, the audit log is the record of account.
Break-glass access to a staff conversation
Section titled “Break-glass access to a staff conversation”Assistant conversations are private to the person who had them — the database rule is self-read-only, and no administrator, and no one at Lurno, can read them in the ordinary course of things.
For legal hold and safeguarding there is one narrow path, and it leaves a trail in three places at once. Someone holding permission to update the organization can export one specific conversation, but only where:
- A second, different person approved that specific request first. The four-eyes rule is enforced by the database, so a self-approval is impossible rather than discouraged.
- An audit entry is written before the transcript is returned. It is in the hash chain like everything else, so a read cannot happen and then fail to be recorded.
- A permanent disclosure is added to the conversation itself. The person whose words were read sees “This conversation has been read by an administrator” with the date and the stated reason, on the conversation. It is not a notification — it cannot be dismissed, missed, or switched off.
All three are load-bearing. If your organization needs this, plan it as a governance action with a named approver, not as a support step.
Integrity — why entries can be trusted
Section titled “Integrity — why entries can be trusted”Each entry is hashed together with the one before it, forming a chain per organization. Change or remove any past entry and every later hash stops matching. The app has no write path into the log at all: entries are created by the system as a side effect of the action itself, and edit and delete rights are revoked outright.
A badge at the top of the page reports the current state of that chain:
| Badge | Meaning |
|---|---|
| Chain verified | Every entry hashes onto the previous one — no tampering detected |
| Known break | A documented break already under review by Lurno’s platform owners. No action needed |
| Integrity break | An unexpected break. Report it to your platform owners; do not attempt to edit records |
| Integrity unknown | The check couldn’t run. Refresh and try again |
A scheduled job also records each chain’s latest hash once a day, so a snapshot of the chain’s state exists independently of the log itself. The badge is read-only by design — there is no repair or rewrite action anywhere in the product.
Retention
Section titled “Retention”Entries are kept for 365 days and then removed by a weekly clean-up. If your obligations require a longer record, export on a schedule and keep the files in your own archive.
Who can read it
Section titled “Who can read it”Anyone with permission to view the audit log for a given organization sees that organization’s entries, and only those. Because audit access doesn’t cascade, a parent-organization admin does not automatically read a sub-organization’s log. Lurno platform staff with platform-level audit access can see across organizations — that access is what makes the cross-tenant surfaces in Privacy & incident queues possible.
Reference
Section titled “Reference”| Term | What it is |
|---|---|
| Actor | The person or scheduled job that performed the action |
| Action | The canonical name of what happened, in resource.verb form |
| Resource | The thing the action affected, plus its id |
| Request ID | The identifier for the single API call — useful for correlating with support |
| On behalf of | The person the actor was acting for, when applicable |
| Authorizing assignment | The role grant that permitted the action |
| Actor roles snapshot | The roles held at the moment of the action, frozen |
| Before / after | The field values on either side of the change |
| Hash chain | Each entry hashed with the previous one, so edits are detectable |
Troubleshooting
Section titled “Troubleshooting”A built-in question returns nothing. The action filter matches an action name exactly, so a partial name such as role. finds nothing. Use a full name — role.assigned, role.revoked — or filter by resource type instead.
I can read my organization’s log but a sub-organization’s is empty or blocked. Audit access doesn’t inherit downward. Ask for the permission to be granted directly on that sub-organization; see Sub-organizations & structure.
Entries older than a year are gone. Retention is 365 days. Export on a schedule if you need to keep more.
An entry shows “system” as the actor. A scheduled job did it — orphan detection, session clean-up, deadline sweeps, quarterly report generation. That’s expected, not a gap.
The integrity badge says “Known break”. That break is documented and under platform-owner review. Nothing for you to do. An Integrity break with no “known” wording is different — raise it.
I need an entry corrected or removed. Not possible, by design. Record the correction as a new action instead; the log is append-only and the hash chain depends on it staying that way.