diff --git a/backend/alembic/versions/71efd2102f49_add_origin_discriminator_inline_.py b/backend/alembic/versions/71efd2102f49_add_origin_discriminator_inline_.py new file mode 100644 index 00000000..22f5947b --- /dev/null +++ b/backend/alembic/versions/71efd2102f49_add_origin_discriminator_inline_.py @@ -0,0 +1,70 @@ +"""add origin discriminator + inline idempotency to script_builder_sessions + +Adds: +- origin VARCHAR(20) NOT NULL DEFAULT 'standalone' with CHECK enum +- invariant: pilot_inline rows must have ai_session_id +- partial unique index: one pilot_inline session per (user, pilot session) + +Revision ID: 71efd2102f49 +Revises: 6492ec8d2d5b +Create Date: 2026-04-24 04:22:10.819809 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '71efd2102f49' +down_revision = '6492ec8d2d5b' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.add_column( + "script_builder_sessions", + sa.Column( + "origin", + sa.String(length=20), + nullable=False, + server_default=sa.text("'standalone'"), + ), + ) + op.create_check_constraint( + "ck_script_builder_sessions_origin", + "script_builder_sessions", + "origin IN ('standalone', 'pilot_inline')", + ) + op.create_check_constraint( + "ck_script_builder_sessions_origin_ai_session", + "script_builder_sessions", + "origin <> 'pilot_inline' OR ai_session_id IS NOT NULL", + ) + op.create_index( + "ux_script_builder_sessions_pilot_inline", + "script_builder_sessions", + ["user_id", "ai_session_id"], + unique=True, + postgresql_where=sa.text("origin = 'pilot_inline'"), + ) + # Drop the server_default — app code owns the default via model default. + op.alter_column("script_builder_sessions", "origin", server_default=None) + + +def downgrade() -> None: + op.drop_index( + "ux_script_builder_sessions_pilot_inline", + table_name="script_builder_sessions", + ) + op.drop_constraint( + "ck_script_builder_sessions_origin_ai_session", + "script_builder_sessions", + type_="check", + ) + op.drop_constraint( + "ck_script_builder_sessions_origin", + "script_builder_sessions", + type_="check", + ) + op.drop_column("script_builder_sessions", "origin")