"""attachments are kept once: inside their message An attachment used to be stored twice — inside the raw message blob, and again as a blob of its own. Now only the raw message is kept; ``part_index`` says which MIME part of it (its position in a walk of the message) holds the attachment, so it can be taken out when downloaded. ``blob_sha256`` stays: the attachment's content hash, which names its thumbnail and checks what is taken out. Rows stored before this have no index; they are found by that hash. Existing separate copies are removed by a background pass on the worker (app/indexer/attachments.py ``dedupe_existing``), only after checking each one can be taken out of its message again. Revision ID: 0023 Revises: 0022 Create Date: 2026-10-08 """ from __future__ import annotations from collections.abc import Sequence from alembic import op revision: str = "0023" down_revision: str | None = "0022" branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None def upgrade() -> None: op.execute("ALTER TABLE attachments ADD COLUMN part_index integer") def downgrade() -> None: op.execute("ALTER TABLE attachments DROP COLUMN IF EXISTS part_index")