parlov-elicit 0.2.0

Elicitation engine: strategy selection and probe plan generation for parlov.
Documentation
# 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`)

| # | ID | Risk | Methods | Prereq |
|---|---|---|---|---|
| 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`)

| # | ID | Risk | Methods | Prereq |
|---|---|---|---|---|
| 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`.