keyhog 0.5.73

GPU-accelerated secret scanner for code, Git history, cloud, containers, browser assets, and live credential verification
use std::path::PathBuf;

/// On-disk `.keyhog.toml` root. Each setting has one table/key owner, and CLI
/// flags override the corresponding file value.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub(crate) struct ConfigFile {
    /// Path to detector TOMLs directory.
    pub detectors: Option<String>,
    /// Composition policy for an explicitly selected detector directory.
    pub detectors_mode: Option<String>,
    /// Enable fast mode (no entropy discovery, ML scoring, or decode recursion).
    pub fast: Option<bool>,
    /// Enable the bounded deep-recovery preset.
    pub deep: Option<bool>,
    /// Enable high-precision mass-scan mode.
    pub precision: Option<bool>,
    /// Skip decode-through scanning.
    pub no_decode: Option<bool>,
    /// Skip entropy-based detection.
    pub no_entropy: Option<bool>,
    /// Whether to verify discovered credentials.
    pub verify: Option<bool>,
    /// Verification timeout in seconds.
    pub timeout: Option<u64>,
    /// Maximum concurrent verification requests per service.
    pub verify_concurrency: Option<usize>,
    /// Maximum git commits to traverse.
    pub max_commits: Option<usize>,
    /// Show full credentials (not redacted).
    pub show_secrets: Option<bool>,
    /// Maximum file size for decode-through scanning.
    pub decode_size_limit: Option<String>,
    /// Enable entropy scanning in source code files.
    pub entropy_source_files: Option<bool>,
    /// Admit credential-keyword-anchored generic values on a relaxed entropy floor.
    pub generic_keyword_low_entropy: Option<bool>,
    /// Disable Unicode normalization.
    pub no_unicode_norm: Option<bool>,
    /// Disable ML-based confidence scoring.
    pub no_ml: Option<bool>,
    /// Maximum file size to scan.
    pub max_file_size: Option<String>,
    /// Per-regex lazy-DFA cache ceiling.
    pub regex_dfa_limit: Option<String>,
    /// ML weight for confidence scoring, 0.0-1.0.
    pub ml_weight: Option<f64>,
    /// Known secret prefixes used to boost confidence.
    pub known_prefixes: Option<Vec<String>>,
    /// Keywords indicating a secret context.
    pub secret_keywords: Option<Vec<String>>,
    /// Keywords indicating a test/mock context.
    pub test_keywords: Option<Vec<String>>,
    /// Keywords indicating a placeholder value.
    pub placeholder_keywords: Option<Vec<String>>,
    /// `[scan]` - canonical runtime scan policy.
    pub scan: Option<ScanSection>,
    /// `[allowlist]` - `.keyhogignore` discovery + governance metadata.
    pub allowlist: Option<AllowlistSection>,
    /// `[detector.<id>]` - per-detector overrides keyed by detector_id.
    pub detector: Option<std::collections::HashMap<String, DetectorSection>>,
    /// `[lockdown]` - refuse to start unless explicit `--lockdown` flag.
    pub lockdown: Option<LockdownSection>,
    /// `[limits]` - source byte/count ceilings.
    pub limits: Option<LimitsSection>,
    /// `[http]` - explicit outbound HTTP proxy/TLS policy.
    pub http: Option<HttpSection>,
    /// `[system]` - host integration paths and other non-scan behavior.
    pub system: Option<SystemSection>,
    /// `[aws]` - AWS-specific offline safety metadata.
    pub aws: Option<AwsSection>,
    /// `[tuning]` - recall-equivalent scanner route tuning.
    pub tuning: Option<TuningSection>,
    /// `[guard]` - perpetual repository and filesystem guard settings.
    pub guard: Option<GuardSection>,
}

/// Canonical `[scan]` table. Scan-policy keys have one on-disk owner here.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct ScanSection {
    pub severity: Option<String>,
    pub min_confidence: Option<f64>,
    pub ml_threshold: Option<f64>,
    /// Shannon entropy threshold in bits per byte.
    pub entropy_threshold: Option<f64>,
    /// BPE word-likeness ceiling.
    pub entropy_bpe_max_bytes_per_token: Option<f64>,
    pub decode_depth: Option<usize>,
    pub min_secret_len: Option<usize>,
    pub format: Option<String>,
    pub exclude: Option<Vec<String>>,
    pub threads: Option<usize>,
    pub reader_threads: Option<usize>,
    pub fused_batch: Option<usize>,
    pub fused_depth: Option<usize>,
    pub per_chunk_timeout_ms: Option<u64>,
    pub dedup: Option<String>,
    pub incremental: Option<bool>,
    pub incremental_cache: Option<PathBuf>,
    /// GPU region-presence batch byte budget.
    pub gpu_batch_input_limit: Option<String>,
}

/// `[allowlist]` nested table.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct AllowlistSection {
    pub file: Option<String>,
    pub require_reason: Option<bool>,
    pub require_approved_by: Option<bool>,
    pub max_expires_days: Option<u64>,
}

/// `[detector.<id>]` per-detector override.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct DetectorSection {
    pub enabled: Option<bool>,
    pub min_confidence: Option<f64>,
}

/// `[lockdown]` enforcement.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub(crate) struct LockdownSection {
    pub require: Option<bool>,
}

/// `[limits]` source byte/count ceilings.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct LimitsSection {
    pub stdin_bytes: Option<String>,
    pub web_response_bytes: Option<String>,
    pub s3_object_bytes: Option<String>,
    pub gcs_object_bytes: Option<String>,
    pub azure_blob_bytes: Option<String>,
    pub cloud_max_objects: Option<usize>,
    pub docker_tar_entry_bytes: Option<String>,
    pub docker_image_config_bytes: Option<String>,
    pub docker_tar_total_bytes: Option<String>,
    pub git_line_bytes: Option<String>,
    pub git_total_bytes: Option<String>,
    pub git_blob_bytes: Option<String>,
    pub git_chunks: Option<usize>,
    pub hosted_git_pages: Option<usize>,
    pub binary_read_bytes: Option<String>,
    pub binary_decompiled_bytes: Option<String>,
}

/// `[http]` explicit outbound HTTP policy.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct HttpSection {
    /// Proxy URL or `off`.
    pub proxy: Option<String>,
    /// Disable TLS certificate verification for outbound HTTP.
    pub insecure_tls: Option<bool>,
    /// Allow cloud endpoints (`--s3-endpoint`, GCS / Azure container URLs) whose
    /// host resolves private / loopback / link-local / cloud-metadata. Off by
    /// default (the SSRF screen refuses them); the `--allow-private-cloud-endpoint`
    /// CLI flag overrides. For trusted private-network deployments only.
    pub allow_private_endpoint: Option<bool>,
}

/// `[system]` host integration settings.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct SystemSection {
    /// Absolute directories allowed by `keyhog_core::safe_bin` in addition to
    /// the compiled system defaults.
    pub trusted_bin_dirs: Option<Vec<PathBuf>>,
    /// Absolute Hyperscan compiled-database cache directory.
    pub cache_dir: Option<PathBuf>,
    /// Absolute autoroute calibration cache file, or `off` to disable.
    pub autoroute_cache: Option<String>,
    /// Absolute MatcherArtifact cache directory, or `off` to disable.
    pub matcher_cache: Option<String>,
    /// Absolute per-detector Bayesian calibration cache file for scan scoring.
    pub calibration_cache: Option<PathBuf>,
    /// Force the coalesced batch scan pipeline.
    pub batch_pipeline: Option<bool>,
    /// GPU runtime policy: auto, off, or required.
    pub gpu: Option<String>,
    /// Allow autoroute calibration to include GPU candidates.
    pub autoroute_gpu: Option<bool>,
}

/// `[aws]` offline AWS safety metadata.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct AwsSection {
    /// Extra 12-digit AWS account IDs treated as canary-token issuers.
    pub canary_accounts: Option<Vec<String>>,
    /// Extra 12-digit AWS account IDs treated as off-brand canary issuers.
    pub knockoff_accounts: Option<Vec<String>>,
}

/// `[tuning]` scanner performance-route overrides.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct TuningSection {
    pub fallback_hs: Option<bool>,
    pub hs_prefilter_max_len: Option<usize>,
    pub hs_shard_target: Option<usize>,
    pub fallback_anchor: Option<bool>,
    pub homoglyph_gate: Option<bool>,
    pub homoglyph_ascii_skip: Option<bool>,
    pub fallback_reverse: Option<bool>,
    pub prefilter_truncate: Option<bool>,
    pub fallback_prefix_gate: Option<bool>,
    pub decode_focus: Option<bool>,
    pub confirmed_suffix_gate: Option<bool>,
    pub confirmed_companion_gate: Option<bool>,
    pub no_candidate_gate: Option<bool>,
    pub fallback_localizer: Option<bool>,
    pub gpu_recall_floor: Option<bool>,
    pub chunk_lane_threshold: Option<usize>,
}

/// `[guard]` perpetual repository and filesystem guard settings.
///
/// Every persisted configuration shape is versioned. Changing its semantics
/// requires a version bump and a stale-copy rejection test.
#[derive(Debug, Default, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub(crate) struct GuardSection {
    /// Hot clean attestation index memory budget (e.g. "64MiB").
    pub hot_index_memory: Option<String>,
    /// Maximum queued events per root.
    pub max_pending_events_per_root: Option<usize>,
    /// Maximum total queued events across all roots.
    pub max_pending_events_total: Option<usize>,
    /// Coalescing window (e.g. "100ms").
    pub coalesce_window: Option<String>,
    /// Scanner residency: "warm" or "idle-unload".
    pub scanner_residency: Option<String>,
    /// Scanner idle-unload timeout (e.g. "5m").
    pub scanner_idle_timeout: Option<String>,
    /// Periodic scrub interval (e.g. "24h").
    pub scrub_interval: Option<String>,
    /// Maximum files for one subtree reconciliation.
    pub subtree_max_files: Option<usize>,
    /// Maximum depth for one subtree reconciliation.
    pub subtree_max_depth: Option<usize>,
    /// Durable guard state path (e.g. "~/.local/state/keyhog/guard.redb").
    /// When set, root records and attestations persist across daemon restarts.
    pub state_path: Option<String>,
}