Skip to main content

parlov_core/
signal.rs

1//! Typed observations extracted from differential analysis.
2
3use serde::{Deserialize, Serialize};
4
5/// A typed observation extracted from differential analysis.
6///
7/// Each signal represents one piece of evidence: a status code difference, a header that appeared
8/// on one side but not the other, a body content change, etc. Signals are the atoms that
9/// classifiers compose into verdicts.
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct Signal {
12    /// What category of differential this signal represents.
13    pub kind: SignalKind,
14    /// Human-readable description of the observation, e.g. `"304 vs 404"`.
15    pub evidence: String,
16    /// RFC section grounding the expected behavior, e.g. `"RFC 9110 \u{00a7}13.1.2"`.
17    #[serde(skip_serializing_if = "Option::is_none", default)]
18    pub rfc_basis: Option<String>,
19}
20
21/// Categories of observable differential signals.
22///
23/// Each variant maps to a distinct signal extractor in `parlov-analysis`.
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub enum SignalKind {
26    /// Status codes differ between baseline and probe responses.
27    StatusCodeDiff,
28    /// A response header is present in one set but absent in the other.
29    HeaderPresence,
30    /// A response header has different values across baseline and probe sets.
31    HeaderValue,
32    /// Response body content differs between sets.
33    BodyDiff,
34    /// Response timing distributions differ (statistical significance required).
35    TimingDiff,
36    /// A response header leaks additional metadata, e.g. `Content-Range` reveals resource size.
37    MetadataLeak,
38}
39
40/// Classification of leak impact, independent of confidence.
41///
42/// Determines severity when gated by confidence threshold. Computed from the peak leak type
43/// among validated signals — existence-only is `Low`, metadata disclosure is `Medium`, sensitive
44/// metadata (exact sizes, internal state) is `High`.
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
46pub enum ImpactClass {
47    /// Existence confirmed, no metadata disclosed.
48    Low,
49    /// Metadata disclosed (validators, auth scheme, timing).
50    Medium,
51    /// Sensitive metadata disclosed (exact size, internal state).
52    High,
53}