parlov-core 0.2.0

Shared types, error types, and oracle class definitions for parlov.
Documentation

parlov-core

Shared types for HTTP oracle detection. Zero I/O, zero async — just data structures.

types

use parlov_core::{ResponseSurface, ProbeDefinition, ProbeSet, OracleResult};

ResponseSurface — one captured HTTP interaction:

pub struct ResponseSurface {
    pub status: StatusCode,
    pub headers: HeaderMap,
    pub body: Bytes,
    pub timing_ns: u64,
}

ProbeDefinition — one HTTP request to execute:

pub struct ProbeDefinition {
    pub url: String,
    pub method: Method,
    pub headers: HeaderMap,      // auth context lives here
    pub body: Option<Bytes>,
}

ProbeSet — paired surfaces for differential analysis:

pub struct ProbeSet {
    pub baseline: Vec<ResponseSurface>,  // known-valid input
    pub probe: Vec<ResponseSurface>,     // suspect input
}

OracleResult — the analysis output:

pub struct OracleResult {
    pub class: OracleClass,             // Existence, Authentication, Timing, ...
    pub verdict: OracleVerdict,         // Confirmed / Likely / NotPresent
    pub evidence: Vec<String>,          // "403 (baseline) vs 404 (probe)"
    pub severity: Option<Severity>,     // High / Medium / Low
    pub label: Option<String>,          // "Authorization-based differential"
    pub leaks: Option<String>,          // "Resource existence confirmed to low-privilege callers"
    pub rfc_basis: Option<String>,      // "RFC 9110 §15.5.4"
}

label, leaks, and rfc_basis are None for NotPresent results. They use #[serde(skip_serializing_if = "Option::is_none", default)] — omitted from JSON when absent, and backward-compatible when deserializing older data.

All types derive Serialize and Deserialize with custom serde helpers for StatusCode, Method, and HeaderMap (the http crate types lack native serde support).

use it

Construct a probe set from captured HTTP interactions:

use parlov_core::{ProbeSet, ResponseSurface};
use bytes::Bytes;
use http::{HeaderMap, StatusCode};

let baseline = ResponseSurface {
    status: StatusCode::FORBIDDEN,
    headers: HeaderMap::new(),
    body: Bytes::new(),
    timing_ns: 12_500_000,
};

let probe = ResponseSurface {
    status: StatusCode::NOT_FOUND,
    headers: HeaderMap::new(),
    body: Bytes::new(),
    timing_ns: 11_800_000,
};

let probe_set = ProbeSet {
    baseline: vec![baseline],
    probe: vec![probe],
};

Build a request definition for the probe engine:

use parlov_core::ProbeDefinition;
use http::{Method, HeaderMap};

let def = ProbeDefinition {
    url: "https://api.example.com/users/123".into(),
    method: Method::GET,
    headers: HeaderMap::new(),
    body: None,
};

errors

use parlov_core::Error;

Three variants via thiserror: Http(String), Analysis(String), Serialization(serde_json::Error).

license

MIT OR Apache-2.0