pub struct ScannerConfig {
pub scan: ScanConfig,
pub entropy_bpe_max_bytes_per_token_override: Option<f64>,
pub ml_weight_override: Option<f64>,
pub multiline: MultilineConfig,
pub penalize_test_paths: bool,
pub per_chunk_timeout_ms: Option<u64>,
pub profile: bool,
pub perf_trace: bool,
pub calibration: Option<Arc<Calibration>>,
}Expand description
Scanner-side configuration: the canonical ScanConfig, the single owned
source of truth for every shared detection knob (decode depth, entropy, ML,
confidence floor, keyword lists, …). PLUS the two knobs that are
scanner-crate-local and have no place on keyhog-core’s ScanConfig:
multiline: its type ([crate::multiline::MultilineConfig]) is defined in THIS crate, andkeyhog-corecannot depend onkeyhog-scannerwithout a dependency cycle, so the field cannot live onScanConfig.penalize_test_paths: a scanner-internal suppression toggle the CLI flips for--no-suppress-test-fixtures; it never appears on the on-disk config.
This is the “thin newtype over ScanConfig” MC-01 calls for. It deliberately
does not restate any of ScanConfig’s fields: every shared knob is read
and written straight through Deref/DerefMut (config.min_confidence,
config.entropy_enabled, config.known_prefixes, …), so there is exactly
ONE definition of each, no parallel field list that can drift, and the
From<ScanConfig> impl below is a structural wrap, never a hand-maintained
field-by-field copy.
ScanConfig’s max_file_size / dedup fields are reachable through the
deref but are NOT consumed by the scan engine, they are enforced elsewhere
(the source walker and the verifier) and carry that caveat in their own doc
comments on ScanConfig. Their presence here is the wrapped truth, not a
second silent copy. min_secret_len is consumed by the entropy fallback.
Fields§
§scan: ScanConfigThe canonical shared detection config, single source of truth for every
knob the engine and CLI agree on. Reached transparently via Deref, so
callers write config.min_confidence, not config.scan.min_confidence.
entropy_bpe_max_bytes_per_token_override: Option<f64>Explicit Tier-A scan override for detector-local BPE policy. None
means each detector TOML owns its ceiling and the wrapped ScanConfig
value is only the compatibility fallback. Some means TOML/CLI scan
configuration explicitly requested one ceiling for every eligible
detector; CLI/config presence is preserved so precedence remains
compiled default -> detector TOML -> scan TOML -> CLI.
ml_weight_override: Option<f64>Explicit Tier-A override for detector-local ML scoring weights. None
keeps each detector TOML authoritative; presence applies one diagnostic
or benchmarking override across eligible detector paths.
multiline: MultilineConfigConfiguration for multiline concatenation (scanner-local type).
penalize_test_paths: boolApply test/example path confidence and hard-suppression heuristics.
The CLI disables this for --no-suppress-test-fixtures.
per_chunk_timeout_ms: Option<u64>Optional caller-resolved per-chunk scan deadline in milliseconds.
profile: boolEmit the scanner-owned hierarchical profile report to stderr.
perf_trace: boolEmit low-level phase timing traces for GPU/perf investigation.
calibration: Option<Arc<Calibration>>Explicit per-detector Bayesian calibration store. Absent means the scan is hermetic and score-stable; the scanner never reads a default disk cache on its own because that would make findings depend on stray host state.
Implementations§
Source§impl ScannerConfig
impl ScannerConfig
Sourcepub const HIGH_PRECISION_MIN_CONFIDENCE: f64 = 0.85
pub const HIGH_PRECISION_MIN_CONFIDENCE: f64 = 0.85
Confidence floor for ScannerConfig::high_precision. Distinct from the
canonical ScanConfig::default() floor (0.40) on purpose: precision mode
trades recall for a near-zero false-positive rate at mass-scan scale.
Sourcepub const DEEP_MAX_DECODE_BYTES: usize = crate::types::MAX_SCAN_CHUNK_BYTES
pub const DEEP_MAX_DECODE_BYTES: usize = crate::types::MAX_SCAN_CHUNK_BYTES
Deep mode admits one complete production scan chunk into decode-through. The default stays at 512 KiB to bound routine work; deep intentionally spends more memory and CPU to recover encoded values anywhere in a filesystem window.
pub fn fast() -> Self
pub fn thorough() -> Self
Sourcepub fn high_precision() -> Self
pub fn high_precision() -> Self
High-precision mass-scan preset: minimise false positives at the cost of some recall, for scanning huge corpora where every FP is expensive to triage. Fully offline, with ML confidence scoring, no entropy sweep, and shallow decode.
entropy_enabled = false: generic high-entropy matching is the single largest FP source; precision mode drops it entirely.ml_enabled = true(inherited): ML is the confidence discriminator that lifts genuine secrets over the high floor while leaving FP-shaped tokens below it. Disabling it would crater the scores the 0.85 bar relies on, so precision KEEPS ML (this mode trades recall for precision, not for speed (use--fastwhen speed is the goal)).min_confidence = HIGH_PRECISION_MIN_CONFIDENCE(0.85): combined with the engine’s checksum policy (valid token → floored 0.9, invalid → capped 0.1) and clamped over every detector’s self-declared floor, this bar admits checksum-validated tokens and strong ML-scored findings while dropping checksum-failures and weak-signal matches.max_decode_depth = 1: deep-decoded payloads are a FP source at scale.
penalize_test_paths stays on (the default) to suppress fixture-shaped
hits. A --min-confidence override still layers on top of this preset.
pub fn min_confidence(self, min_confidence: f64) -> Self
Sourcepub fn sanitise(&mut self)
pub fn sanitise(&mut self)
Clamp every float field into its valid range and replace any
NaN with a safe default. A user-supplied
--min-confidence=-5.0 or a corrupt config TOML feeding
min_confidence = nan would otherwise NaN-infect the
confidence-comparison path and silently drop every finding
(NaN comparisons are always false, so conf < min_confidence
is false, but conf >= min_confidence is also false,
behaviour-dependent on the call site).
Idempotent - sanitising an already-sane config is a no-op.
Called inside From<ScanConfig> so any path that constructs
a ScannerConfig from a user-influenced source pays this
once at config-build time.
pub fn with_calibration(self, calibration: Arc<Calibration>) -> Self
Sourcepub fn with_entropy_bpe_max_bytes_per_token_override(
self,
bound: f64,
) -> Result<Self, ConfigError>
pub fn with_entropy_bpe_max_bytes_per_token_override( self, bound: f64, ) -> Result<Self, ConfigError>
Set an explicit scan-wide BPE ceiling while preserving presence even
when bound equals the compiled fallback. Library callers should use
this instead of relying on From<ScanConfig> when they intend a value
of 2.2 to override detector-local TOML policy: ScanConfig stores only
the number and cannot distinguish “omitted default” from “explicitly set
to the default.” The complete shared scan config is validated before the
override is accepted, so invalid programmatic policy fails closed.
Sourcepub fn with_ml_weight_override(self, weight: f64) -> Result<Self, ConfigError>
pub fn with_ml_weight_override(self, weight: f64) -> Result<Self, ConfigError>
Set an explicit scan-wide model-weight override. Ordinary scans should leave this absent so detector TOMLs retain their calibrated weights.
Methods from Deref<Target = ScanConfig>§
Sourcepub fn validate(&self) -> Result<(), ConfigError>
pub fn validate(&self) -> Result<(), ConfigError>
Validate the configuration parameters, failing closed on any value that
would silently break scanning. This is the “separate later step” the
deserialize path deliberately omits (see the regression_scan_config_fields
contract): ScanConfig::from_toml_str composes deserialize + this into
one validated load, and a library consumer who builds a ScanConfig by
hand calls it directly before handing the config to the engine.
Every check is NaN-safe: RangeInclusive::contains is false for NaN
(so a NaN bound is rejected, not silently admitted), and the entropy
checks reject non-finite values explicitly.
Trait Implementations§
Source§impl Clone for ScannerConfig
impl Clone for ScannerConfig
Source§fn clone(&self) -> ScannerConfig
fn clone(&self) -> ScannerConfig
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ScannerConfig
impl Debug for ScannerConfig
Source§impl Default for ScannerConfig
impl Default for ScannerConfig
Source§impl Deref for ScannerConfig
impl Deref for ScannerConfig
Source§type Target = ScanConfig
type Target = ScanConfig
Source§fn deref(&self) -> &ScanConfig
fn deref(&self) -> &ScanConfig
Source§impl DerefMut for ScannerConfig
impl DerefMut for ScannerConfig
Source§fn deref_mut(&mut self) -> &mut ScanConfig
fn deref_mut(&mut self) -> &mut ScanConfig
Source§impl From<ScanConfig> for ScannerConfig
impl From<ScanConfig> for ScannerConfig
Source§fn from(scan: ScanConfig) -> Self
fn from(scan: ScanConfig) -> Self
Auto Trait Implementations§
impl !RefUnwindSafe for ScannerConfig
impl !UnwindSafe for ScannerConfig
impl Freeze for ScannerConfig
impl Send for ScannerConfig
impl Sync for ScannerConfig
impl Unpin for ScannerConfig
impl UnsafeUnpin for ScannerConfig
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more