"""Add policyactionholds (break-glass desired-state suppression). Backs the admin override: when an admin break-glasses past a policy denial on a desired-mode action, a hold row suspends reconciliation of that action on that endpoint until expiresat, so the override is not immediately undone by the next drift-correcting enqueue. Rows are never swept: expiry is evaluated at resolve time against expiresat, and an expired row stays as the audit record of what was suppressed and why. Idempotent: the create_table is skipped when the table already exists (e.g. a test DB built by db.create_all()). Revision ID: computers0005policyactionholds Revises: computers0004policies """ from alembic import op import sqlalchemy as sa revision = 'computers0005policyactionholds' down_revision = 'computers0004policies' branch_labels = None depends_on = None def upgrade(): bind = op.get_bind() insp = sa.inspect(bind) existing = set(insp.get_table_names()) if 'policyactionholds' not in existing: op.create_table( 'policyactionholds', sa.Column('policyactionholdid', sa.Integer(), nullable=False), sa.Column('assetid', sa.Integer(), nullable=False), sa.Column('action', sa.String(length=100), nullable=False), sa.Column('expiresat', sa.DateTime(), nullable=False), sa.Column('createdbyuserid', sa.Integer(), nullable=True), sa.Column('createdbyusername', sa.String(length=100), nullable=True), sa.Column('reason', sa.Text(), nullable=False), sa.Column('createddate', sa.DateTime(), nullable=False), sa.Column('modifieddate', sa.DateTime(), nullable=False), sa.Column('isactive', sa.Boolean(), nullable=False, server_default=sa.true()), sa.PrimaryKeyConstraint('policyactionholdid'), sa.ForeignKeyConstraint(['assetid'], ['assets.assetid'], ondelete='CASCADE'), sa.ForeignKeyConstraint(['createdbyuserid'], ['users.userid'], ondelete='SET NULL'), ) op.create_index('idx_policyactionhold_asset', 'policyactionholds', ['assetid']) op.create_index('idx_policyactionhold_expiry', 'policyactionholds', ['expiresat']) def downgrade(): bind = op.get_bind() insp = sa.inspect(bind) existing = set(insp.get_table_names()) if 'policyactionholds' in existing: op.drop_index('idx_policyactionhold_expiry', table_name='policyactionholds') op.drop_index('idx_policyactionhold_asset', table_name='policyactionholds') op.drop_table('policyactionholds')