Implement client configuration delivery and reissue lifecycle

This commit is contained in:
2026-10-21 21:52:24 +03:00
parent 6ec593c783
commit f718f739b4
13 changed files with 4911 additions and 20 deletions
+48
View File
@@ -515,6 +515,54 @@ impl SavedStore {
self.vault_path(),
]
}
/// Paths which client plaintext delivery must not replace. This is a
/// read-only view of the resolved installation mapping; source candidates
/// are protected individually so a safe, newly selected sibling output
/// remains available.
pub(crate) fn delivery_output_protection(
&self,
) -> Result<crate::delivery::files::OutputProtection, crate::delivery::files::FileOutputError>
{
let mut protected_files = self.targets().into_iter().collect::<Vec<_>>();
let source_directory = &self.settings.client_source_directory;
match fs::symlink_metadata(source_directory) {
Ok(metadata) if metadata.file_type().is_dir() => {}
Ok(_) => return Err(crate::delivery::files::FileOutputError::UnsafePath),
Err(error) if error.kind() == io::ErrorKind::NotFound => {
return Ok(crate::delivery::files::OutputProtection::new(
protected_files,
vec![
self.settings.data_directory.clone(),
self.settings.archives_directory.clone(),
],
));
}
Err(_) => return Err(crate::delivery::files::FileOutputError::UnsafePath),
}
match fs::read_dir(source_directory) {
Ok(entries) => {
let mut count = 0usize;
for entry in entries {
let entry = entry.map_err(|_| crate::delivery::files::FileOutputError::Io)?;
count += 1;
if count > crate::vault::source::MAX_DIRECTORY_ENTRIES {
return Err(crate::delivery::files::FileOutputError::UnsafePath);
}
protected_files.push(entry.path());
}
}
Err(error) if error.kind() == io::ErrorKind::NotFound => {}
Err(_) => return Err(crate::delivery::files::FileOutputError::UnsafePath),
}
Ok(crate::delivery::files::OutputProtection::new(
protected_files,
vec![
self.settings.data_directory.clone(),
self.settings.archives_directory.clone(),
],
))
}
}
#[derive(Deserialize, Serialize)]