lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit 0491fc9858a319728b731bfe68afe32dc528801b
parent 8f9ee257ea8c2f14be0af88f137ce06882a97bab
Author: triesap <tyson@radroots.org>
Date:   Fri,  3 Jul 2026 06:40:02 +0000

runtime: remove legacy path and fallback surfaces

- delete the public runtime path migration module and reexports
- make secret backend selection primary-only and fail-closed
- update nostr account manager tests for the contracted resolver
- keep runtime path and secret vault docs aligned with the API

Diffstat:
Mcrates/nostr_accounts/src/manager.rs | 15++++-----------
Mcrates/runtime_paths/README | 3+--
Mcrates/runtime_paths/src/lib.rs | 8--------
Dcrates/runtime_paths/src/migration.rs | 184-------------------------------------------------------------------------------
Mcrates/runtime_paths/src/service.rs | 83+++++--------------------------------------------------------------------------
Mcrates/secret_vault/src/error.rs | 32--------------------------------
Mcrates/secret_vault/src/selection.rs | 128++++++++++++++-----------------------------------------------------------------
7 files changed, 32 insertions(+), 421 deletions(-)

diff --git a/crates/nostr_accounts/src/manager.rs b/crates/nostr_accounts/src/manager.rs @@ -883,13 +883,12 @@ mod tests { } #[test] - fn resolve_local_backend_applies_shared_fallback_policy() { - let resolved = RadrootsNostrAccountsManager::resolve_local_backend( + fn resolve_local_backend_fails_when_primary_is_unavailable() { + let err = RadrootsNostrAccountsManager::resolve_local_backend( RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::HostVault( radroots_secret_vault::RadrootsHostVaultPolicy::desktop(), ), - fallback: Some(RadrootsSecretBackend::EncryptedFile), }, RadrootsSecretBackendAvailability { host_vault: RadrootsHostVaultCapabilities::unavailable(), @@ -898,10 +897,9 @@ mod tests { memory: false, }, ) - .expect("fallback resolves"); + .expect_err("unavailable primary fails"); - assert_eq!(resolved.backend, RadrootsSecretBackend::EncryptedFile); - assert!(resolved.used_fallback); + assert_eq!(err.to_string(), "secret backend host_vault is unavailable"); } #[test] @@ -912,7 +910,6 @@ mod tests { temp.path().join("secrets"), RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::ExternalCommand, - fallback: None, }, RadrootsSecretBackendAvailability { host_vault: RadrootsHostVaultCapabilities::unavailable(), @@ -941,7 +938,6 @@ mod tests { primary: RadrootsSecretBackend::HostVault( radroots_secret_vault::RadrootsHostVaultPolicy::desktop(), ), - fallback: None, }, RadrootsSecretBackendAvailability { host_vault: RadrootsHostVaultCapabilities::unavailable(), @@ -968,7 +964,6 @@ mod tests { temp.path().join("secrets"), RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::EncryptedFile, - fallback: None, }, RadrootsSecretBackendAvailability { host_vault: RadrootsHostVaultCapabilities::unavailable(), @@ -992,7 +987,6 @@ mod tests { temp.path().join("secrets"), RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::EncryptedFile, - fallback: None, }, RadrootsSecretBackendAvailability { host_vault: RadrootsHostVaultCapabilities::unavailable(), @@ -1005,7 +999,6 @@ mod tests { .expect("encrypted file manager"); assert_eq!(resolved.backend, RadrootsSecretBackend::EncryptedFile); - assert!(!resolved.used_fallback); assert!(manager.list_accounts().expect("accounts").is_empty()); } diff --git a/crates/runtime_paths/README b/crates/runtime_paths/README @@ -11,8 +11,7 @@ runtime path selection and contract helpers for the `radroots` core libraries. * resolver, override, and runtime-selection helpers that produce structured `RadrootsPaths` outputs; * service and app contract helpers for active profile, override, and root - selection reporting; - * migration and legacy-path inspection helpers for runtime relocation audits. + selection reporting. ## Copyright diff --git a/crates/runtime_paths/src/lib.rs b/crates/runtime_paths/src/lib.rs @@ -2,7 +2,6 @@ pub mod conventions; pub mod error; -pub mod migration; pub mod namespace; pub mod platform; pub mod roots; @@ -25,20 +24,13 @@ pub use conventions::{ default_shared_runtime_logs_dir, }; pub use error::RadrootsRuntimePathsError; -pub use migration::{ - RADROOTS_MIGRATION_COMPATIBILITY_WINDOW, RADROOTS_MIGRATION_POSTURE, - RadrootsLegacyPathCandidate, RadrootsLegacyPathDetection, RadrootsMigrationReport, - inspect_legacy_paths, -}; pub use namespace::{RadrootsRuntimeNamespace, RadrootsRuntimeNamespaceKind}; pub use platform::{RadrootsHostEnvironment, RadrootsPathProfile, RadrootsPlatform}; pub use roots::{RadrootsPathOverrides, RadrootsPathResolver, RadrootsPaths}; pub use service::{ - RadrootsRuntimeLegacyPathContract, RadrootsRuntimeMigrationContract, RadrootsRuntimePathConfigEntry, RadrootsRuntimePathPolicyContract, RadrootsRuntimePathSelection, RadrootsRuntimePathSelectionError, RadrootsRuntimeSelectionContract, RadrootsRuntimeSelectionOverrideContract, - runtime_migration_contract, }; #[cfg(test)] diff --git a/crates/runtime_paths/src/migration.rs b/crates/runtime_paths/src/migration.rs @@ -1,184 +0,0 @@ -use std::path::PathBuf; - -pub const RADROOTS_MIGRATION_POSTURE: &str = "explicit_operator_import_required"; -pub const RADROOTS_MIGRATION_COMPATIBILITY_WINDOW: &str = "detect_and_report_only"; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct RadrootsLegacyPathCandidate { - pub id: String, - pub description: String, - pub path: PathBuf, - pub destination: Option<PathBuf>, - pub import_hint: String, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct RadrootsLegacyPathDetection { - pub id: String, - pub description: String, - pub path: PathBuf, - pub destination: Option<PathBuf>, - pub import_hint: String, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct RadrootsMigrationReport { - pub posture: &'static str, - pub state: &'static str, - pub silent_startup_relocation: bool, - pub compatibility_window: &'static str, - pub detected_legacy_paths: Vec<RadrootsLegacyPathDetection>, -} - -impl RadrootsLegacyPathCandidate { - #[must_use] - pub fn new( - id: impl Into<String>, - description: impl Into<String>, - path: impl Into<PathBuf>, - destination: Option<PathBuf>, - import_hint: impl Into<String>, - ) -> Self { - Self { - id: id.into(), - description: description.into(), - path: path.into(), - destination, - import_hint: import_hint.into(), - } - } - - fn into_detection(self) -> RadrootsLegacyPathDetection { - RadrootsLegacyPathDetection { - id: self.id, - description: self.description, - path: self.path, - destination: self.destination, - import_hint: self.import_hint, - } - } -} - -impl RadrootsMigrationReport { - #[must_use] - pub fn empty() -> Self { - Self::from_detected_legacy_paths(Vec::new()) - } - - #[must_use] - pub fn from_detected_legacy_paths( - detected_legacy_paths: Vec<RadrootsLegacyPathDetection>, - ) -> Self { - let state = if detected_legacy_paths.is_empty() { - "ready" - } else { - "legacy_state_detected" - }; - Self { - posture: RADROOTS_MIGRATION_POSTURE, - state, - silent_startup_relocation: false, - compatibility_window: RADROOTS_MIGRATION_COMPATIBILITY_WINDOW, - detected_legacy_paths, - } - } -} - -#[must_use] -pub fn inspect_legacy_paths( - candidates: impl IntoIterator<Item = RadrootsLegacyPathCandidate>, -) -> RadrootsMigrationReport { - let detected = candidates - .into_iter() - .filter(|candidate| candidate.path.exists()) - .map(RadrootsLegacyPathCandidate::into_detection) - .collect(); - RadrootsMigrationReport::from_detected_legacy_paths(detected) -} - -#[cfg(test)] -mod tests { - use std::path::PathBuf; - - use super::{ - RADROOTS_MIGRATION_COMPATIBILITY_WINDOW, RADROOTS_MIGRATION_POSTURE, - RadrootsLegacyPathCandidate, RadrootsMigrationReport, inspect_legacy_paths, - }; - - fn unique_test_dir() -> PathBuf { - let nanos = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .expect("clock") - .as_nanos(); - let path = std::env::temp_dir().join(format!("radroots_runtime_paths-test-{nanos}")); - std::fs::create_dir_all(&path).expect("create temp test dir"); - path - } - - #[test] - fn inspect_legacy_paths_reports_only_paths_that_exist() { - let temp = unique_test_dir(); - let existing = temp.join("old-state"); - let missing = temp.join("missing-state"); - std::fs::write(&existing, "legacy").expect("write legacy marker"); - - let report = inspect_legacy_paths([ - RadrootsLegacyPathCandidate::new( - "old-state", - "old state", - &existing, - Some(temp.join("new-state")), - "run the explicit importer", - ), - RadrootsLegacyPathCandidate::new( - "missing-state", - "missing state", - &missing, - None, - "nothing to do", - ), - ]); - - assert_eq!(report.posture, RADROOTS_MIGRATION_POSTURE); - assert_eq!(report.state, "legacy_state_detected"); - assert!(!report.silent_startup_relocation); - assert_eq!( - report.compatibility_window, - RADROOTS_MIGRATION_COMPATIBILITY_WINDOW - ); - assert_eq!(report.detected_legacy_paths.len(), 1); - assert_eq!(report.detected_legacy_paths[0].id, "old-state"); - assert_eq!(report.detected_legacy_paths[0].path, existing); - std::fs::remove_dir_all(temp).expect("remove temp test dir"); - } - - #[test] - fn inspect_legacy_paths_is_ready_when_no_candidate_exists() { - let temp = unique_test_dir(); - - let report = inspect_legacy_paths([RadrootsLegacyPathCandidate::new( - "missing-state", - "missing state", - temp.join("missing-state"), - None, - "nothing to do", - )]); - - assert_eq!(report.state, "ready"); - assert!(report.detected_legacy_paths.is_empty()); - std::fs::remove_dir_all(temp).expect("remove temp test dir"); - } - - #[test] - fn empty_report_matches_ready_state() { - let report = RadrootsMigrationReport::empty(); - assert_eq!(report.posture, RADROOTS_MIGRATION_POSTURE); - assert_eq!(report.state, "ready"); - assert!(!report.silent_startup_relocation); - assert_eq!( - report.compatibility_window, - RADROOTS_MIGRATION_COMPATIBILITY_WINDOW - ); - assert!(report.detected_legacy_paths.is_empty()); - } -} diff --git a/crates/runtime_paths/src/service.rs b/crates/runtime_paths/src/service.rs @@ -4,8 +4,8 @@ use serde::Serialize; use thiserror::Error; use crate::{ - RadrootsMigrationReport, RadrootsPathOverrides, RadrootsPathProfile, RadrootsPathResolver, - RadrootsPaths, RadrootsRuntimeNamespace, RadrootsRuntimePathsError, + RadrootsPathOverrides, RadrootsPathProfile, RadrootsPathResolver, RadrootsPaths, + RadrootsRuntimeNamespace, RadrootsRuntimePathsError, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -62,7 +62,6 @@ pub struct RadrootsRuntimePathPolicyContract { pub canonical_root_selection: String, pub canonical_subordinate_path_override: String, pub leaf_path_env_posture: String, - pub compatibility_leaf_path_keys: Vec<String>, } impl RadrootsRuntimePathPolicyContract { @@ -70,61 +69,15 @@ impl RadrootsRuntimePathPolicyContract { canonical_root_selection: &str, canonical_subordinate_path_override: &str, leaf_path_env_posture: &str, - compatibility_leaf_path_keys: &[&str], ) -> Self { Self { canonical_root_selection: canonical_root_selection.to_owned(), canonical_subordinate_path_override: canonical_subordinate_path_override.to_owned(), leaf_path_env_posture: leaf_path_env_posture.to_owned(), - compatibility_leaf_path_keys: compatibility_leaf_path_keys - .iter() - .map(|entry| (*entry).to_owned()) - .collect(), } } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] -pub struct RadrootsRuntimeMigrationContract { - pub posture: String, - pub state: String, - pub silent_startup_relocation: bool, - pub compatibility_window: String, - pub detected_legacy_paths: Vec<RadrootsRuntimeLegacyPathContract>, -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] -pub struct RadrootsRuntimeLegacyPathContract { - pub id: String, - pub description: String, - pub path: PathBuf, - #[serde(skip_serializing_if = "Option::is_none")] - pub destination: Option<PathBuf>, - pub import_hint: String, -} - -pub fn runtime_migration_contract( - report: RadrootsMigrationReport, -) -> RadrootsRuntimeMigrationContract { - RadrootsRuntimeMigrationContract { - 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| RadrootsRuntimeLegacyPathContract { - id: path.id, - description: path.description, - path: path.path, - destination: path.destination, - import_hint: path.import_hint, - }) - .collect(), - } -} - #[derive(Debug, Error, Clone, PartialEq, Eq)] pub enum RadrootsRuntimePathSelectionError { #[error("{env_var} must be valid utf-8 when set")] @@ -352,9 +305,7 @@ mod tests { use super::{ RadrootsRuntimePathConfigEntry, RadrootsRuntimePathPolicyContract, RadrootsRuntimePathSelection, RadrootsRuntimePathSelectionError, - runtime_migration_contract, }; - use crate::{RadrootsLegacyPathDetection, RadrootsMigrationReport}; #[test] fn caller_selection_preserves_profile_and_sources() { @@ -611,8 +562,7 @@ mod tests { let contract = RadrootsRuntimePathPolicyContract::new( "profile_root_env_or_repo_wrapper", "config_artifact", - "compatibility_break_glass", - &["MYC_PATHS_STATE_DIR"], + "runtime_owned_leaf_overrides", ); assert_eq!( @@ -620,31 +570,8 @@ mod tests { "profile_root_env_or_repo_wrapper" ); assert_eq!( - contract.compatibility_leaf_path_keys, - vec!["MYC_PATHS_STATE_DIR".to_owned()] + contract.leaf_path_env_posture, + "runtime_owned_leaf_overrides" ); } - - #[test] - fn runtime_migration_contract_maps_detected_paths() { - let report = RadrootsMigrationReport { - posture: "explicit_operator_import_required", - state: "legacy_state_detected", - silent_startup_relocation: false, - compatibility_window: "detect_and_report_only", - detected_legacy_paths: vec![RadrootsLegacyPathDetection { - id: "legacy_path".to_owned(), - description: "legacy path".to_owned(), - path: PathBuf::from("/tmp/legacy"), - destination: Some(PathBuf::from("/tmp/new")), - import_hint: "copy it manually".to_owned(), - }], - }; - - let contract = runtime_migration_contract(report); - - assert_eq!(contract.posture, "explicit_operator_import_required"); - assert_eq!(contract.detected_legacy_paths.len(), 1); - assert_eq!(contract.detected_legacy_paths[0].id, "legacy_path"); - } } diff --git a/crates/secret_vault/src/error.rs b/crates/secret_vault/src/error.rs @@ -14,14 +14,6 @@ pub enum RadrootsSecretVaultError { BackendUnavailable { backend: RadrootsSecretBackendKind, }, - FallbackDisallowed { - primary: RadrootsSecretBackendKind, - fallback: RadrootsSecretBackendKind, - }, - FallbackUnavailable { - primary: RadrootsSecretBackendKind, - fallback: RadrootsSecretBackendKind, - }, HostVaultPolicyUnsupported { requirement: RadrootsHostVaultRequirement, }, @@ -57,14 +49,6 @@ impl fmt::Display for RadrootsSecretVaultError { Self::BackendUnavailable { backend } => { write!(f, "secret backend {backend} is unavailable") } - Self::FallbackDisallowed { primary, fallback } => write!( - f, - "secret backend {primary} may not silently downgrade to {fallback}" - ), - Self::FallbackUnavailable { primary, fallback } => write!( - f, - "secret backend {primary} fallback {fallback} is unavailable" - ), Self::HostVaultPolicyUnsupported { requirement } => write!( f, "host vault does not satisfy the required {requirement} policy" @@ -138,22 +122,6 @@ mod tests { "secret backend host_vault is unavailable" ); assert_eq!( - RadrootsSecretVaultError::FallbackDisallowed { - primary: RadrootsSecretBackendKind::ExternalCommand, - fallback: RadrootsSecretBackendKind::EncryptedFile, - } - .to_string(), - "secret backend external_command may not silently downgrade to encrypted_file" - ); - assert_eq!( - RadrootsSecretVaultError::FallbackUnavailable { - primary: RadrootsSecretBackendKind::HostVault, - fallback: RadrootsSecretBackendKind::EncryptedFile, - } - .to_string(), - "secret backend host_vault fallback encrypted_file is unavailable" - ); - assert_eq!( RadrootsSecretVaultError::HostVaultPolicyUnsupported { requirement: RadrootsHostVaultRequirement::HardwareBacked, } diff --git a/crates/secret_vault/src/selection.rs b/crates/secret_vault/src/selection.rs @@ -1,11 +1,10 @@ -use crate::backend::{RadrootsSecretBackend, RadrootsSecretBackendKind}; +use crate::backend::RadrootsSecretBackend; use crate::error::RadrootsSecretVaultError; use crate::policy::RadrootsHostVaultCapabilities; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RadrootsSecretBackendSelection { pub primary: RadrootsSecretBackend, - pub fallback: Option<RadrootsSecretBackend>, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -19,7 +18,6 @@ pub struct RadrootsSecretBackendAvailability { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RadrootsResolvedSecretBackend { pub backend: RadrootsSecretBackend, - pub used_fallback: bool, } impl RadrootsSecretBackendSelection { @@ -27,44 +25,10 @@ impl RadrootsSecretBackendSelection { self, availability: RadrootsSecretBackendAvailability, ) -> Result<RadrootsResolvedSecretBackend, RadrootsSecretVaultError> { - if availability.supports(self.primary).is_ok() { - return Ok(RadrootsResolvedSecretBackend { - backend: self.primary, - used_fallback: false, - }); - } - - if let RadrootsSecretBackend::HostVault(policy) = self.primary - && availability.host_vault.available - { - availability.host_vault.validate(policy)?; - } - - match self.fallback { - Some(fallback) => { - if !self.primary.allows_fallback_to(fallback.kind()) { - return Err(RadrootsSecretVaultError::FallbackDisallowed { - primary: self.primary.kind(), - fallback: fallback.kind(), - }); - } - - availability.supports(fallback).map_err(|_| { - RadrootsSecretVaultError::FallbackUnavailable { - primary: self.primary.kind(), - fallback: fallback.kind(), - } - })?; - - Ok(RadrootsResolvedSecretBackend { - backend: fallback, - used_fallback: true, - }) - } - None => Err(RadrootsSecretVaultError::BackendUnavailable { - backend: self.primary.kind(), - }), - } + availability.supports(self.primary)?; + Ok(RadrootsResolvedSecretBackend { + backend: self.primary, + }) } } @@ -82,21 +46,10 @@ impl RadrootsSecretBackendAvailability { } } -impl RadrootsSecretBackend { - const fn allows_fallback_to(self, fallback: RadrootsSecretBackendKind) -> bool { - matches!( - (self.kind(), fallback), - ( - RadrootsSecretBackendKind::HostVault, - RadrootsSecretBackendKind::EncryptedFile - ) - ) - } -} - #[cfg(test)] mod tests { use super::*; + use crate::backend::RadrootsSecretBackendKind; use crate::error::RadrootsHostVaultRequirement; use crate::policy::{ RadrootsHostVaultHardwarePolicy, RadrootsHostVaultPolicy, RadrootsHostVaultResidency, @@ -107,7 +60,6 @@ mod tests { fn host_vault_is_selected_when_available() { let selection = RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::HostVault(RadrootsHostVaultPolicy::desktop()), - fallback: Some(RadrootsSecretBackend::EncryptedFile), }; let resolved = selection @@ -123,69 +75,64 @@ mod tests { resolved, RadrootsResolvedSecretBackend { backend: RadrootsSecretBackend::HostVault(RadrootsHostVaultPolicy::desktop()), - used_fallback: false, } ); } #[test] - fn host_vault_may_explicitly_fallback_to_encrypted_file() { + fn host_vault_unavailable_fails_closed() { let selection = RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::HostVault(RadrootsHostVaultPolicy::desktop()), - fallback: Some(RadrootsSecretBackend::EncryptedFile), }; - let resolved = selection + let err = selection .resolve(RadrootsSecretBackendAvailability { host_vault: RadrootsHostVaultCapabilities::unavailable(), encrypted_file: true, external_command: false, memory: false, }) - .expect("encrypted file fallback resolves"); + .expect_err("unavailable primary must fail"); assert_eq!( - resolved, - RadrootsResolvedSecretBackend { - backend: RadrootsSecretBackend::EncryptedFile, - used_fallback: true, + err, + RadrootsSecretVaultError::BackendUnavailable { + backend: RadrootsSecretBackendKind::HostVault, } ); } #[test] - fn host_vault_without_explicit_fallback_fails_closed() { + fn encrypted_file_unavailable_fails_closed() { let selection = RadrootsSecretBackendSelection { - primary: RadrootsSecretBackend::HostVault(RadrootsHostVaultPolicy::desktop()), - fallback: None, + primary: RadrootsSecretBackend::EncryptedFile, }; let err = selection .resolve(RadrootsSecretBackendAvailability { host_vault: RadrootsHostVaultCapabilities::unavailable(), - encrypted_file: true, + encrypted_file: false, external_command: false, memory: false, }) - .expect_err("missing fallback must fail"); + .expect_err("unavailable primary must fail"); assert_eq!( err, RadrootsSecretVaultError::BackendUnavailable { - backend: RadrootsSecretBackendKind::HostVault, + backend: RadrootsSecretBackendKind::EncryptedFile, } ); } #[test] - fn unsupported_host_vault_policy_fails_before_any_downgrade() { + fn unsupported_host_vault_policy_fails_closed() { let selection = RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::HostVault(RadrootsHostVaultPolicy { residency: RadrootsHostVaultResidency::DeviceLocalOnly, user_presence: RadrootsHostVaultUserPresencePolicy::Required, hardware: RadrootsHostVaultHardwarePolicy::RequireHardwareBacked, }), - fallback: Some(RadrootsSecretBackend::EncryptedFile), }; let err = selection @@ -206,10 +153,9 @@ mod tests { } #[test] - fn external_command_may_not_downgrade_to_encrypted_file() { + fn external_command_unavailable_fails_closed() { let selection = RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::ExternalCommand, - fallback: Some(RadrootsSecretBackend::EncryptedFile), }; let err = selection @@ -219,13 +165,12 @@ mod tests { external_command: false, memory: false, }) - .expect_err("external command downgrade must fail"); + .expect_err("unavailable primary must fail"); assert_eq!( err, - RadrootsSecretVaultError::FallbackDisallowed { - primary: RadrootsSecretBackendKind::ExternalCommand, - fallback: RadrootsSecretBackendKind::EncryptedFile, + RadrootsSecretVaultError::BackendUnavailable { + backend: RadrootsSecretBackendKind::ExternalCommand, } ); } @@ -234,7 +179,6 @@ mod tests { fn external_command_resolves_when_available() { let selection = RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::ExternalCommand, - fallback: None, }; let resolved = selection @@ -250,7 +194,6 @@ mod tests { resolved, RadrootsResolvedSecretBackend { backend: RadrootsSecretBackend::ExternalCommand, - used_fallback: false, } ); } @@ -259,7 +202,6 @@ mod tests { fn memory_backend_must_be_selected_explicitly() { let selection = RadrootsSecretBackendSelection { primary: RadrootsSecretBackend::Memory, - fallback: None, }; let resolved = selection @@ -275,7 +217,6 @@ mod tests { resolved, RadrootsResolvedSecretBackend { backend: RadrootsSecretBackend::Memory, - used_fallback: false, } ); @@ -295,29 +236,4 @@ mod tests { } ); } - - #[test] - fn unavailable_explicit_fallback_reports_fallback_unavailable() { - let selection = RadrootsSecretBackendSelection { - primary: RadrootsSecretBackend::HostVault(RadrootsHostVaultPolicy::desktop()), - fallback: Some(RadrootsSecretBackend::EncryptedFile), - }; - - let err = selection - .resolve(RadrootsSecretBackendAvailability { - host_vault: RadrootsHostVaultCapabilities::unavailable(), - encrypted_file: false, - external_command: false, - memory: false, - }) - .expect_err("unavailable fallback must fail"); - - assert_eq!( - err, - RadrootsSecretVaultError::FallbackUnavailable { - primary: RadrootsSecretBackendKind::HostVault, - fallback: RadrootsSecretBackendKind::EncryptedFile, - } - ); - } }