"""baseline schema The schema as it stands, in one portable revision. The ten that came before built it up on Postgres — with `uuid-ossp`, sequences and `setval` in them — and none of them could run on SQLite, which is now the default. The history they recorded is in git; what a database needs is the shape. Revision ID: ee1b4b4426a3 Revises: Create Date: 2026-08-21 """ import sqlalchemy as sa import sqlmodel.sql.sqltypes from alembic import op # revision identifiers, used by Alembic. revision = "ee1b4b4426a3" down_revision = None branch_labels = None depends_on = None def upgrade(): op.create_table( "engine_event", sa.Column("id", sa.Integer(), nullable=False), sa.Column("ts", sa.DateTime(timezone=True), nullable=False), sa.Column("type", sqlmodel.sql.sqltypes.AutoString(length=32), nullable=False), sa.Column("flow", sqlmodel.sql.sqltypes.AutoString(), nullable=False), sa.Column("node", sqlmodel.sql.sqltypes.AutoString(), nullable=False), sa.Column("detail", sqlmodel.sql.sqltypes.AutoString(), nullable=False), sa.Column("actor", sqlmodel.sql.sqltypes.AutoString(), nullable=False), sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("engine_event", schema=None) as batch_op: batch_op.create_index(batch_op.f("ix_engine_event_ts"), ["ts"], unique=False) batch_op.create_index( batch_op.f("ix_engine_event_type"), ["type"], unique=False ) op.create_table( "flow_run", sa.Column("id", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False), sa.Column("flow", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False), sa.Column("source", sqlmodel.sql.sqltypes.AutoString(), nullable=False), sa.Column("started_at", sa.DateTime(timezone=True), nullable=False), sa.Column("finished_at", sa.DateTime(timezone=True), nullable=True), sa.Column("status", sqlmodel.sql.sqltypes.AutoString(), nullable=False), sa.Column("nodes", sa.Integer(), nullable=False), sa.Column("errors", sa.Integer(), nullable=False), sa.Column("duration_ms", sa.Float(), nullable=False), sa.Column("deliveries", sa.Integer(), nullable=False), sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("flow_run", schema=None) as batch_op: batch_op.create_index(batch_op.f("ix_flow_run_flow"), ["flow"], unique=False) batch_op.create_index( batch_op.f("ix_flow_run_started_at"), ["started_at"], unique=False ) op.create_table( "metric_minute", sa.Column("flow", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False), sa.Column("node", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False), sa.Column("bucket", sa.DateTime(timezone=True), nullable=False), sa.Column("executions", sa.Integer(), nullable=False), sa.Column("errors", sa.Integer(), nullable=False), sa.Column("messages", sa.Integer(), nullable=False), sa.Column("duration_sum_ms", sa.Float(), nullable=False), sa.Column("duration_max_ms", sa.Float(), nullable=False), sa.Column("lag_sum_ms", sa.Float(), nullable=False), sa.Column("lag_max_ms", sa.Float(), nullable=False), sa.Column("items", sa.Integer(), nullable=False), sa.PrimaryKeyConstraint("flow", "node", "bucket"), ) with op.batch_alter_table("metric_minute", schema=None) as batch_op: batch_op.create_index( batch_op.f("ix_metric_minute_bucket"), ["bucket"], unique=False ) op.create_table( "oauth_client", sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "client_name", sqlmodel.sql.sqltypes.AutoString(length=128), nullable=False ), sa.Column("redirect_uris", sa.JSON(), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.PrimaryKeyConstraint("id"), ) op.create_table( "run", sa.Column("id", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False), sa.Column("flow", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False), sa.Column("flow_version", sa.Integer(), nullable=False), sa.Column( "commit", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.Column("params", sa.JSON(), nullable=True), sa.Column( "params_digest", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.Column("seed", sa.Integer(), nullable=True), sa.Column( "group_id", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=True ), sa.Column( "parent_id", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=True ), sa.Column("cause", sqlmodel.sql.sqltypes.AutoString(length=32), nullable=False), sa.Column( "status", sqlmodel.sql.sqltypes.AutoString(length=16), nullable=False ), sa.Column( "status_reason", sqlmodel.sql.sqltypes.AutoString(length=1024), nullable=False, ), sa.Column("labels", sa.JSON(), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.Column("started_at", sa.DateTime(timezone=True), nullable=True), sa.Column("finished_at", sa.DateTime(timezone=True), nullable=True), sa.Column("duration_ms", sa.Float(), nullable=False), sa.Column("result", sa.JSON(), nullable=True), sa.Column( "engine", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.Column("lease_at", sa.DateTime(timezone=True), nullable=True), sa.Column( "actor", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False ), sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("run", schema=None) as batch_op: batch_op.create_index( batch_op.f("ix_run_created_at"), ["created_at"], unique=False ) batch_op.create_index(batch_op.f("ix_run_flow"), ["flow"], unique=False) batch_op.create_index(batch_op.f("ix_run_group_id"), ["group_id"], unique=False) batch_op.create_index( batch_op.f("ix_run_params_digest"), ["params_digest"], unique=False ) batch_op.create_index(batch_op.f("ix_run_status"), ["status"], unique=False) op.create_table( "run_artifact", sa.Column( "run_id", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.Column("name", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False), sa.Column("node", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False), sa.Column( "digest", sqlmodel.sql.sqltypes.AutoString(length=71), nullable=False ), sa.Column("size", sa.Integer(), nullable=False), sa.Column( "media_type", sqlmodel.sql.sqltypes.AutoString(length=128), nullable=False ), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.PrimaryKeyConstraint("run_id", "name"), ) with op.batch_alter_table("run_artifact", schema=None) as batch_op: batch_op.create_index( batch_op.f("ix_run_artifact_digest"), ["digest"], unique=False ) op.create_table( "run_metric", sa.Column( "run_id", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.Column("name", sqlmodel.sql.sqltypes.AutoString(length=128), nullable=False), sa.Column("step", sa.Integer(), nullable=False), sa.Column("node", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False), sa.Column("ts", sa.Float(), nullable=False), sa.Column("value", sa.Float(), nullable=False), sa.PrimaryKeyConstraint("run_id", "name", "step"), ) op.create_table( "run_node", sa.Column( "run_id", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.Column("node", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False), sa.Column( "status", sqlmodel.sql.sqltypes.AutoString(length=16), nullable=False ), sa.Column("attempt", sa.Integer(), nullable=False), sa.Column("started_at", sa.DateTime(timezone=True), nullable=True), sa.Column("duration_ms", sa.Float(), nullable=False), sa.Column( "worker", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.Column("error", sqlmodel.sql.sqltypes.AutoString(), nullable=False), sa.Column("logs", sqlmodel.sql.sqltypes.AutoString(), nullable=False), sa.Column( "cache_key", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.PrimaryKeyConstraint("run_id", "node"), ) with op.batch_alter_table("run_node", schema=None) as batch_op: batch_op.create_index( batch_op.f("ix_run_node_cache_key"), ["cache_key"], unique=False ) op.create_table( "user", sa.Column( "email", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False ), sa.Column("is_active", sa.Boolean(), nullable=False), sa.Column("is_superuser", sa.Boolean(), nullable=False), sa.Column( "full_name", sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True ), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "hashed_password", sqlmodel.sql.sqltypes.AutoString(), nullable=False ), sa.Column( "portal_sub", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=True ), sa.Column("created_at", sa.DateTime(timezone=True), nullable=True), sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("user", schema=None) as batch_op: batch_op.create_index(batch_op.f("ix_user_email"), ["email"], unique=True) batch_op.create_index( batch_op.f("ix_user_portal_sub"), ["portal_sub"], unique=True ) op.create_table( "oauth_authorization_code", sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "code_hash", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.Column("client_id", sa.Uuid(), nullable=False), sa.Column("user_id", sa.Uuid(), nullable=False), sa.Column( "redirect_uri", sqlmodel.sql.sqltypes.AutoString(length=2048), nullable=False, ), sa.Column( "code_challenge", sqlmodel.sql.sqltypes.AutoString(length=128), nullable=False, ), sa.Column( "resource", sqlmodel.sql.sqltypes.AutoString(length=2048), nullable=True ), sa.Column("expires_at", sa.DateTime(timezone=True), nullable=False), sa.Column("used_at", sa.DateTime(timezone=True), nullable=True), sa.Column("refresh_token_id", sa.Uuid(), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.ForeignKeyConstraint(["client_id"], ["oauth_client.id"], ondelete="CASCADE"), sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="CASCADE"), sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("oauth_authorization_code", schema=None) as batch_op: batch_op.create_index( batch_op.f("ix_oauth_authorization_code_code_hash"), ["code_hash"], unique=True, ) op.create_table( "oauth_refresh_token", sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "token_hash", sqlmodel.sql.sqltypes.AutoString(length=64), nullable=False ), sa.Column("client_id", sa.Uuid(), nullable=False), sa.Column("user_id", sa.Uuid(), nullable=False), sa.Column("family_id", sa.Uuid(), nullable=False), sa.Column("expires_at", sa.DateTime(timezone=True), nullable=False), sa.Column("revoked", sa.Boolean(), nullable=False), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.ForeignKeyConstraint(["client_id"], ["oauth_client.id"], ondelete="CASCADE"), sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="CASCADE"), sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("oauth_refresh_token", schema=None) as batch_op: batch_op.create_index( batch_op.f("ix_oauth_refresh_token_token_hash"), ["token_hash"], unique=True ) def downgrade(): with op.batch_alter_table("oauth_refresh_token", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_oauth_refresh_token_token_hash")) op.drop_table("oauth_refresh_token") with op.batch_alter_table("oauth_authorization_code", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_oauth_authorization_code_code_hash")) op.drop_table("oauth_authorization_code") with op.batch_alter_table("user", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_user_portal_sub")) batch_op.drop_index(batch_op.f("ix_user_email")) op.drop_table("user") with op.batch_alter_table("run_node", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_run_node_cache_key")) op.drop_table("run_node") op.drop_table("run_metric") with op.batch_alter_table("run_artifact", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_run_artifact_digest")) op.drop_table("run_artifact") with op.batch_alter_table("run", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_run_status")) batch_op.drop_index(batch_op.f("ix_run_params_digest")) batch_op.drop_index(batch_op.f("ix_run_group_id")) batch_op.drop_index(batch_op.f("ix_run_flow")) batch_op.drop_index(batch_op.f("ix_run_created_at")) op.drop_table("run") op.drop_table("oauth_client") with op.batch_alter_table("metric_minute", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_metric_minute_bucket")) op.drop_table("metric_minute") with op.batch_alter_table("flow_run", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_flow_run_started_at")) batch_op.drop_index(batch_op.f("ix_flow_run_flow")) op.drop_table("flow_run") with op.batch_alter_table("engine_event", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_engine_event_type")) batch_op.drop_index(batch_op.f("ix_engine_event_ts")) op.drop_table("engine_event")