1use std::path::{Path, PathBuf};
6
7#[derive(Debug, Clone)]
10pub struct NodePaths {
11 pub config_path: PathBuf,
12 pub device_key_path: PathBuf,
13 pub user_key_path: PathBuf,
14 pub roster_path: PathBuf,
15 pub state_db_path: PathBuf,
16 pub blobs_dir: PathBuf,
17 pub blob_scopes_path: PathBuf,
18 pub audit_dir: PathBuf,
19}
20
21impl NodePaths {
22 pub fn under_root(root: &Path) -> Self {
25 let config = root.join("config");
26 let data = root.join("data");
27 NodePaths {
28 config_path: config.join("config.toml"),
29 device_key_path: config.join("device.key"),
30 user_key_path: config.join("user.key"),
31 roster_path: config.join("roster.json"),
32 state_db_path: data.join("state.redb"),
33 blobs_dir: data.join("blobs"),
34 blob_scopes_path: data.join("blob-scopes.json"),
35 audit_dir: root.join("state").join("audit"),
36 }
37 }
38
39 pub fn from_env() -> std::io::Result<Self> {
43 use mcpmesh_trust::paths as p;
44 Ok(NodePaths {
45 config_path: p::default_config_path()?,
46 device_key_path: p::default_device_key_path()?,
47 user_key_path: p::default_user_key_path()?,
48 roster_path: p::default_roster_path()?,
49 state_db_path: p::default_state_db_path()?,
50 blobs_dir: p::default_blobs_dir()?,
51 blob_scopes_path: p::default_blob_scopes_path()?,
52 audit_dir: p::default_audit_dir()?,
53 })
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use std::path::Path;
61
62 #[test]
66 fn under_root_matches_the_profile_layout() {
67 let p = NodePaths::under_root(Path::new("/r"));
68 assert_eq!(p.config_path, Path::new("/r/config/config.toml"));
69 assert_eq!(p.device_key_path, Path::new("/r/config/device.key"));
70 assert_eq!(p.user_key_path, Path::new("/r/config/user.key"));
71 assert_eq!(p.roster_path, Path::new("/r/config/roster.json"));
72 assert_eq!(p.state_db_path, Path::new("/r/data/state.redb"));
73 assert_eq!(p.blobs_dir, Path::new("/r/data/blobs"));
74 assert_eq!(p.blob_scopes_path, Path::new("/r/data/blob-scopes.json"));
75 assert_eq!(p.audit_dir, Path::new("/r/state/audit"));
76 }
77}