CI / Check (push) Has been skipped
CI / Detect Changes (push) Successful in 5s
CI / Deploy Agent (push) Successful in 7m36s
CI / Deploy Dashboard (push) Successful in 7m9s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 1m44s
52 lines
1.9 KiB
Rust
52 lines
1.9 KiB
Rust
//! The target-classification port.
|
|
//!
|
|
//! A [`TargetClassifier`] inspects a target's artifacts (and optionally their
|
|
//! ingested working directories) and proposes one or more [`ClassifierVerdict`]s
|
|
//! — a target type, a confidence, and the facts the decision rested on. Concrete
|
|
//! classifiers live in the agent (language/build-system fingerprinting, a
|
|
//! firmware detector backed by tramiton, etc.); a registry merges and ranks
|
|
//! their verdicts. This mirrors the [`crate::traits::Scanner`] port so the two
|
|
//! read the same way.
|
|
|
|
use std::collections::HashMap;
|
|
use std::path::PathBuf;
|
|
|
|
use crate::error::CoreError;
|
|
use crate::models::{Artifact, DetectedFact, TargetType};
|
|
|
|
/// Everything a classifier needs to reason about a target.
|
|
pub struct ClassificationInput<'a> {
|
|
/// The artifacts declared for the target.
|
|
pub artifacts: &'a [Artifact],
|
|
/// Ingested working paths, keyed by [`Artifact::id`]. Absent for artifacts
|
|
/// with no on-disk form (e.g. a live URL).
|
|
pub working_paths: &'a HashMap<String, PathBuf>,
|
|
/// Free-form description of the target, if provided.
|
|
pub description: Option<&'a str>,
|
|
}
|
|
|
|
/// A single classifier's proposal for a target.
|
|
pub struct ClassifierVerdict {
|
|
/// The proposed target type.
|
|
pub target_type: TargetType,
|
|
/// Confidence in `[0.0, 1.0]`.
|
|
pub confidence: f32,
|
|
/// Facts that informed the proposal.
|
|
pub facts: Vec<DetectedFact>,
|
|
/// Human-readable explanation.
|
|
pub rationale: String,
|
|
}
|
|
|
|
/// A source of target-type classification.
|
|
#[allow(async_fn_in_trait)]
|
|
pub trait TargetClassifier: Send + Sync {
|
|
/// Stable identifier for this classifier (recorded in `detected_by`).
|
|
fn name(&self) -> &str;
|
|
|
|
/// Propose zero or more ranked verdicts for the given input.
|
|
async fn classify(
|
|
&self,
|
|
input: &ClassificationInput<'_>,
|
|
) -> Result<Vec<ClassifierVerdict>, CoreError>;
|
|
}
|