From c8c03c2b0dfc0bce775a77c03ff993a330a2eca6 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Fri, 6 Feb 2026 19:36:53 +0530 Subject: [PATCH] feat: add initial migration with schema for gateways, boards, users, agents, tasks, activity events, board memory, approvals, onboarding sessions, and task fingerprints --- .../1d844b04ee06_add_approvals_task_id.py | 101 ----- backend/alembic/versions/1d844b04ee06_init.py | 388 ++++++++++++++++++ .../3b9b2f1a6c2d_board_lead_orchestration.py | 145 ------- ...2dbb6e_rename_gateway_config_to_gateway.py | 95 ----- .../75e05e158ca9_normalize_task_statuses.py | 27 -- backend/alembic/versions/939a1d2dc607_init.py | 156 ------- .../versions/9f2c1a7b0d3e_merge_heads.py | 22 - .../a5aab244d32d_add_board_memory_is_chat.py | 60 --- ...1_add_gateway_skyll_and_agent_templates.py | 104 ----- ...f7b3d0a1c9e2_add_agent_identity_profile.py | 28 -- 10 files changed, 388 insertions(+), 738 deletions(-) delete mode 100644 backend/alembic/versions/1d844b04ee06_add_approvals_task_id.py create mode 100644 backend/alembic/versions/1d844b04ee06_init.py delete mode 100644 backend/alembic/versions/3b9b2f1a6c2d_board_lead_orchestration.py delete mode 100644 backend/alembic/versions/4b2a5e2dbb6e_rename_gateway_config_to_gateway.py delete mode 100644 backend/alembic/versions/75e05e158ca9_normalize_task_statuses.py delete mode 100644 backend/alembic/versions/939a1d2dc607_init.py delete mode 100644 backend/alembic/versions/9f2c1a7b0d3e_merge_heads.py delete mode 100644 backend/alembic/versions/a5aab244d32d_add_board_memory_is_chat.py delete mode 100644 backend/alembic/versions/c1c8b3b9f4d1_add_gateway_skyll_and_agent_templates.py delete mode 100644 backend/alembic/versions/f7b3d0a1c9e2_add_agent_identity_profile.py diff --git a/backend/alembic/versions/1d844b04ee06_add_approvals_task_id.py b/backend/alembic/versions/1d844b04ee06_add_approvals_task_id.py deleted file mode 100644 index 30954f39..00000000 --- a/backend/alembic/versions/1d844b04ee06_add_approvals_task_id.py +++ /dev/null @@ -1,101 +0,0 @@ -"""add approvals task_id - -Revision ID: 1d844b04ee06 -Revises: a5aab244d32d -Create Date: 2026-02-06 17:26:43.336466 - -""" - -from __future__ import annotations - -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = "1d844b04ee06" -down_revision = "a5aab244d32d" -branch_labels = None -depends_on = None - - -def upgrade() -> None: - # This migration may run in databases where the column/index/constraint were created via - # SQLModel `create_all()` (or a previous hotfix). Make it idempotent to avoid blocking - # upgrades in dev environments. - bind = op.get_bind() - inspector = sa.inspect(bind) - - approval_cols = {c["name"] for c in inspector.get_columns("approvals")} - if "task_id" not in approval_cols: - op.add_column("approvals", sa.Column("task_id", sa.Uuid(), nullable=True)) - - approval_index_names = {i["name"] for i in inspector.get_indexes("approvals")} - if "ix_approvals_task_id" not in approval_index_names: - op.create_index("ix_approvals_task_id", "approvals", ["task_id"], unique=False) - - # Backfill from legacy JSON payload keys when they contain a valid UUID. - op.execute( - """ - WITH src AS ( - SELECT - id, - COALESCE( - payload->>'task_id', - payload->>'taskId', - payload->>'taskID' - ) AS task_id_str - FROM approvals - WHERE task_id IS NULL - ), - valid AS ( - SELECT - id, - task_id_str::uuid AS task_id - FROM src - WHERE task_id_str ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' - ), - existing AS ( - SELECT v.id, v.task_id - FROM valid AS v - JOIN tasks AS t ON t.id = v.task_id - ) - UPDATE approvals AS a - SET task_id = existing.task_id - FROM existing - WHERE a.id = existing.id; - """ - ) - - # Avoid FK failures if any approvals point at deleted tasks. - op.execute( - """ - UPDATE approvals AS a - SET task_id = NULL - WHERE task_id IS NOT NULL - AND NOT EXISTS ( - SELECT 1 FROM tasks AS t WHERE t.id = a.task_id - ); - """ - ) - - approval_fks = inspector.get_foreign_keys("approvals") - has_task_fk = any( - (fk.get("referred_table") == "tasks" and "task_id" in (fk.get("constrained_columns") or [])) - for fk in approval_fks - ) - if not has_task_fk: - op.create_foreign_key( - "fk_approvals_task_id_tasks", - "approvals", - "tasks", - ["task_id"], - ["id"], - ondelete="SET NULL", - ) - - -def downgrade() -> None: - op.drop_constraint("fk_approvals_task_id_tasks", "approvals", type_="foreignkey") - op.drop_index("ix_approvals_task_id", table_name="approvals") - op.drop_column("approvals", "task_id") diff --git a/backend/alembic/versions/1d844b04ee06_init.py b/backend/alembic/versions/1d844b04ee06_init.py new file mode 100644 index 00000000..341b31b9 --- /dev/null +++ b/backend/alembic/versions/1d844b04ee06_init.py @@ -0,0 +1,388 @@ +"""init (squashed) + +Revision ID: 1d844b04ee06 +Revises: +Create Date: 2026-02-06 + +This is a squashed init migration representing the current schema at revision +`1d844b04ee06`. + +Note: older Alembic revision files were consolidated into this single revision. +Databases already stamped/applied at `1d844b04ee06` will remain compatible. +""" + +from __future__ import annotations + +from alembic import op +import sqlalchemy as sa +import sqlmodel + +# revision identifiers, used by Alembic. +revision = "1d844b04ee06" +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.create_table( + "gateways", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("url", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("token", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("main_session_key", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("workspace_root", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column( + "skyll_enabled", + sa.Boolean(), + server_default=sa.text("false"), + nullable=False, + ), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("updated_at", sa.DateTime(), nullable=False), + sa.PrimaryKeyConstraint("id"), + ) + + op.create_table( + "boards", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("slug", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("gateway_id", sa.Uuid(), nullable=True), + sa.Column( + "board_type", + sa.String(), + server_default="goal", + nullable=False, + ), + sa.Column("objective", sa.Text(), nullable=True), + sa.Column("success_metrics", sa.JSON(), nullable=True), + sa.Column("target_date", sa.DateTime(), nullable=True), + sa.Column( + "goal_confirmed", + sa.Boolean(), + server_default=sa.text("false"), + nullable=False, + ), + sa.Column("goal_source", sa.Text(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("updated_at", sa.DateTime(), nullable=False), + sa.ForeignKeyConstraint(["gateway_id"], ["gateways.id"]), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index("ix_boards_slug", "boards", ["slug"], unique=False) + op.create_index("ix_boards_gateway_id", "boards", ["gateway_id"], unique=False) + op.create_index("ix_boards_board_type", "boards", ["board_type"], unique=False) + + op.create_table( + "users", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("clerk_user_id", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("email", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("preferred_name", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("pronouns", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("timezone", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("notes", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("context", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("is_super_admin", sa.Boolean(), nullable=False), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index("ix_users_clerk_user_id", "users", ["clerk_user_id"], unique=True) + op.create_index("ix_users_email", "users", ["email"], unique=False) + + op.create_table( + "agents", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("board_id", sa.Uuid(), nullable=True), + sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("status", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("openclaw_session_id", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("agent_token_hash", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("heartbeat_config", sa.JSON(), nullable=True), + sa.Column("identity_profile", sa.JSON(), nullable=True), + sa.Column("identity_template", sa.Text(), nullable=True), + sa.Column("soul_template", sa.Text(), nullable=True), + sa.Column("provision_requested_at", sa.DateTime(), nullable=True), + sa.Column( + "provision_confirm_token_hash", + sqlmodel.sql.sqltypes.AutoString(), + nullable=True, + ), + sa.Column("provision_action", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("delete_requested_at", sa.DateTime(), nullable=True), + sa.Column( + "delete_confirm_token_hash", + sqlmodel.sql.sqltypes.AutoString(), + nullable=True, + ), + sa.Column("last_seen_at", sa.DateTime(), nullable=True), + sa.Column( + "is_board_lead", + sa.Boolean(), + server_default=sa.text("false"), + nullable=False, + ), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("updated_at", sa.DateTime(), nullable=False), + sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index("ix_agents_board_id", "agents", ["board_id"], unique=False) + op.create_index("ix_agents_name", "agents", ["name"], unique=False) + op.create_index("ix_agents_status", "agents", ["status"], unique=False) + op.create_index( + "ix_agents_openclaw_session_id", "agents", ["openclaw_session_id"], unique=False + ) + op.create_index("ix_agents_agent_token_hash", "agents", ["agent_token_hash"], unique=False) + op.create_index( + "ix_agents_provision_confirm_token_hash", + "agents", + ["provision_confirm_token_hash"], + unique=False, + ) + op.create_index("ix_agents_provision_action", "agents", ["provision_action"], unique=False) + op.create_index( + "ix_agents_delete_confirm_token_hash", + "agents", + ["delete_confirm_token_hash"], + unique=False, + ) + op.create_index("ix_agents_is_board_lead", "agents", ["is_board_lead"], unique=False) + + op.create_table( + "tasks", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("board_id", sa.Uuid(), nullable=True), + sa.Column("title", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("status", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("priority", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("due_at", sa.DateTime(), nullable=True), + sa.Column("in_progress_at", sa.DateTime(), nullable=True), + sa.Column("created_by_user_id", sa.Uuid(), nullable=True), + sa.Column("assigned_agent_id", sa.Uuid(), nullable=True), + sa.Column( + "auto_created", + sa.Boolean(), + server_default=sa.text("false"), + nullable=False, + ), + sa.Column("auto_reason", sa.Text(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("updated_at", sa.DateTime(), nullable=False), + sa.ForeignKeyConstraint(["assigned_agent_id"], ["agents.id"]), + sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), + sa.ForeignKeyConstraint(["created_by_user_id"], ["users.id"]), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index("ix_tasks_board_id", "tasks", ["board_id"], unique=False) + op.create_index("ix_tasks_status", "tasks", ["status"], unique=False) + op.create_index("ix_tasks_priority", "tasks", ["priority"], unique=False) + op.create_index("ix_tasks_due_at", "tasks", ["due_at"], unique=False) + op.create_index("ix_tasks_assigned_agent_id", "tasks", ["assigned_agent_id"], unique=False) + op.create_index("ix_tasks_created_by_user_id", "tasks", ["created_by_user_id"], unique=False) + + op.create_table( + "activity_events", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("event_type", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("message", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("agent_id", sa.Uuid(), nullable=True), + sa.Column("task_id", sa.Uuid(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.ForeignKeyConstraint(["agent_id"], ["agents.id"]), + sa.ForeignKeyConstraint(["task_id"], ["tasks.id"]), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index("ix_activity_events_event_type", "activity_events", ["event_type"], unique=False) + op.create_index("ix_activity_events_agent_id", "activity_events", ["agent_id"], unique=False) + op.create_index("ix_activity_events_task_id", "activity_events", ["task_id"], unique=False) + + op.create_table( + "board_memory", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("board_id", sa.Uuid(), nullable=False), + sa.Column("content", sa.Text(), nullable=False), + sa.Column("tags", sa.JSON(), nullable=True), + sa.Column( + "is_chat", + sa.Boolean(), + server_default=sa.text("false"), + nullable=False, + ), + sa.Column("source", sa.Text(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index("ix_board_memory_board_id", "board_memory", ["board_id"], unique=False) + op.create_index("ix_board_memory_is_chat", "board_memory", ["is_chat"], unique=False) + op.create_index( + "ix_board_memory_board_id_is_chat_created_at", + "board_memory", + ["board_id", "is_chat", "created_at"], + unique=False, + ) + + op.create_table( + "approvals", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("board_id", sa.Uuid(), nullable=False), + sa.Column("task_id", sa.Uuid(), nullable=True), + sa.Column("agent_id", sa.Uuid(), nullable=True), + sa.Column("action_type", sa.String(), nullable=False), + sa.Column("payload", sa.JSON(), nullable=True), + sa.Column("confidence", sa.Integer(), nullable=False), + sa.Column("rubric_scores", sa.JSON(), nullable=True), + sa.Column("status", sa.String(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("resolved_at", sa.DateTime(), nullable=True), + sa.ForeignKeyConstraint(["agent_id"], ["agents.id"]), + sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), + sa.ForeignKeyConstraint(["task_id"], ["tasks.id"], ondelete="SET NULL"), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index("ix_approvals_board_id", "approvals", ["board_id"], unique=False) + op.create_index("ix_approvals_agent_id", "approvals", ["agent_id"], unique=False) + op.create_index("ix_approvals_task_id", "approvals", ["task_id"], unique=False) + op.create_index("ix_approvals_status", "approvals", ["status"], unique=False) + + op.create_table( + "board_onboarding_sessions", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("board_id", sa.Uuid(), nullable=False), + sa.Column("session_key", sa.String(), nullable=False), + sa.Column( + "status", + sa.String(), + server_default="active", + nullable=False, + ), + sa.Column("messages", sa.JSON(), nullable=True), + sa.Column("draft_goal", sa.JSON(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("updated_at", sa.DateTime(), nullable=False), + sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index( + "ix_board_onboarding_sessions_board_id", + "board_onboarding_sessions", + ["board_id"], + unique=False, + ) + op.create_index( + "ix_board_onboarding_sessions_status", + "board_onboarding_sessions", + ["status"], + unique=False, + ) + + op.create_table( + "task_fingerprints", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("board_id", sa.Uuid(), nullable=False), + sa.Column("fingerprint_hash", sa.String(), nullable=False), + sa.Column("task_id", sa.Uuid(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), + sa.ForeignKeyConstraint(["task_id"], ["tasks.id"]), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index( + "ix_task_fingerprints_board_hash", + "task_fingerprints", + ["board_id", "fingerprint_hash"], + unique=True, + ) + op.create_index( + "ix_task_fingerprints_board_id", + "task_fingerprints", + ["board_id"], + unique=False, + ) + op.create_index( + "ix_task_fingerprints_fingerprint_hash", + "task_fingerprints", + ["fingerprint_hash"], + unique=False, + ) + op.create_index( + "ix_task_fingerprints_task_id", + "task_fingerprints", + ["task_id"], + unique=False, + ) + + +def downgrade() -> None: + op.drop_index("ix_task_fingerprints_task_id", table_name="task_fingerprints") + op.drop_index( + "ix_task_fingerprints_fingerprint_hash", + table_name="task_fingerprints", + ) + op.drop_index("ix_task_fingerprints_board_id", table_name="task_fingerprints") + op.drop_index("ix_task_fingerprints_board_hash", table_name="task_fingerprints") + op.drop_table("task_fingerprints") + + op.drop_index( + "ix_board_onboarding_sessions_status", + table_name="board_onboarding_sessions", + ) + op.drop_index( + "ix_board_onboarding_sessions_board_id", + table_name="board_onboarding_sessions", + ) + op.drop_table("board_onboarding_sessions") + + op.drop_index("ix_approvals_status", table_name="approvals") + op.drop_index("ix_approvals_task_id", table_name="approvals") + op.drop_index("ix_approvals_agent_id", table_name="approvals") + op.drop_index("ix_approvals_board_id", table_name="approvals") + op.drop_table("approvals") + + op.drop_index( + "ix_board_memory_board_id_is_chat_created_at", + table_name="board_memory", + ) + op.drop_index("ix_board_memory_is_chat", table_name="board_memory") + op.drop_index("ix_board_memory_board_id", table_name="board_memory") + op.drop_table("board_memory") + + op.drop_index("ix_activity_events_task_id", table_name="activity_events") + op.drop_index("ix_activity_events_agent_id", table_name="activity_events") + op.drop_index("ix_activity_events_event_type", table_name="activity_events") + op.drop_table("activity_events") + + op.drop_index("ix_tasks_created_by_user_id", table_name="tasks") + op.drop_index("ix_tasks_assigned_agent_id", table_name="tasks") + op.drop_index("ix_tasks_due_at", table_name="tasks") + op.drop_index("ix_tasks_priority", table_name="tasks") + op.drop_index("ix_tasks_status", table_name="tasks") + op.drop_index("ix_tasks_board_id", table_name="tasks") + op.drop_table("tasks") + + op.drop_index("ix_agents_is_board_lead", table_name="agents") + op.drop_index("ix_agents_delete_confirm_token_hash", table_name="agents") + op.drop_index("ix_agents_provision_action", table_name="agents") + op.drop_index("ix_agents_provision_confirm_token_hash", table_name="agents") + op.drop_index("ix_agents_agent_token_hash", table_name="agents") + op.drop_index("ix_agents_openclaw_session_id", table_name="agents") + op.drop_index("ix_agents_status", table_name="agents") + op.drop_index("ix_agents_name", table_name="agents") + op.drop_index("ix_agents_board_id", table_name="agents") + op.drop_table("agents") + + op.drop_index("ix_users_email", table_name="users") + op.drop_index("ix_users_clerk_user_id", table_name="users") + op.drop_table("users") + + op.drop_index("ix_boards_board_type", table_name="boards") + op.drop_index("ix_boards_gateway_id", table_name="boards") + op.drop_index("ix_boards_slug", table_name="boards") + op.drop_table("boards") + + op.drop_table("gateways") + diff --git a/backend/alembic/versions/3b9b2f1a6c2d_board_lead_orchestration.py b/backend/alembic/versions/3b9b2f1a6c2d_board_lead_orchestration.py deleted file mode 100644 index 8f9dbced..00000000 --- a/backend/alembic/versions/3b9b2f1a6c2d_board_lead_orchestration.py +++ /dev/null @@ -1,145 +0,0 @@ -"""board lead orchestration - -Revision ID: 3b9b2f1a6c2d -Revises: 9f2c1a7b0d3e -Create Date: 2026-02-05 14:45:00.000000 -""" - -from __future__ import annotations - -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = "3b9b2f1a6c2d" -down_revision = "9f2c1a7b0d3e" -branch_labels = None -depends_on = None - - -def upgrade() -> None: - op.add_column("boards", sa.Column("board_type", sa.String(), server_default="goal", nullable=False)) - op.add_column("boards", sa.Column("objective", sa.Text(), nullable=True)) - op.add_column("boards", sa.Column("success_metrics", sa.JSON(), nullable=True)) - op.add_column("boards", sa.Column("target_date", sa.DateTime(), nullable=True)) - op.add_column( - "boards", - sa.Column("goal_confirmed", sa.Boolean(), server_default=sa.text("false"), nullable=False), - ) - op.add_column("boards", sa.Column("goal_source", sa.Text(), nullable=True)) - - op.add_column( - "agents", - sa.Column("is_board_lead", sa.Boolean(), server_default=sa.text("false"), nullable=False), - ) - - op.add_column( - "tasks", - sa.Column("auto_created", sa.Boolean(), server_default=sa.text("false"), nullable=False), - ) - op.add_column("tasks", sa.Column("auto_reason", sa.Text(), nullable=True)) - - op.create_table( - "board_memory", - sa.Column("id", sa.Uuid(), nullable=False), - sa.Column("board_id", sa.Uuid(), nullable=False), - sa.Column("content", sa.Text(), nullable=False), - sa.Column("tags", sa.JSON(), nullable=True), - sa.Column("source", sa.Text(), nullable=True), - sa.Column("created_at", sa.DateTime(), nullable=False), - sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), - sa.PrimaryKeyConstraint("id"), - ) - op.create_index("ix_board_memory_board_id", "board_memory", ["board_id"], unique=False) - - op.create_table( - "approvals", - sa.Column("id", sa.Uuid(), nullable=False), - sa.Column("board_id", sa.Uuid(), nullable=False), - sa.Column("agent_id", sa.Uuid(), nullable=True), - sa.Column("action_type", sa.String(), nullable=False), - sa.Column("payload", sa.JSON(), nullable=True), - sa.Column("confidence", sa.Integer(), nullable=False), - sa.Column("rubric_scores", sa.JSON(), nullable=True), - sa.Column("status", sa.String(), nullable=False), - sa.Column("created_at", sa.DateTime(), nullable=False), - sa.Column("resolved_at", sa.DateTime(), nullable=True), - sa.ForeignKeyConstraint(["agent_id"], ["agents.id"]), - sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), - sa.PrimaryKeyConstraint("id"), - ) - op.create_index("ix_approvals_board_id", "approvals", ["board_id"], unique=False) - op.create_index("ix_approvals_agent_id", "approvals", ["agent_id"], unique=False) - op.create_index("ix_approvals_status", "approvals", ["status"], unique=False) - - op.create_table( - "board_onboarding_sessions", - sa.Column("id", sa.Uuid(), nullable=False), - sa.Column("board_id", sa.Uuid(), nullable=False), - sa.Column("session_key", sa.String(), nullable=False), - sa.Column("status", sa.String(), nullable=False), - sa.Column("messages", sa.JSON(), nullable=True), - sa.Column("draft_goal", sa.JSON(), nullable=True), - sa.Column("created_at", sa.DateTime(), nullable=False), - sa.Column("updated_at", sa.DateTime(), nullable=False), - sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), - sa.PrimaryKeyConstraint("id"), - ) - op.create_index( - "ix_board_onboarding_sessions_board_id", - "board_onboarding_sessions", - ["board_id"], - unique=False, - ) - op.create_index( - "ix_board_onboarding_sessions_status", - "board_onboarding_sessions", - ["status"], - unique=False, - ) - - op.create_table( - "task_fingerprints", - sa.Column("id", sa.Uuid(), nullable=False), - sa.Column("board_id", sa.Uuid(), nullable=False), - sa.Column("fingerprint_hash", sa.String(), nullable=False), - sa.Column("task_id", sa.Uuid(), nullable=False), - sa.Column("created_at", sa.DateTime(), nullable=False), - sa.ForeignKeyConstraint(["board_id"], ["boards.id"]), - sa.ForeignKeyConstraint(["task_id"], ["tasks.id"]), - sa.PrimaryKeyConstraint("id"), - ) - op.create_index( - "ix_task_fingerprints_board_hash", - "task_fingerprints", - ["board_id", "fingerprint_hash"], - unique=True, - ) - - -def downgrade() -> None: - op.drop_index("ix_task_fingerprints_board_hash", table_name="task_fingerprints") - op.drop_table("task_fingerprints") - op.drop_index( - "ix_board_onboarding_sessions_status", table_name="board_onboarding_sessions" - ) - op.drop_index( - "ix_board_onboarding_sessions_board_id", table_name="board_onboarding_sessions" - ) - op.drop_table("board_onboarding_sessions") - op.drop_index("ix_approvals_status", table_name="approvals") - op.drop_index("ix_approvals_agent_id", table_name="approvals") - op.drop_index("ix_approvals_board_id", table_name="approvals") - op.drop_table("approvals") - op.drop_index("ix_board_memory_board_id", table_name="board_memory") - op.drop_table("board_memory") - op.drop_column("tasks", "auto_reason") - op.drop_column("tasks", "auto_created") - op.drop_column("agents", "is_board_lead") - op.drop_column("boards", "goal_source") - op.drop_column("boards", "goal_confirmed") - op.drop_column("boards", "target_date") - op.drop_column("boards", "success_metrics") - op.drop_column("boards", "objective") - op.drop_column("boards", "board_type") diff --git a/backend/alembic/versions/4b2a5e2dbb6e_rename_gateway_config_to_gateway.py b/backend/alembic/versions/4b2a5e2dbb6e_rename_gateway_config_to_gateway.py deleted file mode 100644 index 8cede1d4..00000000 --- a/backend/alembic/versions/4b2a5e2dbb6e_rename_gateway_config_to_gateway.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Rename gateways to gateway. - -Revision ID: 4b2a5e2dbb6e -Revises: c1c8b3b9f4d1 -Create Date: 2026-02-04 18:20:00.000000 -""" - -from alembic import op -import sqlalchemy as sa -import sqlmodel - -revision = "4b2a5e2dbb6e" -down_revision = "c1c8b3b9f4d1" -branch_labels = None -depends_on = None - - -def upgrade() -> None: - bind = op.get_bind() - inspector = sa.inspect(bind) - tables = set(inspector.get_table_names()) - - if "gateway_configs" in tables and "gateways" not in tables: - op.rename_table("gateway_configs", "gateways") - tables.discard("gateway_configs") - tables.add("gateways") - - if "boards" in tables: - columns = {col["name"] for col in inspector.get_columns("boards")} - with op.batch_alter_table("boards") as batch: - if "gateway_config_id" in columns and "gateway_id" not in columns: - batch.alter_column( - "gateway_config_id", - new_column_name="gateway_id", - existing_type=sa.Uuid(), - ) - elif "gateway_id" not in columns: - batch.add_column(sa.Column("gateway_id", sa.Uuid(), nullable=True)) - for legacy_col in ( - "gateway_url", - "gateway_token", - "gateway_main_session_key", - "gateway_workspace_root", - ): - if legacy_col in columns: - batch.drop_column(legacy_col) - - indexes = {index["name"] for index in inspector.get_indexes("boards")} - if "ix_boards_gateway_id" not in indexes: - op.create_index( - op.f("ix_boards_gateway_id"), "boards", ["gateway_id"], unique=False - ) - - -def downgrade() -> None: - bind = op.get_bind() - inspector = sa.inspect(bind) - tables = set(inspector.get_table_names()) - - if "boards" in tables: - columns = {col["name"] for col in inspector.get_columns("boards")} - with op.batch_alter_table("boards") as batch: - if "gateway_id" in columns and "gateway_config_id" not in columns: - batch.alter_column( - "gateway_id", - new_column_name="gateway_config_id", - existing_type=sa.Uuid(), - ) - if "gateway_url" not in columns: - batch.add_column( - sa.Column("gateway_url", sqlmodel.sql.sqltypes.AutoString(), nullable=True) - ) - if "gateway_token" not in columns: - batch.add_column( - sa.Column("gateway_token", sqlmodel.sql.sqltypes.AutoString(), nullable=True) - ) - if "gateway_main_session_key" not in columns: - batch.add_column( - sa.Column( - "gateway_main_session_key", - sqlmodel.sql.sqltypes.AutoString(), - nullable=True, - ) - ) - if "gateway_workspace_root" not in columns: - batch.add_column( - sa.Column( - "gateway_workspace_root", - sqlmodel.sql.sqltypes.AutoString(), - nullable=True, - ) - ) - - if "gateways" in tables and "gateway_configs" not in tables: - op.rename_table("gateways", "gateway_configs") diff --git a/backend/alembic/versions/75e05e158ca9_normalize_task_statuses.py b/backend/alembic/versions/75e05e158ca9_normalize_task_statuses.py deleted file mode 100644 index ad0741b2..00000000 --- a/backend/alembic/versions/75e05e158ca9_normalize_task_statuses.py +++ /dev/null @@ -1,27 +0,0 @@ -"""normalize task statuses - -Revision ID: 75e05e158ca9 -Revises: 4b2a5e2dbb6e -Create Date: 2026-02-05 00:16:48.958679 - -""" -from __future__ import annotations - -from alembic import op - - -# revision identifiers, used by Alembic. -revision = '75e05e158ca9' -down_revision = '4b2a5e2dbb6e' -branch_labels = None -depends_on = None - - -def upgrade() -> None: - op.execute( - "UPDATE tasks SET status='in_progress' WHERE status IN ('assigned','testing')" - ) - - -def downgrade() -> None: - pass diff --git a/backend/alembic/versions/939a1d2dc607_init.py b/backend/alembic/versions/939a1d2dc607_init.py deleted file mode 100644 index be517afc..00000000 --- a/backend/alembic/versions/939a1d2dc607_init.py +++ /dev/null @@ -1,156 +0,0 @@ -"""init - -Revision ID: 939a1d2dc607 -Revises: -Create Date: 2026-02-04 19:34:33.600751 - -""" -from __future__ import annotations - -from alembic import op -import sqlalchemy as sa -import sqlmodel - - -# revision identifiers, used by Alembic. -revision = '939a1d2dc607' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.create_table( - 'gateway_configs', - sa.Column('id', sa.Uuid(), nullable=False), - sa.Column('name', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('url', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('token', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('main_session_key', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('workspace_root', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=False), - sa.Column('updated_at', sa.DateTime(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_table('boards', - sa.Column('id', sa.Uuid(), nullable=False), - sa.Column('name', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('slug', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('gateway_config_id', sa.Uuid(), nullable=True), - sa.Column('created_at', sa.DateTime(), nullable=False), - sa.Column('updated_at', sa.DateTime(), nullable=False), - sa.ForeignKeyConstraint(['gateway_config_id'], ['gateway_configs.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_boards_gateway_config_id'), 'boards', ['gateway_config_id'], unique=False) - op.create_index(op.f('ix_boards_slug'), 'boards', ['slug'], unique=False) - op.create_table('users', - sa.Column('id', sa.Uuid(), nullable=False), - sa.Column('clerk_user_id', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('email', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('name', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('preferred_name', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('pronouns', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('timezone', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('notes', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('context', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('is_super_admin', sa.Boolean(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_users_clerk_user_id'), 'users', ['clerk_user_id'], unique=True) - op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=False) - op.create_table('agents', - sa.Column('id', sa.Uuid(), nullable=False), - sa.Column('board_id', sa.Uuid(), nullable=True), - sa.Column('name', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('status', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('openclaw_session_id', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('agent_token_hash', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('heartbeat_config', sa.JSON(), nullable=True), - sa.Column('provision_requested_at', sa.DateTime(), nullable=True), - sa.Column('provision_confirm_token_hash', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('provision_action', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('delete_requested_at', sa.DateTime(), nullable=True), - sa.Column('delete_confirm_token_hash', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('last_seen_at', sa.DateTime(), nullable=True), - sa.Column('created_at', sa.DateTime(), nullable=False), - sa.Column('updated_at', sa.DateTime(), nullable=False), - sa.ForeignKeyConstraint(['board_id'], ['boards.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_agents_agent_token_hash'), 'agents', ['agent_token_hash'], unique=False) - op.create_index(op.f('ix_agents_board_id'), 'agents', ['board_id'], unique=False) - op.create_index(op.f('ix_agents_delete_confirm_token_hash'), 'agents', ['delete_confirm_token_hash'], unique=False) - op.create_index(op.f('ix_agents_name'), 'agents', ['name'], unique=False) - op.create_index(op.f('ix_agents_openclaw_session_id'), 'agents', ['openclaw_session_id'], unique=False) - op.create_index(op.f('ix_agents_provision_action'), 'agents', ['provision_action'], unique=False) - op.create_index(op.f('ix_agents_provision_confirm_token_hash'), 'agents', ['provision_confirm_token_hash'], unique=False) - op.create_index(op.f('ix_agents_status'), 'agents', ['status'], unique=False) - op.create_table('tasks', - sa.Column('id', sa.Uuid(), nullable=False), - sa.Column('board_id', sa.Uuid(), nullable=True), - sa.Column('title', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('description', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('status', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('priority', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('due_at', sa.DateTime(), nullable=True), - sa.Column('in_progress_at', sa.DateTime(), nullable=True), - sa.Column('created_by_user_id', sa.Uuid(), nullable=True), - sa.Column('assigned_agent_id', sa.Uuid(), nullable=True), - sa.Column('created_at', sa.DateTime(), nullable=False), - sa.Column('updated_at', sa.DateTime(), nullable=False), - sa.ForeignKeyConstraint(['assigned_agent_id'], ['agents.id'], ), - sa.ForeignKeyConstraint(['board_id'], ['boards.id'], ), - sa.ForeignKeyConstraint(['created_by_user_id'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_tasks_assigned_agent_id'), 'tasks', ['assigned_agent_id'], unique=False) - op.create_index(op.f('ix_tasks_board_id'), 'tasks', ['board_id'], unique=False) - op.create_index(op.f('ix_tasks_created_by_user_id'), 'tasks', ['created_by_user_id'], unique=False) - op.create_index(op.f('ix_tasks_priority'), 'tasks', ['priority'], unique=False) - op.create_index(op.f('ix_tasks_status'), 'tasks', ['status'], unique=False) - op.create_table('activity_events', - sa.Column('id', sa.Uuid(), nullable=False), - sa.Column('event_type', sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column('message', sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column('agent_id', sa.Uuid(), nullable=True), - sa.Column('task_id', sa.Uuid(), nullable=True), - sa.Column('created_at', sa.DateTime(), nullable=False), - sa.ForeignKeyConstraint(['agent_id'], ['agents.id'], ), - sa.ForeignKeyConstraint(['task_id'], ['tasks.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_activity_events_agent_id'), 'activity_events', ['agent_id'], unique=False) - op.create_index(op.f('ix_activity_events_event_type'), 'activity_events', ['event_type'], unique=False) - op.create_index(op.f('ix_activity_events_task_id'), 'activity_events', ['task_id'], unique=False) - # ### end Alembic commands ### - - -def downgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.drop_index(op.f('ix_activity_events_task_id'), table_name='activity_events') - op.drop_index(op.f('ix_activity_events_event_type'), table_name='activity_events') - op.drop_index(op.f('ix_activity_events_agent_id'), table_name='activity_events') - op.drop_table('activity_events') - op.drop_index(op.f('ix_tasks_status'), table_name='tasks') - op.drop_index(op.f('ix_tasks_priority'), table_name='tasks') - op.drop_index(op.f('ix_tasks_created_by_user_id'), table_name='tasks') - op.drop_index(op.f('ix_tasks_board_id'), table_name='tasks') - op.drop_index(op.f('ix_tasks_assigned_agent_id'), table_name='tasks') - op.drop_table('tasks') - op.drop_index(op.f('ix_agents_status'), table_name='agents') - op.drop_index(op.f('ix_agents_provision_confirm_token_hash'), table_name='agents') - op.drop_index(op.f('ix_agents_provision_action'), table_name='agents') - op.drop_index(op.f('ix_agents_openclaw_session_id'), table_name='agents') - op.drop_index(op.f('ix_agents_name'), table_name='agents') - op.drop_index(op.f('ix_agents_delete_confirm_token_hash'), table_name='agents') - op.drop_index(op.f('ix_agents_board_id'), table_name='agents') - op.drop_index(op.f('ix_agents_agent_token_hash'), table_name='agents') - op.drop_table('agents') - op.drop_index(op.f('ix_users_email'), table_name='users') - op.drop_index(op.f('ix_users_clerk_user_id'), table_name='users') - op.drop_table('users') - op.drop_index(op.f('ix_boards_slug'), table_name='boards') - op.drop_table('boards') - # ### end Alembic commands ### diff --git a/backend/alembic/versions/9f2c1a7b0d3e_merge_heads.py b/backend/alembic/versions/9f2c1a7b0d3e_merge_heads.py deleted file mode 100644 index 0f5485b2..00000000 --- a/backend/alembic/versions/9f2c1a7b0d3e_merge_heads.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Merge heads 75e05e158ca9 and f7b3d0a1c9e2. - -Revision ID: 9f2c1a7b0d3e -Revises: 75e05e158ca9, f7b3d0a1c9e2 -Create Date: 2026-02-05 00:30:00.000000 -""" - -from __future__ import annotations - -# revision identifiers, used by Alembic. -revision = "9f2c1a7b0d3e" -down_revision = ("75e05e158ca9", "f7b3d0a1c9e2") -branch_labels = None -depends_on = None - - -def upgrade() -> None: - pass - - -def downgrade() -> None: - pass diff --git a/backend/alembic/versions/a5aab244d32d_add_board_memory_is_chat.py b/backend/alembic/versions/a5aab244d32d_add_board_memory_is_chat.py deleted file mode 100644 index da579577..00000000 --- a/backend/alembic/versions/a5aab244d32d_add_board_memory_is_chat.py +++ /dev/null @@ -1,60 +0,0 @@ -"""add board memory is_chat - -Revision ID: a5aab244d32d -Revises: 3b9b2f1a6c2d -Create Date: 2026-02-06 17:57:02.110572 - -""" - -from __future__ import annotations - -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = "a5aab244d32d" -down_revision = "3b9b2f1a6c2d" -branch_labels = None -depends_on = None - - -def upgrade() -> None: - # Idempotent: the column/indexes might already exist if the table was created via - # SQLModel `create_all()`. - bind = op.get_bind() - inspector = sa.inspect(bind) - - memory_cols = {c["name"] for c in inspector.get_columns("board_memory")} - if "is_chat" not in memory_cols: - op.add_column( - "board_memory", - sa.Column("is_chat", sa.Boolean(), server_default=sa.text("false"), nullable=False), - ) - - memory_index_names = {i["name"] for i in inspector.get_indexes("board_memory")} - if "ix_board_memory_is_chat" not in memory_index_names: - op.create_index("ix_board_memory_is_chat", "board_memory", ["is_chat"], unique=False) - if "ix_board_memory_board_id_is_chat_created_at" not in memory_index_names: - op.create_index( - "ix_board_memory_board_id_is_chat_created_at", - "board_memory", - ["board_id", "is_chat", "created_at"], - unique=False, - ) - - # Backfill from existing tags arrays. - op.execute( - """ - UPDATE board_memory - SET is_chat = TRUE - WHERE tags IS NOT NULL - AND tags::jsonb @> '["chat"]'::jsonb; - """ - ) - - -def downgrade() -> None: - op.drop_index("ix_board_memory_board_id_is_chat_created_at", table_name="board_memory") - op.drop_index("ix_board_memory_is_chat", table_name="board_memory") - op.drop_column("board_memory", "is_chat") diff --git a/backend/alembic/versions/c1c8b3b9f4d1_add_gateway_skyll_and_agent_templates.py b/backend/alembic/versions/c1c8b3b9f4d1_add_gateway_skyll_and_agent_templates.py deleted file mode 100644 index cc2a366e..00000000 --- a/backend/alembic/versions/c1c8b3b9f4d1_add_gateway_skyll_and_agent_templates.py +++ /dev/null @@ -1,104 +0,0 @@ -"""Add gateway skyll flag and agent templates. - -Revision ID: c1c8b3b9f4d1 -Revises: 939a1d2dc607 -Create Date: 2026-02-04 22:18:00.000000 -""" - -from __future__ import annotations - -import sqlalchemy as sa -import sqlmodel -from alembic import op - -# revision identifiers, used by Alembic. -revision = "c1c8b3b9f4d1" -down_revision = "939a1d2dc607" -branch_labels = None -depends_on = None - - -def upgrade() -> None: - bind = op.get_bind() - inspector = sa.inspect(bind) - tables = set(inspector.get_table_names()) - created_gateways = False - if "gateways" not in tables and "gateway_configs" not in tables: - op.create_table( - "gateways", - sa.Column("id", sa.Uuid(), nullable=False), - sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column("url", sqlmodel.sql.sqltypes.AutoString(), nullable=False), - sa.Column("token", sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column( - "main_session_key", sqlmodel.sql.sqltypes.AutoString(), nullable=False - ), - sa.Column( - "workspace_root", sqlmodel.sql.sqltypes.AutoString(), nullable=False - ), - sa.Column( - "skyll_enabled", - sa.Boolean(), - nullable=False, - server_default=sa.false(), - ), - sa.Column("created_at", sa.DateTime(), nullable=False), - sa.Column("updated_at", sa.DateTime(), nullable=False), - sa.PrimaryKeyConstraint("id"), - ) - tables.add("gateways") - created_gateways = True - if "gateways" in tables and not created_gateways: - existing_columns = { - column["name"] for column in inspector.get_columns("gateways") - } - if "skyll_enabled" in existing_columns: - pass - else: - op.add_column( - "gateways", - sa.Column( - "skyll_enabled", - sa.Boolean(), - nullable=False, - server_default=sa.false(), - ), - ) - op.alter_column("gateways", "skyll_enabled", server_default=None) - elif "gateways" in tables and created_gateways: - op.alter_column("gateways", "skyll_enabled", server_default=None) - elif "gateway_configs" in tables: - existing_columns = { - column["name"] for column in inspector.get_columns("gateway_configs") - } - if "skyll_enabled" in existing_columns: - pass - else: - op.add_column( - "gateway_configs", - sa.Column( - "skyll_enabled", - sa.Boolean(), - nullable=False, - server_default=sa.false(), - ), - ) - op.alter_column("gateway_configs", "skyll_enabled", server_default=None) - op.add_column( - "agents", - sa.Column("identity_template", sa.Text(), nullable=True), - ) - op.add_column( - "agents", - sa.Column("soul_template", sa.Text(), nullable=True), - ) -def downgrade() -> None: - op.drop_column("agents", "soul_template") - op.drop_column("agents", "identity_template") - bind = op.get_bind() - inspector = sa.inspect(bind) - tables = set(inspector.get_table_names()) - if "gateways" in tables: - op.drop_column("gateways", "skyll_enabled") - elif "gateway_configs" in tables: - op.drop_column("gateway_configs", "skyll_enabled") diff --git a/backend/alembic/versions/f7b3d0a1c9e2_add_agent_identity_profile.py b/backend/alembic/versions/f7b3d0a1c9e2_add_agent_identity_profile.py deleted file mode 100644 index 9037e98a..00000000 --- a/backend/alembic/versions/f7b3d0a1c9e2_add_agent_identity_profile.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Add agent identity profile. - -Revision ID: f7b3d0a1c9e2 -Revises: c1c8b3b9f4d1 -Create Date: 2026-02-04 22:45:00.000000 -""" - -from __future__ import annotations - -import sqlalchemy as sa -from alembic import op - -# revision identifiers, used by Alembic. -revision = "f7b3d0a1c9e2" -down_revision = "c1c8b3b9f4d1" -branch_labels = None -depends_on = None - - -def upgrade() -> None: - op.add_column( - "agents", - sa.Column("identity_profile", sa.JSON(), nullable=True), - ) - - -def downgrade() -> None: - op.drop_column("agents", "identity_profile")