Audit API
Hash-chain, Merkle, SIEM, and crypto-shred.
Entries produced by Rensei's current audit append path are hash-linked and carry per-workspace Ed25519 signatures. Retained history can include legacy unsigned entries. The audit API exposes authenticated event queries, explicit retained-segment verification, Merkle roots and inclusion proofs, optional operator-triggered anchoring, SIEM configuration, and crypto-shredding.
Signature presence is not verification. Hash, linkage, signature, Merkle, and anchor checks each have separate results. A successful check over a supplied segment does not establish event capture, full-history completeness, truth at capture, retention outside that segment, scheduled monitoring, or external timestamp anchoring.
Architecture overview
audit_events is currently an ordinary, non-partitioned PostgreSQL table. Authenticated audit reads use application-level organization/workspace authorization and query filtering. Project filtering is route-dependent and applies only on routes that accept project scope. The inspected audit-read routes are not Cedar-gated, and this page does not claim production database row-level security as their live runtime enforcement boundary.
The list route exposes hash linkage but does not return signature or signing-key fields. Use the explicit verifier for the authenticated retained segment, or use the public redacted sample for a self-contained offline signature check.
Events endpoint
Query audit events with filtering.
GET /api/audit
Authorization: Bearer rsk_live_<key> (or cookie session)Query parameters
| Parameter | Description |
|---|---|
entityType | Filter the returned page by entity type |
entityId | Filter the returned page by entity ID |
from | ISO 8601 start time |
to | ISO 8601 end time |
limit | Maximum results (default: 50, max: 200) |
offset | Non-negative page offset |
Response
{
"events": [
{
"id": 1234,
"workspaceId": "org_01abc...",
"sequenceNumber": 42,
"eventType": "session.started",
"actorId": "user_01abc...",
"entityType": "session",
"entityId": "sess_01abc...",
"payload": {},
"prevHash": "a1b2c3...",
"entryHash": "d4e5f6...",
"occurredAt": "2026-06-02T12:00:00Z"
}
],
"limit": 50,
"offset": 0,
"hasMore": false
}See List tamper-evident audit events for the canonical public-contract reference. The response is scoped to the authenticated organization. Entity filtering is applied only when those filters are supplied, and the response is not a signature-verification bundle.
Decisions endpoint
Query Cedar policy evaluation decisions for compliance review.
GET /api/audit/decisions
Authorization: Bearer rsk_live_<key>GET /api/audit/decisions/{decisionId}Response
{
"decisions": [
{
"decisionId": "dec_01abc...",
"occurredAt": "2026-06-02T12:00:00Z",
"actorId": "agent_01abc...",
"entityType": "session",
"entityId": "sess_01abc...",
"modelId": "provider/model",
"policyDecision": "PERMIT"
}
]
}The list response is a compact projection. GET /api/audit/decisions/{decisionId} returns the full reconstruction for a decision visible to the authenticated organization.
Merkle root
Query the current retained-tree root for the authenticated organization. The root is not an external timestamp anchor by itself.
GET /api/audit/merkle-root
Authorization: Bearer rsk_live_<key>Response
{
"workspaceId": "org_01abc...",
"orgId": "org_01abc...",
"merkleRoot": "f1e2d3...",
"treeSize": 1240,
"lastVerifiedAt": null,
"isValid": true
}isValid is stored chain-head state, not a fresh external verification result. Call GET /api/audit/verify to run the explicit retained-segment verifier.
Anchoring
An organization administrator can request that the current retained-tree root be submitted to a configured RFC 3161 timestamp endpoint. The operation is explicit, not periodic. Production refuses the request when AUDIT_TSA_URL is absent, and external anchoring is not part of the current public sample or published proof.
POST /api/audit/anchor
Cookie: <authenticated organization-admin user session>
Content-Type: application/json{}Response
{
"ok": true,
"anchor": {
"id": 123,
"workspaceId": "org_01abc...",
"merkleRoot": "f1e2d3...",
"merkleLeafCount": 1240,
"tsaStatus": "verified",
"tsaGenTime": "..."
}
}Before storing an external response, the implementation checks granted status, message imprint, and nonce. It does not validate the token's CMS signature or certificate chain. A deliberately requested local-fallback result is not external timestamp proof. GET /api/audit/anchors/{id}/verify rechecks the retained prefix and stored response, but even a verified response does not establish capture or full-history completeness.
Inclusion proof
Return a sibling-hash path showing that an authenticated organization's stored event is included in the current retained Merkle tree. This does not prove that the tree covers every event that should exist, that it includes archived prefixes, or that the root is externally anchored.
GET /api/audit/inclusion-proof
Authorization: Bearer rsk_live_<key>Query parameters
| Parameter | Description |
|---|---|
eventId | Positive numeric ID of the stored event to prove |
Response
{
"eventId": 1234,
"eventHash": "a1b2c3...",
"merkleRoot": "f1e2d3...",
"siblings": [{ "hash": "d4e5f6...", "position": "right" }],
"leafIndex": 42,
"treeSize": 1240
}Verify inclusion
Ask the authenticated platform route to recompute an inclusion proof:
POST /api/audit/verify-inclusionThis route requires authentication. Send either a positive numeric eventId to regenerate and verify the stored proof, or send eventHash, merkleRoot, and siblings from a proof response. It returns a valid result for that inclusion calculation only. For an offline signature exercise that does not rely on an authenticated Rensei route, use the public redacted sample.
Crypto-shredding
Crypto-shredding is an irreversible, organization-wide break-glass operation that destroys the data-encryption key for encrypted audit PII. It derives organization scope from the authenticated caller and requires both an organization administrator and a Rensei operator. Hash and signature metadata remain available for integrity checks, but the initiation entry is not proof that key destruction completed.
POST /api/audit/crypto-shred
Cookie: <authenticated org-admin/operator session>
Content-Type: application/json{
"confirm": true
}Response
{
"ok": true,
"message": "PII encryption key deleted. All encrypted PII is now unrecoverable.",
"workspaceId": "org_01abc..."
}Check shred status
GET /api/audit/crypto-shred/status
Authorization: Bearer rsk_live_<key> (or cookie session)Crypto-shredding is irreversible. The route attempts to append audit.crypto_shred with action: shred_initiated before attempting key destruction. A record, when present, proves initiation only. Use the successful response or authenticated status route to confirm completion. API keys are rejected because this operation requires user-backed org-admin authentication (a cookie session or WorkOS CLI user token) for a user who is also a Rensei operator.
Retention policy
GET /api/audit/retention
Authorization: Bearer rsk_live_<key> (or cookie session)GET returns the authenticated organization's current retention status. It does not update policy. POST /api/audit/retention is a separate operator/cron-authenticated trigger for one organization with body { "orgId": "...", "dryRun": true }; it is not a tenant policy-update endpoint.
Eligible prefixes are exported and checksum-verified before they become purgeable from hot storage. Always read the returned active policy; this page does not promise a universal retention duration. A verifier that sees only the hot segment cannot infer whether older archived material exists or was supplied.
SIEM integration
Rensei supports delivery attempts to external SIEM destinations. Configuration is API-only today; there is no SIEM dashboard page. See Observability for the current endpoints, filters, and delivery limitations.
The current sender is a generic HTTP POST client with three wire formats:
jsonwith anapplication/jsonbodycefwith atext/plainbodyleefwith atext/plainbody
When apiKey is present it is sent as Authorization: Bearer <apiKey>. Vendor-specific authentication and bulk-ingest protocols are not implemented by this sender.
CLI access
The rensei CLI exposes session-attestation lookup today. Audit-chain subcommands exist in the client but remain hidden from --help and are not a supported public CLI surface:
# Retrieve attestation metadata for a session
rensei audit attestation show <sessionId> --jsonThe returned attestation status is not a cryptographic verification performed by this command. Signature presence must remain distinct from a successful verifier result. See CLI: Audit for the exact availability boundary.
JWKS for external verification
Entries produced by the current append path carry Ed25519 signatures and a signing-key identifier. Retained legacy entries can be unsigned. A holder can fetch the matching public key without authentication and explicitly verify signatures that are present:
GET /.well-known/audit-keys/{workspace_id}See Audit JWKS for the full key format and verification guide.
Related pages
- Audit JWKS - public key endpoint for external verification
- Security: Audit Trail - hash-chain architecture, explicit verification, proof limits, and retention
- CLI: Audit -
rensei auditcommand reference and availability boundary