Review

Widen BollardBay pier badge UIDs for dual-band RFID

BollardBay marina dock access: new dual-band owner fobs emit 64-char badge UIDs. Production is Postgres (env.py binds postgresql+psycopg). CI still runs migrations against SQLite. This revision widens pier_scans.badge_uid and adds a lookup index so the gate kiosk can resolve fobs under peak Saturday arrivals. Author wrapped everything in batch_alter_table with recreate='always' so 'SQLite and Postgres take the same path' and the alter is 'atomic'.

AlembicTier 4alembicbatch-alterpostgreslocks

Click a line to flag it, pick one or more labels, then submit. If the change looks correct, approve it.

alembic/versions/2026_08_01_widen_pier_badge_uid.py+35-0
1+"""widen pier_scans.badge_uid for dual-band RFID fobs
2+
3+Revision ID: b4dge_uid
4+Revises: a91slip_map
5+"""
6+from alembic import op
7+import sqlalchemy as sa
8+
9+revision = "b4dge_uid"
10+down_revision = "a91slip_map"
11+branch_labels = None
12+depends_on = None
13+
14+
15+def upgrade() -> None:
16+ # One batch path for SQLite CI + Postgres prod; recreate so every alter is atomic.
17+ with op.batch_alter_table("pier_scans", recreate="always") as batch_op:
18+ batch_op.alter_column(
19+ "badge_uid",
20+ existing_type=sa.String(length=32),
21+ type_=sa.String(length=64),
22+ existing_nullable=False,
23+ )
24+ batch_op.create_index("ix_pier_scans_badge_uid", ["badge_uid"])
25+
26+
27+def downgrade() -> None:
28+ with op.batch_alter_table("pier_scans", recreate="always") as batch_op:
29+ batch_op.drop_index("ix_pier_scans_badge_uid")
30+ batch_op.alter_column(
31+ "badge_uid",
32+ existing_type=sa.String(length=64),
33+ type_=sa.String(length=32),
34+ existing_nullable=False,
35+ )