use anyhow::{Context, Result};
use std::path::{Path, PathBuf};
use crate::orchestrator_config::ResolvedAllowlistConfig;
pub(crate) fn load_allowlist(
scan_path: Option<&Path>,
config: &ResolvedAllowlistConfig,
) -> Result<keyhog_core::Allowlist> {
let base_path = scan_path
.map(allowlist_root)
.unwrap_or_else(|| PathBuf::from(".")); let configured_file = config.file.is_some();
let ignore_path = match config.file.as_ref() {
Some(path) => path.clone(),
None => base_path.join(".keyhogignore"),
};
if configured_file || ignore_path.exists() {
let _load_span = keyhog_profile::span(keyhog_profile::Stage::Preprocess);
keyhog_core::Allowlist::load_with_metadata_policy(
&ignore_path,
config.require_reason,
config.require_approved_by,
config.max_expires_days,
)
.with_context(|| {
format!(
"failed to load {}. Fix or remove the allowlist; refusing to scan with silently ignored policy.",
ignore_path.display()
)
})
} else {
Ok(keyhog_core::Allowlist::default())
}
}
pub(crate) fn load_rule_suppressor(
scan_path: Option<&Path>,
) -> Result<keyhog_core::RuleSuppressor> {
let base_path = scan_path
.map(allowlist_root)
.unwrap_or_else(|| PathBuf::from(".")); let toml_path = base_path.join(".keyhogignore.toml");
if !toml_path.exists() {
return Ok(keyhog_core::RuleSuppressor::default());
}
let raw = std::fs::read_to_string(&toml_path).with_context(|| {
format!(
"failed to read {}. Fix file permissions or remove the file; refusing to scan \
with silently ignored suppression rules.",
toml_path.display()
)
})?;
let _compile_span = keyhog_profile::span(keyhog_profile::Stage::Preprocess);
match raw.parse::<keyhog_core::RuleSuppressor>() {
Ok(s) => {
tracing::debug!(
file = %toml_path.display(),
"loaded declarative suppression policy"
);
Ok(s)
}
Err(e) => anyhow::bail!(
"failed to load {}: {e}. Fix the TOML schema (see docs/src/reference/keyhogignore-toml.md) \
or remove the file; refusing to scan with silently ignored suppression rules.",
toml_path.display()
),
}
}
pub(crate) fn allowlist_root(path: &Path) -> PathBuf {
if path.is_dir() {
return path.to_path_buf();
}
if path.is_file() {
return path
.parent()
.filter(|p| !p.as_os_str().is_empty())
.map(Path::to_path_buf)
.unwrap_or_else(|| PathBuf::from(".")); }
let has_extension = path.extension().is_some();
let parent_opt = path.parent().filter(|p| !p.as_os_str().is_empty());
match (has_extension, parent_opt) {
(true, Some(parent)) => parent.to_path_buf(),
(false, Some(_)) => path.to_path_buf(),
(_, None) => PathBuf::from("."),
}
}