administration
Audit logs
An append-only, tamper-evident audit log with a license-rooted checkpoint chain you can verify offline — scoped to your organization by row-level security.
Updated Aug 16, 2026
Every meaningful action in VaultTerm lands in an append-only audit log. The log is not just write-once; it is tamper-evident, backed by a checkpoint chain that lets you detect after the fact whether any record was altered, removed, or reordered. This is the accountability half of being an audited access broker: the server decrypts secrets in memory for authorized actions, and each of those actions leaves a record that cannot be altered afterwards without the chain showing it. What that detection covers, and the one party it does not cover, is set out under the checkpoint chain below.
The log
The audit log captures who did what, when, and against which resource — reads, brokered sessions, configuration changes, and security events. Entries are written once and never updated in place.
Search and filtering are scoped to the caller’s organization by row-level security. An operator
querying audit data only ever sees rows whose org_id matches the authenticated tenant context; the
isolation is enforced at the database, not in application code. See
Tenant isolation for how the scoping works.
Exporting the trail
The same records the Audit view lists can be downloaded as a file, in CSV or JSON.
- The export is what you were looking at. It takes the action, resource-type and date filters currently applied, and resolves scope the same way the list does — so an org admin exports the organization’s records and a member exports their own. There is no separate permission to grant and no “access denied” state: audit narrows a member to their own records rather than refusing them.
- A capped export says so. A single request returns at most 50,000 records. When that cap is hit,
CSV states it in a trailing comment line and JSON in a
truncatedflag, and the app warns you to narrow the date range and take the rest. An export that is short but looks complete is a compliance artefact that is quietly wrong, so this is stated rather than inferred. - Draining the trail is rate limited. Six exports per five minutes; beyond that the request is refused with a retry hint. Browsing the log is unaffected.
- The export is itself an audited action, like every other read of the trail.
This is the tenant-facing download and is available on every plan. It is a different thing from the Events / SIEM stream, the API that pushes audit events continuously into Splunk or Sentinel; that one is an Enterprise feature. See Events API.
Where you can do it. The export control is in the web app’s Audit view. The mobile app, the CLI and the browser extension can read the trail but cannot export it yet.
The checkpoint chain
On top of the raw log sits a license-rooted checkpoint chain. Periodically, a checkpoint is written that:
- Seals a contiguous range of audit rows with a hash over that range.
- Hash-links to the prior checkpoint, so the checkpoints form a chain — altering an old record changes its range hash, which breaks every checkpoint after it.
- Is stamped with the license counter, a monotonic anti-rollback value, rooting the chain in the deployment’s license rather than in a value an attacker could freely reset.
Because each checkpoint depends on the one before it and on the license counter, you cannot rewrite history without rewriting the entire downstream chain, and deleting the most recent checkpoints to hide a change leaves a visible gap rather than a clean log.
What the checkpoint chain does and does not prove. The genesis link and the chain’s key are derived from the deployment’s license file — the deployment id and the license’s detached signature — and each checkpoint is sealed with an HMAC-SHA256 under that key, not a signature. That makes the chain tamper-evident against anyone who does not hold that file: a splice or truncation made straight against the database, a restored or doctored backup, and a chain lifted from another deployment all fail verification. It does not bind the holder of the license file itself. Whoever holds it can re-derive the key and re-seal a rewritten chain that verifies — and on a self-hosted install, that is the operator. The chain is evidence against everyone except the party that runs the deployment.
Detecting a rewrite by the license holder needs a reference point held by someone else. The vendor that issued the license knows its signature and can re-verify an exported chain independently, so a chain checked against a head that vendor recorded earlier will not match a rewritten one. VaultTerm does not ship the chain head off the deployment on its own today, so that comparison depends on the head having been recorded externally — through your own export, or a copy sent to a system the deployment’s operator does not control.
One caveat on where the root comes from: a deployment running without a .vtlic license file — the
hosted service, or a self-hosted install before licensing — falls back to a fixed root instead of a
per-deployment one. There the checkpoints are still hash-linked and still detect an edit made without
re-sealing, but the key is not deployment-bound, so it adds nothing against an attacker who knows the
construction. Database access control is what carries that case.
Offline reveals
A client that holds an encrypted offline copy of the vault (the browser extension and the mobile app do) fills without reaching the server, so the audit record for that reveal cannot be written before the secret is handed over. It is written afterwards, and the guarantee is enforced on the client:
- The reveal is recorded locally first. Each cache-served fill is appended to a sealed journal on the device — credential, time, surface, host, device, and a strictly increasing sequence number — and hash-chained to the entry before it, using the same construction as the checkpoint chain above.
- Batches are shipped on the next sync and become ordinary audit entries, flagged as having arrived from a device journal and carrying the time the secret was actually handed over as well as the time it reached the server.
- Dropping entries is visible, not silent. The server verifies that a batch continues from the chain position it already holds. A gap, a broken link, a refused batch and a deliberate chain restart are each written as their own audit event and can be alerted on.
- The client stops filling if it cannot report. Once unreported reveals exceed the age or count your organization sets, the device refuses to fill from its copy until it has handed them over.
- You can turn it off. Setting the age limit to zero is strict mode: no new copy is served to any device and existing copies are revoked on next contact, so the audit record is written before the secret is handed over. A device that is offline right now keeps its copy and goes on filling from it until it reaches VaultTerm again, recording those reveals locally to hand over when it returns; the copy’s expiry is what bounds a device that never comes back.
What the batch authentication does and does not prove. A batch is authenticated with an HMAC-SHA256 derived from that device’s server-issued cache key. That proves the batch came from a device holding a key your organization has not withdrawn, and that no entry in it was altered. It is a symmetric MAC — the server holds the same key — so it is not a device signature and does not provide non-repudiation: the record does not distinguish a batch the device produced from one the server could have produced. The server-side chain, the checkpoint chain and row-level security are what protect the trail after it arrives.
Verifying offline
The chain is designed to be checked independently of the running server. The repository ships a verification script:
# from server/
npx tsx scripts/verify-audit-chain.ts
The script walks the checkpoints, recomputes each range hash and link, and confirms the license
counter sequence. If verification fails, the server raises an AUDIT_CHAIN_BROKEN event — a
critical anomaly indicating the checkpoint chain integrity has been broken. The admin console surfaces
the current chain status in its System view; see admin console.
The cryptographic construction behind the checkpoints (SHA-256 range hashing, the HMAC seal, and the license-rooted design) is described in Cryptography.
Retention by plan
How long audit records are kept depends on the plan:
| Plan | Retention |
|---|---|
| Free | 7 days |
| Pro | 30 days |
| Team | 365 days |
| Enterprise | Unlimited |
Self-hosted deployments derive their tier from the signed license rather than a billing catalog; see Billing and plans.
Related pages
- Cryptography — the tamper-evident construction in detail.
- admin console — where audit-chain status is reported.
- Tenant isolation — how audit search is scoped per organization.