"""add config profiles, includes, mounts, and tool instance profile selection Revision ID: 0013_add_config_profiles Revises: 0012_default_port_req Create Date: 2026-05-24 12:00:00.000000 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision: str = "0013_add_config_profiles" down_revision: Union[str, None] = "0012_default_port_req" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # Create config_profiles table op.create_table( "config_profiles", sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("user_id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("name", sa.String(length=255), nullable=False), sa.Column("description", sa.Text(), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()"), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()"), nullable=False), sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("user_id", "name", name="uq_config_profiles_user_name"), ) op.create_index("idx_config_profiles_user", "config_profiles", ["user_id"]) # Create config_includes table op.create_table( "config_includes", sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("profile_id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("included_profile_id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("order_index", sa.Integer(), nullable=False, server_default="0"), sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()"), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()"), nullable=False), sa.ForeignKeyConstraint(["profile_id"], ["config_profiles.id"], ondelete="CASCADE"), sa.ForeignKeyConstraint(["included_profile_id"], ["config_profiles.id"], ondelete="CASCADE"), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("profile_id", "included_profile_id", name="uq_config_includes_pair"), ) op.create_index("idx_config_includes_profile", "config_includes", ["profile_id"]) op.create_index("idx_config_includes_included", "config_includes", ["included_profile_id"]) # Create config_mounts table op.create_table( "config_mounts", sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("profile_id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("mount_path", sa.String(length=1024), nullable=False), sa.Column("content", sa.Text(), nullable=True), sa.Column("source_profile_id", postgresql.UUID(as_uuid=True), nullable=True), sa.Column("order_index", sa.Integer(), nullable=False, server_default="0"), sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()"), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()"), nullable=False), sa.ForeignKeyConstraint(["profile_id"], ["config_profiles.id"], ondelete="CASCADE"), sa.ForeignKeyConstraint(["source_profile_id"], ["config_profiles.id"], ondelete="SET NULL"), sa.PrimaryKeyConstraint("id"), ) op.create_index("idx_config_mounts_profile", "config_mounts", ["profile_id"]) # Add selected_profile_id to tool_instances op.add_column( "tool_instances", sa.Column("selected_profile_id", postgresql.UUID(as_uuid=True), nullable=True), ) op.create_foreign_key( "fk_tool_instances_selected_profile", "tool_instances", "config_profiles", ["selected_profile_id"], ["id"], ondelete="SET NULL", ) op.create_index("idx_tool_instances_selected_profile", "tool_instances", ["selected_profile_id"]) def downgrade() -> None: # Remove selected_profile_id from tool_instances op.drop_index("idx_tool_instances_selected_profile", table_name="tool_instances") op.drop_constraint("fk_tool_instances_selected_profile", "tool_instances", type_="foreignkey") op.drop_column("tool_instances", "selected_profile_id") # Drop config_mounts op.drop_index("idx_config_mounts_profile", table_name="config_mounts") op.drop_table("config_mounts") # Drop config_includes op.drop_index("idx_config_includes_included", table_name="config_includes") op.drop_index("idx_config_includes_profile", table_name="config_includes") op.drop_table("config_includes") # Drop config_profiles op.drop_index("idx_config_profiles_user", table_name="config_profiles") op.drop_table("config_profiles")