"""cameras table for open-camera discovery Revision ID: 002_cameras Revises: 002_fires Create Date: 2026-08-24 """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects.postgresql import UUID revision = '002_cameras' down_revision = '002_fires' branch_labels = None depends_on = None def upgrade() -> None: op.create_table( 'cameras', sa.Column('id', UUID(as_uuid=True), primary_key=True), sa.Column('url_hash', sa.String(64), nullable=False), sa.Column('source_url', sa.Text(), nullable=False), sa.Column('snapshot_url', sa.Text()), sa.Column('discovery_source', sa.String(128), nullable=False), sa.Column('location_lat', sa.Float()), sa.Column('location_lon', sa.Float()), sa.Column('location_name', sa.String(512)), sa.Column('vendor', sa.String(128)), sa.Column('device_type', sa.String(64)), sa.Column('first_seen', sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False), sa.Column('last_seen', sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False), sa.Column('raw', sa.JSON()), ) op.create_index('ix_cameras_location', 'cameras', ['location_lat', 'location_lon']) op.create_index('ix_cameras_last_seen', 'cameras', ['last_seen']) # Dedupe key. NOTE: cameras is intentionally NOT a Timescale hypertable — # it holds current state per camera (one row per url_hash), not time-series. op.create_index('ix_cameras_url_hash', 'cameras', ['url_hash'], unique=True) def downgrade() -> None: op.drop_table('cameras')