commit 00a2bb4df26fb06b312ca4f61b51ef600bf62056
parent 1258ed0ba96c6c5a37b430ad5eb7e17a27823591
Author: triesap <tyson@radroots.org>
Date: Wed, 1 Jul 2026 09:23:55 +0000
rhi: remove runtime migration contract output
- remove migration and legacy-path fields from the runtime contract
- stop inspecting legacy repo-relative paths during startup
- trim startup report logging to canonical runtime path evidence
- update runtime contract tests for the target output shape
Diffstat:
3 files changed, 5 insertions(+), 182 deletions(-)
diff --git a/src/config.rs b/src/config.rs
@@ -640,17 +640,6 @@ proof_mode = "none"
vec!["encrypted_file".to_owned()]
);
assert_eq!(
- contract.migration.posture,
- "explicit_operator_import_required"
- );
- assert_eq!(contract.migration.state, "ready");
- assert_eq!(contract.migration.silent_startup_relocation, false);
- assert_eq!(
- contract.migration.compatibility_window,
- "detect_and_report_only"
- );
- assert!(contract.migration.detected_legacy_paths.is_empty());
- assert_eq!(
contract.canonical_config_path,
PathBuf::from("/home/treesap/.radroots/config/workers/rhi/config.toml")
);
diff --git a/src/main.rs b/src/main.rs
@@ -64,7 +64,6 @@ struct RhiRuntimeStartupReport {
subscriber_state_path_source: String,
canonical_subscriber_state_path: PathBuf,
path_overrides: paths::RhiRuntimePathOverrideContractOutput,
- migration: paths::RhiRuntimeMigrationContractOutput,
default_shared_secret_backend: String,
allowed_shared_secret_backends: Vec<String>,
}
@@ -114,7 +113,6 @@ fn runtime_startup_report(
args: &cli_args,
settings: &config::Settings,
contract: &paths::RhiRuntimeContractOutput,
- migration: paths::RhiRuntimeMigrationContractOutput,
) -> RhiRuntimeStartupReport {
RhiRuntimeStartupReport {
active_profile: contract.active_profile.clone(),
@@ -161,7 +159,6 @@ fn runtime_startup_report(
),
canonical_subscriber_state_path: contract.canonical_subscriber_state_path.clone(),
path_overrides: contract.path_overrides.clone(),
- migration,
default_shared_secret_backend: contract.default_shared_secret_backend.clone(),
allowed_shared_secret_backends: contract.allowed_shared_secret_backends.clone(),
}
@@ -196,10 +193,6 @@ fn log_runtime_startup_report(report: &RhiRuntimeStartupReport) {
repo_local_root = ?report.path_overrides.repo_local_root,
repo_local_root_source = ?report.path_overrides.repo_local_root_source,
subordinate_path_override_source = report.path_overrides.subordinate_path_override_source.as_str(),
- migration_posture = report.migration.posture.as_str(),
- migration_state = report.migration.state.as_str(),
- migration_detected_legacy_paths = report.migration.detected_legacy_paths.len(),
- silent_startup_relocation = report.migration.silent_startup_relocation,
config_path = %report.config_path.display(),
config_path_source = report.config_path_source.as_str(),
canonical_config_path = %report.canonical_config_path.display(),
@@ -235,9 +228,7 @@ async fn run() -> Result<()> {
#[cfg(not(test))]
{
let contract = paths::runtime_contract_for_process().context("resolve runtime contract")?;
- let migration =
- paths::runtime_migration_for_process(&contract).context("inspect runtime migration")?;
- let report = runtime_startup_report(&args, &settings, &contract, migration);
+ let report = runtime_startup_report(&args, &settings, &contract);
log_runtime_startup_report(&report);
}
@@ -312,13 +303,6 @@ mod tests {
},
default_shared_secret_backend: "encrypted_file".to_string(),
allowed_shared_secret_backends: vec!["encrypted_file".to_string()],
- migration: paths::RhiRuntimeMigrationContractOutput {
- posture: "explicit_operator_import_required".to_string(),
- state: "ready".to_string(),
- silent_startup_relocation: false,
- compatibility_window: "detect_and_report_only".to_string(),
- detected_legacy_paths: Vec::new(),
- },
canonical_config_path: PathBuf::from(
"/home/treesap/.radroots/config/workers/rhi/config.toml",
),
@@ -438,8 +422,7 @@ mod tests {
settings.config.subscriber.state.path = PathBuf::from("/tmp/rhi/state.json");
let contract = sample_runtime_contract();
- let report =
- runtime_startup_report(&args, &settings, &contract, contract.migration.clone());
+ let report = runtime_startup_report(&args, &settings, &contract);
assert_eq!(
report,
@@ -464,7 +447,6 @@ mod tests {
"/home/treesap/.radroots/data/workers/rhi/trade-listing/state.json"
),
path_overrides: sample_runtime_contract().path_overrides,
- migration: sample_runtime_contract().migration,
default_shared_secret_backend: "encrypted_file".to_string(),
allowed_shared_secret_backends: vec!["encrypted_file".to_string()],
}
@@ -487,8 +469,7 @@ mod tests {
settings.config.logging.output_dir = contract.canonical_logs_dir.clone();
settings.config.subscriber.state.path = contract.canonical_subscriber_state_path.clone();
- let report =
- runtime_startup_report(&args, &settings, &contract, contract.migration.clone());
+ let report = runtime_startup_report(&args, &settings, &contract);
assert_eq!(report.config_path, contract.canonical_config_path);
assert_eq!(report.config_path_source, "profile_default");
@@ -502,7 +483,6 @@ mod tests {
);
assert_eq!(report.subscriber_state_path_source, "profile_default");
assert_eq!(report.path_overrides, contract.path_overrides);
- assert_eq!(report.migration, contract.migration);
assert_eq!(report.default_shared_secret_backend, "encrypted_file");
assert_eq!(
report.allowed_shared_secret_backends,
diff --git a/src/paths.rs b/src/paths.rs
@@ -2,9 +2,8 @@ use std::path::{Path, PathBuf};
use anyhow::{Context, Result, bail};
use radroots_runtime_paths::{
- DEFAULT_CONFIG_FILE_NAME, DEFAULT_SERVICE_IDENTITY_FILE_NAME, RadrootsLegacyPathCandidate,
- RadrootsMigrationReport, RadrootsPathOverrides, RadrootsPathProfile, RadrootsPathResolver,
- RadrootsRuntimeNamespace, inspect_legacy_paths,
+ DEFAULT_CONFIG_FILE_NAME, DEFAULT_SERVICE_IDENTITY_FILE_NAME, RadrootsPathOverrides,
+ RadrootsPathProfile, RadrootsPathResolver, RadrootsRuntimeNamespace,
};
use serde::Serialize;
@@ -18,7 +17,6 @@ const RHI_ALLOWED_PROFILES: [&str; 3] = ["interactive_user", "service_host", "re
const RHI_ALLOWED_SHARED_SECRET_BACKENDS: [&str; 1] = ["encrypted_file"];
const SUBORDINATE_PATH_OVERRIDE_SOURCE: &str = "config_artifact";
const SUBORDINATE_PATH_OVERRIDE_KEYS: [&str; 2] = ["logging.output_dir", "subscriber.state.path"];
-const MIGRATION_IMPORT_HINT: &str = "stop the worker, inspect this legacy path, then perform an explicit import or manual copy into the canonical destination; rhi will not move it on startup";
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct RhiRuntimePaths {
@@ -35,7 +33,6 @@ pub struct RhiRuntimeContractOutput {
pub path_overrides: RhiRuntimePathOverrideContractOutput,
pub default_shared_secret_backend: String,
pub allowed_shared_secret_backends: Vec<String>,
- pub migration: RhiRuntimeMigrationContractOutput,
pub canonical_config_path: PathBuf,
pub canonical_logs_dir: PathBuf,
pub canonical_identity_path: PathBuf,
@@ -43,25 +40,6 @@ pub struct RhiRuntimeContractOutput {
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
-pub struct RhiRuntimeMigrationContractOutput {
- pub posture: String,
- pub state: String,
- pub silent_startup_relocation: bool,
- pub compatibility_window: String,
- pub detected_legacy_paths: Vec<RhiRuntimeLegacyPathOutput>,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
-pub struct RhiRuntimeLegacyPathOutput {
- pub id: String,
- pub description: String,
- pub path: PathBuf,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub destination: Option<PathBuf>,
- pub import_hint: String,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct RhiRuntimePathOverrideContractOutput {
pub profile_source: String,
pub root_source: String,
@@ -231,7 +209,6 @@ fn runtime_contract_with_selection(
.into_iter()
.map(str::to_owned)
.collect(),
- migration: migration_contract_output(RadrootsMigrationReport::empty()),
canonical_config_path: paths.config_path,
canonical_logs_dir: paths.logs_dir,
canonical_identity_path: paths.identity_path,
@@ -239,73 +216,6 @@ fn runtime_contract_with_selection(
})
}
-pub fn runtime_migration_for_process(
- contract: &RhiRuntimeContractOutput,
-) -> Result<RhiRuntimeMigrationContractOutput> {
- let current_dir = std::env::current_dir().context("resolve current directory")?;
- Ok(runtime_migration_for_current_dir(
- contract,
- current_dir.as_path(),
- ))
-}
-
-pub(crate) fn runtime_migration_for_current_dir(
- contract: &RhiRuntimeContractOutput,
- current_dir: &Path,
-) -> RhiRuntimeMigrationContractOutput {
- let report = inspect_legacy_paths(legacy_path_candidates(contract, current_dir));
- migration_contract_output(report)
-}
-
-fn legacy_path_candidates(
- contract: &RhiRuntimeContractOutput,
- current_dir: &Path,
-) -> Vec<RadrootsLegacyPathCandidate> {
- vec![
- RadrootsLegacyPathCandidate::new(
- "rhi_repo_config_v0",
- "legacy rhi repo-relative config",
- current_dir.join(DEFAULT_CONFIG_FILE_NAME),
- Some(contract.canonical_config_path.clone()),
- MIGRATION_IMPORT_HINT,
- ),
- RadrootsLegacyPathCandidate::new(
- "rhi_repo_logs_v0",
- "legacy rhi repo-relative logs directory",
- current_dir.join("logs"),
- Some(contract.canonical_logs_dir.clone()),
- MIGRATION_IMPORT_HINT,
- ),
- RadrootsLegacyPathCandidate::new(
- "rhi_repo_subscriber_state_v0",
- "legacy rhi repo-relative subscriber state",
- current_dir.join("state/trade-listing-state.json"),
- Some(contract.canonical_subscriber_state_path.clone()),
- MIGRATION_IMPORT_HINT,
- ),
- ]
-}
-
-fn migration_contract_output(report: RadrootsMigrationReport) -> RhiRuntimeMigrationContractOutput {
- RhiRuntimeMigrationContractOutput {
- posture: report.posture.to_owned(),
- state: report.state.to_owned(),
- silent_startup_relocation: report.silent_startup_relocation,
- compatibility_window: report.compatibility_window.to_owned(),
- detected_legacy_paths: report
- .detected_legacy_paths
- .into_iter()
- .map(|path| RhiRuntimeLegacyPathOutput {
- id: path.id,
- description: path.description,
- path: path.path,
- destination: path.destination,
- import_hint: path.import_hint,
- })
- .collect(),
- }
-}
-
fn root_source_for_profile(profile: RadrootsPathProfile) -> &'static str {
match profile {
RadrootsPathProfile::InteractiveUser => "host_defaults",
@@ -314,59 +224,3 @@ fn root_source_for_profile(profile: RadrootsPathProfile) -> &'static str {
RadrootsPathProfile::MobileNative => "mobile_native_defaults",
}
}
-
-#[cfg(test)]
-mod tests {
- use std::path::PathBuf;
-
- use radroots_runtime_paths::{
- RadrootsHostEnvironment, RadrootsPathProfile, RadrootsPathResolver, RadrootsPlatform,
- };
-
- use super::{runtime_contract_with_resolver, runtime_migration_for_current_dir};
-
- fn linux_resolver() -> RadrootsPathResolver {
- RadrootsPathResolver::new(
- RadrootsPlatform::Linux,
- RadrootsHostEnvironment {
- home_dir: Some(PathBuf::from("/home/treesap")),
- ..RadrootsHostEnvironment::default()
- },
- )
- }
-
- #[test]
- fn runtime_migration_detects_legacy_repo_relative_state_without_moving_it() {
- let temp = tempfile::tempdir().expect("tempdir");
- std::fs::write(
- temp.path().join("config.toml"),
- "[metadata]\nname = \"old\"\n",
- )
- .expect("write old config");
- std::fs::create_dir_all(temp.path().join("state")).expect("state dir");
- std::fs::write(temp.path().join("state/trade-listing-state.json"), "{}")
- .expect("write old subscriber state");
- let contract = runtime_contract_with_resolver(
- &linux_resolver(),
- RadrootsPathProfile::InteractiveUser,
- None,
- )
- .expect("contract");
-
- let report = runtime_migration_for_current_dir(&contract, temp.path());
-
- assert_eq!(report.posture, "explicit_operator_import_required");
- assert_eq!(report.state, "legacy_state_detected");
- assert!(!report.silent_startup_relocation);
- assert_eq!(report.detected_legacy_paths.len(), 2);
- assert_eq!(report.detected_legacy_paths[0].id, "rhi_repo_config_v0");
- assert_eq!(
- report.detected_legacy_paths[1].id,
- "rhi_repo_subscriber_state_v0"
- );
- assert_eq!(
- report.detected_legacy_paths[1].destination,
- Some(contract.canonical_subscriber_state_path)
- );
- }
-}