captchaforge 0.2.36

[DO NOT USE — UNDER ACTIVE DEVELOPMENT, NOT PRODUCTION-READY] Captcha solver scaffolding for chromiumoxide-driven browsers. The architecture is in place (vendor solvers, retry-loop iframe walking, VLM provider abstraction, real-WAF bench harness) but the live-vendor success rate is still 0% — Cloudflare Turnstile / hCaptcha / reCAPTCHA detect us at a TLS / CDP fingerprint layer that no flag-based stealth has cleared. Watch the repo; do not depend on this for any real workload.
Documentation
//! Lock the Helm chart structure so a refactor can't accidentally
//! drop a required template file or break the values.yaml schema.

use std::fs;
use std::path::PathBuf;

fn chart_dir() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("deploy")
        .join("charts")
        .join("captchaforge")
}

#[test]
fn chart_yaml_declares_required_fields() {
    let path = chart_dir().join("Chart.yaml");
    let body = fs::read_to_string(&path).expect("Chart.yaml exists");
    for required in ["apiVersion: v2", "name: captchaforge", "type: application", "version:"] {
        assert!(
            body.contains(required),
            "Chart.yaml missing {required:?}"
        );
    }
}

#[test]
fn ships_every_required_template() {
    let templates = chart_dir().join("templates");
    for name in [
        "deployment.yaml",
        "service.yaml",
        "secret.yaml",
        "servicemonitor.yaml",
        "ingress.yaml",
        "_helpers.tpl",
    ] {
        let p = templates.join(name);
        assert!(p.is_file(), "missing template {name} at {}", p.display());
    }
}

#[test]
fn values_yaml_declares_every_field_templates_read() {
    let values = fs::read_to_string(chart_dir().join("values.yaml")).expect("values.yaml");
    for key in [
        "replicaCount",
        "image:",
        "service:",
        "auth:",
        "rateLimitRps:",
        "allowOrigins",
        "resources:",
        "livenessProbe:",
        "readinessProbe:",
        "serviceMonitor:",
        "ingress:",
        "podSecurityContext:",
        "securityContext:",
        "extraArgs:",
        "extraEnv:",
        "nodeSelector",
        "tolerations",
        "affinity",
    ] {
        assert!(
            values.contains(key),
            "values.yaml missing key {key:?}"
        );
    }
}

#[test]
fn deployment_wires_serve_token_from_secret() {
    let dep = fs::read_to_string(chart_dir().join("templates/deployment.yaml")).unwrap();
    assert!(dep.contains("CAPTCHAFORGE_SERVE_TOKEN"));
    assert!(dep.contains("secretKeyRef"));
}

#[test]
fn deployment_passes_rate_limit_env() {
    let dep = fs::read_to_string(chart_dir().join("templates/deployment.yaml")).unwrap();
    assert!(dep.contains("CAPTCHAFORGE_SERVE_RPS"));
}

#[test]
fn deployment_uses_prometheus_scrape_annotations() {
    let dep = fs::read_to_string(chart_dir().join("templates/deployment.yaml")).unwrap();
    assert!(dep.contains("prometheus.io/scrape"));
    assert!(dep.contains("prometheus.io/path"));
}