use systemprompt_extension::{LoaderError, Migration};
use tracing::warn;
use super::{AppliedMigration, MigrationService};
impl MigrationService<'_> {
pub(super) fn verify_slot_identity(
&self,
ext_id: &str,
migration: &Migration,
stored: Option<&AppliedMigration>,
) -> Result<(), LoaderError> {
let Some(stored) = stored else {
return Ok(());
};
if stored.name == migration.name {
return Ok(());
}
if self.config.allow_checksum_drift {
warn!(
extension = %ext_id,
version = migration.version,
stored_name = %stored.name,
current_name = %migration.name,
"Migration slot reuse tolerated by --allow-checksum-drift"
);
return Ok(());
}
Err(LoaderError::MigrationSlotReused {
extension: ext_id.to_owned(),
version: migration.version,
stored_name: stored.name.clone(),
current_name: migration.name.clone(),
})
}
pub(super) fn verify_checksum(
&self,
ext_id: &str,
migration: &Migration,
stored: Option<&str>,
) -> Result<(), LoaderError> {
let Some(stored_checksum) = stored else {
return Ok(());
};
let current_checksum = migration.checksum();
if stored_checksum == current_checksum {
return Ok(());
}
if self.config.allow_checksum_drift {
warn!(
extension = %ext_id,
version = migration.version,
name = %migration.name,
stored_checksum = %stored_checksum,
current_checksum = %current_checksum,
"Migration checksum mismatch tolerated by --allow-checksum-drift"
);
return Ok(());
}
Err(LoaderError::MigrationFailed {
extension: ext_id.to_owned(),
message: format!(
"Migration {ver} ('{name}') has been edited since it was applied (stored checksum \
{stored_checksum}, current {current_checksum}). Refusing to proceed. If the \
database schema already matches the edited file, run `systemprompt infra db \
migrate-repair --reconcile-only --apply` to rewrite the stored checksum without \
executing any SQL. To re-execute the edited migration, run `systemprompt infra \
db migrate-repair --apply`. Passing --allow-checksum-drift bypasses the check \
without fixing it.",
ver = migration.version,
name = migration.name,
),
})
}
}