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

# APC API audit log schema and operations

This document describes the shape of each Astro Private Cloud (APC) API audit event and lists every operation that produces one. Use it when you build queries, alerts, or dashboards on top of APC API audit logs. For background on the feature, see [APC API audit logging overview](/docs/astro-private-cloud/v-2-x/audit-logging-overview).

## Event shape

The APC API emits each audit event as a single JSON object on standard output. The object has stable field names and a consistent top-level structure. The Vector sidecar adds Kubernetes metadata and renames `timestamp` to `@timestamp` before delivering the event to the configured sink.

The following example shows a raw event emitted by the APC API:

```json expandable wrap theme={null}
{
  "timestamp": "<timestamp>",
  "audit": true,
  "audit_version": "1.0",
  "correlationId": "<correlation-id>",
  "sessionId": "<session-id>",
  "userId": "<user-id>",
  "username": "<username>",
  "userEmail": "<user-email>",
  "role": "SYSTEM_ADMIN",
  "clientType": "ui",
  "origin": {
    "requestIp": "<request-ip>",
    "podName": "<pod-name>"
  },
  "action": "workspace.create",
  "operation": "create",
  "entity": {
    "type": "workspace",
    "id": "<workspace-id>",
    "name": "<workspace-name>"
  },
  "outcome": "success",
  "statusCode": 200,
  "request": {
    "graphql": {
      "operation": "createWorkspace",
      "variables": {
        "label": "<workspace-name>"
      }
    }
  },
  "response": {
    "duration": 85.23 // milliseconds
  },
  "component": "houston-api",
  "level": "INFO",
  "message": "Workspace <workspace-name> created successfully"
}
```

The Vector sidecar doesn't drop APC API audit fields. Before delivery to a sink, Vector:

* Renames `timestamp` to `@timestamp`.
* Adds a `kubernetes` object with `pod_name`, `pod_namespace`, and `container_name`.
* Adds `platform`, `component`, and `service` fields that identify the emitting control plane component.
* Converts the `level` field to uppercase.

After the transform, the same event in the sink contains every original APC API audit field plus the added metadata:

```json expandable wrap theme={null}
{
  "@timestamp": "<timestamp>",
  "audit": true,
  "audit_version": "1.0",
  "correlationId": "<correlation-id>",
  "sessionId": "<session-id>",
  "userId": "<user-id>",
  "username": "<username>",
  "userEmail": "<user-email>",
  "role": "SYSTEM_ADMIN",
  "clientType": "ui",
  "origin": {
    "requestIp": "<request-ip>",
    "podName": "<pod-name>"
  },
  "action": "workspace.create",
  "operation": "create",
  "entity": {
    "type": "workspace",
    "id": "<workspace-id>",
    "name": "<workspace-name>"
  },
  "outcome": "success",
  "statusCode": 200,
  "request": {
    "graphql": {
      "operation": "createWorkspace",
      "variables": {
        "label": "<workspace-name>"
      }
    }
  },
  "response": {
    "duration": 85.23 // milliseconds
  },
  "kubernetes": {
    "pod_name": "<pod-name>",
    "pod_namespace": "<pod-namespace>",
    "container_name": "houston"
  },
  "platform": "<release-name>-control-plane",
  "component": "houston-api",
  "service": "houston-api",
  "level": "INFO",
  "message": "Workspace <workspace-name> created successfully"
}
```

Each sink wraps the delivered event in its own envelope. In CloudWatch Logs, the fields appear as a structured log event. In GCP Cloud Logging, they appear inside `jsonPayload`. In Elasticsearch, they appear inside the `_source` object of each document. Field names and values inside the event are identical across sinks.

When you build queries against a sink, use `@timestamp`. When you inspect Pod standard output with `kubectl logs`, use `timestamp`.

## Field reference

| Field                       | Type      | Description                                                                                                           |
| --------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------- |
| `timestamp`                 | string    | ISO 8601 timestamp when the APC API emitted the event. Renamed to `@timestamp` by Vector before delivery to a sink.   |
| `audit`                     | `boolean` | Always `true` for audit events. Vector filters delivered events on this field.                                        |
| `audit_version`             | string    | Schema version of the audit event contract. Currently `1.0`.                                                          |
| `correlationId`             | string    | UUID that links related events in the same request or operation chain.                                                |
| `sessionId`                 | string    | Identifier for the session that initiated the action.                                                                 |
| `userId`                    | string    | APC API user ID of the actor. Set to `system` for system-initiated worker events.                                     |
| `username`                  | string    | Username of the actor. Set to `system` for system-initiated worker events.                                            |
| `userEmail`                 | string    | Email address of the actor when available.                                                                            |
| `role`                      | string    | Role of the actor at the time of the action. Set to `SYSTEM` for system-initiated worker events.                      |
| `clientType`                | string    | Client that initiated the action, for example `ui` or `api`. Set to `system` for system-initiated worker events.      |
| `origin`                    | object    | Origin metadata when available. See [Origin fields](#origin-fields).                                                  |
| `action`                    | string    | Action identifier in the form `<entity>.<operation>`, for example `workspace.create`.                                 |
| `operation`                 | string    | Operation portion of `action`, for example `create`.                                                                  |
| `entity`                    | object    | Target of the action. Always contains `type`. May contain `id`, `name`, and other entity-specific fields.             |
| `outcome`                   | string    | One of `success`, `failure`, or `partial`.                                                                            |
| `statusCode`                | number    | HTTP-style status code. For GraphQL failures, the APC API derives this from the GraphQL error code.                   |
| `request.graphql.operation` | string    | GraphQL operation name for API events, for example `createWorkspace`.                                                 |
| `request.graphql.variables` | object    | GraphQL variables with sensitive values redacted. See [Sensitive data handling](#sensitive-data-handling).            |
| `response.duration`         | number    | Duration of the operation, in milliseconds.                                                                           |
| `component`                 | string    | `houston-api` for GraphQL events, `houston-worker` for background worker events.                                      |
| `level`                     | string    | `ERROR` when `outcome` is `failure`, otherwise `INFO`.                                                                |
| `message`                   | string    | Human-readable message generated from the action, entity, and outcome. See [Message generation](#message-generation). |

### Conditional fields

The following fields are present only in some events:

* `errorMessage` appears only when the APC API records an explicit error message.
* `changes` appears only for change-aware operations, such as `deployment.update_flag`. It holds before and after values for each changed field.
* `origin` appears only when origin metadata is available.
* `username` and `userEmail` can be absent when the APC API can't derive them from the request.

### Origin fields

When present, `origin` contains any of the following fields:

| Field          | Description                                            |
| -------------- | ------------------------------------------------------ |
| `requestIp`    | Remote address observed by the APC API server.         |
| `forwardedFor` | Value of the `X-Forwarded-For` header, when present.   |
| `podName`      | Name of the APC API Pod that handled the request.      |
| `podIp`        | IP address of the APC API Pod.                         |
| `hostIp`       | IP address of the Kubernetes node that hosted the Pod. |

## Sensitive data handling

The APC API sanitizes GraphQL variables before it writes them to `request.graphql.variables`. Matching is case-insensitive.

| Variable name   | Behavior                                                                                                                                                                                                               |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `password`      | Replaced with the string `<redacted>`.                                                                                                                                                                                 |
| `token`         | Replaced with the string `<redacted>`.                                                                                                                                                                                 |
| `secret`        | Replaced with the string `<redacted>`.                                                                                                                                                                                 |
| `authorization` | Replaced with the string `<redacted>`.                                                                                                                                                                                 |
| `apiKey`        | Replaced with `sha256:<12 hex chars>...<last 4 chars>`. The hash prefix and the last four characters of the original value are kept so that the same key hashes identically across events, without exposing the value. |

## Message generation

Each audit event includes a `message` field that APC API generates from the action, entity, and outcome. The patterns follow these rules:

* For most entity operations, success messages use the pattern `<Entity type> <entity> <past-tense action> successfully`, and failure messages use `Failed to <verb> <entity type> <entity>: <error>`.
  * Example: `Workspace abc-123 created successfully`
  * Example: `Failed to delete deployment analytics-prod: Not authorized`
* Authentication events use a dedicated pattern:
  * `User <identity> logged in successfully`
  * `Failed to login as <identity>: <error>`
  * `User <identity> logged out successfully`
* Workspace and Deployment membership operations, such as adding or removing a user or updating a role, use subject-aware messages:
  * `User alice@example.com added to workspace finance successfully`
  * `Team team-123 removed from deployment analytics successfully`
  * `User alice@example.com role changed to WORKSPACE_EDITOR in workspace finance successfully`
* Role binding operations use the pattern `<Entity type> <action> successfully (<role> to <subject>)`.
* Invite token operations include the invited email, for example `Invite for alice@example.com deleted successfully`.
* Flag update operations read from the `changes` payload, for example `Deployment analytics flags updated (paused: changed from disabled to enabled)`.

Messages use plain identifiers without surrounding quotes. When a failure carries an error message, it is appended after a colon.

## Operation inventory

The following tables list every operation that the APC API currently audits, grouped by category. Each row maps the GraphQL mutation or worker action to its audit `action` value. Expand a category to see its operations.

<AccordionGroup>
  <Accordion title="Workspace operations">
    | Mutation                           | Audit action                          |
    | ---------------------------------- | ------------------------------------- |
    | `createWorkspace`                  | `workspace.create`                    |
    | `updateWorkspace`                  | `workspace.update`                    |
    | `deleteWorkspace`                  | `workspace.delete`                    |
    | `workspaceAddUser`                 | `workspace.add_user`                  |
    | `workspaceRemoveUser`              | `workspace.remove_user`               |
    | `workspaceUpdateUserRole`          | `workspace.update_user_role`          |
    | `workspaceUpsertUserRole`          | `workspace.upsert_user_role`          |
    | `workspaceAddTeam`                 | `workspace.add_team`                  |
    | `workspaceRemoveTeam`              | `workspace.remove_team`               |
    | `workspaceUpdateTeamRole`          | `workspace.update_team_role`          |
    | `updateWorkspaceDeploymentsConfig` | `workspace.update_deployments_config` |
    | `deleteWorkspaceDeploymentsConfig` | `workspace.delete_deployments_config` |
  </Accordion>

  <Accordion title="Deployment operations">
    | Mutation                     | Audit action                           |
    | ---------------------------- | -------------------------------------- |
    | `deleteDeployment`           | `deployment.delete`                    |
    | `upsertDeployment`           | `deployment.upsert`                    |
    | `upgradeDeployment`          | `deployment.upgrade`                   |
    | `deployRollback`             | `deployment.rollback`                  |
    | `updateDeploymentImage`      | `deployment.update_image`              |
    | `updateDeploymentVariables`  | `deployment.update_variables`          |
    | `updateDeploymentKedaConfig` | `deployment.update_keda_config`        |
    | `updateDeploymentsResources` | `deployment.update_resources`          |
    | `deploymentAlertsUpdate`     | `deployment.alerts_update`             |
    | `deploymentAddUserRole`      | `deployment.add_user_role`             |
    | `deploymentRemoveUserRole`   | `deployment.remove_user_role`          |
    | `deploymentUpdateUserRole`   | `deployment.update_user_role`          |
    | `deploymentAddTeamRole`      | `deployment.add_team_role`             |
    | `deploymentRemoveTeamRole`   | `deployment.remove_team_role`          |
    | `deploymentUpdateTeamRole`   | `deployment.update_team_role`          |
    | `updateDeploymentConfig`     | `deployment.update_deployments_config` |
    | `deleteDeploymentConfig`     | `deployment.delete_deployments_config` |
  </Accordion>

  <Accordion title="Deploy revision operations">
    | Mutation                 | Audit action              |
    | ------------------------ | ------------------------- |
    | `createDeployRevision`   | `deploy_revision.create`  |
    | `cleanupDeployRevisions` | `deploy_revision.cleanup` |
  </Accordion>

  <Accordion title="User operations">
    | Mutation                 | Audit action                |
    | ------------------------ | --------------------------- |
    | `createUser`             | `user.create`               |
    | `removeUser`             | `user.remove`               |
    | `inviteUser`             | `user.invite`               |
    | `resendConfirmation`     | `user.resend_confirmation`  |
    | `updateSelf`             | `user.update_self`          |
    | `verifyEmail`            | `user.verify_email`         |
    | `deleteTestUsersInBulk`  | `user.delete_bulk`          |
    | `updateUserTeamBindings` | `user.update_team_bindings` |
  </Accordion>

  <Accordion title="Service account operations">
    | Mutation                         | Audit action                        |
    | -------------------------------- | ----------------------------------- |
    | `createServiceAccount`           | `service_account.create`            |
    | `updateServiceAccount`           | `service_account.update`            |
    | `deleteServiceAccount`           | `service_account.delete`            |
    | `createWorkspaceServiceAccount`  | `workspace_service_account.create`  |
    | `updateWorkspaceServiceAccount`  | `workspace_service_account.update`  |
    | `deleteWorkspaceServiceAccount`  | `workspace_service_account.delete`  |
    | `createDeploymentServiceAccount` | `deployment_service_account.create` |
    | `updateDeploymentServiceAccount` | `deployment_service_account.update` |
    | `deleteDeploymentServiceAccount` | `deployment_service_account.delete` |
    | `createSystemServiceAccount`     | `system_service_account.create`     |
    | `updateSystemServiceAccount`     | `system_service_account.update`     |
    | `deleteSystemServiceAccount`     | `system_service_account.delete`     |
  </Accordion>

  <Accordion title="Role binding operations">
    | Mutation                      | Audit action                      |
    | ----------------------------- | --------------------------------- |
    | `createSystemRoleBinding`     | `system_role_binding.create`      |
    | `deleteSystemRoleBinding`     | `system_role_binding.delete`      |
    | `createTeamSystemRoleBinding` | `team_system_role_binding.create` |
    | `deleteTeamSystemRoleBinding` | `team_system_role_binding.delete` |
  </Accordion>

  <Accordion title="Team operations">
    | Mutation     | Audit action  |
    | ------------ | ------------- |
    | `createTeam` | `team.create` |
    | `updateTeam` | `team.update` |
    | `removeTeam` | `team.remove` |
  </Accordion>

  <Accordion title="Authentication operations">
    | Mutation         | Audit action           |
    | ---------------- | ---------------------- |
    | `createToken`    | `auth.login`           |
    | `logout`         | `auth.logout`          |
    | `forgotPassword` | `auth.forgot_password` |
    | `resetPassword`  | `auth.reset_password`  |
    | `confirmEmail`   | `auth.confirm_email`   |
  </Accordion>

  <Accordion title="Invite token operations">
    | Mutation            | Audit action          |
    | ------------------- | --------------------- |
    | `deleteInviteToken` | `invite_token.delete` |
  </Accordion>

  <Accordion title="Cluster operations">
    | Mutation              | Audit action            |
    | --------------------- | ----------------------- |
    | `registerCluster`     | `cluster.register`      |
    | `updateCluster`       | `cluster.update`        |
    | `deregisterCluster`   | `cluster.deregister`    |
    | `cleanupClusterAudit` | `cluster.cleanup_audit` |
  </Accordion>

  <Accordion title="Worker operations">
    The APC API emits worker events from background jobs with `component` set to `houston-worker`. Worker actions aren't triggered by a GraphQL mutation, so they have no mutation mapping. When a worker action has no authenticated actor, the APC API records `userId: "system"`, `username: "system"`, `role: "SYSTEM"`, and `clientType: "system"`.

    | Audit action                           | Description                                           |
    | -------------------------------------- | ----------------------------------------------------- |
    | `deployment.worker_create`             | Applies a newly created Deployment in the data plane. |
    | `deployment.worker_update`             | Applies a Deployment update in the data plane.        |
    | `deployment.worker_delete`             | Applies a Deployment deletion in the data plane.      |
    | `deployment.worker_update_image`       | Applies a Deployment Airflow image update.            |
    | `deployment.worker_update_variables`   | Applies a Deployment environment variable update.     |
    | `deployment.worker_cleanup_db`         | Cleans up the Deployment's Airflow metadata database. |
    | `deployment.worker_refresh_task_usage` | Refreshes task usage metrics for a Deployment.        |
    | `cluster.worker_update_config`         | Applies a cluster configuration update.               |
  </Accordion>
</AccordionGroup>

## Next steps

* To enable audit log shipping, see [Set up audit log shipping](/docs/astro-private-cloud/v-2-x/audit-logging-setup).
* For every Helm value that controls the sidecar and its sinks, see [Audit logging configuration reference](/docs/astro-private-cloud/v-2-x/audit-logging-reference).
