"""fiscal_certificates: partial-unique live index scoped by tenant_ref too (FIX 2, F2 review, 2026-07-17-sowai-fiscal-svc-design.md decisão #4) -- `ix_fiscal_certificates_product_branch_live` (`(product_id, branch_ref) WHERE deleted_at IS NULL`) let two DIFFERENT tenants of the SAME product reusing an identical opaque `branch_ref` (e.g. both `"matriz"`) collapse onto the SAME certificate slot: the second tenant's upload soft-deleted the first tenant's still-live certificate as a legitimate "replace" instead of a 409 conflict, and emission for the first tenant would go on to sign with the second tenant's certificate. Replaces the index with one scoped `(product_id, tenant_ref, branch_ref) WHERE deleted_at IS NULL` -- matching `fiscal_series`'s own tenant-scoped uniqueness and the GET/DELETE certificate lookups, which already filtered by `tenant_ref`. Revision ID: 8f1a2c9d4b6e Revises: 30a80fe36910 Create Date: 2026-07-24 00:00:00.000000 """ from __future__ import annotations from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "8f1a2c9d4b6e" down_revision: Union[str, Sequence[str], None] = "30a80fe36910" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.drop_index("ix_fiscal_certificates_product_branch_live", table_name="fiscal_certificates") op.create_index( "ix_fiscal_certificates_product_tenant_branch_live", "fiscal_certificates", ["product_id", "tenant_ref", "branch_ref"], unique=True, postgresql_where=sa.text("deleted_at IS NULL"), ) def downgrade() -> None: op.drop_index( "ix_fiscal_certificates_product_tenant_branch_live", table_name="fiscal_certificates" ) op.create_index( "ix_fiscal_certificates_product_branch_live", "fiscal_certificates", ["product_id", "branch_ref"], unique=True, postgresql_where=sa.text("deleted_at IS NULL"), )