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.

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:

1{
2 "timestamp": "<timestamp>",
3 "audit": true,
4 "audit_version": "1.0",
5 "correlationId": "<correlation-id>",
6 "sessionId": "<session-id>",
7 "userId": "<user-id>",
8 "username": "<username>",
9 "userEmail": "<user-email>",
10 "role": "SYSTEM_ADMIN",
11 "clientType": "ui",
12 "origin": {
13 "requestIp": "<request-ip>",
14 "podName": "<pod-name>"
15 },
16 "action": "workspace.create",
17 "operation": "create",
18 "entity": {
19 "type": "workspace",
20 "id": "<workspace-id>",
21 "name": "<workspace-name>"
22 },
23 "outcome": "success",
24 "statusCode": 200,
25 "request": {
26 "graphql": {
27 "operation": "createWorkspace",
28 "variables": {
29 "label": "<workspace-name>"
30 }
31 }
32 },
33 "response": {
34 "duration": 85.23 // milliseconds
35 },
36 "component": "houston-api",
37 "level": "INFO",
38 "message": "Workspace <workspace-name> created successfully"
39}

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:

1{
2 "@timestamp": "<timestamp>",
3 "audit": true,
4 "audit_version": "1.0",
5 "correlationId": "<correlation-id>",
6 "sessionId": "<session-id>",
7 "userId": "<user-id>",
8 "username": "<username>",
9 "userEmail": "<user-email>",
10 "role": "SYSTEM_ADMIN",
11 "clientType": "ui",
12 "origin": {
13 "requestIp": "<request-ip>",
14 "podName": "<pod-name>"
15 },
16 "action": "workspace.create",
17 "operation": "create",
18 "entity": {
19 "type": "workspace",
20 "id": "<workspace-id>",
21 "name": "<workspace-name>"
22 },
23 "outcome": "success",
24 "statusCode": 200,
25 "request": {
26 "graphql": {
27 "operation": "createWorkspace",
28 "variables": {
29 "label": "<workspace-name>"
30 }
31 }
32 },
33 "response": {
34 "duration": 85.23 // milliseconds
35 },
36 "kubernetes": {
37 "pod_name": "<pod-name>",
38 "pod_namespace": "<pod-namespace>",
39 "container_name": "houston"
40 },
41 "platform": "<release-name>-control-plane",
42 "component": "houston-api",
43 "service": "houston-api",
44 "level": "INFO",
45 "message": "Workspace <workspace-name> created successfully"
46}

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

FieldTypeDescription
timestampstringISO 8601 timestamp when the APC API emitted the event. Renamed to @timestamp by Vector before delivery to a sink.
auditbooleanAlways true for audit events. Vector filters delivered events on this field.
audit_versionstringSchema version of the audit event contract. Currently 1.0.
correlationIdstringUUID that links related events in the same request or operation chain.
sessionIdstringIdentifier for the session that initiated the action.
userIdstringAPC API user ID of the actor. Set to system for system-initiated worker events.
usernamestringUsername of the actor. Set to system for system-initiated worker events.
userEmailstringEmail address of the actor when available.
rolestringRole of the actor at the time of the action. Set to SYSTEM for system-initiated worker events.
clientTypestringClient that initiated the action, for example ui or api. Set to system for system-initiated worker events.
originobjectOrigin metadata when available. See Origin fields.
actionstringAction identifier in the form <entity>.<operation>, for example workspace.create.
operationstringOperation portion of action, for example create.
entityobjectTarget of the action. Always contains type. May contain id, name, and other entity-specific fields.
outcomestringOne of success, failure, or partial.
statusCodenumberHTTP-style status code. For GraphQL failures, the APC API derives this from the GraphQL error code.
request.graphql.operationstringGraphQL operation name for API events, for example createWorkspace.
request.graphql.variablesobjectGraphQL variables with sensitive values redacted. See Sensitive data handling.
response.durationnumberDuration of the operation, in milliseconds.
componentstringhouston-api for GraphQL events, houston-worker for background worker events.
levelstringERROR when outcome is failure, otherwise INFO.
messagestringHuman-readable message generated from the action, entity, and outcome. See 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:

FieldDescription
requestIpRemote address observed by the APC API server.
forwardedForValue of the X-Forwarded-For header, when present.
podNameName of the APC API Pod that handled the request.
podIpIP address of the APC API Pod.
hostIpIP 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 nameBehavior
passwordReplaced with the string <redacted>.
tokenReplaced with the string <redacted>.
secretReplaced with the string <redacted>.
authorizationReplaced with the string <redacted>.
apiKeyReplaced 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.

MutationAudit action
createWorkspaceworkspace.create
updateWorkspaceworkspace.update
deleteWorkspaceworkspace.delete
workspaceAddUserworkspace.add_user
workspaceRemoveUserworkspace.remove_user
workspaceUpdateUserRoleworkspace.update_user_role
workspaceUpsertUserRoleworkspace.upsert_user_role
workspaceAddTeamworkspace.add_team
workspaceRemoveTeamworkspace.remove_team
workspaceUpdateTeamRoleworkspace.update_team_role
updateWorkspaceDeploymentsConfigworkspace.update_deployments_config
deleteWorkspaceDeploymentsConfigworkspace.delete_deployments_config
MutationAudit action
deleteDeploymentdeployment.delete
upsertDeploymentdeployment.upsert
upgradeDeploymentdeployment.upgrade
deployRollbackdeployment.rollback
updateDeploymentImagedeployment.update_image
updateDeploymentVariablesdeployment.update_variables
updateDeploymentKedaConfigdeployment.update_keda_config
updateDeploymentsResourcesdeployment.update_resources
deploymentAlertsUpdatedeployment.alerts_update
deploymentAddUserRoledeployment.add_user_role
deploymentRemoveUserRoledeployment.remove_user_role
deploymentUpdateUserRoledeployment.update_user_role
deploymentAddTeamRoledeployment.add_team_role
deploymentRemoveTeamRoledeployment.remove_team_role
deploymentUpdateTeamRoledeployment.update_team_role
updateDeploymentConfigdeployment.update_deployments_config
deleteDeploymentConfigdeployment.delete_deployments_config
MutationAudit action
createDeployRevisiondeploy_revision.create
cleanupDeployRevisionsdeploy_revision.cleanup
MutationAudit action
createUseruser.create
removeUseruser.remove
inviteUseruser.invite
resendConfirmationuser.resend_confirmation
updateSelfuser.update_self
verifyEmailuser.verify_email
deleteTestUsersInBulkuser.delete_bulk
updateUserTeamBindingsuser.update_team_bindings
MutationAudit action
createServiceAccountservice_account.create
updateServiceAccountservice_account.update
deleteServiceAccountservice_account.delete
createWorkspaceServiceAccountworkspace_service_account.create
updateWorkspaceServiceAccountworkspace_service_account.update
deleteWorkspaceServiceAccountworkspace_service_account.delete
createDeploymentServiceAccountdeployment_service_account.create
updateDeploymentServiceAccountdeployment_service_account.update
deleteDeploymentServiceAccountdeployment_service_account.delete
createSystemServiceAccountsystem_service_account.create
updateSystemServiceAccountsystem_service_account.update
deleteSystemServiceAccountsystem_service_account.delete
MutationAudit action
createSystemRoleBindingsystem_role_binding.create
deleteSystemRoleBindingsystem_role_binding.delete
createTeamSystemRoleBindingteam_system_role_binding.create
deleteTeamSystemRoleBindingteam_system_role_binding.delete
MutationAudit action
createTeamteam.create
updateTeamteam.update
removeTeamteam.remove
MutationAudit action
createTokenauth.login
logoutauth.logout
forgotPasswordauth.forgot_password
resetPasswordauth.reset_password
confirmEmailauth.confirm_email
MutationAudit action
deleteInviteTokeninvite_token.delete
MutationAudit action
registerClustercluster.register
updateClustercluster.update
deregisterClustercluster.deregister
cleanupClusterAuditcluster.cleanup_audit

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 actionDescription
deployment.worker_createApplies a newly created Deployment in the data plane.
deployment.worker_updateApplies a Deployment update in the data plane.
deployment.worker_deleteApplies a Deployment deletion in the data plane.
deployment.worker_update_imageApplies a Deployment Airflow image update.
deployment.worker_update_variablesApplies a Deployment environment variable update.
deployment.worker_cleanup_dbCleans up the Deployment’s Airflow metadata database.
deployment.worker_refresh_task_usageRefreshes task usage metrics for a Deployment.
cluster.worker_update_configApplies a cluster configuration update.

Next steps