parlov-core
Shared vocabulary crate — request/response primitives, oracle domain types, technique metadata, signal types, scoring types, and the OracleResult.
Version: 0.5.0 | Files: 7 | Lines: 977 | Dependencies: none (workspace root)
The shared vocabulary crate. Every other workspace crate depends on parlov-core for its type definitions. It contains zero business logic — only data structures, enums, error types, and deterministic helper functions.
Public API
Request / Response Primitives
ProbeDefinition — A fully specified HTTP request before execution.
| Field | Type | Description |
|---|---|---|
url | String | Target URL with {id} already substituted |
method | http::Method | HTTP method (GET, POST, PUT, PATCH, DELETE) |
headers | http::HeaderMap | Request headers |
body | Option<bytes::Bytes> | Optional request body |
ResponseSurface — The observable surface area of an HTTP response, stripped to what analysis needs.
| Field | Type | Description |
|---|---|---|
status | http::StatusCode | HTTP status code |
headers | http::HeaderMap | Response headers |
body | bytes::Bytes | Response body (raw bytes) |
timing_ns | u64 | Round-trip time in nanoseconds |
Both types derive Serialize and Deserialize via custom serde helpers (see Internal Modules).
Exchange Types
ProbeExchange — A paired request + response. Every response permanently travels with the request that produced it.
pub struct ProbeExchange {
pub request: ProbeDefinition,
pub response: ResponseSurface,
}DifferentialSet — The unit of analysis. Replaces the deprecated ProbeSet (which carried only ResponseSurface vectors without request context).
pub struct DifferentialSet {
pub baseline: Vec<ProbeExchange>, // Known-valid inputs
pub probe: Vec<ProbeExchange>, // Unknown/suspect inputs
pub technique: Technique, // Why these probes were generated
}ProbeSet (deprecated) — Use DifferentialSet instead.
Oracle Domain Types
OracleClass — Which class of oracle is being tested. Currently one variant:
Existence— Does the resource exist?
Future variants (see Methodology): Authentication, Timing, Verification, TokenValidation, State.
OracleVerdict — The analysis conclusion.
| Variant | Meaning |
|---|---|
Confirmed | Confidence >= 80. Strong evidence of the oracle condition. |
Likely | Confidence 60–79. Probable but not confirmed. |
Inconclusive | Ambiguous evidence. |
NotPresent | No differential detected or confidence < 60. |
Severity — Gated by confidence. Only present when verdict is Confirmed or Likely.
| Variant | When |
|---|---|
High | Confirmed + High impact |
Medium | Confirmed + Medium impact, or Likely + High impact |
Low | Everything else that passes the confidence gate |
Technique Metadata
Technique — Probe generation context, set by the strategy at generation time, carried through execution unchanged, consumed by the analyzer for confidence calibration and evidence labeling.
pub struct Technique {
pub id: &'static str, // e.g. "if-none-match"
pub name: &'static str, // e.g. "If-None-Match conditional request"
pub oracle_class: OracleClass,
pub vector: Vector,
pub strength: NormativeStrength,
}Vector — Detection method used to produce the differential.
| Variant | Description |
|---|---|
StatusCodeDiff | Compare status codes across baseline/probe |
CacheProbing | Manipulate cache-related headers (If-None-Match, If-Modified-Since, etc.) |
ErrorMessageGranularity | Compare error message body content across baseline/probe |
NormativeStrength — How strongly the RFC mandates the expected behavior. Directly affects confidence calibration.
| Variant | RFC Keyword | Confidence Multiplier |
|---|---|---|
Must | MUST | 1.0x |
MustNot | MUST NOT | 1.0x |
Should | SHOULD | 0.9x |
May | MAY | 0.75x |
Signal Types
Signal — A typed observation extracted from differential analysis. Signals are the atoms that classifiers compose into verdicts.
pub struct Signal {
pub kind: SignalKind,
pub evidence: String, // e.g. "304 vs 404"
pub rfc_basis: Option<String>, // e.g. "RFC 9110 §13.1.2"
}SignalKind — Categories of observable differentials.
| Variant | What it detects |
|---|---|
StatusCodeDiff | Status codes differ between baseline and probe |
HeaderPresence | Header present on one side, absent on the other |
HeaderValue | Same header, different values |
BodyDiff | Body content differs |
TimingDiff | Timing distributions differ (statistical) |
MetadataLeak | Header leaks metadata (e.g. Content-Range reveals size) |
ImpactClass — Classification of leak severity, independent of confidence.
| Variant | Meaning |
|---|---|
Low | Existence confirmed, no metadata disclosed |
Medium | Metadata disclosed (validators, auth scheme, timing) |
High | Sensitive metadata disclosed (exact size, internal state) |
Scoring Types
ScoringReason — One contribution to the confidence or impact score. Accumulated during classification to give operators a transparent audit trail.
pub struct ScoringReason {
pub description: String, // e.g. "Status differential 416 vs 404"
pub points: i16, // Positive or negative
pub dimension: ScoringDimension,
}ScoringDimension — Which axis a reason contributes to: Confidence (0–100 numeric) or Impact.
The OracleResult
OracleResult — The complete output of analysis. Carries everything needed for output formatting and SARIF generation.
| Field | Type | Description |
|---|---|---|
class | OracleClass | Which oracle was tested |
verdict | OracleVerdict | Conclusion |
severity | Option<Severity> | Present only when confidence gate passes |
confidence | u8 | 0–100 numeric score |
impact_class | Option<ImpactClass> | Leak classification |
reasons | Vec<ScoringReason> | Transparent scoring breakdown |
signals | Vec<Signal> | All extracted observations |
technique_id | Option<String> | Back-reference to the generating technique |
vector | Option<Vector> | Detection vector used |
normative_strength | Option<NormativeStrength> | RFC mandate level |
label | Option<String> | Human-readable pattern label |
leaks | Option<String> | What metadata was leaked |
rfc_basis | Option<String> | RFC section grounding |
Method: primary_evidence(&self) -> &str — Returns the evidence string from the first StatusCodeDiff signal, or falls back to the first signal of any kind. Returns "—" (em dash) when no signals exist.
Deterministic Finding IDs
finding_id(technique_id, target_url, oracle_class, method, strategy_id) -> String
Produces a stable 12-character hex fingerprint by SHA-256 hashing the canonical identity fields and truncating to 6 bytes. Used for SARIF partialFingerprints and deduplication.
Error Type
Error — Unified error enum.
| Variant | Source |
|---|---|
Http(String) | HTTP client or transport errors |
Analysis(String) | Analysis pipeline errors |
Serialization(serde_json::Error) | Serde serialization/deserialization errors (auto-converted via #[from]) |
Internal Modules
serde_helpers
Custom serde implementations for types that don't have native Serialize/Deserialize support:
| Helper | Purpose |
|---|---|
status_code | Serializes http::StatusCode as u16 |
header_map | Serializes http::HeaderMap as HashMap<String, String> |
bytes / opt_bytes | Serializes bytes::Bytes as a byte sequence (integer array in JSON) |
method | Serializes http::Method as string |
These are applied via #[serde(with = "...")] attributes on ProbeDefinition and ResponseSurface.
Extension Points
Adding a new oracle class: Add a variant to OracleClass. This is the only change in parlov-core. The corresponding analyzer, strategies, and patterns live in parlov-analysis and parlov-elicit.
Adding a new vector: Add a variant to Vector. Strategies declare their vector via Technique; the analyzer uses it for signal extractor selection.
Adding a new signal kind: Add a variant to SignalKind. Then implement the extractor in parlov-analysis::signals and add weights in parlov-analysis::existence::signal_weights.