Audit Log
Every state-changing action through the application is captured automatically into an append-only, DB-sealed audit trail, no configuration required to begin collection. Read-only queries are excluded by design.
A change usually leaves two entries. The request entry is written for every create, update, delete or action request, whether it succeeded or was refused, and reads like Delete script succeeded or Login failed; its after values hold the outcome, HTTP status, duration and the request body with secrets redacted. The record's own entry, such as Delete script or Update script, holds the values before and after the change.
A request entry is named after what the request reached, never after an id, an email address or the query string, so every change of one kind shares one name in the Action filter. Requests that do something other than create say what they did, for example Read live schema succeeded when a Schema ERD is loaded, Run AI agent succeeded, Mark read succeeded, Signoff release succeeded or Test compliance rule succeeded. Entries are sealed when written, so entries recorded by an earlier version keep the names they were recorded with.
Record Fields
| Field | Contents |
|---|---|
| When | Action timestamp, in your browser's time zone |
| User | Acting account email (system for automated actions) |
| Action | What was done, in words (for example Login succeeded, Create repo source, Delete script); hover to see the recorded code, such as LOGIN_SUCCEEDED |
| Entity | The kind of record and the start of its id (for example Script · 3f2a1b4c); hover for the recorded type and the full id |
| Before / After | Pre- and post-change values, with every credential-bearing field, secret setting value, URL credential and private key redacted before write |
| IP | The client's address, on every entry. Behind a reverse proxy or load balancer, list it in TRUST_PROXY (see Configuration, Rate Limiting and Query Guards), or the proxy's address is recorded instead. An address a client writes into X-Forwarded-For itself is not believed. |
Integrity Model
Each row is sealed by a database trigger into a SHA-256 hash chain (monotonic sequence + prior-hash linkage), one row at a time, so changes recorded at the same moment cannot fork the chain. On an installation upgraded from an earlier release, a break the check reports among entries written before the upgrade can come from two changes recorded at once rather than from an edit. UPDATE/DELETE are refused at the table level; the only sanctioned removal is the purge, which trims the oldest tail while keeping the surviving chain verifiable. Verify end-to-end via GET /api/db-devops/audit/integrity, which returns { valid, brokenSeq, total } and pinpoints the first broken sequence, detecting even direct superuser edits. See Best Practices, Audit & Compliance for the full scheme and the superuser caveat.
Viewing
Open Administration → Audit Log in the Database DevOps tool (also reachable via the ⌘K palette). The Audit Log is for administrators and for anyone with a role that grants Read and export the Audit Log, such as an Auditors role: those readers see Audit Log on its own in the navigation, and can read, filter and export the trail but not purge it. Other accounts are not offered it, and the audit API refuses them with 403, and the page says which permission to ask for. It also needs an active license; entries are recorded whatever the license state, and appear here once a license is activated.
- Filter by user, action, or date range. The User and Action filters open a picker listing the distinct values recorded in the trail, with actions in words; search, check any number of them, and Apply. Filters combine: selected users AND selected actions AND the date range. Date Range applies once both From and To are set.
- Active filters render as removable chips under the filter bar; remove one to drop that filter, or Clear All to reset.
- Open a row for its full before and after values: click the row, or Tab to the arrow at its start and press Enter.
- Paginate 100 entries at a time and Refresh across history, filtered or not.
- On narrow screens the table scrolls sideways inside its card.
Because this is a database IDE, you can also attach a connection to the application's own metadata database and query audit_logs directly from the editor for ad-hoc forensics.
Export
Export CSV and Export JSON at the top of the Audit Log download every entry that matches the filters in place (user, action, date range), in chain order with the oldest first, or the whole trail when no filter is set; the export is not limited to the page on screen. Each entry carries its sequence number, time, user, action, entity type and id, client address, the values before and after (as JSON text in CSV), and its place in the hash chain (prev_hash, row_hash), so an auditor can check the export against the chain. Exporting is recorded in the trail itself as Export audit log, with the format, the filters and how many entries left. Anyone who can read the Audit Log can export it.
Change-control evidence
Evidence Report at the top of the Audit Log builds the change-management evidence for a period (whole days, UTC) and one environment or all of them, for an auditor or a SOC 2 review. It downloads a zip of four files:
- change-control-report.html: the scope, a table of the SOC 2 CC8.1 points of focus with the evidence for each and how many changes met it, the audit trail’s hash-chain check, the exceptions, and every change with its target, run, approval and checks. It prints cleanly.
- changes.csv: one row per change, with the result of each check.
- evidence.json: everything in the report, including each approver, decision snapshot and shadow run.
- SHA256SUMS: the SHA-256 of the other three, in the format
sha256sum -c SHA256SUMSchecks.
A change is every script run in the period whose connection belongs to the environment, including rollbacks. Each one is checked six ways, as Pass, Exception, or Not recorded:
| Check | Pass | Exception |
|---|---|---|
| Approved before it ran | An approval of the script was granted before the run | None is on record (a revoked approval no longer counts) |
| Ran the approved SQL | The SHA-256 of the SQL that ran equals the one recorded when it was approved; for a rollback, the approved rollback or the rollback captured from the run it undoes | They differ |
| Approved by others than the requester | As many approvers as the request required, none of them the requester | The requester approved it, or approvers are missing |
| Tested in a shadow run | A shadow run of the script succeeded before the run | Shadow runs before the run all failed |
| Decision snapshot captured | A snapshot of the target was captured with the approval | — |
| Rollback captured | Rollback SQL was captured for the run, or the run is itself a rollback | — |
Building the report is recorded in the trail as Export change evidence, with the period, the environment, the counts and the SHA-256 of the zip, so the file an auditor receives can be matched to the entry. Anyone who can read the Audit Log can build it.
Streaming to a security log system
Streaming at the top of the Audit Log sends every audit entry, as it is recorded, to a security log system. An admin sets it up; anyone who can read the Audit Log sees its delivery status.
- HTTPS: each batch is a
POSTto the URL you give (anhttps://address), either as Splunk HTTP Event Collector events (time,host,sourceset to the app name,sourcetype_json, and the entry asevent) or as one JSON array of entries. An optional header, such asAuthorization: Splunk <token>, is sent with each request; its value is encrypted at rest, never shown again and never written to the audit trail. - Syslog over TLS: each entry is an RFC 5424 message (facility log audit, severity informational, or warning for a failed action; the app name you give; the action as the message id; the entry as JSON) sent with RFC 5425 octet counting to the host and port you give (6514 when left blank).
Each entry carries the same fields as an export, including seq, prev_hash and row_hash, so the receiver can check the chain. The certificate the receiver presents must be trusted: by a public authority, or by the CA certificate you paste in. Entries are sent in order, up to 200 at a time, every few seconds; a new stream starts with the entries recorded from then on, or with the whole trail if you choose. When the receiver refuses or cannot be reached, the stream shows Failing with the receiver's answer and tries again after 5 seconds, then 15, 30, 60, 120 and every 5 minutes, without skipping an entry, until delivery succeeds; the status shows the entry delivered through, how many are waiting and when the last delivery was. Send Test Event sends one event marked AUDIT_STREAM_TEST, and Turn Off stops the stream. Setting up, changing and turning off the stream are recorded in the trail. With several servers, one sends at a time.
Retention
Entries stay until an administrator purges them: DELETE /api/db-devops/audit/cleanup?days=N removes the entries older than N days (a whole number, 1 or more; 90 when omitted) and returns { "deleted": n }. Run it on your compliance schedule, and archive the oldest entries off-box first when you keep them longer than the purge window.