Audit logs

A workspace records who did what: who signed in, who opened or downloaded a file, who searched, who chatted with an AI assistant, and which sensitive administrative actions ran. This page covers where those records are kept, what an entry contains, how the files are protected against tampering, and how to verify and export them with curiosity-cli.

Two places an event is recorded

Every audited event can end up in two places, and each has its own rules.

graph LR E[Audited event] --> F["Audit log files on disk<br/>(MSK_AUDIT_LOG_PATH)"] E --> G{"Type enabled?<br/>Node type audited?"} G -->|yes| R["Audit records in the graph<br/>(retention period applies)"] G -->|no| X[not stored in the graph] F --> V["Audit log tab:<br/>search, download, verify"] F --> C["curiosity-cli<br/>verify-audit-log / convert-audit-log"]
Audit log files Audit records in the graph
Where One folder on the server's disk, set by MSK_AUDIT_LOG_PATH Stored in the workspace graph
What is written Every audited event, whether or not its type is enabled on the audit page. The one exception is ChatAI, which is written only while that type is enabled. Only events whose type is enabled. An event about a node (viewed, downloaded, changed, …) is also filtered by the audit node types list.
Retention Not deleted by the workspace. Rotate or archive them with your own policy. The Retention Period setting (Forever, one week, … ten years). Older records are removed by a scheduled task.
Tamper evidence Each line is chained to the one before it with SHA-256. See How the files are protected. None beyond the graph's own access control
Read with Audit Log tab, raw download, SIEM forwarding, curiosity-cli The exportable workbook

The files are the complete trail and the one to archive or forward to a SIEM. The graph records are the filtered view the workspace itself works with.

Configuring auditing

Open Manage → Access → Audit log (#/manage/access/audit). The Auditing Settings tab has three settings:

  • Retention Period: how long the graph records are kept. It does not affect the files.
  • Audit Types: which kinds of events are stored as graph records.
  • Audit node types: which node types an event must be about to be stored as a graph record.

On a workspace where nothing is configured yet, Configure Auditing applies the default set. It enables the types Node, Search, Viewed, ChatAI, Download, Login, Changed, Deleted, Admin Action and Secret Accessed. It audits the _FileEntry node type, and it sets the retention period to Forever.

Type Recorded when
Node A node or field is read directly.
Search A node is returned in search results.
Viewed A user opens a file or node.
Download A user downloads data.
ChatAI A user chats with an AI assistant. The entry carries the messages.
Login A user signs in (password, SSO, OTP, …), and again for a signed-in user making requests, at most once an hour per user and network address. The latter entries carry the IP address.
Code Code is executed.
Query A query is executed.
NewToken A token is created.
Changed / Deleted Data is modified or deleted.
AdminAction A system administrator performs a sensitive administrative operation. See Security.
SecretAccessed Endpoint or AI tool code reads a stored workspace secret. The value never appears in the entry.

Where the files are

The folder is set by MSK_AUDIT_LOG_PATH (see the configuration reference). When it resolves to the same folder as MSK_LOG_PATH, the workspace writes the audit files into an audit subfolder so they are not mixed with the application logs.

File Contents
2026-09-24_audit_logs_000.jsonl Audit events.
2026-09-24_audit_config_logs_000.log Configuration changes.
…_audit_logs_replica-<uid>_000.jsonl The same, written by a read-only replica on its own disk.

A new file starts every day (by the server's local date) and whenever the current one reaches 1 MB, with the number at the end counting up. The configuration .log files are pruned by the workspace: beyond the 500 most recent, files older than 30 days are deleted. The .jsonl audit files are never deleted by the workspace.

What an entry contains

Each line is one entry. It is written as a single-quoted object followed by its signature:

{'i':'42','t':'20260924101503123','k':'Viewed','u':'Bq3r5sx8Tb9aWnFP1uLcKd','s':'Nd1111111111111111111a','d':'viewed','sig':'mJ3…='}
Key Meaning
i Sequence number. It restarts at 1 when the server restarts.
t Time in UTC, as yyyyMMddHHmmssfff.
k Audit type, such as Login, Viewed or ChatAI. -1 marks a server start (see below).
u UID of the user who acted.
s UID of the node the event is about, when there is one.
d Details text, JavaScript-escaped.
p JSON payload, used instead of d by events that carry structured data (ChatAI messages).
un, ue, uf, ul On Login entries only: the user's user name, email, first name and last name.
sig The entry's signature.

An entry names its user only by UID. The user's name and email are written on their login entries. A signed-in user making requests gets a login entry at least once an hour, so a file normally contains one for each user active in it. curiosity-cli convert-audit-log uses those lines to fill in the user on every entry. Files written by workspace versions before login entries carried user details contain only UIDs.

Configuration-change lines in the .log files are JSON objects with i, t, k, u, m (the change message) and p.

How the files are protected

Every line carries sig = SHA-256(signature of the previous line + this line's content). The chain runs through every line one server process writes, across files: the first line of a new file continues from the last line of the file before it.

When a server process starts, it writes a start entry, 'k':'-1', carrying the host name in d. That line is signed on its own content alone, and begins a new chain. A server that restarts during the day appends to that day's file, so a start entry can appear in the middle of a file.

Editing, removing, inserting or reordering any line breaks the chain from that line on. Hiding the change would mean recomputing the signature of every later line.

What the chain does not prove

The chain has no secret key. Someone with write access to the audit folder who knows the algorithm can rewrite a file and recompute every signature. Verification proves the files were not altered after they were written, provided the copy you verify is one you have held since. To make that hold, ship the files off the server as they are written (to a SIEM, WORM storage, or an archive with its own checksums), and verify that copy.

Verifying and exporting the files

In the workspace

The Audit Log tab lists the .jsonl files. You can:

  • search inside the files, and filter by user, node or audit type;
  • select files and download them as they are on disk (several at once arrive as a zip);
  • press Verify Signature to check a file's chain. The check also reads the last line of the file before it, so the file's first entry is verified too.

With curiosity-cli

curiosity-cli works on copies of the files, offline, with no connection to the workspace:

# Check the chain across every file in the folder
curiosity-cli verify-audit-log ./audit

# Export to CSV with names and emails, refusing to convert if anything was tampered with
curiosity-cli convert-audit-log ./audit --template ./who-did-what.template --output ./audit.csv --verify
  • verify-audit-log replays the chain across any set of files, reports server restarts and exits with 1 when an entry was altered. Use it to check an archived copy, or in a scheduled job.
  • convert-audit-log turns the files into CSV, TSV, JSON Lines or JSON. A small template picks the columns. It fills in each user's name and email from their login entries.

Recommendations

  • Point MSK_AUDIT_LOG_PATH at storage outside the data volume, and ship the files off the server as they are written.
  • Archive the .jsonl files on a schedule. The workspace does not delete them, and your retention policy decides how long to keep them.
  • Verify archived copies periodically with curiosity-cli verify-audit-log ./archive --strict, and keep the report.
  • Enable the audit types and node types your compliance obligations require. They decide what the graph records contain, and the ChatAI type also decides whether chat messages reach the files.
  • Treat the files as personal data. Login entries carry names and email addresses, and ChatAI entries carry message content.
© 2026 Curiosity. All rights reserved.
Powered by Neko