use anyhow::{Context, Result, anyhow};
pub fn load_project_pinned_roots() -> Vec<String> {
let Ok(output) = crate::subprocess::git_command(&["rev-parse", "--show-toplevel"]).output()
else {
return Vec::new();
};
if !output.status.success() {
return Vec::new();
}
let root = std::path::PathBuf::from(String::from_utf8_lossy(&output.stdout).trim());
auths_sdk::workflows::roots::load_pinned_roots(
&crate::adapters::config_store::FileConfigStore,
&root.join(".auths"),
)
.unwrap_or_default()
}
pub fn discover_project_bundle() -> Option<std::path::PathBuf> {
let output = crate::subprocess::git_command(&["rev-parse", "--show-toplevel"])
.output()
.ok()?;
if !output.status.success() {
return None;
}
let root = std::path::PathBuf::from(String::from_utf8_lossy(&output.stdout).trim());
let bundle = root.join(".auths").join("ci-bundle.json");
bundle.is_file().then_some(bundle)
}
pub fn freshness_label(freshness: auths_verifier::Freshness) -> &'static str {
match freshness {
auths_verifier::Freshness::Fresh => "fresh",
auths_verifier::Freshness::Unknown => "unknown",
auths_verifier::Freshness::Stale => "stale",
}
}
pub fn parse_witness_keys(keys: &[String]) -> Result<Vec<(String, Vec<u8>)>> {
keys.iter()
.map(|s| {
let last_colon = s
.rfind(':')
.ok_or_else(|| anyhow!("Invalid witness key format '{}': expected format: <did>:<public_key_hex> (e.g. did:key:z6Mk...:abcd1234)", s))?;
let did = &s[..last_colon];
let pk_hex = &s[last_colon + 1..];
let pk_bytes = hex::decode(pk_hex)
.with_context(|| format!("Invalid hex in witness key for '{}'", did))?;
Ok((did.to_string(), pk_bytes))
})
.collect()
}
pub fn require_registry(configured: Option<String>) -> Result<String> {
configured.ok_or_else(|| {
anyhow!(
"{}\nOur public registry is {} — pass it, or point --registry at your own.",
auths_sdk::domains::identity::error::RegistrationError::NoRegistryConfigured,
auths_sdk::PUBLIC_REGISTRY_URL
)
})
}