Skip to main content
Version: Latest (1.8.x dev)

Build audit evidence for every AI decision

With audit storage configured, DVARA records what happened to an AI request: which workspace sent it, which governance controls ran, what they decided, and how the request ended. Use this trail to investigate incidents, answer an auditor, or show that a policy was enforced at a specific time.

Which audit path should you use?

The Open Source distribution and the Enterprise platform produce different audit surfaces. Choose the one that matches your deployment.

NeedOpen Source distributionEnterprise platform
HMAC-signed, hash-chained recordsLocal JSON Lines file; opt-in and off by defaultDurable store; enabled in the packaged platform
Search and filter in a browserNoDVARA Console and workspace Portal
CSV and JSON exportRead the local file with standard toolsExport the complete filtered result from the Console
SIEM deliveryUse your log or file collectorSplunk HEC, CloudWatch Logs, and Kafka integrations
Compliance reportsNoSOC 2, HIPAA, GDPR, RBI, and SEBI PDFs
MCP and A2A evidenceNoAvailable when the licensed MCP or A2A plane is active

The Enterprise audit, SIEM, and report features run without a licence in the Development posture. A licence adds production rights, support, and the MCP and A2A planes.

Record a request with the Open Source distribution

Complete the Open Source distribution quickstart first. It starts the built-in Mock provider, so this example does not send data to an external model.

Set both audit values before starting DVARA:

export DVARA_AUDIT_FILE_PATH="$PWD/var/audit.jsonl"
export DVARA_AUDIT_HMAC_SECRET='<generated-hmac-secret>'

Generate the secret with openssl rand -base64 32. The file path is blank by default, so the Open Source distribution drops audit events unless you set it. If you set the path without a secret, or keep the published development secret, DVARA refuses to start instead of creating evidence that looks trustworthy but is not.

Send a governed request. The quickstart leaves API-key enforcement off, so this local request does not need an authorization header:

curl -sS http://localhost:8080/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "mock/gpt-4",
"messages": [
{"role": "user", "content": "Summarize the refund policy."}
]
}' | jq

The Mock provider returns a normal OpenAI-compatible response:

{
"id": "mock-6d0d5f08d3dd4aa5b536ba765cb0be63",
"object": "chat.completion",
"created": 1789092000,
"model": "mock/gpt-4",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "This is a mock response"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 5,
"total_tokens": 17
}
}

Now inspect the newest audit record:

tail -n 1 "$DVARA_AUDIT_FILE_PATH" |
jq '{eventType, workspaceId, payload, seq, previousHash, hmac}'

You should see eventType: "GATEWAY_RESPONSE". DVARA writes this event after each /v1/* request completes. Its payload records the outcome, including the model, provider, status, latency, token total, policy decision, and error code when those values apply.

Other controls write their own events. For example, a policy denial writes POLICY_DENIED, PII enforcement writes PII_DETECTED or PII_REDACTED, and a blocking guardrail writes GUARDRAIL_BLOCKED. DVARA does not write a separate GATEWAY_REQUEST event in 1.8.

Which audit events should you monitor?

Start with GATEWAY_RESPONSE. It is the completion record for each governed model request and carries the outcome needed to join policy, provider, token, and error evidence. Add the event families that match the controls you have enabled.

EventWhat it provesCondition
GATEWAY_RESPONSEA governed model request completed or failedWritten when audit storage is configured; there is no separate GATEWAY_REQUEST event in 1.8
POLICY_DENIEDAn active policy refused a requestA matching policy rule returned DENY
PII_DETECTED / PII_REDACTED / PII_TOKENIZEDRequest PII was observed, permanently removed, or replaced with a recoverable tokenThe workspace's PII action decides; LOG is the default
PII_RESPONSE_DETOKENIZEDOne or more request-created tokens were restored in a non-streaming responseEnterprise auto-detokenization is enabled for the workspace; off by default
PII_RESPONSE_DETOKENIZE_INCOMPLETEAuto-detokenization restored only part of the responseCarries tokens_restored, tokens_unresolved, and reason; the response also carries X-Gateway-Pii-Unresolved with the unresolved count
PII_BLOCKED_STREAMING / GUARDRAIL_BLOCKED_STREAMING / HALLUCINATION_DETECTED_STREAMINGDeferred response enforcement refused a streamThe corresponding response control is enabled with a blocking action
STREAM_TOO_LARGE_TO_SCAN / STREAM_TOOL_ARGUMENTS_UNENFORCEABLE / STREAM_INCOMPLETE_UNGROUNDEDDeferred delivery was refused because DVARA could not complete the required whole-response checkWritten only for the matching bound, tool-argument, or truncated-grounding condition
STREAMING_ENFORCEMENT_SUMMARYThe final LLM stream enforcement stateWritten for governed streams; inspect pii_entity_count, guardrail_detection_count, scan_incomplete, scan_failed, and truncated when present
SCOPED_RATE_LIMIT_UPDATED / SCOPED_RATE_LIMIT_CLEAREDAn operator changed or removed an account or team limitEnterprise hierarchy editor only

The Enterprise MCP plane uses one stable family for request and response PII:

EventMeaning
MCP_PII_DETECTEDRequest PII was logged or the request was blocked
MCP_PII_REDACTEDRequest PII was removed permanently
MCP_PII_TOKENIZEDRequest PII was replaced with recoverable tokens
MCP_PII_REDACT_DEGRADEDRequest tokenization was selected but no token store was available; action is TOKENIZE despite the retained event name
MCP_PII_OUTPUT_LEAKPII was found in a tool response; inspect action to see whether DVARA logged, redacted, or blocked it

MCP_PII_TOKENIZE_UNAVAILABLE is the HTTP error code returned when request tokenization cannot run. It is not a second audit event. These events are available only when the licensed MCP plane is active, and their payloads contain entity types and counts—not detected values or recovery tokens.

The licensed A2A plane writes to its separate audit chain. It uses one A2A_PII_DETECTED event for recorded PII enforcement; read its action and side (request or response) fields instead of looking for action-specific event names. Every governed A2A stream also writes A2A_STREAM_SUMMARY. In that payload, pii_enforced_group_count counts continuation groups containing PII and pii_entity_count counts individual detections. scan_incomplete, scan_failed, truncated, blocked, and error_code describe independent parts of the final outcome when present.

Do not configure alerts for POLICY_PROMOTED_TO_WORKSPACE. The current 1.8 runtime has no Console, API, or other production path that emits it. Use the documented GitOps export and import workflow to move a policy between workspaces.

What does tamper-evident mean?

Each audit record carries an HMAC signature and the previous record's HMAC. Changing, removing, inserting, or reordering a record breaks verification at that point.

The chain detects changes; it does not prevent changes to the storage:

  • The API does not provide a way to update an audit event.
  • A person with direct storage access can still delete or replace data.
  • A person who also holds the signing secret can rebuild a valid-looking chain.
  • Deleting the whole local file destroys the Open Source distribution's evidence.

Protect the audit store and signing secret separately. Keep the Open Source audit file on a persistent volume, restrict access to it, and retain rotated chain segments together.

Search an incident in the Enterprise platform

Open Governance → Audit in the DVARA Console. The default Shared plane contains LLM and MCP events. If the licensed A2A plane is active, choose A2A to search its separate chain.

Filter by workspace, event type, and time range. Expand a row to see its payload and signing fields. To hand the result to another system, export the same filtered set as CSV or JSON. JSON preserves nested payloads and is the better choice for a SIEM or an automated diff.

The following request exports every matching shared-plane event. Replace the base URL, browser session cookie, workspace, and timestamps:

curl -sS \
-H 'Cookie: <flightdeck-session-cookie>' \
'https://flightdeck.acme.example.com/audit/export?workspace_id=payments-prod&event_type=POLICY_DENIED&from=2026-09-01T00%3A00%3A00Z&to=2026-10-01T00%3A00%3A00Z&format=json' \
| jq

The response is a JSON array. Each item has the same public shape:

[
{
"eventId": "0NZP8Q6E5R2KJ",
"timestamp": "2026-09-14T16:42:18.208Z",
"workspaceId": "payments-prod",
"eventType": "POLICY_DENIED",
"payload": {
"policy_id": "production-model-policy",
"rule_id": "deny-unapproved-models",
"reason": "Model is not approved for this workspace",
"workspace_id": "payments-prod",
"api_key": "key_0NZP8MV76C2AT"
}
}
]

Treat eventId as an opaque string. Older records can use UUIDs while newer records use sortable IDs, and both formats can appear in the same export. Store, compare, and forward the value without parsing its format.

The payload's api_key is the key's opaque ID, not the gw_... bearer credential or its display prefix. Usage, cost, per-key budgets, access logs, analytics, and exports use the same ID, so you can correlate evidence without copying a secret into it. A request made without an authenticated key records anonymous. CSV and JSON exports preserve this attribution value.

An empty array means no event matched all filters. Remove one filter at a time, then confirm that you selected the correct plane and time zone.

The Enterprise platform checks the most recent 1,000 chain records every hour by default. Set dvara.audit.chain-verify.enabled=false only when another process performs the same check. Change the interval with dvara.audit.chain-verify.interval-ms and the window with dvara.audit.chain-verify.max-envelopes. A detected break increments gateway_audit_chain_gaps_total and writes a warning to the application log; verification does not stop request traffic.

Keep prompts out of the audit trail by default

The Enterprise platform removes prompt and message content from audit payloads by default. Set dvara.audit.store-prompts-by-default=true only when your retention policy permits prompt storage. A workspace can override the install default with its Store prompts in audit governance setting.

Even when prompt storage is off, the trail keeps structural evidence such as the event type, actor, workspace, decision, model, status, and trace ID when those fields apply. PII audit events record entity types and counts, not the detected values.

Generate a compliance evidence report

Open Governance → Compliance in the Console, then choose a report type, workspace, and time range. DVARA supports SOC2, HIPAA, GDPR, RBI, and SEBI reports.

Select Generate, wait for the new row to appear, and download its PDF. The report combines audit events, policy and workspace state, usage evidence, and a chain-integrity result for the selected period. When the licensed A2A plane is active, the report also includes A2A activity and verification of its separate chain.

Generation writes COMPLIANCE_REPORT_GENERATED to the audit trail. Deleting a saved report writes COMPLIANCE_REPORT_DELETED; downloading it is read-only and does not create an event.

Evidence is not certification

A DVARA report organizes technical evidence for a review. It does not certify your organization, guarantee compliance, or replace an auditor's assessment.

Send evidence to your SIEM

The Enterprise platform can forward audit events to Splunk HEC, AWS CloudWatch Logs, or Apache Kafka. Export failures do not block primary audit persistence. Configure and test those destinations in SIEM and webhooks.

What should you verify before production?

  1. Use a strong signing secret and make it available to every process that writes to the same chain.
  2. Keep the audit store on durable storage and restrict direct access.
  3. Leave prompt storage off unless a documented retention rule requires it.
  4. Test a denial and confirm both the governance event and GATEWAY_RESPONSE appear.
  5. Export a narrow time range and confirm that your downstream system preserves the JSON payload.
  6. Alert on gateway_audit_chain_gaps_total; any unexpected increase needs investigation.