1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub enum DataLossRisk {
34 None,
35 Column,
36 Table,
37}
38
39#[derive(Debug, Clone, Copy)]
41pub struct MigrationMeta {
42 pub version: i64,
45 pub name: &'static str,
49 pub idempotent: bool,
55 pub reversible: bool,
60 pub data_loss_risk: DataLossRisk,
62}
63
64pub const MIGRATION_LADDER: &[MigrationMeta] = &[
76 MigrationMeta {
78 version: 2,
79 name: "ADD_CONFIDENCE_DEFAULT",
80 idempotent: true,
81 reversible: true,
82 data_loss_risk: DataLossRisk::None,
83 },
84 MigrationMeta {
85 version: 3,
86 name: "ADD_TIER",
87 idempotent: true,
88 reversible: true,
89 data_loss_risk: DataLossRisk::None,
90 },
91 MigrationMeta {
92 version: 4,
93 name: "ADD_AGENT_ID_INDEX",
94 idempotent: true,
95 reversible: true,
96 data_loss_risk: DataLossRisk::None,
97 },
98 MigrationMeta {
99 version: 5,
100 name: "ADD_FTS5",
101 idempotent: true,
102 reversible: true,
103 data_loss_risk: DataLossRisk::None,
104 },
105 MigrationMeta {
106 version: 6,
107 name: "ADD_HNSW_EMBEDDINGS",
108 idempotent: true,
109 reversible: true,
110 data_loss_risk: DataLossRisk::None,
111 },
112 MigrationMeta {
113 version: 7,
114 name: "ADD_LINKS_TABLE",
115 idempotent: true,
116 reversible: true,
117 data_loss_risk: DataLossRisk::None,
118 },
119 MigrationMeta {
120 version: 8,
121 name: "ADD_ARCHIVE_TABLE",
122 idempotent: true,
123 reversible: true,
124 data_loss_risk: DataLossRisk::None,
125 },
126 MigrationMeta {
127 version: 9,
128 name: "ADD_NAMESPACE_META",
129 idempotent: true,
130 reversible: true,
131 data_loss_risk: DataLossRisk::None,
132 },
133 MigrationMeta {
134 version: 10,
135 name: "ADD_PERMISSIONS_RULES",
136 idempotent: true,
137 reversible: true,
138 data_loss_risk: DataLossRisk::None,
139 },
140 MigrationMeta {
141 version: 11,
142 name: "ADD_SIGNED_EVENTS",
143 idempotent: true,
144 reversible: true,
145 data_loss_risk: DataLossRisk::None,
146 },
147 MigrationMeta {
148 version: 12,
149 name: "ADD_AGENTS_REGISTRATION",
150 idempotent: true,
151 reversible: true,
152 data_loss_risk: DataLossRisk::None,
153 },
154 MigrationMeta {
155 version: 13,
156 name: "ADD_LINKS_ATTESTATION",
157 idempotent: true,
158 reversible: true,
159 data_loss_risk: DataLossRisk::None,
160 },
161 MigrationMeta {
162 version: 14,
163 name: "ADD_FED_NONCES_INDEX",
164 idempotent: true,
165 reversible: true,
166 data_loss_risk: DataLossRisk::None,
167 },
168 MigrationMeta {
169 version: 15,
170 name: "ADD_HOOKS_CONFIG",
171 idempotent: true,
172 reversible: true,
173 data_loss_risk: DataLossRisk::None,
174 },
175 MigrationMeta {
176 version: 16,
177 name: "ADD_PENDING_ACTIONS",
178 idempotent: true,
179 reversible: true,
180 data_loss_risk: DataLossRisk::None,
181 },
182 MigrationMeta {
183 version: 17,
184 name: "ADD_TRANSCRIPTS",
185 idempotent: true,
186 reversible: true,
187 data_loss_risk: DataLossRisk::None,
188 },
189 MigrationMeta {
190 version: 18,
191 name: "ADD_OBSERVATIONS",
192 idempotent: true,
193 reversible: true,
194 data_loss_risk: DataLossRisk::None,
195 },
196 MigrationMeta {
197 version: 19,
198 name: "ADD_HOOK_SUBSCRIBERS",
199 idempotent: true,
200 reversible: true,
201 data_loss_risk: DataLossRisk::None,
202 },
203 MigrationMeta {
204 version: 20,
205 name: "ADD_AUDIT_INDEX",
206 idempotent: true,
207 reversible: true,
208 data_loss_risk: DataLossRisk::None,
209 },
210 MigrationMeta {
211 version: 21,
212 name: "ADD_AGENT_QUOTAS",
213 idempotent: true,
214 reversible: true,
215 data_loss_risk: DataLossRisk::None,
216 },
217 MigrationMeta {
218 version: 22,
219 name: "ADD_GOVERNANCE_RULES",
220 idempotent: true,
221 reversible: true,
222 data_loss_risk: DataLossRisk::None,
223 },
224 MigrationMeta {
225 version: 23,
226 name: "ADD_KG_TRAVERSAL_CACHE",
227 idempotent: true,
228 reversible: true,
229 data_loss_risk: DataLossRisk::None,
230 },
231 MigrationMeta {
232 version: 24,
233 name: "ADD_FED_PEERS",
234 idempotent: true,
235 reversible: true,
236 data_loss_risk: DataLossRisk::None,
237 },
238 MigrationMeta {
239 version: 25,
240 name: "ADD_INDEX_REFLECTS_ON",
241 idempotent: true,
242 reversible: true,
243 data_loss_risk: DataLossRisk::None,
244 },
245 MigrationMeta {
246 version: 26,
247 name: "ADD_SKILL_REGISTRY",
248 idempotent: true,
249 reversible: true,
250 data_loss_risk: DataLossRisk::None,
251 },
252 MigrationMeta {
253 version: 27,
254 name: "ADD_PERSONA_REGISTRY",
255 idempotent: true,
256 reversible: true,
257 data_loss_risk: DataLossRisk::None,
258 },
259 MigrationMeta {
260 version: 28,
261 name: "ADD_OFFLOAD_REGISTRY",
262 idempotent: true,
263 reversible: true,
264 data_loss_risk: DataLossRisk::None,
265 },
266 MigrationMeta {
267 version: 29,
268 name: "ADD_REFLECTION_DEPTH",
269 idempotent: true,
270 reversible: true,
271 data_loss_risk: DataLossRisk::None,
272 },
273 MigrationMeta {
274 version: 30,
275 name: "ADD_KG_CYCLE_CHECK",
276 idempotent: true,
277 reversible: true,
278 data_loss_risk: DataLossRisk::None,
279 },
280 MigrationMeta {
281 version: 31,
282 name: "ADD_FORENSIC_SINK",
283 idempotent: true,
284 reversible: true,
285 data_loss_risk: DataLossRisk::None,
286 },
287 MigrationMeta {
288 version: 32,
289 name: "ADD_CONFIDENCE_CALIBRATION",
290 idempotent: true,
291 reversible: true,
292 data_loss_risk: DataLossRisk::None,
293 },
294 MigrationMeta {
295 version: 33,
296 name: "ADD_CONSOLIDATION_LEDGER",
297 idempotent: true,
298 reversible: true,
299 data_loss_risk: DataLossRisk::None,
300 },
301 MigrationMeta {
302 version: 34,
303 name: "BACKFILL_SIGNED_CHAIN",
304 idempotent: true,
305 reversible: false,
306 data_loss_risk: DataLossRisk::None,
307 },
308 MigrationMeta {
309 version: 35,
310 name: "ADD_KG_AGE_PROJECTION",
311 idempotent: true,
312 reversible: true,
313 data_loss_risk: DataLossRisk::None,
314 },
315 MigrationMeta {
316 version: 36,
317 name: "ADD_ATOMISATION_SCHEMA",
318 idempotent: true,
319 reversible: true,
320 data_loss_risk: DataLossRisk::None,
321 },
322 MigrationMeta {
323 version: 37,
324 name: "ADD_MEMORY_KIND",
325 idempotent: true,
326 reversible: true,
327 data_loss_risk: DataLossRisk::None,
328 },
329 MigrationMeta {
330 version: 38,
331 name: "ADD_ENTITY_REGISTRY",
332 idempotent: true,
333 reversible: true,
334 data_loss_risk: DataLossRisk::None,
335 },
336 MigrationMeta {
337 version: 39,
338 name: "ADD_FORM4_PROVENANCE",
339 idempotent: true,
340 reversible: true,
341 data_loss_risk: DataLossRisk::None,
342 },
343 MigrationMeta {
344 version: 40,
345 name: "ADD_FORM5_CONFIDENCE_SOURCE",
346 idempotent: true,
347 reversible: true,
348 data_loss_risk: DataLossRisk::None,
349 },
350 MigrationMeta {
351 version: 41,
352 name: "ADD_PERSONA_VERSION",
353 idempotent: true,
354 reversible: true,
355 data_loss_risk: DataLossRisk::None,
356 },
357 MigrationMeta {
358 version: 42,
359 name: "ADD_HOOK_DLQ",
360 idempotent: true,
361 reversible: true,
362 data_loss_risk: DataLossRisk::None,
363 },
364 MigrationMeta {
365 version: 43,
366 name: "ADD_RECURSIVE_LEARNING_LEDGER",
367 idempotent: true,
368 reversible: true,
369 data_loss_risk: DataLossRisk::None,
370 },
371 MigrationMeta {
372 version: 44,
373 name: "ADD_BATMAN_VOCABULARY_COLUMNS",
374 idempotent: true,
375 reversible: true,
376 data_loss_risk: DataLossRisk::None,
377 },
378 MigrationMeta {
379 version: 45,
380 name: "ADD_VERSION_OPTIMISTIC_CONCURRENCY",
381 idempotent: true,
382 reversible: true,
383 data_loss_risk: DataLossRisk::None,
384 },
385 MigrationMeta {
386 version: 46,
387 name: "ADD_SHARE_LINKS",
388 idempotent: true,
389 reversible: true,
390 data_loss_risk: DataLossRisk::None,
391 },
392 MigrationMeta {
393 version: 47,
394 name: "ADD_MENTIONED_ENTITY_ID",
395 idempotent: true,
396 reversible: true,
397 data_loss_risk: DataLossRisk::None,
398 },
399 MigrationMeta {
400 version: 48,
401 name: "ADD_FEDERATION_PUSH_DLQ",
402 idempotent: true,
403 reversible: true,
404 data_loss_risk: DataLossRisk::None,
405 },
406 MigrationMeta {
407 version: 49,
408 name: "BACKFILL_ARCHIVED_MEMORIES_COLUMNS",
409 idempotent: true,
410 reversible: true,
411 data_loss_risk: DataLossRisk::None,
412 },
413 MigrationMeta {
414 version: 50,
415 name: "EXPAND_AGENT_QUOTAS_PK",
416 idempotent: true,
417 reversible: false,
420 data_loss_risk: DataLossRisk::Column,
421 },
422 MigrationMeta {
423 version: 51,
424 name: "ADD_FEDERATION_NONCES",
425 idempotent: true,
426 reversible: true,
427 data_loss_risk: DataLossRisk::None,
428 },
429 MigrationMeta {
430 version: 52,
431 name: "ADD_TRANSCRIPT_LINE_DEDUP",
432 idempotent: true,
433 reversible: true,
434 data_loss_risk: DataLossRisk::None,
435 },
436 MigrationMeta {
445 version: 53,
446 name: "SCOPE_MEMORIES_AU_TRIGGER_TO_FTS_COLUMNS",
447 idempotent: true,
448 reversible: true,
449 data_loss_risk: DataLossRisk::None,
450 },
451 MigrationMeta {
461 version: crate::storage::migrations::current_schema_version(),
462 name: "BACKFILL_NULL_EXPIRY_TIER_DEFAULT",
463 idempotent: true,
464 reversible: false,
465 data_loss_risk: DataLossRisk::None,
466 },
467];
468
469#[must_use]
471pub fn meta_for(version: i64) -> Option<&'static MigrationMeta> {
472 MIGRATION_LADDER.iter().find(|m| m.version == version)
473}
474
475#[cfg(test)]
476mod tests {
477 use super::*;
478
479 #[test]
480 fn arch_8_ladder_versions_strictly_monotonic() {
481 let mut prev = 1_i64;
482 for meta in MIGRATION_LADDER {
483 assert!(
484 meta.version > prev,
485 "ARCH-8: migration ladder is not strictly monotonic at version {}; prev={prev}",
486 meta.version,
487 );
488 prev = meta.version;
489 }
490 }
491
492 #[test]
493 fn arch_8_ladder_terminates_at_current_schema_version() {
494 let last = MIGRATION_LADDER
495 .last()
496 .expect("MIGRATION_LADDER is non-empty")
497 .version;
498 let current = crate::storage::current_schema_version_for_tests();
499 assert_eq!(
500 last, current,
501 "ARCH-8: MIGRATION_LADDER tail = {last}, but CURRENT_SCHEMA_VERSION = {current}; \
502 when bumping the ladder add a meta row in lockstep.",
503 );
504 }
505
506 #[test]
507 fn arch_8_every_meta_row_has_a_non_empty_name() {
508 for meta in MIGRATION_LADDER {
509 assert!(
510 !meta.name.is_empty(),
511 "ARCH-8: migration v{} has an empty `name`",
512 meta.version,
513 );
514 }
515 }
516
517 #[test]
518 fn arch_8_meta_for_round_trip() {
519 assert!(meta_for(2).is_some());
521 assert!(meta_for(51).is_some());
522 assert!(meta_for(9999).is_none());
523 assert!(meta_for(0).is_none());
524 }
525}