Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/monetize

crates/monetize-fast/src/walk.rs

//! **The owner's walk on the real boxes** (T-OWNERFLOW, owner order 2026-10-26): once the site
//! is ready, a NEW visitor buys an account plan on the site's own pages, through its REAL front
//! (the product's front binary, its console and the shared relay), the way the owner bought on
//! test2.gunnar.rs by hand: the plans, ONE checkout at the fake Stripe, paid once, the signed
//! webhook at the ONE box, the welcome page until the account is made. Then the private ladder
//! the same page sells (`/signup?plan=private`).
//!
//! The site here is the ONE box's OWN operator site, laid by the box: the shape of
//! test2.gunnar.rs, where alica's paid plan read "Free" afterwards (ALICA-4).
//!
//! Every request goes to the front's utility address under the site's name, trusting only the
//! certificate the shop minted for that front (the sale check's own client,
//! `monetize_shop_pairing::sale_check::Https`). Pure parts are tested below; the walk itself is
//! `cargo xtask fast` in gunnar and holger.

use std::net::SocketAddr;
use std::path::{Path, PathBuf};
use std::time::{Duration, Instant};

use monetize_shop_pairing::sale_check::{Front, Https, FRONT_CERT};

use crate::Receipt;

/// The account the walk makes (a test name; its address is `*@mock.invalid`).
pub const BUYER: &str = "alica";
/// Its address.
pub const BUYER_MAIL: &str = "alica@mock.invalid";
/// The paid plan the walk buys: `<product>/10gb-1m`, declared by [`signup_block`].
pub fn paid_plan(product: &str) -> String {
    format!("{product}/10gb-1m")
}

/// How long the welcome page is asked before the walk calls the settle stuck.
pub const SETTLE_WITHIN: Duration = Duration::from_secs(120);

/// Pure: **the ONE box's sign-up block for the walk** (`[signups.<product>]`): the free account
/// row and the one paid row the walk buys, as the prod box is fed them (solo.toml).
pub fn signup_block(product: &str) -> String {
    let meter = if product == "holger" { "disk_bytes" } else { "pack_bytes" };
    format!(
        "\n[signups.{product}]\ncap_meter = \"{meter}\"\nmax_sold_percent_of_capacity = 600\n\
         [signups.{product}.plans.\"{product}/account\"]\namount_minor = 0\ncurrency = \"Eur\"\ncap_bytes = 0\nperiod_days = 0\n\
         [signups.{product}.plans.\"{plan}\"]\namount_minor = 1000\ncurrency = \"Eur\"\ncap_bytes = 10737418240\nperiod_days = 30\n",
        plan = paid_plan(product)
    )
}

/// Pure: the checkout session in a pay page's URL (its last path segment).
pub fn session_of(url: &str) -> String {
    url.rsplit('/').next().unwrap_or_default().split(['#', '?']).next().unwrap_or_default().to_owned()
}

/// Pure: **does the welcome page's answer say "maintenance"** while it settles (PAID-1: nothing
/// was down; the box was only waiting on the site's main)?
pub fn says_maintenance(answer: &serde_json::Value) -> bool {
    answer.to_string().to_ascii_lowercase().contains("maintenance")
}

/// The certificate the shop minted for the site's front, where the shop keeps it (the run's
/// folder under the ONE box's data).
pub fn front_cert_under(root: &Path) -> Option<PathBuf> {
    let mut stack = vec![root.to_path_buf()];
    while let Some(d) = stack.pop() {
        for e in std::fs::read_dir(&d).ok()?.flatten() {
            let p = e.path();
            if p.is_dir() {
                stack.push(p);
            } else if p.file_name().is_some_and(|n| n == FRONT_CERT) {
                return Some(p);
            }
        }
    }
    None
}

/// Pure: **the hostname prefix of the site's FRONT machines**, from the product's media kinds
/// (`front` → `gunnar-front-`, Holger's `holger-front` → `holger-web-ui-`); never a keep medium.
pub fn front_prefix(kinds: &[(String, String)]) -> Option<String> {
    kinds.iter().find(|(k, _)| k.ends_with("front")).map(|(_, p)| p.clone())
}

/// Where the walk goes: the site's name, its front's address, the shop's certificate for it,
/// and the edges it pays through.
pub struct Site<'a> {
    pub product: &'a str,
    pub host: String,
    pub front: SocketAddr,
    pub cert: Vec<u8>,
    /// The fake Stripe's control door (the buyer at the pay page).
    pub control: SocketAddr,
    /// The ONE box's HTTP door (the vendor's webhook goes to `/callback/stripe/<vendor>`).
    pub one: SocketAddr,
    /// The vendor instance the site bills through (`stripe/<instance>`): its webhook path.
    pub vendor_instance: &'a str,
}

/// **The walk.** Each step one receipt row; answers whether every judged row passed.
pub fn run(r: &Receipt, site: &Site<'_>) -> bool {
    let front = match Https::new(&site.host, site.front, Some(&site.cert)) {
        Ok(f) => f,
        Err(e) => return r.step("walk: the site's front, trusted to the shop's own certificate for it", Err(e)),
    };
    let json = |s: &str| serde_json::from_str::<serde_json::Value>(s).unwrap_or(serde_json::Value::Null);
    let plan = paid_plan(site.product);
    // 1. the plans a visitor sees on /signup
    let ladder = front.get("/auth/signup/ladder", None).map(|(st, b)| (st, json(&b)));
    let offered = match &ladder {
        Ok((200, v)) if v["plans"].as_array().is_some_and(|p| p.iter().any(|x| x["id"] == plan.as_str())) => Ok(format!("{} offers {plan} at {}", site.host, v["plans"].as_array().and_then(|p| p.iter().find(|x| x["id"] == plan.as_str())).map(|x| x["price_words"].to_string()).unwrap_or_default())),
        Ok((st, v)) => Err(format!("GET https://{}/auth/signup/ladder: {st} {v}", site.host)),
        Err(e) => Err(e.clone()),
    };
    if !r.step("walk: a new visitor on the site's /signup sees its account plans (over the real front)", offered) {
        return false;
    }
    // 2. the paid plan started: ONE checkout at the fake
    let body = serde_json::json!({"username": BUYER, "email": BUYER_MAIL, "plan": plan, "next": "/"}).to_string();
    let started = front.post("/auth/signup/start", &body, None).map(|(st, b)| (st, json(&b)));
    let cs = match &started {
        Ok((200, v)) => session_of(v["url"].as_str().unwrap_or_default()),
        _ => String::new(),
    };
    let seen = !cs.is_empty() && crate::one_box::http(site.control, "GET", &format!("/seen/{cs}"), &[], b"").is_ok_and(|(st, _)| st == 200);
    if !r.step("walk: the visitor starts the paid plan: ONE checkout at the fake Stripe", if seen { Ok(format!("{cs} for {BUYER}")) } else { Err(format!("POST /auth/signup/start: {started:?}")) }) {
        return false;
    }
    // 3. paid once at the page; the signed webhook to the ONE box
    let paid: Result<String, String> = (|| {
        let (st, b) = crate::one_box::http(site.control, "POST", &format!("/pay/{cs}"), &[], b"")?;
        if st != 200 {
            return Err(format!("the fake's page refused to pay {cs}: {st} {b}"));
        }
        let v = json(&b);
        let (sig, event) = (v["signature"].as_str().unwrap_or_default().to_string(), v["body"].as_str().unwrap_or_default().to_string());
        let (st, b) = crate::one_box::http(site.one, "POST", &format!("/callback/stripe/{}", site.vendor_instance), &[("Stripe-Signature", &sig), ("Content-Type", "application/json")], event.as_bytes())?;
        if st != 200 {
            return Err(format!("the box's callback door: {st} {b}"));
        }
        Ok(format!("{cs} paid once; its webhook taken"))
    })();
    if !r.step("walk: paid once at the fake Stripe; the signed webhook reaches the ONE box", paid) {
        return false;
    }
    // 4. the welcome page until the account is made; what it said on the way
    let t0 = Instant::now();
    let mut last = serde_json::Value::Null;
    let mut maintenance = false;
    let mut states: Vec<String> = Vec::new();
    while t0.elapsed() < SETTLE_WITHIN {
        if let Ok((_, b)) = front.get(&format!("/auth/signup/status?session={cs}"), None) {
            last = json(&b);
            maintenance |= says_maintenance(&last);
            let s = last["state"].as_str().unwrap_or_default().to_string();
            if states.last() != Some(&s) {
                states.push(s.clone());
            }
            if s == "created" || s == "refused" || s == "failed" {
                break;
            }
        }
        std::thread::sleep(Duration::from_secs(2));
    }
    let created = last["state"] == "created" && last["username"] == BUYER;
    let ok = r.step(
        "walk: the welcome page reads created: the account is made on the site's main",
        if created { Ok(format!("{} after {} s ({})", BUYER, t0.elapsed().as_secs(), states.join(" → "))) } else { Err(format!("after {} s: {last} ({})", t0.elapsed().as_secs(), states.join(" → "))) },
    );
    // PAID-1 (PAID-WORDS, merged 2026-10-27): judged now; it was KNOWN RED until then.
    let quiet = r.step("walk: the settle never says \"maintenance\" (nothing was down)", if maintenance { Err(format!("the welcome page said maintenance on the way: {}", states.join(" → "))) } else { Ok(format!("no maintenance word ({})", states.join(" → "))) });
    // 5. the private ladder the same page sells
    let private = front.get("/auth/private/ladder", None).map(|(st, b)| (st, json(&b)));
    let sells = match &private {
        Ok((200, v)) if v["steps"].as_array().is_some_and(|s| !s.is_empty()) => Ok(format!("{} steps, the first {}", v["steps"].as_array().map(Vec::len).unwrap_or(0), v["steps"][0]["name"])),
        Ok((st, v)) => Err(format!("GET /auth/private/ladder: {st} {v}")),
        Err(e) => Err(e.clone()),
    };
    r.step("walk: the same site sells a private instance (/signup?plan=private's ladder)", sells) && ok && quiet
}

/// A row whose red is a fix another lane owns (`row`): said in the receipt, never a FAIL of the
/// run; green once the fix is in.
pub fn known_red(r: &Receipt, step: &str, row: &str, verdict: Result<String, String>) -> bool {
    match verdict {
        Ok(w) => r.step(step, Ok(w)),
        Err(w) => r.step(&format!("{step} [KNOWN RED until {row}]"), Ok(format!("RED, not judged: {w}"))),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn the_walk_declares_the_one_paid_plan_it_buys_with_the_products_meter() {
        let g = signup_block("gunnar");
        assert!(g.contains("[signups.gunnar]") && g.contains("cap_meter = \"pack_bytes\"") && g.contains("[signups.gunnar.plans.\"gunnar/10gb-1m\"]"), "{g}");
        let h = signup_block("holger");
        assert!(h.contains("cap_meter = \"disk_bytes\"") && h.contains("\"holger/10gb-1m\"") && !h.contains("gunnar"), "{h}");
    }

    #[test]
    fn the_front_is_named_by_its_medium_kind_for_both_products() {
        for product in ["gunnar", "holger"] {
            let kinds = crate::one_box::media_kinds(product).unwrap();
            let want = if product == "gunnar" { "gunnar-front-" } else { "holger-web-ui-" };
            assert_eq!(front_prefix(&kinds).as_deref(), Some(want), "{product}: {kinds:?}");
        }
        assert_eq!(front_prefix(&[("gunnar".into(), "gunnar-appliance-".into())]), None);
    }

    #[test]
    fn a_pay_pages_session_is_its_last_segment() {
        assert_eq!(session_of("http://10.0.0.1:9000/c/pay/cs_test_abc#frag"), "cs_test_abc");
        assert_eq!(session_of("https://checkout.stripe.com/c/pay/cs_test_x?y=1"), "cs_test_x");
        assert_eq!(session_of(""), "");
    }

    #[test]
    fn maintenance_is_seen_in_any_field_of_the_answer() {
        assert!(says_maintenance(&serde_json::json!({"state": "pending", "words": "Payment received. The shop is temporarily down for Maintenance"})));
        assert!(!says_maintenance(&serde_json::json!({"state": "pending", "words": "Payment received. Setting up your account"})));
    }

    #[test]
    fn a_known_red_row_is_said_and_does_not_fail_the_run() {
        let r = Receipt::default();
        r.start();
        assert!(known_red(&r, "x", "ROW-1", Err("red".into())));
        assert!(r.passed());
        let rows = r.rows();
        assert!(rows[0].step.contains("[KNOWN RED until ROW-1]") && rows[0].words.starts_with("RED, not judged"), "{:?}", rows[0].step);
        assert!(known_red(&r, "y", "ROW-1", Ok("green".into())));
        assert_eq!(r.rows()[1].step, "y");
    }

    #[test]
    fn the_shops_front_certificate_is_found_under_the_box_data() {
        let d = std::env::temp_dir().join(format!("walk-cert-{}", std::process::id()));
        let run = d.join("estate-orders/acme");
        std::fs::create_dir_all(&run).unwrap();
        assert_eq!(front_cert_under(&d), None);
        std::fs::write(run.join(FRONT_CERT), "pem").unwrap();
        assert_eq!(front_cert_under(&d), Some(run.join(FRONT_CERT)));
        let _ = std::fs::remove_dir_all(&d);
    }
}