captchaforge 0.2.39

Captcha detection and solving for Firefox and BiDi-driven browsers. Detection, vendor solver scaffolding, trusted cross-origin click delivery into nested OOPIFs, and stealth personas are implemented and tested; broad live-vendor solve rates are not yet benchmarked.
Documentation
//! Criterion benchmarks for the captchaforge hot paths. Run with
//! `cargo bench --bench hot_path`. Numbers feed the published
//! latency-vs-competitors comparison.

use captchaforge::adversarial_replay::{AdversarialCapture, ExpectedOutcome};
use captchaforge::frame_graph::FrameGraph;
use captchaforge::solver::token_shapes::for_vendor;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use std::collections::HashMap;

fn bench_token_shape_classify(c: &mut Criterion) {
    let oracle = for_vendor("cloudflare-turnstile").expect("CF Turnstile oracle is wired");
    let token = "A".repeat(280);
    c.bench_function("token_shape::classify(plausible 280-char)", |b| {
        b.iter(|| {
            let _ = oracle.classify(black_box(&token));
        });
    });
    c.bench_function("token_shape::classify(decoy short)", |b| {
        b.iter(|| {
            let _ = oracle.classify(black_box("FAILED"));
        });
    });
}

fn bench_frame_graph_construction(c: &mut Criterion) {
    c.bench_function("FrameGraph::default + bfs (empty)", |b| {
        b.iter(|| {
            let g = FrameGraph::default();
            let _ = g.bfs();
        });
    });
}

fn bench_token_shape_for_vendor_lookup(c: &mut Criterion) {
    c.bench_function("for_vendor(cloudflare-turnstile)", |b| {
        b.iter(|| {
            let _ = for_vendor(black_box("cloudflare-turnstile"));
        });
    });
}

fn bench_adversarial_capture_serde(c: &mut Criterion) {
    let cap = AdversarialCapture {
        id: "abc".into(),
        vendor: "cloudflare-turnstile".into(),
        status: 403,
        headers: HashMap::new(),
        body: "x".repeat(2048),
        cookie_names: vec!["cf_clearance".into()],
        expected: ExpectedOutcome::Recognised,
        notes: "bench".into(),
        captured_at_unix: 1_700_000_000,
    };
    c.bench_function("AdversarialCapture::serialize 2KB", |b| {
        b.iter(|| {
            let _ = serde_json::to_string(black_box(&cap)).unwrap();
        });
    });
    let json = serde_json::to_string(&cap).unwrap();
    c.bench_function("AdversarialCapture::deserialize 2KB", |b| {
        b.iter(|| {
            let _: AdversarialCapture = serde_json::from_str(black_box(&json)).unwrap();
        });
    });
}

criterion_group!(
    hot_path,
    bench_token_shape_classify,
    bench_token_shape_for_vendor_lookup,
    bench_frame_graph_construction,
    bench_adversarial_capture_serde,
);
criterion_main!(hot_path);