Audit API
Every action that mutates state writes an AuditEntry row. The chain is per-Tenant and HMAC-signed by AUDIT_HMAC_SECRET. The two endpoints below let an operator read the chain and verify its integrity. See Concepts — Security for the model.
List audit entries
GET /api/audit?limit=100&cursor=...
Returns the most recent entries for the caller's Tenant. Pagination is cursor-based; pass the returned nextCursor on the next call.
200 OK
{
"items": [
{
"id": "ae_01",
"tenantId": "ten_01",
"occurredAt": "2026-05-25T11:30:00.000Z",
"actorUserId": "usr_01",
"kind": "agent.chat",
"entity": "agent:sales",
"summary": "User asked the sales agent about pricing",
"prevHash": "...",
"hash": "..."
}
],
"nextCursor": "ae_00"
}Requires Owner or Admin.
Verify the audit chain
GET /api/audit/verify
Recomputes the HMAC chain end-to-end against the caller's Tenant and returns the result. A successful verification means every row's stored hash equals the recomputed value of HMAC-SHA-256(content || prevHash). A failure pinpoints the first row at which the chain breaks — useful for forensic work after a suspected tamper.
200 OK
{
"tenantId": "ten_01",
"ok": true,
"rowsChecked": 12834,
"elapsedMs": 217
}
200 OK (failed verify)
{
"tenantId": "ten_01",
"ok": false,
"rowsChecked": 12834,
"firstBreakAt": "ae_4421",
"detail": "Stored hash does not match recomputed HMAC"
}
500 Internal Server Error
{ "error": "audit_hmac_secret_missing" }Requires Owner.
What gets audited
The following kinds are written into the chain:
agent.chat,agent.tool_use,agent.tool_resultagent.created,agent.patched,agent.paused,agent.resumed,agent.archivedtenant.created,tenant.patched,tenant.archivedbrand.created,brand.patched,brand.suspended,brand.offboardedrole.granted,role.revokedsecret.created,secret.updated,secret.deletedapproval.opened,approval.resolvedtrigger.fired,broadcast.firedsignin.success,signin.rejected
Operational notes
AUDIT_HMAC_SECRETis mandatory onNODE_ENV=production— the platform refuses to boot without it.- Verification cost is linear in the number of rows but parallel-safe per Tenant — verifying one Tenant doesn't block writes to another.
- The verify endpoint never modifies the chain; it's safe to call from a cron / external monitor.
Source: src/platform/audit.ts, src/platform/api.ts.