"""Add write_mode to identity_sync_targets. Revision ID: 371 Revises: 370 Create Date: 2026-07-01 The operation dimension of the sync-template matrix (Authing-parity): ``create_update`` (default — the historical behaviour: upsert every in-scope person), ``create_only`` (link once, never re-touch — the runner is skipped for anyone Helix has already linked), ``update_only`` (only maintain already-linked people, never create a new downstream record). Gated centrally in ``_sweep`` on the per-(target,person) ``identity_sync_state.external_id`` link state, so no runner internals change. ``String(16)`` enum-as-string, NOT NULL, server_default keeps every existing target on the historical ``create_update`` behaviour. """ from __future__ import annotations import sqlalchemy as sa from alembic import op revision = "371" down_revision = "370" branch_labels = None depends_on = None _TABLE = "identity_sync_targets" _COL = "write_mode" def _has_column(bind, table: str, column: str) -> bool: return bind.execute( sa.text( "SELECT 1 FROM information_schema.COLUMNS " "WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :t " "AND COLUMN_NAME = :c" ), {"t": table, "c": column}, ).scalar() is not None def upgrade() -> None: bind = op.get_bind() if not _has_column(bind, _TABLE, _COL): op.add_column( _TABLE, sa.Column( _COL, sa.String(16), nullable=False, server_default="create_update", ), ) def downgrade() -> None: bind = op.get_bind() if _has_column(bind, _TABLE, _COL): op.drop_column(_TABLE, _COL)