"""Add integrity_status + integrity_checked_at to image_record. Tracks per-image structural verification state so corrupt files (truncated downloads, broken containers, partial archives) can be flagged and excluded from random/showcase/ML/suggestion paths instead of blowing up downstream preprocessing. Status values: - unknown: never verified (default for existing rows + freshly imported until the verifier runs) - ok: passed marker check + format-level verify - truncated: missing trailing bytes (PIL EOI/IEND, ffprobe end-of-stream) - unreadable: header/structure invalid; can't even open the file - missing: filepath doesn't exist on disk Revision ID: l26042501 Revises: k26042201 Create Date: 2026-04-25 """ from __future__ import annotations from alembic import op import sqlalchemy as sa revision = 'l26042501' down_revision = 'k26042201' branch_labels = None depends_on = None def upgrade(): op.add_column( 'image_record', sa.Column( 'integrity_status', sa.String(16), nullable=False, server_default='unknown', ), ) op.add_column( 'image_record', sa.Column( 'integrity_checked_at', sa.DateTime(timezone=True), nullable=True, ), ) # Partial index so the "list flagged rows" report and the # exclude-from-random/ML filters stay cheap on a million-row table. op.create_index( 'image_record_integrity_status_idx', 'image_record', ['integrity_status'], postgresql_where=sa.text("integrity_status <> 'ok'"), ) def downgrade(): op.drop_index('image_record_integrity_status_idx', table_name='image_record') op.drop_column('image_record', 'integrity_checked_at') op.drop_column('image_record', 'integrity_status')