Audit log events
The audit log captures a structured record of every state-modifying administrative action in Tetrate Agent Router. Entries are immutable and support compliance frameworks such as SOC 2 and ISO 27001. The wire schema returned by the management API and shown in Admin Console exports is documented here: the fields on every entry, the action and resource vocabulary, and how related rows join.
Event envelope
Every audit entry mirrors a row of the audit_logs table. The management API exposes that row as AuditLogEntry (JSON field names are camelCase; OpenAPI also documents snake_case titles such as action_type).
| Field | Type | Description |
|---|---|---|
id | string | Server-generated audit entry UUID (primary key) |
timestamp | string (RFC 3339, UTC) | When the audited action occurred |
createdAt | string (RFC 3339, UTC) | When the audit row was persisted (defaults to the event time) |
userId | string | Id of the user that performed the action; empty for system actions. From 0.9.0, a change made through a console names the signed-in person here, not the console's key (see Who an entry names) |
userEmail | string | Email of the acting user, captured at write time. From 0.9.0, set for user and management-key callers |
actorType | string | Actor category (for example USER, SERVICE, or SYSTEM) |
actionType | string | Action performed (for example CREATE, UPDATE, DELETE, CREATE_SECRET, or SET_GUARDRAIL_STATUS) |
resourceType | string | Type of the affected resource (for example secret, provider, guardrail, or api_key) |
resourceId | string | Id of the affected resource |
success | boolean | Whether the action succeeded |
statusCode | integer | HTTP status code of the response |
errorMessage | string | Error detail when the action failed; empty on success |
sourceIp | string | Client IP the request originated from. For a Developer Console call, the address of the console |
userAgent | string | User-Agent header of the originating request. From 0.9.0, a Developer Console call carries the browser's User-Agent |
httpMethod | string | HTTP method of the originating request (for example POST) |
endpoint | string | Request path or RPC endpoint that triggered the action |
correlationId | string | Correlation id grouping the audit entries that one administrative call produced; distinct from the request X-Request-ID used by data-plane telemetry |
metadata | object | Additional structured context attached to the entry |
requestParams | object | Request path or query parameters captured for the action |
requestBody | object | Request body captured for the action (sensitive values may be redacted) |
responseData | object | Response payload captured for the action |
userId, userEmail, and actorType answer who. actionType, resourceType, and resourceId answer what and to which thing. metadata, requestBody, requestParams, and responseData carry operation-specific context. correlationId joins the audit rows produced by one administrative call. It is an audit-scoped identifier, not the request X-Request-ID, so it does not join audit entries to data-plane telemetry such as traces or request logs.
The Admin Console Audit Logs table projects a subset of these fields (timestamp, actor, action, resource, source, and result). The UI may show a human-readable resource label next to resourceId; that label is a presentation detail, not a separate wire field on AuditLogEntry.
Who an entry names
Both consoles call the management API with a service key. From 0.9.0, an entry names the signed-in person behind such a call rather than the key. The actor is chosen in this order:
- The user of the
X-Acting-Session-Tokenheader. This header also narrows what the call is allowed to do. - The user of the
X-Audit-Session-Tokenheader. This header changes attribution only and grants no access. - Neither header: the caller itself, as before 0.9.0. A call made with a bare management key names the same actor as before, now with its email.
When either header names a person, userId and userEmail name that person and the key ID moves to metadata.via_key. The Developer Console sends X-Audit-Session-Token on its calls from 0.9.0. Admin Console calls that already send X-Acting-Session-Token change the same way: userId changes from the key to the person, and metadata.via_key is added. A data plane report (actor SYSTEM) keeps its actor.
X-Audit-Session-Token is read only on a call made with an admin key; a session or a management key is its own actor, and the header is ignored on those credentials. The token must be a live sign-in session. A token that is not one fails the call with Unauthenticated, and a session of a user from another organization fails it with PermissionDenied.
Developer Console request context
From 0.9.0, entries for Developer Console calls carry the browser's userAgent, and the X-Forwarded-For chain that the console received in metadata.forwarded_for. sourceIp stays the address of the console. Client addresses are read from metadata.forwarded_for, which is only as trustworthy as the ingress in front of the console.
Metadata keys
| Key | Present when |
|---|---|
metadata.via_key | Since 0.9.0. The entry names a person who acted through a key; the value is the key ID |
metadata.forwarded_for | Since 0.9.0. The call came through the Developer Console; the value is the X-Forwarded-For chain the console received |
metadata.phase | On FINISH_DATAPLANE_UPGRADE: the final phase of the upgrade (Completed, Failed, RolledBack, or Cancelled) |
Write guarantees
From 0.9.0, an entry is written in the same database transaction as the change it records:
- A failed or refused change leaves one entry with
successset tofalse. - An entry that cannot be written is counted in the management plane's
audit_write_failures_totalmetric, labelled byaction. The change itself still commits, so an alert on this metric is the way to learn that an entry is missing. - Granting or revoking Super Admin is the exception: when its entry cannot be written, the call fails with
Internaland changes nothing. Retrying the call is safe.
Action and resource vocabulary
actionType and resourceType are stable strings that dashboard filters and SIEM consumers use. They are not dotted <resource>.<verb> names.
Action types
Many mutations use a verb-plus-resource form such as CREATE_SECRET, UPDATE_GUARDRAIL, or DELETE_DATAPLANE. Shorter verbs such as CREATE, UPDATE, DELETE, and UPGRADE also appear. Representative values include:
actionType | Typical when |
|---|---|
CREATE_SECRET / DELETE_SECRET / ROTATE_SECRET | Secret lifecycle |
CREATE_GUARDRAIL / UPDATE_GUARDRAIL / DELETE_GUARDRAIL / SET_GUARDRAIL_STATUS | Guardrail lifecycle and enablement |
CREATE_GUARDRAIL_RULE / UPDATE_GUARDRAIL_RULE / DELETE_GUARDRAIL_RULE | Guardrail rule changes |
CREATE_GUARDRAIL_PROVIDER / UPDATE_GUARDRAIL_PROVIDER / DELETE_GUARDRAIL_PROVIDER | Guardrail provider changes |
ADD_PROJECT_MODEL / REMOVE_PROJECT_MODEL | Project model catalog changes |
ADD_PROJECT_PROVIDER / REMOVE_PROJECT_PROVIDER | Project provider attachment |
CREATE_CLIENT_KEY / ADD_CLIENT_KEY / ROTATE_CLIENT_KEY / DISABLE_CLIENT_KEY / ENABLE_CLIENT_KEY / DESTROY_CLIENT_KEY | API key and client-key lifecycle. From 0.9.0, ROTATE_CLIENT_KEY has resourceType client_key and the client ID as resourceId (before: api_key and the key ID). A legacy key with no client keeps api_key and the key ID until a later release |
ISSUE_MY_KEY / REVOKE_MY_KEY | A management key issued or revoked by its owner. From 0.9.0, these replace the record the Developer Console wrote itself |
CREATE_PROJECT / UPDATE_PROJECT / DELETE_PROJECT | Project lifecycle |
ADD_PROJECT_MEMBER / UPDATE_PROJECT_MEMBER / REMOVE_PROJECT_MEMBER | Project membership |
CREATE_DATAPLANE / UPDATE_DATAPLANE / SET_DATAPLANE_PROJECT / DELETE_DATAPLANE | Data plane lifecycle. From 0.9.0, changes made through the workspace API are recorded too |
FINISH_DATAPLANE_UPGRADE | Since 0.9.0. A data plane upgrade ended. One entry per upgrade, with actor SYSTEM, resourceType dataplane_upgrade, and the final phase in metadata.phase. Only Completed has success set to true |
SET_DATAPLANE_URL | An address stored for a data plane through the admin API. Deprecated in 0.7.0, when a data plane declares its hostnames in its own Helm values, so the action becomes rare and stops once no supported data plane predates 0.7.0 |
QUEUE_DATAPLANE_ZEROIZE | Since 0.7.0. Deleting a data plane left a zeroize directive for the data plane to collect on its next configuration poll, beside the DELETE_DATAPLANE entry |
PROJECT_SERVED_NOWHERE | Since 0.7.0. The last data plane serving a project stopped serving it: a detach or label removal took the project off its last data plane, or a change landing during a data plane delete left the project unserved. The entry names the project and the data plane. Alert on it, because the project's API keys are accepted nowhere until a data plane serves the project again |
SET_DATAPLANE_CONFIG_OVERRIDE / CLEAR_DATAPLANE_CONFIG_OVERRIDE | Since 0.7.0. A provider address or key set or cleared for one data plane |
ACKNOWLEDGE_CONFIG_DIFFERENCE | Since 0.7.0. An administrator or project owner acknowledged a configuration difference a data plane reported |
RESOLVE_DATAPLANE_CREDENTIAL | Since 0.7.0. A data plane asked for a key override's credential and was refused. Successful resolutions are not recorded |
CREATE_PROJECT_GATEWAY / UPDATE_PROJECT_GATEWAY / DELETE_PROJECT_GATEWAY | Project gateway lifecycle |
SET_PROJECT_GATEWAY_URL | A project gateway URL set through the admin API. Deprecated in 0.7.0 together with SET_DATAPLANE_URL |
ATTACH_PROJECT_GATEWAY_PROJECT / DETACH_PROJECT_GATEWAY_PROJECT | Gateway-to-project binding. From 0.9.0, a refused attach leaves an ATTACH_PROJECT_GATEWAY_PROJECT entry with success set to false |
CREATE_TELEMETRY_CONFIG / UPDATE_TELEMETRY_CONFIG / DELETE_TELEMETRY_CONFIG | Telemetry and SIEM forward configuration. From 0.9.0, project telemetry changes made in the Developer Console are recorded as CREATE_TELEMETRY_CONFIG and UPDATE_TELEMETRY_CONFIG with the configuration ID as resourceId, replacing the console's telemetry.project_config.set and telemetry.project_config.disable entries (which had the project ID) |
CREATE_PATTERN / UPDATE_PATTERN / DELETE_PATTERN | Since 0.9.0. Guardrail pattern changes |
CREATE_FALLBACK_CHAIN_POLICY / UPDATE_FALLBACK_CHAIN_POLICY / DELETE_FALLBACK_CHAIN_POLICY / SET_FALLBACK_CHAIN_POLICY_STATUS | Fallback policy changes. From 0.9.0, a fallback policy saved through UpsertFallbackPolicy is recorded too |
REVOKE_USER_TOKEN / UPSERT_MCP_CATALOG_SERVER | Token revocations and MCP catalog entries. From 0.9.0, those a data plane writes are recorded too, as is the data plane URL it sets (SET_DATAPLANE_URL) |
UPSERT_SYSTEM_SETTING / UPSERT_PROJECT_SETTING / DELETE_PROJECT_SETTING | Settings changes |
AUTHORIZATION_DENIED | Since 0.9.0. A management API call refused for missing permissions on the identity, tenancy, API key, AI key, model catalog, MCP, RBAC, and Developer Console request-log APIs. resourceType is rpc, resourceId is the operation called, and success is false; metadata.customer_id and metadata.project_id hold the customer and project the call named. Refusals on other management API endpoints are not recorded yet |
This table is representative, not exhaustive. New management APIs can introduce additional actionType values; filter on observed values from QueryAuditLogs or the Audit Logs UI when building SIEM rules.
Spellings before 0.5.0
API key entries written before 0.5.0 use an older vocabulary: dotted action names (apikey.create, apikey.update, apikey.rotate, apikey.delete), the resource_type value apikey, and lowercase actor_type values. Entries written before the change keep their old values, and nothing rewrites them, so a SIEM rule that spans the upgrade has to match both vocabularies: the old spellings for historical entries and the tables above for everything written since.
Two more properties of the 0.5.0 change matter to a SIEM consumer:
- Before 0.9.0, the envelope's four request columns (
sourceIp,userAgent,httpMethod,endpoint) are populated for management-plane services only, and entries the Developer Console wrote itself leave them empty. A blank column on such an entry is not a sign the entry was altered. From 0.9.0, Developer Console calls carry the browser'suserAgentandmetadata.forwarded_for, as described in Developer Console request context. - Entries are append-only either side of the boundary: the spelling change is visible as a discontinuity in the values, never as a modified historical row.
Changes in 0.9.0
Entries written before the upgrade keep their values. A SIEM rule that spans the upgrade accounts for these changes:
- Actor. Console calls name the signed-in person in
userIdanduserEmail, and the key ID moves tometadata.via_key. A rule matching a console's key ID on the user field moves tometadata.via_key. - Failure entries. A refused or failed change leaves one entry with
successset tofalse, so failure counts rise. - Newly recorded changes. Workspace API changes, guardrail pattern changes,
UpsertFallbackPolicy, refused gateway attaches, data plane upgrade outcomes, and the data plane URL, token revocations, and MCP catalog entries a data plane writes now leave entries. - Developer Console entries. The management plane writes the entries for key rotation, management key issue and revoke, and project telemetry changes (
ROTATE_CLIENT_KEY,ISSUE_MY_KEY,REVOKE_MY_KEY,CREATE_TELEMETRY_CONFIG, andUPDATE_TELEMETRY_CONFIG), and the console no longer writes its own. Filters ontelemetry.project_config.setandtelemetry.project_config.disablemove toCREATE_TELEMETRY_CONFIGandUPDATE_TELEMETRY_CONFIG, and theresourceTypeandresourceIdof key rotation and telemetry entries change as described in Action types. - Data plane upgrades. An upgrade outcome is one
FINISH_DATAPLANE_UPGRADEentry with the final phase inmetadata.phase. - Refused calls. A call refused for missing permissions on the identity, tenancy, API key, AI key, model catalog, MCP, RBAC, and Developer Console request-log APIs leaves an
AUTHORIZATION_DENIEDentry, so a rule that counts entries per user sees these too.
Until a later release removes the Admin Console's own audit writes, an Admin Console change that the management API also audits leaves two entries, and both name the signed-in user. For example, a data plane update writes UPDATE from the console and UPDATE_DATAPLANE with metadata.via_key from the management API. To count each change once, keep the entries that carry metadata.via_key and the management API's action names (such as UPDATE_DATAPLANE), or treat two entries with the same user and resource ID a few seconds apart as one change.
Query by subject
Since 0.5.0, audit queries also take subject_user_id. The two user filters answer different questions: user_id names the admin who performed the action, and subject_user_id names the identity the action was about. Finding every change made by an administrator filters on user_id; finding every change made to a user (their roles, their team, their keys) filters on subject_user_id, whoever performed it.
Search and sort
From 0.9.0, QueryAuditLogs and QueryPlatformAuditLogs take two optional fields:
| Field | Behavior |
|---|---|
search | Case-insensitive substring match over the actor's email, user ID, and type, the action, the resource type and ID, the correlation ID, the endpoint, the source IP, and the error message. At most 200 characters; % and _ match as literal text. The total count and statistics apply the search too |
order_by | Sort key: timestamp, actor, action, resource, source, or outcome. Entries that tie on a key other than timestamp are ordered newest first, so pages stay stable |
A search that sets no start_time covers the 30 days before end_time (or before now when end_time is unset), starting at the beginning of that UTC day, so every page of one search shares the same window. An explicit start_time always applies. A sort with no search keeps the full time range. With both fields empty, the queries behave as before 0.9.0.
Resource types
resourceType | Resource family |
|---|---|
secret | Stored secrets |
guardrail / guardrail_rule / guardrail_provider / pattern | Guardrails and guardrail patterns |
fallback_chain_policy | Fallback policies |
project / project_member / project_model / project_provider / project_setting / project_mcp_server | Project-scoped resources |
project_gateway | Project gateways |
dataplane | Data planes |
dataplane_upgrade | Data plane upgrades |
client / client_key | Clients and API keys |
user_token | User tokens |
service_account | Service accounts |
customer | Customers |
telemetry_config | Telemetry forward configs |
system_setting | Deployment-global settings |
mcp_route | MCP route status |
mcp_catalog_server | MCP catalog entries |
rpc | A refused management API operation, on AUTHORIZATION_DENIED entries |
Example event
{
"id": "8f14e45f-ceea-467f-a8f0-6b2a1c3d4e5f",
"timestamp": "2026-07-25T19:11:11Z",
"createdAt": "2026-07-25T19:11:11Z",
"userId": "c631d6d5-afb2-41fe-a284-eaf7be377c14",
"actorType": "USER",
"actionType": "CREATE_SECRET",
"resourceType": "secret",
"resourceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"success": true,
"statusCode": 200,
"errorMessage": "",
"sourceIp": "203.0.113.10",
"userAgent": "Mozilla/5.0",
"httpMethod": "POST",
"endpoint": "/v1/secrets",
"correlationId": "corr-7c9e6679-7425-40de-944b-e07fc1f90ae7",
"metadata": {
"name": "0-salesforce"
},
"requestParams": {},
"requestBody": {},
"responseData": {}
}
Sensitive values in requestBody, responseData, and metadata may be redacted. Credential material is not written in cleartext to the audit log.
Coverage and immutability
- Coverage. Every state-modifying administrative action generates an audit event. There is no path through the Admin Console that changes Agent Router state without leaving a record. From 0.9.0, the event is written in the same transaction as the change, and an event that cannot be written is counted (see Write guarantees).
- Immutability. Audit entries cannot be edited or deleted by any user, regardless of role. There is no "delete from the log" operation anywhere in Agent Router. Signed Merkle checkpoints support tamper-evidence for sealed windows of the log; see the Admin API's audit checkpoint operations.
Retention is configured per deployment. For long-horizon retention beyond the in-Console window, the audit stream is exported to an external SIEM or log store; see Export audit decisions to SIEM.
Related
- Audit Agent Router activity, the surface for browsing audit events and usage analytics
- QueryAuditLogs and GetAuditLog, management API operations that return
AuditLogEntry - OTel metrics, metric stream that complements the audit stream
Where to go next