"""M0 domain foundation. Revision ID: 20260824_0001 Revises: None """ import sqlalchemy as sa from alembic import op from modelforge_api.persistence.models import Base revision = "20260824_0001" down_revision = None branch_labels = None depends_on = None def upgrade() -> None: # The declarative metadata is the reviewed M0 schema contract. create_all is # used only from this baseline migration; later changes require explicit ops. Base.metadata.create_all(bind=op.get_bind(), checkfirst=False) # BenchmarkRun was part of M0. The evolving metadata also contains RC-LAB-02's later # capability-target, actor/idempotency and environment fields, so rebuild its original # shape here; migration 0039 adds those fields at the correct historical boundary. op.drop_table("benchmark_runs") op.create_table( "benchmark_runs", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("deployment_id", sa.Uuid(), nullable=False), sa.Column("suite_id", sa.Uuid(), nullable=False), sa.Column("model_revision_sha", sa.String(length=64), nullable=False), sa.Column("artifact_sha256", sa.String(length=64), nullable=False), sa.Column("runtime_type", sa.String(length=32), nullable=False), sa.Column("runtime_version", sa.String(length=128), nullable=False), sa.Column("runtime_image_digest", sa.String(length=71), nullable=True), sa.Column("launch_arguments", sa.JSON(), nullable=False), sa.Column("suite_revision", sa.String(length=128), nullable=False), sa.Column("dataset_revision", sa.String(length=255), nullable=False), sa.Column("environment_fingerprint", sa.JSON(), nullable=False), sa.Column("environment_digest", sa.String(length=64), nullable=False), sa.Column("seed", sa.Integer(), nullable=True), sa.Column("results", sa.JSON(), nullable=False), sa.Column("status", sa.String(length=32), nullable=False), sa.Column("comparable", sa.Boolean(), nullable=False), sa.Column("stale_reason", sa.Text(), nullable=True), sa.Column("started_at", sa.DateTime(timezone=True), nullable=False), sa.Column("completed_at", sa.DateTime(timezone=True), nullable=True), sa.ForeignKeyConstraint(["deployment_id"], ["deployments.id"], ondelete="RESTRICT"), sa.ForeignKeyConstraint(["suite_id"], ["benchmark_suites.id"], ondelete="RESTRICT"), sa.PrimaryKeyConstraint("id"), ) op.create_index("ix_benchmark_runs_deployment_id", "benchmark_runs", ["deployment_id"]) op.create_index("ix_benchmark_runs_suite_id", "benchmark_runs", ["suite_id"]) op.create_index("ix_benchmark_runs_artifact_sha256", "benchmark_runs", ["artifact_sha256"]) op.create_index( "ix_benchmark_runs_environment_digest", "benchmark_runs", ["environment_digest"] ) op.create_index( "ix_benchmark_runs_deployment_completed", "benchmark_runs", ["deployment_id", "completed_at"], ) op.drop_constraint("ck_capability_serving_generation", "capability_contracts", type_="check") op.drop_column("capability_contracts", "serving_generation") # Freeze the original M0 shape even though the declarative metadata evolves. # Remove newer foreign-key columns before dropping the tables they target. for column in ( "profile_config", "health_contract", "device_policy", "modality", "dtype", "version", "artifact_set_id", "runtime_environment_id", ): op.drop_column("runtime_profiles", column) for table in ( # Later milestone tables are present in the evolving declarative metadata # used to build this baseline. Drop dependants before their M5/M0 targets # so a fresh upgrade still reconstructs each historical revision exactly. "model_change_cases", "selected_model_comparisons", "external_creative_action_attestations", "external_creative_profile_observations", "external_creative_resources", "external_creative_allocations", "model_update_notices", "model_update_watches", "portfolio_repository_observations", "portfolio_reconciliation_runs", "platform_secret_activations", "platform_secret_tests", "platform_secret_versions", "platform_secret_state", "managed_operator_credential_activations", "managed_operator_credentials", "managed_operator_identities", "managed_operator_state", "configuration_revisions", "project_onboarding", "configuration_state", "audit_chain_heads", "node_decommission_operations", # M15 recovery tables come first: artifact_recovery_operations references # artifact_jobs, download_plans, artifact_sets, model_revisions and storage_roots, # all of which are dropped further down this list. "artifact_recovery_operations", "restore_operation_events", "restore_operations", "restore_plans", "backup_manifest_entries", "backup_sets", "recovery_asset_records", "recovery_policy_revisions", "incident_timeline_events", # The M37 outbox restricts deletion of its alert history parent. "alert_notification_deliveries", "alert_history_events", "operational_alerts", "operational_incidents", "maintenance_windows", "alert_rule_revisions", "slo_evaluations", "slo_policy_revisions", "service_level_indicators", "capacity_aggregates", "capacity_snapshots", "migration_events", "migration_cutover_operations", "migration_rollback_snapshots", "migration_shadow_sessions", "migration_validation_snapshots", "migration_batch_checkpoints", "migration_plans", "migration_validation_policy_revisions", "artifact_location_removal_records", "lifecycle_canary_runs", "lifecycle_operations", "lifecycle_rollback_snapshots", "lifecycle_promotion_plans", "lifecycle_approval_evidence", "lifecycle_approval_requests", "lifecycle_cleanup_plans", "lifecycle_retention_records", "retention_policy_revisions", "lifecycle_events", "lifecycle_policy_revisions", "lifecycle_subjects", "project_fit_evidence", "scheduler_evictions", "co_residency_evidence", "placement_plans", "scheduler_policy_revisions", "scheduler_accelerator_states", "capability_evaluation_runs", "capability_evaluation_suites", "reranking_case_results", "reranking_evaluation_runs", "retrieval_candidate_pools", "advisor_recommendations", "retrieval_pipeline_identities", "discovery_candidate_assessments", "advisor_policies", "model_comparisons", "evaluation_comparisons", "evaluation_case_results", "evaluation_runs", "evaluation_cases", "evaluation_suite_revisions", "evaluation_suites", "embedding_migrations", "project_evaluation_bindings", "serving_gpu_leases", "serving_jobs", # M38 durable LAB history owns a restrictive reference to gateway_requests; # drop it before the M0 gateway table while reconstructing the historical baseline. "lab_execution_runs", "gateway_requests", "residency_allocations", "service_credentials", "service_clients", "capability_resource_envelopes", "capability_experiment_routes", "capability_deployments", "embedding_spaces", "production_execution_approvals", "deployment_candidates", "runtime_probe_metrics", "runtime_probes", "execution_approvals", "runtime_compatibility_assessments", "artifact_set_members", "artifact_inspections", "artifact_job_attempts", "artifact_jobs", "download_plan_files", "download_plans", "artifact_sets", "upstream_files", "upstream_snapshots", "artifact_locations", "derived_artifact_sources", "storage_roots", ): op.drop_table(table) op.drop_table("runtime_environments") for column in ("source_type", "upstream_metadata", "local_metadata", "interpretation_metadata", "description"): op.drop_column("models", column) op.drop_column("model_revisions", "archived_at") op.drop_column("audit_events", "canonical_payload") op.drop_column("audit_events", "hash_format") for column in ("status", "verification_details", "archived_at"): op.drop_column("model_artifacts", column) for column in ("transformation_type", "environment_snapshot", "status", "verification_details"): op.drop_column("derived_artifacts", column) for table in ( "node_credentials", "node_enrollments", "hardware_inventory_runs", "storage_volume_states", "accelerator_telemetry_latest", "host_telemetry_latest", ): op.drop_table(table) for column in ( "inventory_at", "last_seen_at", "first_seen_at", "inventory_source", "status_reason", "status", "mig_mode_current", "total_vram_bytes", "compute_capability_minor", "compute_capability_major", "architecture", "vendor", "pci_bus_id", ): op.drop_column("accelerators", column) for column in ( "decommissioned_by", "decommission_reason", "decommissioned_at", "generation", "telemetry_sequence", "inventory_sequence", "last_connection_error", "last_telemetry_observed_at", "last_telemetry_received_at", "last_inventory_observed_at", "last_inventory_received_at", "last_heartbeat_at", "agent_started_at", "agent_capabilities", "agent_protocol_version", "liveness_state", "observation_source", "benchmark_eligible", "lab_eligible", "production_eligible", "labels", "role", "enabled", ): op.drop_column("compute_nodes", column) for column in ( "inventory_at", "first_seen_at", "status_reason", "agent_version", "total_ram_bytes", "physical_core_count", "logical_cpu_count", "cpu_model", "kernel_version", "architecture", "os_version", "os_name", "identity_source", "display_name", ): op.drop_column("compute_nodes", column) def downgrade() -> None: existing = set(sa.inspect(op.get_bind()).get_table_names()) for table in reversed(Base.metadata.sorted_tables): if table.name in existing: op.drop_table(table.name)