Skip to main content

gloves_core/
paths.rs

1use std::path::{Path, PathBuf};
2
3const DEFAULT_AGENT_ID: &str = "default-agent";
4const AGENTS_DIR_NAME: &str = "agents";
5const AGE_KEY_FILE_NAME: &str = "age.key";
6const SIGNING_KEY_FILE_NAME: &str = "signing.key";
7const GPG_DIR_NAME: &str = "gpg";
8
9/// Canonical path layout for secrets runtime files.
10#[derive(Debug, Clone)]
11pub struct SecretsPaths {
12    root: PathBuf,
13}
14
15impl SecretsPaths {
16    /// Creates a path layout rooted at `root`.
17    pub fn new(root: impl AsRef<Path>) -> Self {
18        Self {
19            root: root.as_ref().to_path_buf(),
20        }
21    }
22
23    /// Root directory.
24    pub fn root(&self) -> &Path {
25        &self.root
26    }
27
28    /// Agent ciphertext store directory.
29    pub fn store_dir(&self) -> PathBuf {
30        self.root.join("store")
31    }
32
33    /// Secret metadata directory.
34    pub fn metadata_dir(&self) -> PathBuf {
35        self.root.join("meta")
36    }
37
38    /// Pending requests JSON file.
39    pub fn pending_file(&self) -> PathBuf {
40        self.root.join("pending.json")
41    }
42
43    /// Audit log JSONL file.
44    pub fn audit_file(&self) -> PathBuf {
45        self.root.join("audit.jsonl")
46    }
47
48    /// Default age identity file for CLI agent.
49    pub fn default_identity_file(&self) -> PathBuf {
50        self.identity_file_for_agent(DEFAULT_AGENT_ID)
51    }
52
53    /// Canonical per-agent identity root.
54    pub fn agents_dir(&self) -> PathBuf {
55        self.root.join(AGENTS_DIR_NAME)
56    }
57
58    /// Canonical per-agent runtime directory.
59    pub fn agent_dir(&self, agent_id: &str) -> PathBuf {
60        self.agents_dir().join(agent_id)
61    }
62
63    /// Age identity file for one agent id.
64    pub fn identity_file_for_agent(&self, agent_id: &str) -> PathBuf {
65        self.agent_dir(agent_id).join(AGE_KEY_FILE_NAME)
66    }
67
68    /// Legacy root-level age identity file for one agent id.
69    pub fn legacy_identity_file_for_agent(&self, agent_id: &str) -> PathBuf {
70        self.root.join(format!("{agent_id}.agekey"))
71    }
72
73    /// Legacy namespaced-store age identity file for one agent id.
74    pub fn namespaced_identity_file_for_agent(&self, agent_id: &str) -> PathBuf {
75        self.root.join("identities").join(format!("{agent_id}.age"))
76    }
77
78    /// Default Ed25519 signing key file for CLI agent.
79    pub fn default_signing_key_file(&self) -> PathBuf {
80        self.signing_key_file_for_agent(DEFAULT_AGENT_ID)
81    }
82
83    /// Ed25519 signing key file for one agent id.
84    pub fn signing_key_file_for_agent(&self, agent_id: &str) -> PathBuf {
85        self.agent_dir(agent_id).join(SIGNING_KEY_FILE_NAME)
86    }
87
88    /// Legacy root-level Ed25519 signing key file for one agent id.
89    pub fn legacy_signing_key_file_for_agent(&self, agent_id: &str) -> PathBuf {
90        self.root.join(format!("{agent_id}.signing.key"))
91    }
92
93    /// Vault configuration directory.
94    pub fn vaults_dir(&self) -> PathBuf {
95        self.root.join("vaults")
96    }
97
98    /// Per-agent GPG homedir root.
99    pub fn gpg_homes_dir(&self) -> PathBuf {
100        self.agents_dir()
101    }
102
103    /// GPG homedir for one agent id.
104    pub fn gpg_home(&self, agent_id: &str) -> PathBuf {
105        self.agent_dir(agent_id).join(GPG_DIR_NAME)
106    }
107
108    /// Legacy GPG homedir for one agent id.
109    pub fn legacy_gpg_home(&self, agent_id: &str) -> PathBuf {
110        self.root.join(GPG_DIR_NAME).join(agent_id)
111    }
112
113    /// Vault session metadata file.
114    pub fn vault_sessions_file(&self) -> PathBuf {
115        self.vaults_dir().join("sessions.json")
116    }
117
118    /// Encrypted vault payload root directory.
119    pub fn encrypted_dir(&self) -> PathBuf {
120        self.root.join("encrypted")
121    }
122
123    /// Default vault mount root directory.
124    pub fn mounts_dir(&self) -> PathBuf {
125        self.root.join("mnt")
126    }
127
128    /// Path to one vault config file.
129    pub fn vault_config_file(&self, vault_name: &str) -> PathBuf {
130        self.vaults_dir().join(format!("{vault_name}.toml"))
131    }
132
133    /// Path to one vault ciphertext directory.
134    pub fn vault_cipher_dir(&self, vault_name: &str) -> PathBuf {
135        self.encrypted_dir().join(vault_name)
136    }
137
138    /// Path to one vault mountpoint.
139    pub fn vault_mountpoint(&self, vault_name: &str) -> PathBuf {
140        self.mounts_dir().join(vault_name)
141    }
142}