refactor: formalize FileStore and IdentitySource ports in notfiles
- Create FileStore trait in crates/notfiles/src/ports.rs capturing all file I/O operations (read, write, rename, remove, metadata, symlink, etc.) - Create FileStoreImpl adapter in crates/notfiles/src/adapters/fs.rs wrapping std::fs - Update linker.rs State::load/save and link_package/unlink_package to accept FileStore parameter for dependency injection - Create IdentitySource port in crates/notsecrets/src/ports.rs - Move IdentitySource trait from sources/mod.rs to ports.rs, maintain backward compatibility via re-export - Update all source implementations to import from ports - Update lib.rs in both crates to re-export ports - Pass FileStoreImpl through call chain in main.rs and lib.rs public API Maintains 100% backward compatible public API; FileStore dependency is internal.
This commit is contained in:
@@ -3,6 +3,7 @@ pub mod encrypt;
|
||||
pub mod error;
|
||||
pub mod format;
|
||||
pub mod identities;
|
||||
pub mod ports;
|
||||
pub mod recipients;
|
||||
pub mod sources;
|
||||
|
||||
@@ -13,17 +14,18 @@ pub use identities::{
|
||||
EncryptedIdentity, FileKey, Header, Identity, ScryptIdentity, SshEd25519Identity,
|
||||
SshRsaIdentity, Stanza, X25519Identity,
|
||||
};
|
||||
pub use ports::IdentitySource;
|
||||
pub use recipients::{
|
||||
Recipient, ScryptRecipient, SshEd25519Recipient, SshRsaRecipient, X25519Recipient,
|
||||
};
|
||||
pub use sources::{BitwardenSource, FileSource, IdentitySource, PromptSource};
|
||||
pub use sources::{BitwardenSource, FileSource, PromptSource};
|
||||
|
||||
/// Try each `IdentitySource` in order; collect all identities that load successfully.
|
||||
///
|
||||
/// Returns an error only if all sources fail. Partial success is accepted because
|
||||
/// not every source needs to hold the key for the target file.
|
||||
pub fn resolve_identities(
|
||||
sources: Vec<Box<dyn sources::IdentitySource>>,
|
||||
sources: Vec<Box<dyn IdentitySource>>,
|
||||
) -> Result<Vec<Box<dyn Identity>>, AgeError> {
|
||||
let mut identities: Vec<Box<dyn Identity>> = Vec::new();
|
||||
let mut last_err: Option<AgeError> = None;
|
||||
@@ -51,7 +53,7 @@ pub fn resolve_identities(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::sources::IdentitySource;
|
||||
use crate::ports::IdentitySource;
|
||||
|
||||
struct AlwaysFailSource;
|
||||
impl IdentitySource for AlwaysFailSource {
|
||||
|
||||
12
crates/notsecrets/src/ports.rs
Normal file
12
crates/notsecrets/src/ports.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use crate::error::AgeError;
|
||||
use crate::identities::Identity;
|
||||
|
||||
/// Infra boundary trait: an identity resolver that loads key material from an
|
||||
/// external source and returns a concrete Identity.
|
||||
pub trait IdentitySource {
|
||||
/// Human-readable name of the identity source (e.g., "bitwarden", "file", "prompt").
|
||||
fn name(&self) -> &str;
|
||||
|
||||
/// Load and return a concrete identity from the source.
|
||||
fn load(&self) -> Result<Box<dyn Identity>, AgeError>;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::error::AgeError;
|
||||
use crate::identities::Identity;
|
||||
use crate::identities::x25519::X25519Identity;
|
||||
use crate::sources::IdentitySource;
|
||||
use crate::ports::IdentitySource;
|
||||
use std::io::Write;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::error::AgeError;
|
||||
use crate::identities::Identity;
|
||||
use crate::identities::encrypted::EncryptedIdentity;
|
||||
use crate::identities::x25519::X25519Identity;
|
||||
use crate::sources::IdentitySource;
|
||||
use crate::ports::IdentitySource;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct FileSource {
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
use crate::error::AgeError;
|
||||
use crate::identities::Identity;
|
||||
|
||||
pub mod bitwarden;
|
||||
pub mod file;
|
||||
pub mod prompt;
|
||||
|
||||
pub use crate::ports::IdentitySource;
|
||||
pub use bitwarden::BitwardenSource;
|
||||
pub use file::FileSource;
|
||||
pub use prompt::PromptSource;
|
||||
|
||||
/// Infra boundary trait: an identity resolver that loads key material from an
|
||||
/// external source and returns a concrete Identity.
|
||||
pub trait IdentitySource {
|
||||
fn name(&self) -> &str;
|
||||
fn load(&self) -> Result<Box<dyn Identity>, AgeError>;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::error::AgeError;
|
||||
use crate::identities::Identity;
|
||||
use crate::identities::scrypt::ScryptIdentity;
|
||||
use crate::sources::IdentitySource;
|
||||
use crate::ports::IdentitySource;
|
||||
|
||||
pub struct PromptSource;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user