"""Personal tokens, atomic research requests and minimal MCP audit evidence.""" import sqlalchemy as sa from alembic import op revision = "0010" down_revision = "0009" branch_labels = None depends_on = None def upgrade(): op.create_table( "mcp_tokens", sa.Column("id", sa.String(36), primary_key=True), sa.Column("token_hash", sa.String(64), nullable=False, unique=True), sa.Column("name", sa.String(100), nullable=False), sa.Column("admin_id", sa.Integer(), sa.ForeignKey("admins.id"), nullable=False), sa.Column("account_id", sa.Integer(), sa.ForeignKey("accounts.id"), nullable=False), sa.Column("wq_user_id", sa.String(100), nullable=False), sa.Column("scopes", sa.JSON(), nullable=False), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.Column("expires_at", sa.DateTime(timezone=True), nullable=False), sa.Column("revoked_at", sa.DateTime(timezone=True)), ) op.create_index("ix_mcp_tokens_expires_at", "mcp_tokens", ["expires_at"]) op.create_table( "research_requests", sa.Column("id", sa.String(36), primary_key=True), sa.Column("account_id", sa.Integer(), sa.ForeignKey("accounts.id"), nullable=False), sa.Column("operation", sa.String(50), nullable=False), sa.Column("idempotency_key", sa.String(100), nullable=False), sa.Column("digest", sa.String(64), nullable=False), sa.Column("business_id", sa.String(36), nullable=False), sa.Column("response", sa.JSON(), nullable=False), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.UniqueConstraint("account_id", "operation", "idempotency_key"), ) op.create_table( "mcp_audits", sa.Column("id", sa.String(36), primary_key=True), sa.Column("token_id", sa.String(36), sa.ForeignKey("mcp_tokens.id"), nullable=False), sa.Column("tool", sa.String(100), nullable=False), sa.Column("request_id", sa.String(100), nullable=False), sa.Column("input_digest", sa.String(64), nullable=False), sa.Column("business_id", sa.String(100)), sa.Column("result_code", sa.String(60), nullable=False), sa.Column("elapsed_ms", sa.Integer(), nullable=False), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), ) op.create_index("ix_mcp_audits_token_id", "mcp_audits", ["token_id"]) op.create_index("ix_mcp_audits_created_at", "mcp_audits", ["created_at"]) def downgrade(): op.drop_table("mcp_audits") op.drop_table("research_requests") op.drop_table("mcp_tokens")