diff --git a/braintrust/examples/google-autopilot/values.yaml b/braintrust/examples/google-autopilot/values.yaml index 8e9dff9..dc9f482 100644 --- a/braintrust/examples/google-autopilot/values.yaml +++ b/braintrust/examples/google-autopilot/values.yaml @@ -18,6 +18,15 @@ objectStorage: brainstoreBucket: "" apiBucket: "" +# BTQL query.read audit logging (requires data plane v2.6.0+). +# Uncomment exactly one block to enable audit logging for specific orgs. +# Strict mode writes the audit row before returning results; best-effort +# writes asynchronously and logs failures. Setting both is a template error. +# +# btqlAuditLogsStrictOrgIds: [""] +# +# btqlAuditLogsBestEffortOrgIds: [""] + api: name: "braintrust-api" annotations: diff --git a/braintrust/templates/api-configmap.yaml b/braintrust/templates/api-configmap.yaml index 1bd41c2..6742b78 100644 --- a/braintrust/templates/api-configmap.yaml +++ b/braintrust/templates/api-configmap.yaml @@ -10,6 +10,21 @@ {{- fail "global.primaryOrgName or api.extraEnvVars PRIMARY_ORG_NAME is required when global.orgName is empty or \"*\"; self-hosted service-token management needs a primary organization." -}} {{- end -}} {{- $allowedOrgIds := .Values.global.allowedOrgIds | default "" | toString | trim -}} +{{- $btqlStrictOrgIds := .Values.btqlAuditLogsStrictOrgIds | default list -}} +{{- $btqlBestEffortOrgIds := .Values.btqlAuditLogsBestEffortOrgIds | default list -}} +{{- if and (gt (len $btqlStrictOrgIds) 0) (gt (len $btqlBestEffortOrgIds) 0) -}} +{{- fail "Set either btqlAuditLogsStrictOrgIds or btqlAuditLogsBestEffortOrgIds, not both." -}} +{{- end -}} +{{- range $btqlStrictOrgIds -}} +{{- if not (regexMatch "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" .) -}} +{{- fail (printf "btqlAuditLogsStrictOrgIds: %q is not a valid UUID" .) -}} +{{- end -}} +{{- end -}} +{{- range $btqlBestEffortOrgIds -}} +{{- if not (regexMatch "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" .) -}} +{{- fail (printf "btqlAuditLogsBestEffortOrgIds: %q is not a valid UUID" .) -}} +{{- end -}} +{{- end -}} --- apiVersion: v1 kind: ConfigMap @@ -94,3 +109,9 @@ data: {{- if .Values.aiGateway.useGateway }} GATEWAY_URL: {{ include "braintrust.aiGatewayInternalUrl" . | quote }} {{- end }} + {{- if $btqlStrictOrgIds }} + BTQL_AUDIT_LOGS_STRICT_ORG_IDS: {{ $btqlStrictOrgIds | join "," | quote }} + {{- end }} + {{- if $btqlBestEffortOrgIds }} + BTQL_AUDIT_LOGS_BEST_EFFORT_ORG_IDS: {{ $btqlBestEffortOrgIds | join "," | quote }} + {{- end }} diff --git a/braintrust/tests/api-configmap_test.yaml b/braintrust/tests/api-configmap_test.yaml index 04854ef..27de0d0 100644 --- a/braintrust/tests/api-configmap_test.yaml +++ b/braintrust/tests/api-configmap_test.yaml @@ -505,3 +505,83 @@ tests: - equal: path: data.SKIP_PG_FOR_BRAINSTORE_OBJECTS value: "exclude:project_logs:abc123" + + - it: should omit BTQL audit log env vars when both lists are empty + values: + - __fixtures__/base-values.yaml + release: + namespace: "braintrust" + asserts: + - isNull: + path: data.BTQL_AUDIT_LOGS_STRICT_ORG_IDS + - isNull: + path: data.BTQL_AUDIT_LOGS_BEST_EFFORT_ORG_IDS + + - it: should set BTQL_AUDIT_LOGS_STRICT_ORG_IDS when strict org IDs are configured + values: + - __fixtures__/base-values.yaml + set: + btqlAuditLogsStrictOrgIds: + - "00000000-0000-4000-8000-000000000001" + - "00000000-0000-4000-8000-000000000002" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BTQL_AUDIT_LOGS_STRICT_ORG_IDS + value: "00000000-0000-4000-8000-000000000001,00000000-0000-4000-8000-000000000002" + - isNull: + path: data.BTQL_AUDIT_LOGS_BEST_EFFORT_ORG_IDS + + - it: should set BTQL_AUDIT_LOGS_BEST_EFFORT_ORG_IDS when best-effort org IDs are configured + values: + - __fixtures__/base-values.yaml + set: + btqlAuditLogsBestEffortOrgIds: + - "00000000-0000-4000-8000-000000000001" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BTQL_AUDIT_LOGS_BEST_EFFORT_ORG_IDS + value: "00000000-0000-4000-8000-000000000001" + - isNull: + path: data.BTQL_AUDIT_LOGS_STRICT_ORG_IDS + + - it: should fail when both strict and best-effort org IDs are set + values: + - __fixtures__/base-values.yaml + set: + btqlAuditLogsStrictOrgIds: + - "00000000-0000-4000-8000-000000000001" + btqlAuditLogsBestEffortOrgIds: + - "00000000-0000-4000-8000-000000000002" + release: + namespace: "braintrust" + asserts: + - failedTemplate: + errorMessage: "Set either btqlAuditLogsStrictOrgIds or btqlAuditLogsBestEffortOrgIds, not both." + + - it: should fail when a strict org ID is not a valid UUID + values: + - __fixtures__/base-values.yaml + set: + btqlAuditLogsStrictOrgIds: + - "not-a-uuid" + release: + namespace: "braintrust" + asserts: + - failedTemplate: + errorMessage: "btqlAuditLogsStrictOrgIds: \"not-a-uuid\" is not a valid UUID" + + - it: should fail when a best-effort org ID is not a valid UUID + values: + - __fixtures__/base-values.yaml + set: + btqlAuditLogsBestEffortOrgIds: + - "not-a-uuid" + release: + namespace: "braintrust" + asserts: + - failedTemplate: + errorMessage: "btqlAuditLogsBestEffortOrgIds: \"not-a-uuid\" is not a valid UUID" diff --git a/braintrust/values.yaml b/braintrust/values.yaml index bd780e9..1ba5758 100644 --- a/braintrust/values.yaml +++ b/braintrust/values.yaml @@ -87,6 +87,19 @@ skipPgForBrainstoreObjects: "all" # Progression: "" (disabled) -> "v1" (on 1.1.32) -> "v3" (on 2.0) brainstoreWalFooterVersion: "v3" +# BTQL query.read audit logging configuration (requires data plane v2.6.0+). +# When set, the API emits a query.read audit log entry for each BTQL query +# run by users belonging to the listed org UUIDs. Two mutually exclusive modes: +# strict: audit rows are written synchronously before results are returned. +# best-effort: audit rows are written asynchronously; failures are logged. +# Set UUIDs in exactly one list — setting both is a template error. +# Example (strict mode): +# btqlAuditLogsStrictOrgIds: ["11111111-1111-4111-8111-111111111111", "22222222-2222-4222-8222-222222222222"] +# Example (best-effort mode): +# btqlAuditLogsBestEffortOrgIds: ["11111111-1111-4111-8111-111111111111"] +btqlAuditLogsStrictOrgIds: [] +btqlAuditLogsBestEffortOrgIds: [] + api: name: "braintrust-api" labels: {}