mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add ai_providers table, queries, dbauthz, audit, RBAC (#24892)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
DROP TABLE IF EXISTS ai_provider_keys;
|
||||
DROP TABLE IF EXISTS ai_providers;
|
||||
DROP TYPE IF EXISTS ai_provider_type;
|
||||
-- No-op for ALTER TYPE resource_type / api_key_scope ADD VALUE:
|
||||
-- Postgres does not allow removing enum values safely.
|
||||
@@ -0,0 +1,67 @@
|
||||
CREATE TYPE ai_provider_type AS ENUM (
|
||||
'openai',
|
||||
'anthropic'
|
||||
);
|
||||
|
||||
CREATE TABLE ai_providers (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
type ai_provider_type NOT NULL,
|
||||
name text NOT NULL
|
||||
CONSTRAINT ai_providers_name_check
|
||||
CHECK (name ~ '^[a-z0-9]+(-[a-z0-9]+)*$'),
|
||||
display_name text,
|
||||
enabled boolean NOT NULL DEFAULT TRUE,
|
||||
deleted boolean NOT NULL DEFAULT FALSE,
|
||||
base_url text NOT NULL,
|
||||
settings text,
|
||||
settings_key_id text REFERENCES dbcrypt_keys(active_key_digest),
|
||||
created_at timestamp with time zone NOT NULL DEFAULT NOW(),
|
||||
updated_at timestamp with time zone NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Provider names are unique among live rows only. Soft-deleted rows
|
||||
-- are retained for audit and FK history but do not reserve names.
|
||||
CREATE UNIQUE INDEX ai_providers_name_unique
|
||||
ON ai_providers (name)
|
||||
WHERE deleted = FALSE;
|
||||
|
||||
COMMENT ON TABLE ai_providers IS 'Runtime configuration for AI providers. Authoritative source for the provider set served by aibridged. Replaces deployment-time CODER_AIBRIDGE_* environment variables.';
|
||||
|
||||
COMMENT ON COLUMN ai_providers.settings IS 'Encrypted JSON blob holding type-specific configuration (e.g. AWS Bedrock region, model, access key secret). Plaintext is a JSON object. NULL when no type-specific settings are required.';
|
||||
|
||||
COMMENT ON COLUMN ai_providers.settings_key_id IS 'The ID of the key used to encrypt settings. If this is NULL, settings is not encrypted.';
|
||||
|
||||
COMMENT ON COLUMN ai_providers.deleted IS 'Soft delete flag. Soft-deleted rows are preserved for audit and FK history but do not block name reuse by future live rows.';
|
||||
|
||||
COMMENT ON COLUMN ai_providers.display_name IS 'Optional human-readable label. When NULL, callers should fall back to name.';
|
||||
|
||||
CREATE INDEX idx_ai_providers_enabled ON ai_providers (enabled) WHERE deleted = FALSE;
|
||||
|
||||
CREATE TABLE ai_provider_keys (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
provider_id uuid NOT NULL REFERENCES ai_providers(id) ON DELETE CASCADE,
|
||||
api_key text NOT NULL,
|
||||
api_key_key_id text REFERENCES dbcrypt_keys(active_key_digest),
|
||||
created_at timestamp with time zone NOT NULL DEFAULT NOW(),
|
||||
updated_at timestamp with time zone NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
COMMENT ON TABLE ai_provider_keys IS 'API keys associated with AI providers. Bedrock providers have zero keys (they authenticate via settings). OpenAI and Anthropic providers have one or more keys for failover.';
|
||||
|
||||
COMMENT ON COLUMN ai_provider_keys.api_key IS 'API key used to authenticate with the upstream AI provider. Encrypted at rest via dbcrypt when api_key_key_id is set.';
|
||||
|
||||
COMMENT ON COLUMN ai_provider_keys.api_key_key_id IS 'The ID of the key used to encrypt the provider API key. If this is NULL, the API key is not encrypted.';
|
||||
|
||||
CREATE INDEX idx_ai_provider_keys_provider_id ON ai_provider_keys (provider_id);
|
||||
|
||||
-- Audit support: allow ai_providers and ai_provider_keys to appear in
|
||||
-- audit_log.resource_type.
|
||||
ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'ai_provider';
|
||||
ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'ai_provider_key';
|
||||
|
||||
-- API key scopes for ai_provider resources.
|
||||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'ai_provider:*';
|
||||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'ai_provider:create';
|
||||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'ai_provider:delete';
|
||||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'ai_provider:read';
|
||||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'ai_provider:update';
|
||||
@@ -0,0 +1,56 @@
|
||||
INSERT INTO ai_providers (
|
||||
id,
|
||||
type,
|
||||
name,
|
||||
display_name,
|
||||
enabled,
|
||||
deleted,
|
||||
base_url,
|
||||
settings
|
||||
) VALUES
|
||||
(
|
||||
'8e3c6e18-2b75-4c3f-9b35-9d1c6f4e1a01',
|
||||
'openai',
|
||||
'openai',
|
||||
'OpenAI (Fixture)',
|
||||
TRUE,
|
||||
FALSE,
|
||||
'https://api.openai.com/v1/',
|
||||
''
|
||||
),
|
||||
(
|
||||
'8e3c6e18-2b75-4c3f-9b35-9d1c6f4e1a02',
|
||||
'anthropic',
|
||||
'anthropic-bedrock',
|
||||
'Anthropic via Bedrock (Fixture)',
|
||||
TRUE,
|
||||
FALSE,
|
||||
'https://bedrock-runtime.us-west-2.amazonaws.com/',
|
||||
'{"bedrock_region":"us-west-2","bedrock_model":"global.anthropic.claude-sonnet-4-5-20250929-v1:0","bedrock_access_key":"fixture-bedrock-access-key","bedrock_access_key_secret":"fixture-bedrock-access-key-secret"}'
|
||||
),
|
||||
(
|
||||
'8e3c6e18-2b75-4c3f-9b35-9d1c6f4e1a03',
|
||||
'openai',
|
||||
'openai-deleted',
|
||||
'OpenAI (Deleted Fixture)',
|
||||
FALSE,
|
||||
TRUE,
|
||||
'https://api.openai.com/v1/',
|
||||
''
|
||||
);
|
||||
|
||||
INSERT INTO ai_provider_keys (
|
||||
id,
|
||||
provider_id,
|
||||
api_key
|
||||
) VALUES
|
||||
(
|
||||
'8e3c6e18-2b75-4c3f-9b35-9d1c6f4e1b01',
|
||||
'8e3c6e18-2b75-4c3f-9b35-9d1c6f4e1a01',
|
||||
'fixture-openai-key'
|
||||
),
|
||||
(
|
||||
'8e3c6e18-2b75-4c3f-9b35-9d1c6f4e1b02',
|
||||
'8e3c6e18-2b75-4c3f-9b35-9d1c6f4e1a01',
|
||||
'fixture-openai-key-failover'
|
||||
);
|
||||
Reference in New Issue
Block a user