"""Fix schema drifts — VARCHAR lengths + missing tables. Revision ID: 0135 Revises: 0134 Create Date: 2026-08-21 """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects.postgresql import UUID, JSONB revision = "0135" down_revision = "0134" branch_labels = None depends_on = None def upgrade() -> None: # 1. Fix VARCHAR length mismatches (model defines longer than DB) # Drop notifications_legacy view first — it depends on notifications.type column op.execute("DROP VIEW IF EXISTS notifications_legacy CASCADE;") op.execute("ALTER TABLE contacts ALTER COLUMN status TYPE VARCHAR(30);") op.execute("ALTER TABLE notifications ALTER COLUMN type TYPE VARCHAR(100);") op.execute("ALTER TABLE notification_preferences ALTER COLUMN type_key TYPE VARCHAR(100);") # 2. Create missing table: forgejo_reported_errors (only if not exists) op.execute(""" CREATE TABLE IF NOT EXISTS forgejo_reported_errors ( id SERIAL PRIMARY KEY, dedup_key VARCHAR(64) NOT NULL UNIQUE, message TEXT NOT NULL, stack TEXT, forgejo_issue_number INTEGER, reported_at TIMESTAMPTZ DEFAULT now() NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'reported' ) """) # 3. Create missing table: pgp_keys (only if not exists) op.execute(""" CREATE TABLE IF NOT EXISTS pgp_keys ( id UUID DEFAULT gen_random_uuid() NOT NULL PRIMARY KEY, tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE, user_id UUID NOT NULL, key_id VARCHAR(255) NOT NULL, encrypted_private_key TEXT NOT NULL, public_key_armored TEXT NOT NULL ) """) op.execute("CREATE INDEX IF NOT EXISTS ix_pgp_keys_user ON pgp_keys (user_id);") op.execute("ALTER TABLE pgp_keys ENABLE ROW LEVEL SECURITY;") op.execute("DROP POLICY IF EXISTS pgp_keys_tenant_isolation ON pgp_keys;") op.execute("CREATE POLICY pgp_keys_tenant_isolation ON pgp_keys USING (tenant_id::text = current_setting('app.current_tenant_id', true));") def downgrade() -> None: op.drop_table("pgp_keys") op.drop_table("forgejo_reported_errors") op.execute("ALTER TABLE notification_preferences ALTER COLUMN type_key TYPE VARCHAR(20);") op.execute("ALTER TABLE notifications ALTER COLUMN type TYPE VARCHAR(20);") op.execute("ALTER TABLE contacts ALTER COLUMN status TYPE VARCHAR(20);")