keyhog 0.5.73

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

use clap::{Parser, ValueEnum};

#[derive(Parser)]
pub struct DetectorArgs {
    /// Detector TOML directory
    #[arg(short, long, default_value = "detectors")]
    pub detectors: PathBuf,
    #[arg(skip)]
    pub(crate) detectors_cli_explicit: bool,
    /// Filter detectors by substring match (case-insensitive) against id,
    /// name, service, and keywords (e.g. `keyhog detectors --search aws`).
    ///
    /// The short `--help` line is intentionally count-free; the long `--help`
    /// (rendered via [`crate::args::command`]) injects the live embedded
    /// detector count so the cited corpus size can never drift from the
    /// detectors actually compiled into this binary.
    #[arg(short, long)]
    pub search: Option<String>,
    /// Print the matching-policy summary (regexes, keywords, companions,
    /// verification presence) instead of the grouped service summary. Pairs
    /// naturally with `--search`. Use `--format json` for the redaction-safe
    /// declared schema, including verification structure and test coverage.
    #[arg(short, long, default_value_t = false)]
    pub verbose: bool,
    /// Audit detectors against the quality gate (`keyhog_core::validate_detector`).
    /// Prints every issue grouped by detector and exits non-zero (3) if any
    /// `Error`-severity issue was found. Warnings are reported but do not
    /// fail the run. Pairs with `--detectors <DIR>` for CI gating.
    #[arg(long, conflicts_with = "fix")]
    pub audit: bool,
    /// Apply safe automated fixes to the detector TOMLs in `--detectors`.
    /// Currently rewrites single-brace template references (`{name}`) to
    /// the double-brace form (`{{name}}`) within `[detector.verify*]`
    /// blocks: the one fix the interpolator's contract makes safe to
    /// perform mechanically. Other validator findings are left alone
    /// (they need human judgement). Use `--dry-run` to preview rewrites
    /// without touching the filesystem.
    #[arg(long, conflicts_with = "audit")]
    pub fix: bool,
    /// Show the rewrites `--fix` *would* make without writing them. No-op
    /// unless `--fix` is also set.
    #[arg(long, requires = "fix")]
    pub dry_run: bool,
    /// Print the generated mechanism manifest: which recovery mechanisms each
    /// detector actually declares.
    ///
    /// KeyHog advertises regex matching, structural validation, entropy
    /// scoring, BPE token efficiency, decode recovery, companion
    /// confirmation, live verification, and detector-owned suppression, but
    /// nothing in the product will tell you which of those a given detector
    /// uses. This does, and it derives every answer from the loaded corpus:
    /// each mechanism is a predicate over detector TOML fields and the field
    /// that made it active is reported as its evidence, so there is no
    /// per-detector table in Rust to drift.
    ///
    /// A mechanism KeyHog cannot express yet is reported as unavailable with
    /// the reason rather than omitted, because a missing row cannot be told
    /// apart from "no detector uses this".
    ///
    /// Pairs with `--search` to scope the manifest, and with `--format json`
    /// for the machine-readable document. Does not scan.
    #[arg(long, conflicts_with_all = ["audit", "fix", "verbose"])]
    pub mechanisms: bool,
    /// Output format for the detector listing. `text` (default) is the grouped,
    /// human-readable summary; `json` emits the structured detector array. This
    /// is the canonical flag, it matches `scan --format` so the
    /// two surfaces share one convention (CLI-01). Only `text`/`json` apply to a
    /// detector listing, so the format set is intentionally narrower than
    /// `scan`'s. Mutually exclusive with `--audit` / `--fix` (they emit their own
    /// structured formats).
    #[arg(long, value_enum, conflicts_with_all = ["audit", "fix"])]
    pub format: Option<DetectorFormat>,
}

/// Output formats valid for the `detectors` listing. Deliberately a narrow
/// pair (not the full [`super::OutputFormat`]): a detector listing has exactly
/// one structured form (JSON) and one human form (text); SARIF/JUnit/CSV/HTML
/// are findings-report shapes with no meaning here, so offering them would be
/// an incoherent surface. Shares the `--format` flag *name* with `scan` for
/// convention parity (CLI-01) without sharing the irrelevant variants.
#[derive(Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum DetectorFormat {
    Text,
    Json,
}