use std::path::{Path, PathBuf};
pub struct VaultPaths {
root: PathBuf,
}
impl VaultPaths {
pub fn new(root: impl Into<PathBuf>) -> Self {
Self { root: root.into() }
}
pub fn vault_dir(&self) -> PathBuf {
self.root.join(".agent-vault")
}
pub fn config_file(&self) -> PathBuf {
self.vault_dir().join("config.yaml")
}
pub fn owner_pub_file(&self) -> PathBuf {
self.vault_dir().join("owner.pub")
}
pub fn manifest_file(&self) -> PathBuf {
self.vault_dir().join("manifest.yaml")
}
pub fn gitignore_file(&self) -> PathBuf {
self.vault_dir().join(".gitignore")
}
pub fn agents_dir(&self) -> PathBuf {
self.vault_dir().join("agents")
}
pub fn agent_dir(&self, name: &str) -> PathBuf {
self.agents_dir().join(name)
}
pub fn agent_pub_file(&self, name: &str) -> PathBuf {
self.agent_dir(name).join("public.key")
}
pub fn agent_escrow_file(&self, name: &str) -> PathBuf {
self.agent_dir(name).join("private.key.escrow")
}
pub fn secrets_dir(&self) -> PathBuf {
self.vault_dir().join("secrets")
}
pub fn secret_enc_file(&self, path: &str) -> PathBuf {
let (group, name) = split_secret_path(path);
self.secrets_dir().join(group).join(format!("{name}.enc"))
}
pub fn secret_meta_file(&self, path: &str) -> PathBuf {
let (group, name) = split_secret_path(path);
self.secrets_dir().join(group).join(format!("{name}.meta"))
}
pub fn root(&self) -> &Path {
&self.root
}
}
pub fn owner_key_path() -> PathBuf {
home_vault_dir().join("owner.key")
}
pub fn agent_key_path(name: &str) -> PathBuf {
home_vault_dir().join("agents").join(format!("{name}.key"))
}
pub fn home_vault_dir() -> PathBuf {
dirs::home_dir()
.expect("could not determine home directory")
.join(".agent-vault")
}
fn split_secret_path(path: &str) -> (&str, &str) {
match path.split_once('/') {
Some((group, name)) => (group, name),
None => ("default", path),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_split_secret_path() {
assert_eq!(split_secret_path("stripe/api-key"), ("stripe", "api-key"));
assert_eq!(split_secret_path("my-secret"), ("default", "my-secret"));
}
#[test]
fn test_vault_paths() {
let paths = VaultPaths::new("/tmp/repo");
assert_eq!(paths.vault_dir(), PathBuf::from("/tmp/repo/.agent-vault"));
assert_eq!(
paths.secret_enc_file("stripe/api-key"),
PathBuf::from("/tmp/repo/.agent-vault/secrets/stripe/api-key.enc")
);
}
}