Skip to main content

microsandbox_migration/
schema_metadata.rs

1//! Static metadata for downgrade planning.
2//!
3//! `Migrator::migrations()` owns the executable migration order. This module
4//! keeps the user-facing downgrade metadata in the same crate so release checks
5//! can ensure every migration has an explicit reversibility and cache-impact
6//! decision before a new binary ships.
7
8//--------------------------------------------------------------------------------------------------
9// Constants
10//--------------------------------------------------------------------------------------------------
11
12/// Version of the hidden schema-baseline JSON shape emitted by the CLI.
13pub const SCHEMA_BASELINE_FORMAT_VERSION: u32 = 1;
14
15/// Oldest release supported by the downgrade flow.
16pub const DOWNGRADE_FLOOR: &str = "0.6.0";
17
18/// Migration that introduced the DB-backed maintenance lease table.
19pub const MAINTENANCE_LEASE_MIGRATION_ID: &str = "m20260621_000002_create_maintenance_lease";
20
21/// Migration that introduced desired-vs-active sandbox config tracking.
22pub const ACTIVE_CONFIG_MIGRATION_ID: &str = "m20260703_000001_add_sandbox_active_config";
23
24/// Frozen migration baseline for the transitional 0.6.0 release.
25///
26/// The released 0.6.0 binary predates `msb __schema-baseline --json`, so
27/// downgrade uses this fixture when inspecting that exact target. Do not extend
28/// this list when adding later migrations; future targets should answer with
29/// their own hidden baseline command.
30pub const BASELINE_0_6_0_MIGRATIONS: &[&str] = &[
31    "m20260305_000001_create_image_tables",
32    "m20260305_000002_create_sandbox_tables",
33    "m20260305_000003_create_storage_tables",
34    "m20260305_000004_create_sandbox_images_table",
35    "m20260410_000001_erofs_image_schema",
36    "m20260501_000001_create_snapshot_index",
37    "m20260517_000001_drop_sandbox_metric",
38    "m20260527_000001_migrate_oci_rootfs_source",
39    "m20260531_000001_create_sandbox_labels",
40    "m20260531_000002_index_sandbox_labels_key_value",
41    "m20260606_000001_named_volume_kinds",
42    "m20260621_000001_add_sandbox_ephemeral",
43    MAINTENANCE_LEASE_MIGRATION_ID,
44];
45
46/// Metadata for every migration in `Migrator::migrations()` order.
47pub const MIGRATION_METADATA: &[MigrationMetadata] = &[
48    MigrationMetadata {
49        id: "m20260305_000001_create_image_tables",
50        reversible: true,
51        affects_cache: true,
52        affects_user_data: false,
53        summary: "remove legacy OCI image catalog tables",
54    },
55    MigrationMetadata {
56        id: "m20260305_000002_create_sandbox_tables",
57        reversible: true,
58        affects_cache: false,
59        affects_user_data: false,
60        summary: "remove sandbox and run tables",
61    },
62    MigrationMetadata {
63        id: "m20260305_000003_create_storage_tables",
64        reversible: true,
65        affects_cache: false,
66        affects_user_data: false,
67        summary: "remove volume and snapshot storage tables",
68    },
69    MigrationMetadata {
70        id: "m20260305_000004_create_sandbox_images_table",
71        reversible: true,
72        affects_cache: true,
73        affects_user_data: false,
74        summary: "remove sandbox image references",
75    },
76    MigrationMetadata {
77        id: "m20260410_000001_erofs_image_schema",
78        reversible: true,
79        affects_cache: true,
80        affects_user_data: false,
81        summary: "remove EROFS rootfs catalog tables",
82    },
83    MigrationMetadata {
84        id: "m20260501_000001_create_snapshot_index",
85        reversible: true,
86        affects_cache: false,
87        affects_user_data: false,
88        summary: "remove snapshot index table",
89    },
90    MigrationMetadata {
91        id: "m20260517_000001_drop_sandbox_metric",
92        reversible: false,
93        affects_cache: false,
94        affects_user_data: false,
95        summary: "restore legacy sandbox metrics table",
96    },
97    MigrationMetadata {
98        id: "m20260527_000001_migrate_oci_rootfs_source",
99        reversible: false,
100        affects_cache: false,
101        affects_user_data: false,
102        summary: "rewrite OCI rootfs config back to the legacy string shape",
103    },
104    MigrationMetadata {
105        id: "m20260531_000001_create_sandbox_labels",
106        reversible: true,
107        affects_cache: false,
108        affects_user_data: false,
109        summary: "remove sandbox labels table",
110    },
111    MigrationMetadata {
112        id: "m20260531_000002_index_sandbox_labels_key_value",
113        reversible: true,
114        affects_cache: false,
115        affects_user_data: false,
116        summary: "remove sandbox label key/value index",
117    },
118    MigrationMetadata {
119        id: "m20260606_000001_named_volume_kinds",
120        reversible: true,
121        affects_cache: false,
122        affects_user_data: false,
123        summary: "remove named volume kind columns and attachments",
124    },
125    MigrationMetadata {
126        id: "m20260621_000001_add_sandbox_ephemeral",
127        reversible: true,
128        affects_cache: false,
129        affects_user_data: false,
130        summary: "remove sandbox ephemeral flag",
131    },
132    MigrationMetadata {
133        id: MAINTENANCE_LEASE_MIGRATION_ID,
134        reversible: true,
135        affects_cache: false,
136        affects_user_data: false,
137        summary: "remove maintenance lease table",
138    },
139    MigrationMetadata {
140        id: ACTIVE_CONFIG_MIGRATION_ID,
141        reversible: true,
142        affects_cache: false,
143        affects_user_data: false,
144        summary: "remove active sandbox config snapshots",
145    },
146];
147
148//--------------------------------------------------------------------------------------------------
149// Types
150//--------------------------------------------------------------------------------------------------
151
152/// Downgrade metadata for one migration.
153#[derive(Debug, Clone, Copy, PartialEq, Eq)]
154pub struct MigrationMetadata {
155    /// Migration identifier returned by `MigrationName::name()`.
156    pub id: &'static str,
157
158    /// Whether `down()` actually restores a target-compatible schema/state.
159    pub reversible: bool,
160
161    /// Whether rolling this migration back invalidates re-pullable image cache
162    /// contents on disk.
163    pub affects_cache: bool,
164
165    /// Whether rolling this migration back may leave snapshots or disk-backed
166    /// named volumes in a format the target release cannot read.
167    pub affects_user_data: bool,
168
169    /// Short human-readable summary used in destructive downgrade prompts.
170    pub summary: &'static str,
171}
172
173//--------------------------------------------------------------------------------------------------
174// Functions
175//--------------------------------------------------------------------------------------------------
176
177/// Return all migration identifiers in schema order.
178pub fn migration_ids() -> impl Iterator<Item = &'static str> {
179    MIGRATION_METADATA.iter().map(|metadata| metadata.id)
180}
181
182//--------------------------------------------------------------------------------------------------
183// Tests
184//--------------------------------------------------------------------------------------------------
185
186#[cfg(test)]
187mod tests {
188    use super::*;
189    use crate::{Migrator, MigratorTrait};
190
191    #[test]
192    fn metadata_matches_migrator_order() {
193        let migrations = Migrator::migrations();
194        let migrator_ids: Vec<_> = migrations
195            .iter()
196            .map(|migration| migration.name().to_string())
197            .collect();
198        let metadata_ids: Vec<_> = migration_ids().map(str::to_string).collect();
199
200        assert_eq!(metadata_ids, migrator_ids);
201    }
202
203    #[test]
204    fn frozen_0_6_0_baseline_is_current_prefix() {
205        let metadata_ids: Vec<_> = migration_ids().collect();
206        assert!(metadata_ids.starts_with(BASELINE_0_6_0_MIGRATIONS));
207    }
208}