> ## Documentation Index
> Fetch the complete documentation index at: https://langwatch.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Audit log

> Who did what, when, to which resource, gateway mutations land in the same audit log as the rest of the platform.

Every gateway-resource mutation (Virtual Key, Budget, ModelProvider, Routing Policy, Cache Rule) writes a row to the platform-wide `AuditLog` table. There is no separate gateway-only audit table, gateway events live alongside org-level platform events (member changes, settings, RBAC, billing) in **/settings/audit-log**, with a Source badge distinguishing the two.

<Note>**One audit log, two write shapes.** Gateway-shape rows carry `targetKind`, `targetId`, `before`, `after`. Platform-shape rows carry `args`, `metadata`, `error`. The viewer renders both with the same row template, computes `source` from the presence of `targetKind`, and offers a target-kind filter for narrowing to gateway events only.</Note>

## What's logged

Action codes for gateway mutations (TypeScript `const` union in `langwatch/src/server/gateway/auditLog.repository.ts`):

Action codes use a `gateway.<resource>.<verb>` dotted-lowercase shape, parallel to platform-side codes (`organization.member.add`, `project.update`). Verbs are past-tense to match Stripe, GitHub, Slack, Datadog audit conventions.

| Action code                                                         | Actor                                                       | Target                                                                      |
| ------------------------------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------- |
| `gateway.virtual_key.{created, updated, rotated, revoked, deleted}` | resolved user (session, PAT, or API token mapped to a user) | `targetKind=virtual_key`, `targetId=<vk_id>`                                |
| `gateway.budget.{created, updated, deleted}`                        | same                                                        | `targetKind=budget`, `targetId=<budget_id>` (`deleted` is the soft-archive) |
| `gateway.provider_binding.{created, updated, deleted}`              | same                                                        | `targetKind=provider_binding`, `targetId=<binding_id>`                      |
| `gateway.cache_rule.{created, updated, deleted}`                    | same                                                        | `targetKind=cache_rule`, `targetId=<rule_id>`                               |

<Info>Guardrail attach/detach events are NOT recorded as standalone audit rows, guardrail configuration changes flow through `gateway.virtual_key.updated` (the guardrail list is a field on `VirtualKey.config`). Standalone `gateway.guardrail.{attached, detached}` actions are a v1.1 follow-up if operators want finer-grained audit.</Info>

Reads are **not** logged, the volume would swamp the ledger without adding governance value. If you need read-access attribution for compliance, use OTel trace logs (every request has `langwatch.principal_id`).

## Viewing in the UI

Go to **/settings/audit-log** (Enterprise plan, gated on `auditLog:view`, granted by default to all four TeamUser roles incl. CUSTOM) and use the filters to narrow:

1. **Source badge**: purple "Gateway", grey "Platform" on every row.
2. **Filter by action**: `gateway.virtual_key.created`, `gateway.virtual_key.rotated`, etc. for gateway rows; platform rows use the same dotted style (e.g. `organization.member.add`, `project.update`). All gateway codes share the `gateway.` prefix so a single `LIKE 'gateway.%'` clause filters the entire gateway surface for SIEM exports.
3. **Filter by Target**: `virtual_key`, `budget`, `provider_binding`, `cache_rule`. Selecting any value implicitly hides platform rows (which have null targetKind).
4. **Expand with changed-fields diff summary**: UPDATE rows expand to show a compact top-level diff (e.g. `priority 200 → 300`, `action.ttl 300 → 600` as red/green code badges) above the raw Before/After JSON panels.
5. **CREATE/DELETE events show the full field list**: since those events have a null Before (or null After), the diff summary renders the relevant half as a field list instead of leaving the panel blank for the most common audit event class.
6. **Deep-link IN from resource detail pages**: every VK detail and budget detail page carries an **Audit history** button that takes you to `/settings/audit-log?targetKind=<kind>&targetId=<id>` with a pre-filled filter chip scoped to just that resource. Clear the chip with the `×` icon to re-expand the view. The pattern stays reachable on revoked VKs and archived budgets so forensic investigations start from the current state, not some "active only" fork.

## Querying programmatically

There is **no public REST endpoint** for audit log retrieval, gateway audit reads share the same tRPC procedure (`organization.getAuditLogs`) that powers `/settings/audit-log`. Three paths, ranked by typical operator use case:

1. **One-off, human review**: open `/settings/audit-log`, set the filters you want (Source, Action, Target), then hit **Export CSV** to download the filtered rows. The CSV carries gateway-shape fields (`targetKind`, `targetId`, `before`, `after`) for gateway rows and platform-shape fields (`args`, `metadata`) for platform rows.
2. **Scripted, scheduled SIEM export**: query the Postgres `AuditLog` table directly from your SIEM ingestion pipeline. Filter on `targetKind IN ('virtual_key', 'budget', 'provider_binding', 'cache_rule')` to scope to gateway rows; join `User` on `userId` for actor enrichment. The schema is documented in `langwatch/prisma/schema.prisma → model AuditLog`.
3. **In-app integrations**: call the tRPC procedure from a TypeScript client that already has a session: `await trpc.organization.getAuditLogs.query({ organizationId, targetKind, targetId, since, limit })`. Mirrors what the UI does. Not intended for cross-network REST consumers.

A first-class REST audit-export endpoint is a v1.2 follow-up; until then, the CSV download is the supported export path for governance, compliance use cases.

## Retention

Default: 7 years, extendable on request. Stored in the primary app Postgres under `AuditLog`. The table is indexed on `(organizationId, createdAt)` and `(targetKind, targetId)` to keep both org-tail queries and per-resource queries fast.

## Migration note (v3.1)

Earlier v3.0 builds wrote gateway audit rows to a dedicated `GatewayAuditLog` table with a `GatewayAuditAction` Postgres enum. The consolidation migration `20260425000000_consolidate_gateway_audit_into_audit_log` extends `AuditLog` with `targetKind`, `targetId`, `before`, `after` columns and drops the gateway-only table. Self-hosters upgrading from v3.0 should run pending Prisma migrations on app boot per the standard upgrade procedure, the gateway audit log table goes away and downstream gateway services start writing to `AuditLog` directly. Per the v3.0 release note no audit rows were retained.

## Security considerations

* **Can the audit log be tampered with?** Writes are append-only at the service layer, no UPDATE or DELETE is exposed. Deletions are only possible via direct database access, which is control-plane-operator-only and also audit-logged (via Postgres' built-in `pgaudit` extension, configured in the self-hosted deployment guide).
* **Can an audit entry be forged?** No. Gateway writes happen inside the same transaction as the resource mutation; either both land or neither lands. A caller cannot emit a fake audit entry via REST or CLI.
* **Notifications on security-sensitive writes.** Rotations and revocations generate an organization-wide notification by default (configurable per org).

## See also

* [AI Governance → Compliance Architecture](/docs/ai-governance/compliance-architecture): how audit events get OCSF-mapped and exported to your SIEM (Splunk, Datadog, Sentinel, Elastic, Sumo).
* [Security](/docs/ai-gateway/security): how audit fits into the broader governance story.
* [RBAC](/docs/ai-gateway/rbac): who can view the unified audit log.
* [Virtual Keys → Rotation](/docs/ai-gateway/virtual-keys#rotation): the operation that makes auditability load-bearing.
