# parlov-elicit
Elicitation engine for parlov. Given a target endpoint and operator context, generates a plan of `ProbeSpec`s designed to trigger specific server-side differentials that reveal resource existence.
## Overview
The engine codifies the [elicitation playbook](../../docs/existenceOracle/elicitationPlaybook.md) as 25 composable strategies across two detection vectors. Each strategy targets a different layer of the HTTP pipeline — content negotiation, conditional headers, cache validation, auth, payload validation, rate limiting — and produces probe definitions with `Technique` metadata that the binary feeds into its execution loops.
## Usage
```rust
use parlov_elicit::{generate_plan, RiskLevel, ScanContext};
use http::HeaderMap;
let ctx = ScanContext {
target: "https://api.example.com/users/{id}".to_string(),
baseline_id: "1001".to_string(),
probe_id: "9999".to_string(),
headers: HeaderMap::new(),
max_risk: RiskLevel::Safe,
known_duplicate: None,
state_field: None,
alt_credential: None,
};
let plan = generate_plan(&ctx);
// plan contains ProbeSpec::Pair, ::Burst, and ::HeaderDiff items
// ready for dispatch by the binary's scan pipeline
```
## Strategies
### Status Code Diff (`Vector::StatusCodeDiff`)
| 1 | `accept-elicit` | Safe | GET, HEAD | — |
| 2 | `if-none-match-elicit` | Safe | GET, HEAD | — |
| 3 | `trailing-slash-elicit` | Safe | GET, HEAD | — |
| 4 | `case-normalize-elicit` | Safe | GET, HEAD | — |
| 5 | `long-uri-elicit` | Safe | GET, HEAD | — |
| 6 | `auth-strip-elicit` | Safe | GET, HEAD | `Authorization` header |
| 7 | `low-privilege-elicit` | Safe | GET, HEAD | `Authorization` header |
| 8 | `scope-manipulation-elicit` | Safe | GET, HEAD | `alt_credential` |
| 9 | `rate-limit-headers-elicit` | Safe | GET, HEAD | — |
| 10 | `content-type-elicit` | MethodDestructive | POST, PUT, PATCH | — |
| 11 | `if-match-elicit` | MethodDestructive | PUT, PATCH, DELETE | — |
| 12 | `empty-body-elicit` | MethodDestructive | POST, PUT, PATCH | — |
| 13 | `oversized-body-elicit` | MethodDestructive | POST, PUT, PATCH | — |
| 14 | `state-transition-elicit` | MethodDestructive | PATCH, PUT | `state_field` |
| 15 | `uniqueness-elicit` | OperationDestructive | POST, PUT | `known_duplicate` |
| 16 | `dependency-delete-elicit` | OperationDestructive | DELETE | — |
| 17 | `rate-limit-burst-elicit` | OperationDestructive | GET, HEAD | — |
### Cache Probing (`Vector::CacheProbing`)
| 18 | `cp-if-none-match` | Safe | GET, HEAD | — |
| 19 | `cp-if-modified-since` | Safe | GET, HEAD | — |
| 20 | `cp-if-match` | Safe | GET, HEAD | — |
| 21 | `cp-if-unmodified-since` | Safe | GET, HEAD | — |
| 22 | `cp-range` | Safe | GET | — |
| 23 | `cp-range-unsatisfiable` | Safe | GET | — |
| 24 | `cp-if-range` | Safe | GET | — |
| 25 | `cp-accept` | Safe | GET, HEAD | — |
## Design
- **Pure computation** — no I/O, no async. The binary owns the async boundary.
- **Strategy as trait** — adding a strategy is one file + one registry line.
- **Two detection vectors** — `StatusCodeDiff` (status code differentials) and `CacheProbing` (cache-conditional header responses). Strategies are organized by vector under `existence/status_code_diff/` and `existence/cache_probing/`.
- **`Technique` metadata** — every `ProbeSpec` carries technique context (id, name, vector, normative strength) that flows through execution into analysis. Signal extraction is unconditional.
- **`ProbeSpec` variants** drive dispatch in the binary: `Pair` → adaptive loop, `Burst` → volume loop, `HeaderDiff` → single-request header comparison.
- **`RiskLevel` uses `Ord`** — `generate_plan` filters with `risk() <= ctx.max_risk`.