9.7Export and audit chain integrity
Last updated
You can export the log from the console or through the REST API. Verifying the audit chain is available through the REST API only. Both need the matching permission. See Chapter 15, REST API for integrators, for authentication.
Exporting the log
To export from the console, set the filters you want on the Operations page and select Export. The file holds every operation that matches the filters, every page of them, not only the ones on screen; the status selected in the stat bar applies too. Export is shown only when your role holds audit:export.
Through the REST API, GET /api/operations/logs/export streams the operations log as newline-delimited JSON (one operation per line, oldest first), as a file named operations-<date>-<time>.ndjson. It requires audit:export. It accepts the same filters as the log, for example from and to for the time range, status, nature=command, requestedBy, via or target. The export covers only the directories your role may use, like the log itself.
GET /api/operations/logs/export?from=2026-09-01T00:00:00Z&to=2026-10-01T00:00:00Z
X-API-Key: <your key>Each line contains the operation's id, command and display name, source, status, action, time, duration, requester and the role they acted as, the API key or agent that made the request, directory, target object, error and result messages, approver and decision time, dismissal, and the before and after states.
Tip: Export the log before log retention removes old rows. Operation records are not forwarded anywhere else, so once retention has deleted them there is no other copy.
Log retention
Log retention is off by default, and there is no screen for it. An administrator turns it on in the Operations:Retention section of the server's configuration file by setting Enabled to true. It then runs once a day and works in two stages:
| Setting | Default | What happens |
|---|---|---|
PersonalDataRetentionDays | 400 | Personal data is removed from older rows; the fact that the operation happened is kept. |
RetentionDays | 1095 | Older rows are deleted. |
MinimumRetentionDays | 90 | A retention period below this is refused at startup, so a typing mistake cannot empty the log. |
Exported rows whose personal data was removed carry pseudonymizedAt and, when a pseudonym salt is configured (ActorPseudonymSalt, or the RETENTION_PSEUDONYM_SALT environment variable, at least 16 characters), an opaque requestedByActorHash instead of an email address. Without a salt no pseudonym is stored. The defaults are placeholders: choose the retention periods according to your organisation's legal and compliance requirements.
Verifying the audit chain
Operations are recorded in a tamper-evident audit chain: each entry carries a keyed hash linked to the previous one. GET /api/operations/logs/verify recomputes the chain and reports the first place it diverges. It requires audit:verify.
GET /api/operations/logs/verify?fromSequence=1&maxEntries=10000
X-API-Key: <your key>The call answers 200 even when it finds a problem; the finding is in the response. isValid gives the answer, and failureKind says what went wrong:
| failureKind | Meaning |
|---|---|
HashMismatch | An entry's contents were changed. |
SequenceGap | An entry was removed. |
BrokenLink | Entries were reordered or substituted. |
UnknownKeyEpoch | No key is configured for the period that signed the entry, so it cannot be judged. This is not evidence of tampering. |
If enabled is false, the chain is switched off and there is nothing to verify. Each call checks at most maxEntries entries (default 10,000); use fromSequence to walk a long chain in windows.
Last updated
Thank you for your feedback.