Audit log
Every mutating handler calls recordAudit, which appends one row: the action,
the resource, the record id, the acting user (id, username, role), the client
IP and — where the flow captures them — before_json/after_json snapshots.
Plugin settings changes write their row through the same service, inside the
settings transaction.
| Table | Columns | Notes |
|---|---|---|
audit_log |
id PK · action · resource · record_id · reason · before_json · after_json · user_id · username · role · ip · created_at (indexed) |
append-only: nothing in the app updates or deletes an audit row; user_id is informational with no FK, so the row outlives the user it describes |
Relationships
None enforced. The row references users, roles and records by value, never by constraint — that is what makes it durable across the very deletions it records.
Access
The audit resource is read-only (no write/delete gate exists — no route
gates a mutation of the log) and is granted to manager alone by default. The
screen (/audit) is paginated and filterable by user, action, resource and
date range.
Rendered from simple-lms/data-model/audit.md · OKF bundle · regenerate with npm run render