Files
kite/backend/migrations/versions/0005_system_settings.py
T
curo1305 4eb317749f feat(07-01): Alembic migration 0005 + SystemSettings ORM model
- Add backend/migrations/versions/0005_system_settings.py (revision 0005, down_revision 0004)
- Creates system_settings table with 9 columns: id (UUID PK gen_random_uuid()), provider_id (String NOT NULL UNIQUE), api_key_enc (Text NULL), base_url (Text NULL), model_name (Text NOT NULL default ''), context_chars (Integer NOT NULL default 8000), is_active (Boolean NOT NULL default false), created_at/updated_at (TIMESTAMPTZ default now())
- UniqueConstraint uq_system_settings_provider_id on provider_id
- Add SystemSettings ORM model to backend/db/models.py following CloudConnection style
- downgrade() drops system_settings table cleanly
2026-06-04 18:46:11 +02:00

83 lines
2.5 KiB
Python

"""Add system_settings table for AI provider configuration.
Revision ID: 0005
Revises: 0004
Create Date: 2026-06-04
Changes:
1. Create system_settings table with one row per AI provider.
Stores: api_key_enc (Fernet-encrypted), base_url, model_name,
context_chars, is_active flag, and timestamps.
2. Add UNIQUE constraint on provider_id (uq_system_settings_provider_id)
to enforce one row per provider name.
Design notes (07-RESEARCH.md Pattern 1):
- One row per provider (not key-value store) — typed columns, enforced uniqueness.
- id column uses gen_random_uuid() server default.
- api_key_enc is Text nullable (NULL for local providers like Ollama/LMStudio).
- is_active = TRUE for the single active provider; all others FALSE.
- Encryption uses HKDF with info=b"ai-provider-settings" (domain separation from
cloud credentials which use info=b"cloud-credentials" — same master key, different
derived keys; see services/ai_config.py).
"""
from __future__ import annotations
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import UUID as PG_UUID
from alembic import op
# revision identifiers, used by Alembic.
revision = "0005"
down_revision = "0004"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.create_table("system_settings",
sa.Column(
"id",
PG_UUID(as_uuid=True),
primary_key=True,
server_default=sa.text("gen_random_uuid()"),
),
sa.Column("provider_id", sa.String, nullable=False),
sa.Column("api_key_enc", sa.Text, nullable=True),
sa.Column("base_url", sa.Text, nullable=True),
sa.Column(
"model_name",
sa.Text,
nullable=False,
server_default="",
),
sa.Column(
"context_chars",
sa.Integer,
nullable=False,
server_default="8000",
),
sa.Column(
"is_active",
sa.Boolean,
nullable=False,
server_default="false",
),
sa.Column(
"created_at",
sa.TIMESTAMP(timezone=True),
nullable=False,
server_default=sa.text("now()"),
),
sa.Column(
"updated_at",
sa.TIMESTAMP(timezone=True),
nullable=False,
server_default=sa.text("now()"),
),
sa.UniqueConstraint("provider_id", name="uq_system_settings_provider_id"),
)
def downgrade() -> None:
op.drop_table("system_settings")