Skip to content

Commit 3e37b1f

Browse files
feat(enterprise): audit group AI budget mutations
1 parent 238968c commit 3e37b1f

14 files changed

Lines changed: 84 additions & 12 deletions

File tree

coderd/apidoc/docs.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/audit/diff.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type Auditable interface {
3737
database.AIProvider |
3838
database.AIProviderKey |
3939
database.Chat |
40+
database.GroupAiBudget |
4041
database.UserSecret
4142
}
4243

coderd/audit/request.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ func ResourceTarget[T Auditable](tgt T) string {
141141
// provider's UUID so the row can be correlated back to its
142142
// provider in the audit UI.
143143
return typed.ProviderID.String()
144+
case database.GroupAiBudget:
145+
// Budgets have no user-facing name; show the parent group's
146+
// UUID so the row can be correlated back to its group in the
147+
// audit UI.
148+
return typed.GroupID.String()
144149
case database.Chat:
145150
// Chat titles can contain sensitive content (secrets, internal
146151
// project names), so we use a short UUID prefix as a display
@@ -221,6 +226,8 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
221226
return typed.ID
222227
case database.AIProviderKey:
223228
return typed.ID
229+
case database.GroupAiBudget:
230+
return typed.GroupID
224231
case database.Chat:
225232
return typed.ID
226233
case database.UserSecret:
@@ -286,6 +293,8 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
286293
return database.ResourceTypeAiProvider
287294
case database.AIProviderKey:
288295
return database.ResourceTypeAiProviderKey
296+
case database.GroupAiBudget:
297+
return database.ResourceTypeGroupAiBudget
289298
case database.Chat:
290299
return database.ResourceTypeChat
291300
case database.UserSecret:
@@ -356,6 +365,9 @@ func ResourceRequiresOrgID[T Auditable]() bool {
356365
case database.AIProviderKey:
357366
// AI provider keys are deployment-scoped, not org-scoped.
358367
return false
368+
case database.GroupAiBudget:
369+
// Group AI budgets are org-scoped through their parent group.
370+
return true
359371
case database.Chat:
360372
// Chats always have a non-null organization_id (since
361373
// migration 000467).

coderd/database/dump.sql

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-- Postgres does not support removing enum values.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- Audit log resource type for group AI budgets.
2+
ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'group_ai_budget';

coderd/database/models.go

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codersdk/audit.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ const (
4848
ResourceTypeAISeat ResourceType = "ai_seat"
4949
ResourceTypeAIProvider ResourceType = "ai_provider"
5050
ResourceTypeAIProviderKey ResourceType = "ai_provider_key"
51+
ResourceTypeGroupAIBudget ResourceType = "group_ai_budget"
5152
ResourceTypeChat ResourceType = "chat"
5253
ResourceTypeUserSecret ResourceType = "user_secret"
5354
)
@@ -114,6 +115,8 @@ func (r ResourceType) FriendlyString() string {
114115
return "ai provider"
115116
case ResourceTypeAIProviderKey:
116117
return "ai provider key"
118+
case ResourceTypeGroupAIBudget:
119+
return "group AI budget"
117120
case ResourceTypeChat:
118121
return "chat"
119122
case ResourceTypeUserSecret:

docs/admin/security/audit-logs.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ We track the following resources:
2525
| Chat<br><i>create, write</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>agent_id</td><td>false</td></tr><tr><td>archived</td><td>true</td></tr><tr><td>build_id</td><td>false</td></tr><tr><td>client_type</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>dynamic_tools</td><td>false</td></tr><tr><td>heartbeat_at</td><td>false</td></tr><tr><td>id</td><td>true</td></tr><tr><td>labels</td><td>true</td></tr><tr><td>last_error</td><td>false</td></tr><tr><td>last_injected_context</td><td>false</td></tr><tr><td>last_model_config_id</td><td>false</td></tr><tr><td>last_read_message_id</td><td>false</td></tr><tr><td>last_turn_summary</td><td>false</td></tr><tr><td>mcp_server_ids</td><td>true</td></tr><tr><td>mode</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>owner_id</td><td>true</td></tr><tr><td>owner_name</td><td>false</td></tr><tr><td>owner_username</td><td>false</td></tr><tr><td>parent_chat_id</td><td>false</td></tr><tr><td>pin_order</td><td>true</td></tr><tr><td>plan_mode</td><td>false</td></tr><tr><td>root_chat_id</td><td>false</td></tr><tr><td>started_at</td><td>false</td></tr><tr><td>status</td><td>false</td></tr><tr><td>title</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>worker_id</td><td>false</td></tr><tr><td>workspace_id</td><td>true</td></tr></tbody></table> |
2626
| CustomRole<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>is_system</td><td>false</td></tr><tr><td>member_permissions</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>org_permissions</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>site_permissions</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_permissions</td><td>true</td></tr></tbody></table> |
2727
| GitSSHKey<br><i>create</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>private_key</td><td>true</td></tr><tr><td>public_key</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_id</td><td>true</td></tr></tbody></table> |
28+
| GroupAiBudget<br><i>write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>group_id</td><td>true</td></tr><tr><td>spend_limit_micros</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> |
2829
| GroupSyncSettings<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>auto_create_missing_groups</td><td>true</td></tr><tr><td>field</td><td>true</td></tr><tr><td>legacy_group_name_mapping</td><td>false</td></tr><tr><td>mapping</td><td>true</td></tr><tr><td>regex_filter</td><td>true</td></tr></tbody></table> |
2930
| HealthSettings<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>dismissed_healthchecks</td><td>true</td></tr><tr><td>id</td><td>false</td></tr></tbody></table> |
3031
| License<br><i>create, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>exp</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>jwt</td><td>false</td></tr><tr><td>uploaded_at</td><td>true</td></tr><tr><td>uuid</td><td>true</td></tr></tbody></table> |

0 commit comments

Comments
 (0)