From f22d4e2cbb064dfe3dae11b9097dca3f6065bda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Banaszewski?= Date: Tue, 2 Jun 2026 09:28:43 +0200 Subject: [PATCH] feat: add ai_gateway_keys table and related RBAC (#25563) Adds table to store keys that AI Gateway standalone replicas will use to authenticate into Coderd. Also adds RBAC and audit boilerplate. --- coderd/apidoc/docs.go | 12 ++++++ coderd/apidoc/swagger.json | 12 ++++++ coderd/audit/diff.go | 1 + coderd/audit/request.go | 9 +++++ coderd/database/check_constraint.go | 3 ++ coderd/database/dump.sql | 34 +++++++++++++++- .../000514_ai_gateway_keys.down.sql | 6 +++ .../migrations/000514_ai_gateway_keys.up.sql | 25 ++++++++++++ .../fixtures/000514_ai_gateway_keys.up.sql | 15 +++++++ coderd/database/models.go | 30 +++++++++++++- coderd/database/sqlc.yaml | 2 + coderd/database/unique_constraint.go | 4 ++ coderd/rbac/object_gen.go | 10 +++++ coderd/rbac/policy/policy.go | 8 ++++ coderd/rbac/roles_test.go | 18 +++++++++ coderd/rbac/scopes_constants_gen.go | 9 +++++ codersdk/apikey_scopes_gen.go | 4 ++ codersdk/audit.go | 3 ++ codersdk/rbacresources_gen.go | 2 + docs/admin/security/audit-logs.md | 1 + docs/reference/api/members.md | 40 +++++++++---------- docs/reference/api/schemas.md | 18 ++++----- docs/reference/api/users.md | 10 ++--- enterprise/audit/table.go | 9 +++++ site/src/api/rbacresourcesGenerated.ts | 5 +++ site/src/api/typesGenerated.ts | 12 ++++++ 26 files changed, 264 insertions(+), 38 deletions(-) create mode 100644 coderd/database/migrations/000514_ai_gateway_keys.down.sql create mode 100644 coderd/database/migrations/000514_ai_gateway_keys.up.sql create mode 100644 coderd/database/migrations/testdata/fixtures/000514_ai_gateway_keys.up.sql diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 1bbb216b1a..7aca308f9d 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -15269,6 +15269,10 @@ const docTemplate = `{ "enum": [ "all", "application_connect", + "ai_gateway_key:*", + "ai_gateway_key:create", + "ai_gateway_key:delete", + "ai_gateway_key:read", "ai_model_price:*", "ai_model_price:read", "ai_model_price:update", @@ -15499,6 +15503,10 @@ const docTemplate = `{ "x-enum-varnames": [ "APIKeyScopeAll", "APIKeyScopeApplicationConnect", + "APIKeyScopeAiGatewayKeyAll", + "APIKeyScopeAiGatewayKeyCreate", + "APIKeyScopeAiGatewayKeyDelete", + "APIKeyScopeAiGatewayKeyRead", "APIKeyScopeAiModelPriceAll", "APIKeyScopeAiModelPriceRead", "APIKeyScopeAiModelPriceUpdate", @@ -22329,6 +22337,7 @@ const docTemplate = `{ "type": "string", "enum": [ "*", + "ai_gateway_key", "ai_model_price", "ai_provider", "ai_seat", @@ -22380,6 +22389,7 @@ const docTemplate = `{ ], "x-enum-varnames": [ "ResourceWildcard", + "ResourceAIGatewayKey", "ResourceAiModelPrice", "ResourceAIProvider", "ResourceAiSeat", @@ -22641,6 +22651,7 @@ const docTemplate = `{ "ai_seat", "ai_provider", "ai_provider_key", + "ai_gateway_key", "group_ai_budget", "chat", "user_secret", @@ -22676,6 +22687,7 @@ const docTemplate = `{ "ResourceTypeAISeat", "ResourceTypeAIProvider", "ResourceTypeAIProviderKey", + "ResourceTypeAIGatewayKey", "ResourceTypeGroupAIBudget", "ResourceTypeChat", "ResourceTypeUserSecret", diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 6f7224e972..842eac0c08 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -13653,6 +13653,10 @@ "enum": [ "all", "application_connect", + "ai_gateway_key:*", + "ai_gateway_key:create", + "ai_gateway_key:delete", + "ai_gateway_key:read", "ai_model_price:*", "ai_model_price:read", "ai_model_price:update", @@ -13883,6 +13887,10 @@ "x-enum-varnames": [ "APIKeyScopeAll", "APIKeyScopeApplicationConnect", + "APIKeyScopeAiGatewayKeyAll", + "APIKeyScopeAiGatewayKeyCreate", + "APIKeyScopeAiGatewayKeyDelete", + "APIKeyScopeAiGatewayKeyRead", "APIKeyScopeAiModelPriceAll", "APIKeyScopeAiModelPriceRead", "APIKeyScopeAiModelPriceUpdate", @@ -20460,6 +20468,7 @@ "type": "string", "enum": [ "*", + "ai_gateway_key", "ai_model_price", "ai_provider", "ai_seat", @@ -20511,6 +20520,7 @@ ], "x-enum-varnames": [ "ResourceWildcard", + "ResourceAIGatewayKey", "ResourceAiModelPrice", "ResourceAIProvider", "ResourceAiSeat", @@ -20762,6 +20772,7 @@ "ai_seat", "ai_provider", "ai_provider_key", + "ai_gateway_key", "group_ai_budget", "chat", "user_secret", @@ -20797,6 +20808,7 @@ "ResourceTypeAISeat", "ResourceTypeAIProvider", "ResourceTypeAIProviderKey", + "ResourceTypeAIGatewayKey", "ResourceTypeGroupAIBudget", "ResourceTypeChat", "ResourceTypeUserSecret", diff --git a/coderd/audit/diff.go b/coderd/audit/diff.go index a26924552b..0beec46153 100644 --- a/coderd/audit/diff.go +++ b/coderd/audit/diff.go @@ -36,6 +36,7 @@ type Auditable interface { database.AiSeatState | database.AIProvider | database.AIProviderKey | + database.AIGatewayKey | database.Chat | database.AuditableGroupAiBudget | database.UserSecret | diff --git a/coderd/audit/request.go b/coderd/audit/request.go index c690bd56f1..2304d37e82 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -138,6 +138,8 @@ func ResourceTarget[T Auditable](tgt T) string { return typed.Name case database.AIProviderKey: return typed.ID.String() + case database.AIGatewayKey: + return typed.Name case database.AuditableGroupAiBudget: return typed.GroupName case database.Chat: @@ -222,6 +224,8 @@ func ResourceID[T Auditable](tgt T) uuid.UUID { return typed.ID case database.AIProviderKey: return typed.ID + case database.AIGatewayKey: + return typed.ID case database.AuditableGroupAiBudget: return typed.GroupID case database.Chat: @@ -291,6 +295,8 @@ func ResourceType[T Auditable](tgt T) database.ResourceType { return database.ResourceTypeAIProvider case database.AIProviderKey: return database.ResourceTypeAIProviderKey + case database.AIGatewayKey: + return database.ResourceTypeAIGatewayKey case database.AuditableGroupAiBudget: return database.ResourceTypeGroupAiBudget case database.Chat: @@ -366,6 +372,9 @@ func ResourceRequiresOrgID[T Auditable]() bool { // AI provider keys inherit the deployment scope of their parent // provider. return false + case database.AIGatewayKey: + // AI Gateway keys are deployment-scoped, not org-scoped. + return false case database.AuditableGroupAiBudget: // Group AI budgets are org-scoped through their parent group. return true diff --git a/coderd/database/check_constraint.go b/coderd/database/check_constraint.go index 1c20622e58..c1fa991032 100644 --- a/coderd/database/check_constraint.go +++ b/coderd/database/check_constraint.go @@ -6,6 +6,9 @@ type CheckConstraint string // CheckConstraint enums. const ( + CheckAiGatewayKeysHashedSecretCheck CheckConstraint = "ai_gateway_keys_hashed_secret_check" // ai_gateway_keys + CheckAiGatewayKeysNameCheck CheckConstraint = "ai_gateway_keys_name_check" // ai_gateway_keys + CheckAiGatewayKeysSecretPrefixCheck CheckConstraint = "ai_gateway_keys_secret_prefix_check" // ai_gateway_keys CheckAiModelPricesCacheReadPriceCheck CheckConstraint = "ai_model_prices_cache_read_price_check" // ai_model_prices CheckAiModelPricesCacheWritePriceCheck CheckConstraint = "ai_model_prices_cache_write_price_check" // ai_model_prices CheckAiModelPricesInputPriceCheck CheckConstraint = "ai_model_prices_input_price_check" // ai_model_prices diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 82aa376d34..0bc0874e51 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -253,7 +253,11 @@ CREATE TYPE api_key_scope AS ENUM ( 'boundary_log:*', 'boundary_log:create', 'boundary_log:delete', - 'boundary_log:read' + 'boundary_log:read', + 'ai_gateway_key:*', + 'ai_gateway_key:create', + 'ai_gateway_key:delete', + 'ai_gateway_key:read' ); CREATE TYPE app_sharing_level AS ENUM ( @@ -564,7 +568,8 @@ CREATE TYPE resource_type AS ENUM ( 'ai_provider', 'ai_provider_key', 'group_ai_budget', - 'user_skill' + 'user_skill', + 'ai_gateway_key' ); CREATE TYPE shareable_workspace_owners AS ENUM ( @@ -1287,6 +1292,22 @@ BEGIN END; $$; +CREATE TABLE ai_gateway_keys ( + id uuid NOT NULL, + created_at timestamp with time zone NOT NULL, + name text NOT NULL, + secret_prefix character varying(11) NOT NULL, + hashed_secret bytea NOT NULL, + last_used_at timestamp with time zone, + CONSTRAINT ai_gateway_keys_hashed_secret_check CHECK ((length(hashed_secret) > 0)), + CONSTRAINT ai_gateway_keys_name_check CHECK (((length(name) <= 64) AND (name ~ '^[a-z0-9]+(-[a-z0-9]+)*$'::text))), + CONSTRAINT ai_gateway_keys_secret_prefix_check CHECK ((length((secret_prefix)::text) = 11)) +); + +COMMENT ON TABLE ai_gateway_keys IS 'Hashed bearer secrets used by AI Gateway standalone replicas to authenticate into coderd.'; + +COMMENT ON COLUMN ai_gateway_keys.secret_prefix IS 'Public token prefix for display and audit correlation. Auth uses hashed_secret.'; + CREATE TABLE ai_model_prices ( provider text NOT NULL, model text NOT NULL, @@ -3763,6 +3784,9 @@ ALTER TABLE ONLY workspace_resource_metadata ALTER COLUMN id SET DEFAULT nextval ALTER TABLE ONLY workspace_agent_stats ADD CONSTRAINT agent_stats_pkey PRIMARY KEY (id); +ALTER TABLE ONLY ai_gateway_keys + ADD CONSTRAINT ai_gateway_keys_pkey PRIMARY KEY (id); + ALTER TABLE ONLY ai_model_prices ADD CONSTRAINT ai_model_prices_pkey PRIMARY KEY (provider, model); @@ -4147,6 +4171,12 @@ ALTER TABLE ONLY workspace_resources ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_pkey PRIMARY KEY (id); +CREATE UNIQUE INDEX ai_gateway_keys_hashed_secret_idx ON ai_gateway_keys USING btree (hashed_secret); + +CREATE UNIQUE INDEX ai_gateway_keys_name_idx ON ai_gateway_keys USING btree (lower(name)); + +CREATE UNIQUE INDEX ai_gateway_keys_secret_prefix_idx ON ai_gateway_keys USING btree (secret_prefix); + CREATE UNIQUE INDEX ai_providers_name_unique ON ai_providers USING btree (name) WHERE (deleted = false); CREATE INDEX api_keys_last_used_idx ON api_keys USING btree (last_used DESC); diff --git a/coderd/database/migrations/000514_ai_gateway_keys.down.sql b/coderd/database/migrations/000514_ai_gateway_keys.down.sql new file mode 100644 index 0000000000..698983673f --- /dev/null +++ b/coderd/database/migrations/000514_ai_gateway_keys.down.sql @@ -0,0 +1,6 @@ +-- Enum additions to resource_type and api_key_scope are intentionally not +-- reverted because Postgres cannot drop enum values safely. +DROP INDEX IF EXISTS ai_gateway_keys_hashed_secret_idx; +DROP INDEX IF EXISTS ai_gateway_keys_secret_prefix_idx; +DROP INDEX IF EXISTS ai_gateway_keys_name_idx; +DROP TABLE IF EXISTS ai_gateway_keys; diff --git a/coderd/database/migrations/000514_ai_gateway_keys.up.sql b/coderd/database/migrations/000514_ai_gateway_keys.up.sql new file mode 100644 index 0000000000..537f437ce5 --- /dev/null +++ b/coderd/database/migrations/000514_ai_gateway_keys.up.sql @@ -0,0 +1,25 @@ +CREATE TABLE ai_gateway_keys ( + id uuid PRIMARY KEY, + created_at timestamptz NOT NULL, + name text NOT NULL, + secret_prefix varchar(11) NOT NULL, + hashed_secret bytea NOT NULL, + last_used_at timestamptz NULL, + CONSTRAINT ai_gateway_keys_name_check CHECK (length(name) <= 64 AND name ~ '^[a-z0-9]+(-[a-z0-9]+)*$'), + CONSTRAINT ai_gateway_keys_secret_prefix_check CHECK (length(secret_prefix) = 11), + CONSTRAINT ai_gateway_keys_hashed_secret_check CHECK (length(hashed_secret) > 0) +); + +COMMENT ON TABLE ai_gateway_keys IS 'Hashed bearer secrets used by AI Gateway standalone replicas to authenticate into coderd.'; +COMMENT ON COLUMN ai_gateway_keys.secret_prefix IS 'Public token prefix for display and audit correlation. Auth uses hashed_secret.'; + +CREATE UNIQUE INDEX ai_gateway_keys_name_idx ON ai_gateway_keys USING btree (lower(name)); +CREATE UNIQUE INDEX ai_gateway_keys_secret_prefix_idx ON ai_gateway_keys USING btree (secret_prefix); +CREATE UNIQUE INDEX ai_gateway_keys_hashed_secret_idx ON ai_gateway_keys USING btree (hashed_secret); + +ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'ai_gateway_key'; + +ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'ai_gateway_key:*'; +ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'ai_gateway_key:create'; +ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'ai_gateway_key:delete'; +ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'ai_gateway_key:read'; diff --git a/coderd/database/migrations/testdata/fixtures/000514_ai_gateway_keys.up.sql b/coderd/database/migrations/testdata/fixtures/000514_ai_gateway_keys.up.sql new file mode 100644 index 0000000000..531946e06f --- /dev/null +++ b/coderd/database/migrations/testdata/fixtures/000514_ai_gateway_keys.up.sql @@ -0,0 +1,15 @@ +INSERT INTO ai_gateway_keys ( + id, + created_at, + name, + secret_prefix, + hashed_secret, + last_used_at +) VALUES ( + '8b6f0a82-9a3a-4d2e-8c0c-2c9c9b9b1a01', + '2026-05-21 00:00:00+00', + 'example-key', + 'cdr_1234567', + '\x00'::bytea, + NULL +); diff --git a/coderd/database/models.go b/coderd/database/models.go index ebfaa7a051..b2d7fda98f 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -324,6 +324,10 @@ const ( ApiKeyScopeBoundaryLogCreate APIKeyScope = "boundary_log:create" ApiKeyScopeBoundaryLogDelete APIKeyScope = "boundary_log:delete" ApiKeyScopeBoundaryLogRead APIKeyScope = "boundary_log:read" + ApiKeyScopeAiGatewayKey APIKeyScope = "ai_gateway_key:*" + ApiKeyScopeAiGatewayKeyCreate APIKeyScope = "ai_gateway_key:create" + ApiKeyScopeAiGatewayKeyDelete APIKeyScope = "ai_gateway_key:delete" + ApiKeyScopeAiGatewayKeyRead APIKeyScope = "ai_gateway_key:read" ) func (e *APIKeyScope) Scan(src interface{}) error { @@ -588,7 +592,11 @@ func (e APIKeyScope) Valid() bool { ApiKeyScopeBoundaryLog, ApiKeyScopeBoundaryLogCreate, ApiKeyScopeBoundaryLogDelete, - ApiKeyScopeBoundaryLogRead: + ApiKeyScopeBoundaryLogRead, + ApiKeyScopeAiGatewayKey, + ApiKeyScopeAiGatewayKeyCreate, + ApiKeyScopeAiGatewayKeyDelete, + ApiKeyScopeAiGatewayKeyRead: return true } return false @@ -822,6 +830,10 @@ func AllAPIKeyScopeValues() []APIKeyScope { ApiKeyScopeBoundaryLogCreate, ApiKeyScopeBoundaryLogDelete, ApiKeyScopeBoundaryLogRead, + ApiKeyScopeAiGatewayKey, + ApiKeyScopeAiGatewayKeyCreate, + ApiKeyScopeAiGatewayKeyDelete, + ApiKeyScopeAiGatewayKeyRead, } } @@ -3353,6 +3365,7 @@ const ( ResourceTypeAIProviderKey ResourceType = "ai_provider_key" ResourceTypeGroupAiBudget ResourceType = "group_ai_budget" ResourceTypeUserSkill ResourceType = "user_skill" + ResourceTypeAIGatewayKey ResourceType = "ai_gateway_key" ) func (e *ResourceType) Scan(src interface{}) error { @@ -3424,7 +3437,8 @@ func (e ResourceType) Valid() bool { ResourceTypeAIProvider, ResourceTypeAIProviderKey, ResourceTypeGroupAiBudget, - ResourceTypeUserSkill: + ResourceTypeUserSkill, + ResourceTypeAIGatewayKey: return true } return false @@ -3465,6 +3479,7 @@ func AllResourceTypeValues() []ResourceType { ResourceTypeAIProviderKey, ResourceTypeGroupAiBudget, ResourceTypeUserSkill, + ResourceTypeAIGatewayKey, } } @@ -4435,6 +4450,17 @@ type AIBridgeUserPrompt struct { CreatedAt time.Time `db:"created_at" json:"created_at"` } +// Hashed bearer secrets used by AI Gateway standalone replicas to authenticate into coderd. +type AIGatewayKey struct { + ID uuid.UUID `db:"id" json:"id"` + CreatedAt time.Time `db:"created_at" json:"created_at"` + Name string `db:"name" json:"name"` + // Public token prefix for display and audit correlation. Auth uses hashed_secret. + SecretPrefix string `db:"secret_prefix" json:"secret_prefix"` + HashedSecret []byte `db:"hashed_secret" json:"hashed_secret"` + LastUsedAt sql.NullTime `db:"last_used_at" json:"last_used_at"` +} + // Runtime configuration for AI providers. Authoritative source for the provider set served by aibridged. Replaces deployment-time CODER_AIBRIDGE_* environment variables. type AIProvider struct { ID uuid.UUID `db:"id" json:"id"` diff --git a/coderd/database/sqlc.yaml b/coderd/database/sqlc.yaml index 18c738c992..78448df9de 100644 --- a/coderd/database/sqlc.yaml +++ b/coderd/database/sqlc.yaml @@ -261,8 +261,10 @@ sql: ai_provider: AIProvider ai_provider_key: AIProviderKey ai_provider_type: AIProviderType + ai_gateway_key: AIGatewayKey resource_type_ai_provider: ResourceTypeAIProvider resource_type_ai_provider_key: ResourceTypeAIProviderKey + resource_type_ai_gateway_key: ResourceTypeAIGatewayKey mcp_server_config: MCPServerConfig mcp_server_configs: MCPServerConfigs mcp_server_user_token: MCPServerUserToken diff --git a/coderd/database/unique_constraint.go b/coderd/database/unique_constraint.go index 3d5e5dabcf..fd11ab2e06 100644 --- a/coderd/database/unique_constraint.go +++ b/coderd/database/unique_constraint.go @@ -7,6 +7,7 @@ type UniqueConstraint string // UniqueConstraint enums. const ( UniqueAgentStatsPkey UniqueConstraint = "agent_stats_pkey" // ALTER TABLE ONLY workspace_agent_stats ADD CONSTRAINT agent_stats_pkey PRIMARY KEY (id); + UniqueAiGatewayKeysPkey UniqueConstraint = "ai_gateway_keys_pkey" // ALTER TABLE ONLY ai_gateway_keys ADD CONSTRAINT ai_gateway_keys_pkey PRIMARY KEY (id); UniqueAiModelPricesPkey UniqueConstraint = "ai_model_prices_pkey" // ALTER TABLE ONLY ai_model_prices ADD CONSTRAINT ai_model_prices_pkey PRIMARY KEY (provider, model); UniqueAiProviderKeysPkey UniqueConstraint = "ai_provider_keys_pkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_pkey PRIMARY KEY (id); UniqueAiProvidersPkey UniqueConstraint = "ai_providers_pkey" // ALTER TABLE ONLY ai_providers ADD CONSTRAINT ai_providers_pkey PRIMARY KEY (id); @@ -135,6 +136,9 @@ const ( UniqueWorkspaceResourceMetadataPkey UniqueConstraint = "workspace_resource_metadata_pkey" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_pkey PRIMARY KEY (id); UniqueWorkspaceResourcesPkey UniqueConstraint = "workspace_resources_pkey" // ALTER TABLE ONLY workspace_resources ADD CONSTRAINT workspace_resources_pkey PRIMARY KEY (id); UniqueWorkspacesPkey UniqueConstraint = "workspaces_pkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_pkey PRIMARY KEY (id); + UniqueAiGatewayKeysHashedSecretIndex UniqueConstraint = "ai_gateway_keys_hashed_secret_idx" // CREATE UNIQUE INDEX ai_gateway_keys_hashed_secret_idx ON ai_gateway_keys USING btree (hashed_secret); + UniqueAiGatewayKeysNameIndex UniqueConstraint = "ai_gateway_keys_name_idx" // CREATE UNIQUE INDEX ai_gateway_keys_name_idx ON ai_gateway_keys USING btree (lower(name)); + UniqueAiGatewayKeysSecretPrefixIndex UniqueConstraint = "ai_gateway_keys_secret_prefix_idx" // CREATE UNIQUE INDEX ai_gateway_keys_secret_prefix_idx ON ai_gateway_keys USING btree (secret_prefix); UniqueAiProvidersNameUnique UniqueConstraint = "ai_providers_name_unique" // CREATE UNIQUE INDEX ai_providers_name_unique ON ai_providers USING btree (name) WHERE (deleted = false); UniqueIndexAPIKeyName UniqueConstraint = "idx_api_key_name" // CREATE UNIQUE INDEX idx_api_key_name ON api_keys USING btree (user_id, token_name) WHERE (login_type = 'token'::login_type); UniqueIndexChatDebugRunsIDChat UniqueConstraint = "idx_chat_debug_runs_id_chat" // CREATE UNIQUE INDEX idx_chat_debug_runs_id_chat ON chat_debug_runs USING btree (id, chat_id); diff --git a/coderd/rbac/object_gen.go b/coderd/rbac/object_gen.go index 824cf92fdd..5ff60562b1 100644 --- a/coderd/rbac/object_gen.go +++ b/coderd/rbac/object_gen.go @@ -15,6 +15,15 @@ var ( Type: "*", } + // ResourceAIGatewayKey + // Valid Actions + // - "ActionCreate" :: create an AI Gateway key + // - "ActionDelete" :: delete an AI Gateway key + // - "ActionRead" :: read AI Gateway keys + ResourceAIGatewayKey = Object{ + Type: "ai_gateway_key", + } + // ResourceAiModelPrice // Valid Actions // - "ActionRead" :: read AI model prices @@ -479,6 +488,7 @@ var ( func AllResources() []Objecter { return []Objecter{ ResourceWildcard, + ResourceAIGatewayKey, ResourceAiModelPrice, ResourceAIProvider, ResourceAiSeat, diff --git a/coderd/rbac/policy/policy.go b/coderd/rbac/policy/policy.go index f2b17927bd..f97b2a78bc 100644 --- a/coderd/rbac/policy/policy.go +++ b/coderd/rbac/policy/policy.go @@ -429,6 +429,14 @@ var RBACPermissions = map[string]PermissionDefinition{ ActionDelete: "delete boundary logs", }, }, + "ai_gateway_key": { + Name: "AIGatewayKey", + Actions: map[Action]ActionDefinition{ + ActionCreate: "create an AI Gateway key", + ActionRead: "read AI Gateway keys", + ActionDelete: "delete an AI Gateway key", + }, + }, "boundary_usage": { Actions: map[Action]ActionDefinition{ ActionRead: "read boundary usage statistics", diff --git a/coderd/rbac/roles_test.go b/coderd/rbac/roles_test.go index 0ac992fc86..7fee71935c 100644 --- a/coderd/rbac/roles_test.go +++ b/coderd/rbac/roles_test.go @@ -1204,6 +1204,24 @@ func TestRolePermissions(t *testing.T) { }, }, }, + { + // Only owners can manage AI Gateway keys. They hold + // a hashed bearer secret used to authenticate Gateway + // replicas to coderd. Keys are deployment-wide. + Name: "AIGatewayKey", + Actions: []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionDelete}, + Resource: rbac.ResourceAIGatewayKey, + AuthorizeMap: map[bool][]hasAuthSubjects{ + true: {owner}, + false: { + memberMe, agentsAccessUser, + orgAdmin, otherOrgAdmin, + orgAuditor, otherOrgAuditor, + templateAdmin, orgTemplateAdmin, otherOrgTemplateAdmin, + userAdmin, orgUserAdmin, otherOrgUserAdmin, + }, + }, + }, { Name: "BoundaryUsage", Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, diff --git a/coderd/rbac/scopes_constants_gen.go b/coderd/rbac/scopes_constants_gen.go index b664a4371a..3adad84a59 100644 --- a/coderd/rbac/scopes_constants_gen.go +++ b/coderd/rbac/scopes_constants_gen.go @@ -7,6 +7,9 @@ package rbac // declared in code, not here, to avoid duplication. const ( + ScopeAiGatewayKeyCreate ScopeName = "ai_gateway_key:create" + ScopeAiGatewayKeyDelete ScopeName = "ai_gateway_key:delete" + ScopeAiGatewayKeyRead ScopeName = "ai_gateway_key:read" ScopeAiModelPriceRead ScopeName = "ai_model_price:read" ScopeAiModelPriceUpdate ScopeName = "ai_model_price:update" ScopeAiProviderCreate ScopeName = "ai_provider:create" @@ -187,6 +190,9 @@ func (e ScopeName) Valid() bool { case ScopeName("coder:all"), ScopeName("coder:application_connect"), ScopeName("no_user_data"), + ScopeAiGatewayKeyCreate, + ScopeAiGatewayKeyDelete, + ScopeAiGatewayKeyRead, ScopeAiModelPriceRead, ScopeAiModelPriceUpdate, ScopeAiProviderCreate, @@ -368,6 +374,9 @@ func AllScopeNameValues() []ScopeName { ScopeName("coder:all"), ScopeName("coder:application_connect"), ScopeName("no_user_data"), + ScopeAiGatewayKeyCreate, + ScopeAiGatewayKeyDelete, + ScopeAiGatewayKeyRead, ScopeAiModelPriceRead, ScopeAiModelPriceUpdate, ScopeAiProviderCreate, diff --git a/codersdk/apikey_scopes_gen.go b/codersdk/apikey_scopes_gen.go index 4e4fb8d803..450a5221f0 100644 --- a/codersdk/apikey_scopes_gen.go +++ b/codersdk/apikey_scopes_gen.go @@ -6,6 +6,10 @@ const ( APIKeyScopeAll APIKeyScope = "all" // Deprecated: use codersdk.APIKeyScopeCoderApplicationConnect instead. APIKeyScopeApplicationConnect APIKeyScope = "application_connect" + APIKeyScopeAiGatewayKeyAll APIKeyScope = "ai_gateway_key:*" + APIKeyScopeAiGatewayKeyCreate APIKeyScope = "ai_gateway_key:create" + APIKeyScopeAiGatewayKeyDelete APIKeyScope = "ai_gateway_key:delete" + APIKeyScopeAiGatewayKeyRead APIKeyScope = "ai_gateway_key:read" APIKeyScopeAiModelPriceAll APIKeyScope = "ai_model_price:*" APIKeyScopeAiModelPriceRead APIKeyScope = "ai_model_price:read" APIKeyScopeAiModelPriceUpdate APIKeyScope = "ai_model_price:update" diff --git a/codersdk/audit.go b/codersdk/audit.go index eceae40649..e58bbb71f7 100644 --- a/codersdk/audit.go +++ b/codersdk/audit.go @@ -48,6 +48,7 @@ const ( ResourceTypeAISeat ResourceType = "ai_seat" ResourceTypeAIProvider ResourceType = "ai_provider" ResourceTypeAIProviderKey ResourceType = "ai_provider_key" + ResourceTypeAIGatewayKey ResourceType = "ai_gateway_key" ResourceTypeGroupAIBudget ResourceType = "group_ai_budget" ResourceTypeChat ResourceType = "chat" ResourceTypeUserSecret ResourceType = "user_secret" @@ -116,6 +117,8 @@ func (r ResourceType) FriendlyString() string { return "ai provider" case ResourceTypeAIProviderKey: return "ai provider key" + case ResourceTypeAIGatewayKey: + return "ai gateway key" case ResourceTypeGroupAIBudget: return "group ai budget" case ResourceTypeChat: diff --git a/codersdk/rbacresources_gen.go b/codersdk/rbacresources_gen.go index 75b1e82421..622c59c54b 100644 --- a/codersdk/rbacresources_gen.go +++ b/codersdk/rbacresources_gen.go @@ -5,6 +5,7 @@ type RBACResource string const ( ResourceWildcard RBACResource = "*" + ResourceAIGatewayKey RBACResource = "ai_gateway_key" ResourceAiModelPrice RBACResource = "ai_model_price" ResourceAIProvider RBACResource = "ai_provider" ResourceAiSeat RBACResource = "ai_seat" @@ -82,6 +83,7 @@ const ( // said resource type. var RBACResourceActions = map[RBACResource][]RBACAction{ ResourceWildcard: {}, + ResourceAIGatewayKey: {ActionCreate, ActionDelete, ActionRead}, ResourceAiModelPrice: {ActionRead, ActionUpdate}, ResourceAIProvider: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, ResourceAiSeat: {ActionCreate, ActionRead}, diff --git a/docs/admin/security/audit-logs.md b/docs/admin/security/audit-logs.md index 712724e064..6e65c5fec5 100644 --- a/docs/admin/security/audit-logs.md +++ b/docs/admin/security/audit-logs.md @@ -15,6 +15,7 @@ We track the following resources: | Resource | | | |-----------------------------------------------------------------|----------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| AIGatewayKey
create, delete | |
FieldTracked
created_atfalse
hashed_secrettrue
idtrue
last_used_atfalse
nametrue
secret_prefixtrue
| | AIProvider
create, write, delete | |
FieldTracked
base_urltrue
created_atfalse
deletedtrue
display_nametrue
enabledtrue
idtrue
nametrue
settingstrue
settings_key_idfalse
typetrue
updated_atfalse
| | AIProviderKey
create, delete | |
FieldTracked
api_keytrue
api_key_key_idfalse
created_atfalse
idtrue
provider_idtrue
updated_atfalse
| | APIKey
login, logout, register, create, write, delete | |
FieldTracked
allow_listfalse
created_attrue
expires_attrue
hashed_secretfalse
idfalse
ip_addressfalse
last_usedtrue
lifetime_secondsfalse
login_typefalse
scopesfalse
token_namefalse
updated_atfalse
user_idtrue
| diff --git a/docs/reference/api/members.md b/docs/reference/api/members.md index fae805d3a7..602577852e 100644 --- a/docs/reference/api/members.md +++ b/docs/reference/api/members.md @@ -193,10 +193,10 @@ Status Code **200** #### Enumerated Values -| Property | Value(s) | -|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | -| `resource_type` | `*`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | +| Property | Value(s) | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | +| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -326,10 +326,10 @@ Status Code **200** #### Enumerated Values -| Property | Value(s) | -|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | -| `resource_type` | `*`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | +| Property | Value(s) | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | +| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -459,10 +459,10 @@ Status Code **200** #### Enumerated Values -| Property | Value(s) | -|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | -| `resource_type` | `*`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | +| Property | Value(s) | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | +| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -554,10 +554,10 @@ Status Code **200** #### Enumerated Values -| Property | Value(s) | -|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | -| `resource_type` | `*`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | +| Property | Value(s) | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | +| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -960,9 +960,9 @@ Status Code **200** #### Enumerated Values -| Property | Value(s) | -|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | -| `resource_type` | `*`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | +| Property | Value(s) | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `action` | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` | +| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index ea8f19c4bf..47268ba974 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -1444,9 +1444,9 @@ None #### Enumerated Values -| Value(s) | -|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ai_model_price:*`, `ai_model_price:read`, `ai_model_price:update`, `ai_provider:*`, `ai_provider:create`, `ai_provider:delete`, `ai_provider:read`, `ai_provider:update`, `ai_seat:*`, `ai_seat:create`, `ai_seat:read`, `aibridge_interception:*`, `aibridge_interception:create`, `aibridge_interception:read`, `aibridge_interception:update`, `all`, `api_key:*`, `api_key:create`, `api_key:delete`, `api_key:read`, `api_key:update`, `application_connect`, `assign_org_role:*`, `assign_org_role:assign`, `assign_org_role:create`, `assign_org_role:delete`, `assign_org_role:read`, `assign_org_role:unassign`, `assign_org_role:update`, `assign_role:*`, `assign_role:assign`, `assign_role:read`, `assign_role:unassign`, `audit_log:*`, `audit_log:create`, `audit_log:read`, `boundary_log:*`, `boundary_log:create`, `boundary_log:delete`, `boundary_log:read`, `boundary_usage:*`, `boundary_usage:delete`, `boundary_usage:read`, `boundary_usage:update`, `chat:*`, `chat:create`, `chat:delete`, `chat:read`, `chat:share`, `chat:update`, `coder:all`, `coder:apikeys.manage_self`, `coder:application_connect`, `coder:templates.author`, `coder:templates.build`, `coder:workspaces.access`, `coder:workspaces.create`, `coder:workspaces.delete`, `coder:workspaces.operate`, `connection_log:*`, `connection_log:read`, `connection_log:update`, `crypto_key:*`, `crypto_key:create`, `crypto_key:delete`, `crypto_key:read`, `crypto_key:update`, `debug_info:*`, `debug_info:read`, `deployment_config:*`, `deployment_config:read`, `deployment_config:update`, `deployment_stats:*`, `deployment_stats:read`, `file:*`, `file:create`, `file:read`, `group:*`, `group:create`, `group:delete`, `group:read`, `group:update`, `group_member:*`, `group_member:read`, `idpsync_settings:*`, `idpsync_settings:read`, `idpsync_settings:update`, `inbox_notification:*`, `inbox_notification:create`, `inbox_notification:read`, `inbox_notification:update`, `license:*`, `license:create`, `license:delete`, `license:read`, `notification_message:*`, `notification_message:create`, `notification_message:delete`, `notification_message:read`, `notification_message:update`, `notification_preference:*`, `notification_preference:read`, `notification_preference:update`, `notification_template:*`, `notification_template:read`, `notification_template:update`, `oauth2_app:*`, `oauth2_app:create`, `oauth2_app:delete`, `oauth2_app:read`, `oauth2_app:update`, `oauth2_app_code_token:*`, `oauth2_app_code_token:create`, `oauth2_app_code_token:delete`, `oauth2_app_code_token:read`, `oauth2_app_secret:*`, `oauth2_app_secret:create`, `oauth2_app_secret:delete`, `oauth2_app_secret:read`, `oauth2_app_secret:update`, `organization:*`, `organization:create`, `organization:delete`, `organization:read`, `organization:update`, `organization_member:*`, `organization_member:create`, `organization_member:delete`, `organization_member:read`, `organization_member:update`, `prebuilt_workspace:*`, `prebuilt_workspace:delete`, `prebuilt_workspace:update`, `provisioner_daemon:*`, `provisioner_daemon:create`, `provisioner_daemon:delete`, `provisioner_daemon:read`, `provisioner_daemon:update`, `provisioner_jobs:*`, `provisioner_jobs:create`, `provisioner_jobs:read`, `provisioner_jobs:update`, `replicas:*`, `replicas:read`, `system:*`, `system:create`, `system:delete`, `system:read`, `system:update`, `tailnet_coordinator:*`, `tailnet_coordinator:create`, `tailnet_coordinator:delete`, `tailnet_coordinator:read`, `tailnet_coordinator:update`, `task:*`, `task:create`, `task:delete`, `task:read`, `task:update`, `template:*`, `template:create`, `template:delete`, `template:read`, `template:update`, `template:use`, `template:view_insights`, `usage_event:*`, `usage_event:create`, `usage_event:read`, `usage_event:update`, `user:*`, `user:create`, `user:delete`, `user:read`, `user:read_personal`, `user:update`, `user:update_personal`, `user_secret:*`, `user_secret:create`, `user_secret:delete`, `user_secret:read`, `user_secret:update`, `user_skill:*`, `user_skill:create`, `user_skill:delete`, `user_skill:read`, `user_skill:update`, `webpush_subscription:*`, `webpush_subscription:create`, `webpush_subscription:delete`, `webpush_subscription:read`, `workspace:*`, `workspace:application_connect`, `workspace:create`, `workspace:create_agent`, `workspace:delete`, `workspace:delete_agent`, `workspace:read`, `workspace:share`, `workspace:ssh`, `workspace:start`, `workspace:stop`, `workspace:update`, `workspace:update_agent`, `workspace_agent_devcontainers:*`, `workspace_agent_devcontainers:create`, `workspace_agent_resource_monitor:*`, `workspace_agent_resource_monitor:create`, `workspace_agent_resource_monitor:read`, `workspace_agent_resource_monitor:update`, `workspace_dormant:*`, `workspace_dormant:application_connect`, `workspace_dormant:create`, `workspace_dormant:create_agent`, `workspace_dormant:delete`, `workspace_dormant:delete_agent`, `workspace_dormant:read`, `workspace_dormant:share`, `workspace_dormant:ssh`, `workspace_dormant:start`, `workspace_dormant:stop`, `workspace_dormant:update`, `workspace_dormant:update_agent`, `workspace_proxy:*`, `workspace_proxy:create`, `workspace_proxy:delete`, `workspace_proxy:read`, `workspace_proxy:update` | +| Value(s) | +|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `ai_gateway_key:*`, `ai_gateway_key:create`, `ai_gateway_key:delete`, `ai_gateway_key:read`, `ai_model_price:*`, `ai_model_price:read`, `ai_model_price:update`, `ai_provider:*`, `ai_provider:create`, `ai_provider:delete`, `ai_provider:read`, `ai_provider:update`, `ai_seat:*`, `ai_seat:create`, `ai_seat:read`, `aibridge_interception:*`, `aibridge_interception:create`, `aibridge_interception:read`, `aibridge_interception:update`, `all`, `api_key:*`, `api_key:create`, `api_key:delete`, `api_key:read`, `api_key:update`, `application_connect`, `assign_org_role:*`, `assign_org_role:assign`, `assign_org_role:create`, `assign_org_role:delete`, `assign_org_role:read`, `assign_org_role:unassign`, `assign_org_role:update`, `assign_role:*`, `assign_role:assign`, `assign_role:read`, `assign_role:unassign`, `audit_log:*`, `audit_log:create`, `audit_log:read`, `boundary_log:*`, `boundary_log:create`, `boundary_log:delete`, `boundary_log:read`, `boundary_usage:*`, `boundary_usage:delete`, `boundary_usage:read`, `boundary_usage:update`, `chat:*`, `chat:create`, `chat:delete`, `chat:read`, `chat:share`, `chat:update`, `coder:all`, `coder:apikeys.manage_self`, `coder:application_connect`, `coder:templates.author`, `coder:templates.build`, `coder:workspaces.access`, `coder:workspaces.create`, `coder:workspaces.delete`, `coder:workspaces.operate`, `connection_log:*`, `connection_log:read`, `connection_log:update`, `crypto_key:*`, `crypto_key:create`, `crypto_key:delete`, `crypto_key:read`, `crypto_key:update`, `debug_info:*`, `debug_info:read`, `deployment_config:*`, `deployment_config:read`, `deployment_config:update`, `deployment_stats:*`, `deployment_stats:read`, `file:*`, `file:create`, `file:read`, `group:*`, `group:create`, `group:delete`, `group:read`, `group:update`, `group_member:*`, `group_member:read`, `idpsync_settings:*`, `idpsync_settings:read`, `idpsync_settings:update`, `inbox_notification:*`, `inbox_notification:create`, `inbox_notification:read`, `inbox_notification:update`, `license:*`, `license:create`, `license:delete`, `license:read`, `notification_message:*`, `notification_message:create`, `notification_message:delete`, `notification_message:read`, `notification_message:update`, `notification_preference:*`, `notification_preference:read`, `notification_preference:update`, `notification_template:*`, `notification_template:read`, `notification_template:update`, `oauth2_app:*`, `oauth2_app:create`, `oauth2_app:delete`, `oauth2_app:read`, `oauth2_app:update`, `oauth2_app_code_token:*`, `oauth2_app_code_token:create`, `oauth2_app_code_token:delete`, `oauth2_app_code_token:read`, `oauth2_app_secret:*`, `oauth2_app_secret:create`, `oauth2_app_secret:delete`, `oauth2_app_secret:read`, `oauth2_app_secret:update`, `organization:*`, `organization:create`, `organization:delete`, `organization:read`, `organization:update`, `organization_member:*`, `organization_member:create`, `organization_member:delete`, `organization_member:read`, `organization_member:update`, `prebuilt_workspace:*`, `prebuilt_workspace:delete`, `prebuilt_workspace:update`, `provisioner_daemon:*`, `provisioner_daemon:create`, `provisioner_daemon:delete`, `provisioner_daemon:read`, `provisioner_daemon:update`, `provisioner_jobs:*`, `provisioner_jobs:create`, `provisioner_jobs:read`, `provisioner_jobs:update`, `replicas:*`, `replicas:read`, `system:*`, `system:create`, `system:delete`, `system:read`, `system:update`, `tailnet_coordinator:*`, `tailnet_coordinator:create`, `tailnet_coordinator:delete`, `tailnet_coordinator:read`, `tailnet_coordinator:update`, `task:*`, `task:create`, `task:delete`, `task:read`, `task:update`, `template:*`, `template:create`, `template:delete`, `template:read`, `template:update`, `template:use`, `template:view_insights`, `usage_event:*`, `usage_event:create`, `usage_event:read`, `usage_event:update`, `user:*`, `user:create`, `user:delete`, `user:read`, `user:read_personal`, `user:update`, `user:update_personal`, `user_secret:*`, `user_secret:create`, `user_secret:delete`, `user_secret:read`, `user_secret:update`, `user_skill:*`, `user_skill:create`, `user_skill:delete`, `user_skill:read`, `user_skill:update`, `webpush_subscription:*`, `webpush_subscription:create`, `webpush_subscription:delete`, `webpush_subscription:read`, `workspace:*`, `workspace:application_connect`, `workspace:create`, `workspace:create_agent`, `workspace:delete`, `workspace:delete_agent`, `workspace:read`, `workspace:share`, `workspace:ssh`, `workspace:start`, `workspace:stop`, `workspace:update`, `workspace:update_agent`, `workspace_agent_devcontainers:*`, `workspace_agent_devcontainers:create`, `workspace_agent_resource_monitor:*`, `workspace_agent_resource_monitor:create`, `workspace_agent_resource_monitor:read`, `workspace_agent_resource_monitor:update`, `workspace_dormant:*`, `workspace_dormant:application_connect`, `workspace_dormant:create`, `workspace_dormant:create_agent`, `workspace_dormant:delete`, `workspace_dormant:delete_agent`, `workspace_dormant:read`, `workspace_dormant:share`, `workspace_dormant:ssh`, `workspace_dormant:start`, `workspace_dormant:stop`, `workspace_dormant:update`, `workspace_dormant:update_agent`, `workspace_proxy:*`, `workspace_proxy:create`, `workspace_proxy:delete`, `workspace_proxy:read`, `workspace_proxy:update` | ## codersdk.AddLicenseRequest @@ -10818,9 +10818,9 @@ Only certain features set these fields: - FeatureManagedAgentLimit| #### Enumerated Values -| Value(s) | -|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `*`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | +| Value(s) | +|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | ## codersdk.RateLimitConfig @@ -11036,9 +11036,9 @@ Only certain features set these fields: - FeatureManagedAgentLimit| #### Enumerated Values -| Value(s) | -|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ai_provider`, `ai_provider_key`, `ai_seat`, `api_key`, `chat`, `convert_login`, `custom_role`, `git_ssh_key`, `group`, `group_ai_budget`, `health_settings`, `idp_sync_settings_group`, `idp_sync_settings_organization`, `idp_sync_settings_role`, `license`, `notification_template`, `notifications_settings`, `oauth2_provider_app`, `oauth2_provider_app_secret`, `organization`, `organization_member`, `prebuilds_settings`, `task`, `template`, `template_version`, `user`, `user_secret`, `user_skill`, `workspace`, `workspace_agent`, `workspace_app`, `workspace_build`, `workspace_proxy` | +| Value(s) | +|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `ai_gateway_key`, `ai_provider`, `ai_provider_key`, `ai_seat`, `api_key`, `chat`, `convert_login`, `custom_role`, `git_ssh_key`, `group`, `group_ai_budget`, `health_settings`, `idp_sync_settings_group`, `idp_sync_settings_organization`, `idp_sync_settings_role`, `license`, `notification_template`, `notifications_settings`, `oauth2_provider_app`, `oauth2_provider_app_secret`, `organization`, `organization_member`, `prebuilds_settings`, `task`, `template`, `template_version`, `user`, `user_secret`, `user_skill`, `workspace`, `workspace_agent`, `workspace_app`, `workspace_build`, `workspace_proxy` | ## codersdk.Response diff --git a/docs/reference/api/users.md b/docs/reference/api/users.md index 0bedde7b0c..c82ca65701 100644 --- a/docs/reference/api/users.md +++ b/docs/reference/api/users.md @@ -865,11 +865,11 @@ Status Code **200** #### Enumerated Values -| Property | Value(s) | -|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `type` | `*`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | -| `login_type` | `github`, `oidc`, `password`, `token` | -| `scope` | `all`, `application_connect` | +| Property | Value(s) | +|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `task`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_dormant`, `workspace_proxy` | +| `login_type` | `github`, `oidc`, `password`, `token` | +| `scope` | `all`, `application_connect` | To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go index e97a76daed..315f6af228 100644 --- a/enterprise/audit/table.go +++ b/enterprise/audit/table.go @@ -31,6 +31,7 @@ var AuditActionMap = map[string][]codersdk.AuditAction{ "AiSeatState": {codersdk.AuditActionCreate}, "AIProvider": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete}, "AIProviderKey": {codersdk.AuditActionCreate, codersdk.AuditActionDelete}, + "AIGatewayKey": {codersdk.AuditActionCreate, codersdk.AuditActionDelete}, "AuditableGroupAiBudget": {codersdk.AuditActionWrite, codersdk.AuditActionDelete}, "Chat": {codersdk.AuditActionCreate, codersdk.AuditActionWrite}, // chats get 'archived' by users, not deleted. "UserSecret": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete}, @@ -400,6 +401,14 @@ var auditableResourcesTypes = map[any]map[string]Action{ "created_at": ActionIgnore, // Implicit; not useful in a diff. "updated_at": ActionIgnore, // Changes; not useful in a diff. }, + &database.AIGatewayKey{}: { + "id": ActionTrack, + "name": ActionTrack, + "secret_prefix": ActionTrack, + "hashed_secret": ActionSecret, // Bearer token hash, never expose. + "created_at": ActionIgnore, // Implicit; not useful in a diff. + "last_used_at": ActionIgnore, // Bumped on every use. + }, &database.TaskTable{}: { "id": ActionTrack, "organization_id": ActionIgnore, // Never changes. diff --git a/site/src/api/rbacresourcesGenerated.ts b/site/src/api/rbacresourcesGenerated.ts index 2ac260c98a..15fd4a0f43 100644 --- a/site/src/api/rbacresourcesGenerated.ts +++ b/site/src/api/rbacresourcesGenerated.ts @@ -8,6 +8,11 @@ import type { RBACAction, RBACResource } from "./typesGenerated"; export const RBACResourceActions: Partial< Record>> > = { + ai_gateway_key: { + create: "create an AI Gateway key", + delete: "delete an AI Gateway key", + read: "read AI Gateway keys", + }, ai_model_price: { read: "read AI model prices", update: "update AI model prices", diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index a42e1489ff..a0aad00206 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -518,6 +518,10 @@ export interface APIKey { // From codersdk/apikey.go export type APIKeyScope = + | "ai_gateway_key:*" + | "ai_gateway_key:create" + | "ai_gateway_key:delete" + | "ai_gateway_key:read" | "ai_model_price:*" | "ai_model_price:read" | "ai_model_price:update" @@ -748,6 +752,10 @@ export type APIKeyScope = | "workspace:update_agent"; export const APIKeyScopes: APIKeyScope[] = [ + "ai_gateway_key:*", + "ai_gateway_key:create", + "ai_gateway_key:delete", + "ai_gateway_key:read", "ai_model_price:*", "ai_model_price:read", "ai_model_price:update", @@ -6873,6 +6881,7 @@ export const RBACActions: RBACAction[] = [ // From codersdk/rbacresources_gen.go export type RBACResource = + | "ai_gateway_key" | "ai_provider" | "ai_model_price" | "ai_seat" @@ -6924,6 +6933,7 @@ export type RBACResource = | "workspace_proxy"; export const RBACResources: RBACResource[] = [ + "ai_gateway_key", "ai_provider", "ai_model_price", "ai_seat", @@ -7080,6 +7090,7 @@ export interface ResolveAutostartResponse { // From codersdk/audit.go export type ResourceType = + | "ai_gateway_key" | "ai_provider" | "ai_provider_key" | "ai_seat" @@ -7115,6 +7126,7 @@ export type ResourceType = | "workspace_proxy"; export const ResourceTypes: ResourceType[] = [ + "ai_gateway_key", "ai_provider", "ai_provider_key", "ai_seat",