Skip to content

Tail and Query the Audit Stream

Every OPA evaluation — allow and deny — is recorded in the audit log. The caracal audit tail command streams live events from the database. The caracal explain command shows the full diagnostics for a single request ID: which policies determined the decision, what diagnostics were returned, and what the full input object looked like.

  • CARACAL_ADMIN_TOKEN set.
  • Events in the audit log (any token exchange generates at least one event).
Terminal window
caracal audit tail

Default output is a human-readable table. Events appear in near real time as token exchanges complete.

Terminal window
caracal audit tail --json

Each line is a JSON object. Pipe to jq for field extraction:

Terminal window
caracal audit tail --json | jq '{id, decision, event_type, occurred_at}'
Terminal window
# Only denied exchanges
caracal audit tail --decision deny
# Only allowed exchanges
caracal audit tail --decision allow
Terminal window
# Only token exchange events
caracal audit tail --event-type token_exchange
# Step-up related events
caracal audit tail --event-type challenge_invalid
caracal audit tail --event-type challenge_cooldown
Terminal window
caracal audit tail --zone zone-abc123
Terminal window
# Events since a specific timestamp (ISO 8601)
caracal audit tail --since 2026-05-11T08:00:00Z
# Events within a window
caracal audit tail \
--since 2026-05-11T08:00:00Z \
--until 2026-05-11T09:00:00Z
Terminal window
# Last 50 events (default: 100)
caracal audit tail --limit 50

Every token exchange carries a request_id in the response and in the mandate’s claim set. Correlate a specific exchange:

Terminal window
caracal audit tail --request-id req-abc123

explain shows the complete audit record for one request: the principal, resource, decision, determining policies, policy-returned diagnostics, and metadata:

Terminal window
caracal explain req-abc123

Example output:

Request: req-abc123
Zone: my-zone
Decision: deny
Event: token_exchange
Determining policies:
- payments-policy (psv-def456)
Diagnostics:
- step_up_required: mfa
Metadata:
principal_id: app-xyz789
resource_id: res-ghi012
session_id: sess-jkl345
agent_session_id: sess-mno678

As JSON:

Terminal window
caracal explain req-abc123 --json
FieldDescription
idAudit event UUID
zone_idZone the exchange occurred in
event_typetoken_exchange, jti_collision, challenge_invalid, challenge_cooldown, etc.
request_idCorrelation ID from the exchange request
decisionallow or deny
policy_set_idActive policy set
policy_set_version_idExact version that was evaluated
manifest_shaSHA-256 of the policy set version manifest
determining_policiesArray of {"policy": "name"} objects
diagnosticsArray of diagnostic objects from the policy (e.g., {"step_up_required": "mfa"})
metadataPrincipal, resource, session, and agent session IDs
occurred_atMicrosecond-precision timestamp

Find all denies for a specific application

Section titled “Find all denies for a specific application”
Terminal window
caracal audit tail --decision deny --json \
| jq 'select(.metadata.principal_id == "app-abc123")'
Terminal window
caracal audit tail --decision deny --json \
| jq 'select(.diagnostics[]?.step_up_required != null)'

Check which policy version is making decisions

Section titled “Check which policy version is making decisions”
Terminal window
caracal audit tail --limit 10 --json \
| jq '{policy_set_version_id, decision, determining_policies}'

Find JTI collision events (replay attempts)

Section titled “Find JTI collision events (replay attempts)”
Terminal window
caracal audit tail --event-type jti_collision --json

The audit log is HMAC-chained. Each event includes a chain_hmac that links it to the previous event. Tamper detection runs at Audit service startup and hourly thereafter. Any detected break is recorded in audit_ingest_alerts.

The CLI does not expose chain validation directly. To verify the chain, query audit_ingest_alerts via the Audit service’s API or the database directly.