# Migration Consolidation Plan (On-Prem Upgradeable) Date: 2026-02-22 (UTC) Status: Active sprint plan for `MGC-02`, `MGC-03`, and `MGC-12` ## Objective Consolidate StellaOps database migrations to one canonical mechanism and one operational runner entrypoint so upgrades are deterministic for self-hosted and long-lived on-prem installations. ## Canonical Migration Mechanism The canonical mechanism is the shared PostgreSQL migration stack in `src/__Libraries/StellaOps.Infrastructure.Postgres/Migrations/`: - `MigrationRunner` for execution, advisory lock coordination, checksum validation, and migration history. - `StartupMigrationHost` for automatic startup-time migration execution. - `MigrationStatusService` for status inspection. Module discovery for this runner is plug-in based: - One migration module plug-in per web service implementing `src/Platform/__Libraries/StellaOps.Platform.Database/IMigrationModulePlugin.cs`. - Consolidated module registry auto-discovers plug-ins through `src/Platform/__Libraries/StellaOps.Platform.Database/MigrationModulePluginDiscovery.cs`. - Current built-in plug-ins are in `src/Platform/__Libraries/StellaOps.Platform.Database/MigrationModulePlugins.cs`. - Optional external plug-in directories can be injected with `STELLAOPS_MIGRATION_PLUGIN_DIR` (path-list separated by OS path separator). Canonical history table format is: - `.schema_migrations` - Required columns: `migration_name`, `category`, `checksum`, `applied_at`, `applied_by`, `duration_ms` ## Canonical Migration Types and Numbering Only these categories are valid: - `startup`: automatic; prefix `001-099` - `release`: manual gate; prefix `100+` - `seed`: automatic; prefix `S001-S999` - `data`: manual/background; prefix `DM001-DM999` Naming standard: - `NNN_description.sql` - `SNNN_description.sql` - `DMNNN_description.sql` Legacy naming is allowed only for already shipped files. New migrations must follow the canonical format. ## Canonical Runner Entrypoint Policy Upgrade and deployment gate entrypoint: - `stella system migrations-status --module all` - `stella system migrations-verify --module all` - `stella system migrations-run --module all --category release --dry-run` - `stella system migrations-run --module all --category release --force` Startup behavior: - Services may run only `startup` and `seed` categories automatically through `StartupMigrationHost` / `AddStartupMigrations(...)`. - Pending `release` or `data` migrations must block startup when startup migration hosts are enabled. Compose/bootstrap behavior: - `devops/compose/postgres-init` remains bootstrap-only (first initialization). - Release upgrades must never rely on `docker-entrypoint-initdb.d`; they must use the canonical CLI entrypoint. UI/API execution path (implemented): - Module registry ownership is platform-level: `src/Platform/__Libraries/StellaOps.Platform.Database/MigrationModuleRegistry.cs`. - UI-triggered migration execution must call Platform WebService administrative APIs (no browser-direct database execution). - Platform endpoint contract: - `GET /api/v1/admin/migrations/modules` - `GET /api/v1/admin/migrations/status?module=` - `GET /api/v1/admin/migrations/verify?module=` - `POST /api/v1/admin/migrations/run` - Endpoint authorization policy: `platform.setup.admin` (`PlatformPolicies.SetupAdmin`). - Endpoint implementation and server-side runner path: - `src/Platform/StellaOps.Platform.WebService/Endpoints/MigrationAdminEndpoints.cs` - `src/Platform/StellaOps.Platform.WebService/Services/PlatformMigrationAdminService.cs` ## Legacy Compatibility Mapping The following non-canonical history tables must be migrated to `.schema_migrations` via one-time compatibility scripts/adapters: | Module | Legacy history table | Mapping target | | --- | --- | --- | | EvidenceLocker | `evidence_locker.evidence_schema_version` | `evidence_locker.schema_migrations` | | ExportCenter | `export_center.export_schema_version` | `export_center.schema_migrations` | | BinaryIndex | `binaries.schema_migrations` (`name`, `applied_at`) | `binaries.schema_migrations` canonical columns | | Plugin Registry | `.plugin_migrations` | `.schema_migrations` | Compatibility rules: - Preserve applied order and timestamps. - Preserve or derive deterministic checksums for already-applied scripts. - Never rewrite already-applied migration file contents. ## Cutover Waves (Runner Entrypoint Consolidation) | Wave | Goal | Module Set | Current Mechanism | Target Mechanism | Rollback Marker | | --- | --- | --- | --- | --- | --- | | W0 | Governance baseline | Docs + CLI contract | Mixed | Canonical policy published | Docs and runbooks merged | | W1 | Expand CLI/shared-runner coverage | Authority, Scheduler, Concelier, Policy, Notify, Excititor, Scanner, AirGap, TimelineIndexer, ReleaseOrchestrator | Shared runner partial coverage | Canonical CLI entrypoint for all shared-runner modules | `migrations-status` parity before/after | | W2 | Convert custom history runners | EvidenceLocker, ExportCenter, BinaryIndex, Plugin Registry | Custom runners/history tables | Shared `MigrationRunner` with compatibility mapping | Legacy table snapshot and compare report | | W3 | Wire currently unwired migration folders | Modules marked unwired in `docs/db/MIGRATION_INVENTORY.md` | Embedded SQL without runtime invocation | Shared runner via startup/CLI registration | Per-module dry-run evidence | | W4 | Count consolidation/baselining | High-count modules (for example Platform release scripts) | Long historical chains | Approved baseline/squash strategy | Rehearsed upgrade from previous GA | | W5 | On-prem rehearsal gate | Full product stack | Mixed in-flight state | Canonical entrypoint only | Deterministic replay report | ## Migration Count Consolidation Rules - Baseline/squash is allowed only after: - at least one release where compatibility mappings are shipped, - deterministic replay tests pass for clean install and upgrade paths, - installed-version compatibility window is documented. - A baseline migration must not remove upgradeability from supported in-field versions. - Squash output must retain checksum determinism and clear mapping to superseded migration ranges. ## EF Core v10 Phase Gate The Dapper-to-EF Core v10 transition starts only after waves W1-W5 complete and gate evidence is accepted. Exit criteria before EF phase opens: - One canonical migration mechanism in production paths. - One canonical operational entrypoint in runbooks and CI/CD automation. - Legacy history tables mapped and validated. - Migration replay determinism proven for clean install and upgrade scenarios.