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
//! Statistical decoy classifier (operator-facing CLI demo).
//!
//! ```sh
//! cargo run --example 03_decoy_classify -- turnstile "0.aB3xY7zQ..."
//! cargo run --example 03_decoy_classify -- hcaptcha "P0_eyJh..."
//! ```
//!
//! Pretty-prints the 11 feature scores + final verdict so an
//! operator can sanity-check the detector against tokens captured
//! from production.

use captchaforge::solver::decoy_detector::{classify, extract_features};

fn main() {
    let mut args = std::env::args().skip(1);
    let vendor = args.next().unwrap_or_else(|| "turnstile".to_string());
    let token = args
        .next()
        .unwrap_or_else(|| "0.example_token_for_demo".to_string());

    let features = extract_features(&token, &vendor);
    let verdict = classify(&token, &vendor);

    println!("vendor:           {}", vendor);
    println!("token length:     {} bytes", token.len());
    println!();
    println!("FEATURE BREAKDOWN");
    println!("─────────────────────────────────────────────────────");
    println!("entropy:               {:.3}", features.entropy);
    println!("ks_uniform:            {:.3}", features.ks_uniform);
    println!("markov:                {:.3}", features.markov);
    println!("chi_sq_uniform:        {:.3}", features.chi_sq_uniform);
    println!("run_length:            {:.3}", features.run_length);
    println!("compressibility:       {:.3}", features.compressibility);
    println!("ascii_concentration:   {:.3}", features.ascii_concentration);
    println!("dot_segment_cv:        {:.3}", features.dot_segment_cv);
    println!("hex_ratio:             {:.3}", features.hex_ratio);
    println!("bigram_coverage:       {:.3}", features.bigram_coverage);
    println!("length_match:          {:.3}", features.length_match);
    println!("─────────────────────────────────────────────────────");
    println!("aggregate score:       {:.3}", features.score());
    println!();
    println!("VERDICT:           {:?}", verdict);
}