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}