auths_cli/factories/
storage.rs1use std::path::Path;
2use std::sync::Arc;
3
4use anyhow::Result;
5use auths_infra_git::GitRepo;
6use auths_sdk::attestation::AttestationSink;
7use auths_sdk::context::AuthsContext;
8use auths_sdk::core_config::EnvironmentConfig;
9use auths_sdk::keychain::get_platform_keychain_with_config;
10use auths_sdk::ports::AttestationSource;
11use auths_sdk::ports::CoreStorageError as StorageError;
12use auths_sdk::ports::IdentityStorage;
13use auths_sdk::ports::RegistryBackend;
14use auths_sdk::ports::SystemClock;
15use auths_sdk::signing::PassphraseProvider;
16use auths_sdk::storage::{
17 GitRegistryBackend, RegistryAttestationStorage, RegistryConfig, RegistryIdentityStorage,
18};
19
20pub fn open_git_repo(path: &Path) -> Result<GitRepo, StorageError> {
32 GitRepo::open(path)
33}
34
35pub fn init_git_repo(path: &Path) -> Result<GitRepo, StorageError> {
45 GitRepo::init(path)
46}
47
48pub fn ensure_git_repo(path: &Path) -> Result<GitRepo, StorageError> {
62 if path.exists() {
63 match GitRepo::open(path) {
64 Ok(repo) => Ok(repo),
65 Err(_) => GitRepo::init(path),
66 }
67 } else {
68 std::fs::create_dir_all(path)
69 .map_err(|e| StorageError::Io(format!("failed to create directory: {}", e)))?;
70 GitRepo::init(path)
71 }
72}
73
74pub fn discover_git_repo(start_path: &Path) -> Result<std::path::PathBuf, StorageError> {
86 let repo = git2::Repository::discover(start_path)
87 .map_err(|e| StorageError::not_found(format!("no Git repository found: {}", e)))?;
88 let path: &Path = repo
89 .workdir()
90 .or_else(|| repo.path().parent())
91 .ok_or_else(|| StorageError::Io("could not determine repository path".into()))?;
92 Ok(path.to_path_buf())
93}
94
95pub fn build_auths_context(
111 repo_path: &Path,
112 env_config: &EnvironmentConfig,
113 passphrase_provider: Option<Arc<dyn PassphraseProvider + Send + Sync>>,
114) -> Result<AuthsContext> {
115 let backend: Arc<dyn RegistryBackend + Send + Sync> = Arc::new(
116 GitRegistryBackend::from_config_unchecked(RegistryConfig::single_tenant(repo_path)),
117 );
118 let identity_storage: Arc<dyn IdentityStorage + Send + Sync> =
119 Arc::new(RegistryIdentityStorage::new(repo_path.to_path_buf()));
120 let attestation_store = Arc::new(RegistryAttestationStorage::new(repo_path));
121 let attestation_sink: Arc<dyn AttestationSink + Send + Sync> =
122 Arc::clone(&attestation_store) as Arc<dyn AttestationSink + Send + Sync>;
123 let attestation_source: Arc<dyn AttestationSource + Send + Sync> =
124 attestation_store as Arc<dyn AttestationSource + Send + Sync>;
125 let key_storage = get_platform_keychain_with_config(env_config)
126 .map_err(|e| anyhow::anyhow!("Failed to initialize keychain: {}", e))?;
127 let mut builder = AuthsContext::builder()
128 .registry(backend)
129 .key_storage(Arc::from(key_storage))
130 .clock(Arc::new(SystemClock))
131 .identity_storage(identity_storage)
132 .attestation_sink(attestation_sink)
133 .attestation_source(attestation_source);
134 builder = builder.agent_signing(crate::factories::build_agent_provider());
135 if let Some(pp) = passphrase_provider {
136 builder = builder.passphrase_provider(pp);
137 }
138 Ok(builder.build())
139}
140
141pub fn read_git_config(key: &str) -> Result<Option<String>, StorageError> {
151 let config = git2::Config::open_default()
152 .map_err(|e| StorageError::Io(format!("failed to open git config: {}", e)))?;
153 match config.get_string(key) {
154 Ok(value) => Ok(Some(value)),
155 Err(_) => Ok(None),
156 }
157}