"""add download_jobs.error_code — a category for a failed download (S2) The worker already stores the raw yt-dlp/ffmpeg failure text in `download_jobs.error`. This adds a small category code (`unavailable` / `login_required` / `geo_blocked` / `format_unavailable` / `drm` / `postprocess` / `source_missing` / `network` / `unknown`) computed by `app.downloads.errors.classify`, so the UI can show a clean localized explanation and decide whether a retry makes sense, keeping the raw text as a technical-detail disclosure. Nullable; only set on the error path. Forward-only — an existing errored row simply has NULL until its next failure/retry. """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "0061_dl_job_error_code" down_revision: Union[str, None] = "0060_plex_jsonb_null_normalize" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.add_column("download_jobs", sa.Column("error_code", sa.String(length=24), nullable=True)) def downgrade() -> None: op.drop_column("download_jobs", "error_code")