HomeAudit trail

Every action on the record. The record doesn't change.

What the assistant said and which passages it used. Who claimed a case, who changed its status, who read the audit log itself. Serviceplane writes each of these as an event that cannot be edited or deleted, chained to the one before it by its hash, and hands you the tools to prove it.

How the record is built

Append-only by construction, verifiable by anyone with the role

Every command is an event

A case opened, a label applied, a reply sent, an answer given, a record linked, a setting changed, a legal hold placed, an export taken — each is one event on the organization's own sequence, with who did it (a person, the assistant, an integration key, the public) and the request's trace id.

One spine per organization

Hash-chained, in order

Each event carries a SHA-256 hash computed over its content and the previous event's hash. Change one byte of any past event and every hash after it stops matching. The events table refuses updates and deletes at the database level; in production the grants are revoked as well.

SHA-256 · prev_hash

Readable, filtered, exportable

The audit log is a tab in the workspace, not a support ticket to us: filter by kind, resource, actor, trace id or time; page through it newest first; export a range as CSV or JSON. A read-only auditor role sees the log and nothing else — and reading or exporting the log is itself an event.

Auditor role

Verified in one call

A verification endpoint walks the whole chain and reports the first event, if any, whose hash does not match. It is the same check the tests run after deliberately tampering with a row, so "the chain verifies" is a statement about the data, not about trust in us.

verify()

Exported nightly to storage you own

Each night the next contiguous range of events is written as a file to your S3-compatible bucket, and a ledger row records the range, the file's SHA-256 digest and its size. The digest is also written to the chain as an event, so the following night's export carries the proof of the previous one. The chain can be re-verified from the files alone, without Serviceplane.

Nightly export · digest ledger

"Why did it say that" is one query

The search the assistant ran, the passages it retrieved, the answer it gave and the model that gave it share a trace id — and the operational log line for the same request carries it too. A reviewer sees the whole chain of reasoning without reconstructing it.

Trace id

The assistant's actions carry the instruction

When a staff member tells the copilot "assign this to Billing and mark it high priority", the resulting events are attributed to the copilot acting on that person's instruction — the instruction text rides on every one. Anything outbound, a reply or an email, is held for the person's click and recorded as confirmed.

Copilot under policy

Retention removes content, never the record

A retention policy blanks message content on schedule — chat text, transcripts, email bodies — and stamps when it did. Rows, cases, counts and the events themselves stay, so an audit of what happened survives the deletion of what was said. A case on legal hold is skipped entirely.

Retention · Legal hold

A whole case as one file

For a public records request or a complaint review: one export holds the case, the person, every chat turn, email, text, note and attachment record, and the case's own audit trail with hashes — as text or JSON. Taking the export is, of course, an event.

Records requests

What tampering looks like

Change one event, and the chain says so

Six events on one case, as an auditor sees them
#2107case.created · channel chat · public9f2c…e1
#2108case.labeled · Homestead credit · assistant41b0…7d
#2109case.routed · team assessor · assistantc8a4…02
#2110case.claimed · user Dana M.e77f…b4
#2111case.replied · channel chat · user Dana M.0a93…5c
#2112case.solved · user Dana M.6d1a…98
The same six, after someone edits #2110 in the database
#2107case.created9f2c…e1
#2108case.labeled41b0…7d
#2109case.routedc8a4…02
#2110case.claimed · user Dana M. Alex R.verify() stops here
#2111case.repliedprev_hash mismatch
#2112case.solvedprev_hash mismatch

Hashes shortened for the page. The database refuses the edit in the first place; this is what the check reports if it ever got through.

Plain words

What an auditor can do, and what nobody can

An auditor can

  • Read every event of the organization, filtered by kind, actor, case, trace or time
  • Export any range as CSV or JSON, up to 50,000 rows a file
  • Run the chain verification and get the first bad sequence number, if any
  • See the ledger of nightly exports with each file's digest, and re-verify from the files alone
  • Pull one whole case — messages, notes, attachments and its trail — as a single file

Nobody can

  • Edit or delete an event, including Serviceplane's own operators — the table refuses it
  • Read the log without the role — agents get a refusal, and the refusal is not silent
  • Read or export the log without that read becoming an event
  • Make the assistant send anything outbound without a person's confirmation on the record
  • Purge a case that is on legal hold

Questions we get

From auditors, counsel and security reviews

Can a Serviceplane administrator delete an event?
No. The events table carries database rules that turn updates and deletes into no-ops, and production revokes the grants as well. Retention policies blank message content in other tables; they never touch events.
How would we know if the log had been tampered with?
Run the verification call: it walks the chain and names the first event whose hash does not match. Because each event's hash includes the previous one, a change anywhere breaks every hash after it. The nightly export files carry their own digests on the chain, so the check can be repeated from your bucket without us.
Where does the nightly export go?
To an S3-compatible bucket you own — Amazon S3, Cloudflare R2, Backblaze B2, MinIO — or any authenticated PUT endpoint. Configure the bucket write-once on your side (Object Lock or a retention rule) for storage-level immutability.
Does the AI's reasoning appear in the log?
The search it ran, the passages it retrieved, the model it used, the answer it gave, whether it abstained and which citations it showed are all on the log, joined by one trace id. Prompts and raw model output are not stored as events.
How does retention interact with the audit trail?
Retention removes what was said; the audit trail keeps what happened. After a purge you still see that a chat took place, when, on which case, who replied and when it was solved — only the message text is gone, and its removal is itself recorded.
Can an outside auditor get access without seeing cases?
Yes. The auditor role reads the audit log and its exports and nothing else. Their reads are events too.

Ask us to break it. Then run verify().

In a walkthrough we open a case, let the assistant and a person act on it, tamper with a row in a scratch database, and show you the chain refuse to verify.