"""add controlled first-administrator enrollment evidence Revision ID: f25c9d3e7a01 Revises: e14b8c2d6f90 Create Date: 2026-08-04 00:00:00.000000 """ from __future__ import annotations from alembic import op import sqlalchemy as sa revision = "f25c9d3e7a01" down_revision = "e14b8c2d6f90" branch_labels = None depends_on = None def upgrade() -> None: inspector = sa.inspect(op.get_bind()) tables = set(inspector.get_table_names()) if "core_first_admin_enrollments" not in tables: op.create_table( "core_first_admin_enrollments", sa.Column("installation_id", sa.String(length=100), nullable=False), sa.Column("state", sa.String(length=24), nullable=False), sa.Column("generation", sa.Integer(), nullable=False), sa.Column("token_sha256", sa.String(length=64), nullable=True), sa.Column("token_fingerprint", sa.String(length=16), nullable=True), sa.Column("issued_at", sa.DateTime(timezone=True), nullable=True), sa.Column("expires_at", sa.DateTime(timezone=True), nullable=True), sa.Column("consumed_at", sa.DateTime(timezone=True), nullable=True), sa.Column("consumed_account_id", sa.String(length=36), nullable=True), sa.Column("consumed_membership_id", sa.String(length=36), nullable=True), sa.Column("consumed_tenant_id", sa.String(length=36), nullable=True), sa.Column("consumed_email", sa.String(length=320), nullable=True), sa.Column("consumed_display_name", sa.String(length=255), nullable=True), sa.Column("consumed_request_sha256", sa.String(length=64), nullable=True), sa.Column("issue_reason", sa.String(length=500), nullable=True), sa.Column("event_count", sa.Integer(), nullable=False), sa.Column("evidence_head_sha256", sa.String(length=64), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False), sa.PrimaryKeyConstraint( "installation_id", name=op.f("pk_core_first_admin_enrollments"), ), ) op.create_index( op.f("ix_core_first_admin_enrollments_state"), "core_first_admin_enrollments", ["state"], unique=False, ) op.create_index( op.f("ix_core_first_admin_enrollments_expires_at"), "core_first_admin_enrollments", ["expires_at"], unique=False, ) inspector = sa.inspect(op.get_bind()) tables = set(inspector.get_table_names()) if "core_first_admin_enrollment_events" not in tables: op.create_table( "core_first_admin_enrollment_events", sa.Column("id", sa.String(length=36), nullable=False), sa.Column("installation_id", sa.String(length=100), nullable=False), sa.Column("sequence", sa.Integer(), nullable=False), sa.Column("event_type", sa.String(length=80), nullable=False), sa.Column("generation", sa.Integer(), nullable=False), sa.Column("evidence", sa.JSON(), nullable=False), sa.Column("previous_sha256", sa.String(length=64), nullable=True), sa.Column("event_sha256", sa.String(length=64), nullable=False), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.ForeignKeyConstraint( ["installation_id"], ["core_first_admin_enrollments.installation_id"], name=op.f( "fk_core_first_admin_enrollment_events_installation_id_core_first_admin_enrollments" ), ondelete="CASCADE", ), sa.PrimaryKeyConstraint( "id", name=op.f("pk_core_first_admin_enrollment_events"), ), sa.UniqueConstraint( "installation_id", "sequence", name="uq_core_first_admin_enrollment_event_sequence", ), ) for column in ("installation_id", "event_type", "event_sha256"): op.create_index( op.f(f"ix_core_first_admin_enrollment_events_{column}"), "core_first_admin_enrollment_events", [column], unique=False, ) def downgrade() -> None: inspector = sa.inspect(op.get_bind()) tables = set(inspector.get_table_names()) if "core_first_admin_enrollment_events" in tables: op.drop_table("core_first_admin_enrollment_events") if "core_first_admin_enrollments" in tables: op.drop_table("core_first_admin_enrollments")