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/one_box.rs

//! **The real ONE box in its container** (monetize v2.0 P1, A24 §8.2, step 1): `monetize-admin
//! server --config` with the run's test-CA-signed guests (the product's, the UpCloud cloud guest
//! against mock-upcloud's API, the Stripe vendor guest against the fake Stripe), laying the
//! product's estate through the mock's API — the driver describes no machine.
//!
//! ```text
//!  podman's rootless network namespace (this process; the utility bridge's gateway X.Y.15.254)
//!  ├── mock-upcloud --engine container   the UpCloud API on 0.0.0.0:<P> (the box reaches it at the
//!  │                                     gateway: `http_resolve = ["localhost=X.Y.15.254"]`, the
//!  │                                     guest's `api_base` stays loopback); a container per machine
//!  ├── fake_stripe_serve --listen 0.0.0.0   Stripe's API, dialled by the vendor guest at the
//!  │                                     gateway (the bridge's address exists only once a
//!  │                                     container joins it); the payer's control
//!  │                                     (POST /pay/<session>) on loopback
//!  └── podman network fast-<run>
//!       ├── one (X.Y.8.90): monetize-admin server, and fast-edge: TLS :443 → h2c :50061
//!       └── the laid machines: front, main, twin (the product's binaries, their own TUN)
//! ```
//!
//! The operator is this process: `EstateOrder.OrderSite` over gRPC with the box's operator
//! bearer (the site `acme`, declared `operator_site`), the page paid at the fake Stripe's
//! control, the signed webhook POSTed to the box's callback door — then `EstateOrder.Status`
//! until `ready`. What is real from there on is the ONE box's whole lay, install, pairing,
//! sale check and capture, on its own code.

use std::collections::BTreeMap;
use std::io::{Read as _, Write as _};
use std::net::{SocketAddr, TcpStream};
use std::path::{Path, PathBuf};
use std::process::{Child, Command, Stdio};
use std::time::{Duration, Instant};

use crate::{head_of, on_the_utility_bridge, tail, work_dir_of, Config, Receipt};

/// The ONE box's address on the utility network (`X.Y.8.90`).
pub const ONE_HOST: &str = "8.90";
/// The ONE box's gRPC (h2c) and callback port.
pub const ONE_GRPC: u16 = 50061;
/// The TLS door's port.
pub const ONE_TLS: u16 = 443;
/// The name the sold boxes dial the ONE box by (the shop door; the edge's certificate name).
pub const ONE_NAME: &str = "one.fast.invalid";
/// The mock's API port, the fake Stripe's API port and its control port.
pub const MOCK_PORT: u16 = 8791;
pub const STRIPE_PORT: u16 = 12791;
pub const STRIPE_CONTROL: u16 = 12792;

/// **One parallel slot's ports** in the shared rootless namespace: the mock, the fake Stripe and
/// its control. Slot `n` adds `10 × n` to slot 0's ([`MOCK_PORT`], [`STRIPE_PORT`], [`STRIPE_CONTROL`]).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FastPorts {
    pub mock: u16,
    pub stripe: u16,
    pub control: u16,
}

/// Pure: slot `slot`'s ports; `None` beyond [`mock_upcloud::container::FAST_SLOTS`].
pub fn ports_of(slot: u8) -> Option<FastPorts> {
    if slot >= mock_upcloud::container::FAST_SLOTS {
        return None;
    }
    let d = 10 * slot as u16;
    Some(FastPorts { mock: MOCK_PORT + d, stripe: STRIPE_PORT + d, control: STRIPE_CONTROL + d })
}

/// The directory of the slots' locks (`$MONETIZE_FAST_SLOTS`, else `/tmp/monetize-fast-slots`).
pub fn slots_dir() -> PathBuf {
    std::env::var_os("MONETIZE_FAST_SLOTS").map(PathBuf::from).unwrap_or_else(|| std::env::temp_dir().join("monetize-fast-slots"))
}

/// **Claim a parallel slot**: `wanted` or the first free one, held by the returned file's lock
/// for as long as the run keeps it. A slot another run holds is refused by name.
pub fn claim_slot(dir: &Path, wanted: Option<u8>) -> Result<(u8, std::fs::File), String> {
    std::fs::create_dir_all(dir).map_err(|e| format!("{}: {e}", dir.display()))?;
    let slots: Vec<u8> = match wanted {
        Some(n) if n < mock_upcloud::container::FAST_SLOTS => vec![n],
        Some(n) => return Err(format!("[fast-slot] slot {n}: there are {} (0..{})", mock_upcloud::container::FAST_SLOTS, mock_upcloud::container::FAST_SLOTS - 1)),
        None => (0..mock_upcloud::container::FAST_SLOTS).collect(),
    };
    for n in &slots {
        let p = dir.join(format!("slot-{n}.lock"));
        let f = std::fs::OpenOptions::new().create(true).truncate(false).write(true).open(&p).map_err(|e| format!("{}: {e}", p.display()))?;
        if f.try_lock().is_ok() {
            return Ok((*n, f));
        }
    }
    Err(match wanted {
        Some(n) => format!("[fast-slot-busy] slot {n} is held by another fast run"),
        None => format!("[fast-slots-busy] all {} fast slots are held by other runs", mock_upcloud::container::FAST_SLOTS),
    })
}
/// The fake Stripe's TEST key and webhook secret (never live; the fake refuses a live key).
pub const STRIPE_KEY: &str = "sk_test_fastBENCHneverLIVE";
pub const STRIPE_HOOK: &str = "whsec_test_fastBENCH";
/// The mock's clock, in thousandths of real time: 20× (the KVM gate's). At `0` (virtual only)
/// every request moves the clock half-way to the next deadline, so each of the provider's
/// waits (a server's 100 s create, a clone's 130 s sync) cost the box ~16 polls of 2 s.
pub const MOCK_SPEED: &str = "20000";
/// The mock's token (any non-empty bearer; never the account's).
pub const MOCK_TOKEN: &str = "ucat_mock_fast_one_box";
/// The ONE box's service bearer, written to its token file.
pub const BEARER: &str = "fast-one-box-bearer-0123456789abcdef0123456789";
/// The OPERATOR bearer (`<data_dir>/operator-token`): a site order is the operator's alone.
pub const OPERATOR: &str = "fast-one-box-operator-9876543210fedcba9876543210";
/// The vendor instance the sold estates bill through: `stripe/<product>`.
pub fn vendor_of(product: &str) -> String {
    format!("stripe/{product}")
}

/// The custody secret names of that instance's key and webhook secret:
/// `MONETIZE_STRIPE_<PRODUCT>_SECRET_KEY`, `MONETIZE_STRIPE_<PRODUCT>_WEBHOOK_SECRET`.
pub fn stripe_secrets_of(product: &str) -> (String, String) {
    let p = product.to_uppercase().replace(['-', '.'], "_");
    (format!("MONETIZE_STRIPE_{p}_SECRET_KEY"), format!("MONETIZE_STRIPE_{p}_WEBHOOK_SECRET"))
}

/// The ONE box's pieces, built by `cargo xtask fast` (the product's) and by monetize's own build.
#[derive(Debug, Clone)]
pub struct Kit {
    pub monetize_admin: PathBuf,
    pub fast_edge: PathBuf,
    pub mock_upcloud: PathBuf,
    pub fake_stripe: PathBuf,
    /// The guests, unsigned: `product` (the sold product's), `upcloud`, `stripe`.
    pub guests: BTreeMap<String, PathBuf>,
}

impl Kit {
    /// The kit in `dir`: `monetize-admin`, `fast-edge`, `mock-upcloud`, `fake_stripe_serve`,
    /// `guest-<name>.wasm`.
    pub fn from_dir(dir: &Path) -> Result<Kit, String> {
        let need = |n: &str| {
            let p = dir.join(n);
            if p.is_file() { Ok(p) } else { Err(format!("[fast-kit] {} is not in the kit", p.display())) }
        };
        let mut guests = BTreeMap::new();
        for e in std::fs::read_dir(dir).map_err(|e| format!("{}: {e}", dir.display()))?.flatten() {
            let name = e.file_name().to_string_lossy().into_owned();
            if let Some(g) = name.strip_prefix("guest-").and_then(|n| n.strip_suffix(".wasm")) {
                guests.insert(g.to_string(), e.path());
            }
        }
        Ok(Kit { monetize_admin: need("monetize-admin")?, fast_edge: need("fast-edge")?, mock_upcloud: need("mock-upcloud")?, fake_stripe: need("fake_stripe_serve")?, guests })
    }
}

/// The media KINDS a product's `[estate_orders.media_objects]` names, and the hostname prefix
/// of the machines each boots (the keep media boot the same program): the product's facts
/// ([`crate::facts_of`]), never a table of names here.
pub fn media_kinds(product: &str) -> Result<Vec<(String, String)>, String> {
    crate::facts_of(product).map(|f| f.media)
}

/// Pure: **the grants a guest's imports need** (`monetize_product_guest::grants::for_import`),
/// in the vocabulary's order; an import outside the vocabulary is refused by name.
pub fn grants_for_imports(imports: &[String]) -> Result<Vec<String>, String> {
    use monetize_product_guest::grants;
    let mut need = Vec::new();
    for imp in imports {
        match grants::for_import(imp) {
            None => return Err(format!("[fast-facts] the guest imports `env::{imp}`, which is not a monetize host door")),
            Some("") => {}
            Some(g) => need.push(g),
        }
    }
    Ok(grants::VOCABULARY.iter().filter(|g| need.contains(*g)).map(|g| g.to_string()).collect())
}

/// **The grants the signed module asks for**: its import section, read as the ONE box's gate
/// reads it (signature checked first). The ONE box's `[products.<product>] grants` are these.
pub fn grants_of_guest(module: &Path, trust_root: &Path) -> Result<Vec<String>, String> {
    let bytes = std::fs::read(module).map_err(|e| format!("{}: {e}", module.display()))?;
    let trust = guest_host::ModuleTrust::required([trust_root.to_path_buf()]);
    let m = guest_host::module::LoadedModule::from_bytes(module.to_path_buf(), &bytes, &guest_host::PluginLimits::default(), &trust, &[]).map_err(|e| format!("[fast-facts] {}: {e}", module.display()))?;
    grants_for_imports(&m.imports_from(monetize_product_guest::imports::MODULE))
}

/// **The product's own facts, from its signed guest** (op 90, `lifecycle.facts`): the module
/// is loaded as the ONE box loads it (`[products.<product>] instance = … guest = …`: a pulled
/// product, never dialled, under `trust_root`, with the grants it asks for) and followed into the lifecycle registry, so the estate the run lays
/// and the media it uploads are the ones the guest names. Answers the line that says so and the
/// grants; `Err` when the guest does not load or brings no lifecycle for `product`.
pub fn follow_guest(product: &str, module: &Path, trust_root: &Path, scratch: &Path) -> Result<(String, Vec<String>), String> {
    let grants = grants_of_guest(module, trust_root)?;
    std::fs::create_dir_all(scratch.join("data")).map_err(|e| format!("{}: {e}", scratch.display()))?;
    let toml = scratch.join("facts.toml");
    std::fs::write(
        &toml,
        format!("data_dir = {:?}\n[products.{product}]\ninstance = \"acme\"\nguest = {:?}\nguest_trust_roots = [{:?}]\ngrants = {grants:?}\n", scratch.join("data").display().to_string(), module.display().to_string(), trust_root.display().to_string()),
    )
    .map_err(|e| format!("{}: {e}", toml.display()))?;
    let cfg = monetize_server::config::Config::load(&toml).map_err(|e| format!("[fast-facts] {}: {e}", toml.display()))?;
    let registry = monetize_server::registry::Registry::from_config(&cfg).map_err(|e| format!("[fast-facts] the {product} guest does not load: {e:#}"))?;
    let lines = monetize_server::estate_order::guest_lifecycle::follow(&registry);
    let line = lines
        .iter()
        .find(|l| l.starts_with(&format!("lifecycle {product}: taken from the guest")))
        .cloned()
        .ok_or_else(|| format!("[fast-facts] the {product} guest brings no lifecycle for `{product}` (lifecycle.facts): {lines:?}; refused at start: {:?}", registry.start_refusals()))?;
    Ok((line, grants))
}

fn sha256_hex(b: &[u8]) -> String {
    use sha2::Digest as _;
    sha2::Sha256::digest(b).iter().map(|x| format!("{x:02x}")).collect()
}

/// One HTTP/1.1 request on its own connection; `(status, body)`.
pub fn http(addr: SocketAddr, method: &str, path: &str, headers: &[(&str, &str)], body: &[u8]) -> Result<(u16, String), String> {
    let mut s = TcpStream::connect_timeout(&addr, Duration::from_secs(10)).map_err(|e| format!("{addr}: {e}"))?;
    s.set_read_timeout(Some(Duration::from_secs(60))).ok();
    let mut req = format!("{method} {path} HTTP/1.1\r\nHost: {addr}\r\nContent-Length: {}\r\nConnection: close\r\n", body.len());
    for (k, v) in headers {
        req.push_str(&format!("{k}: {v}\r\n"));
    }
    req.push_str("\r\n");
    s.write_all(req.as_bytes()).and_then(|()| s.write_all(body)).map_err(|e| format!("{addr}: {e}"))?;
    let mut raw = Vec::new();
    s.read_to_end(&mut raw).map_err(|e| format!("{addr}: {e}"))?;
    let text = String::from_utf8_lossy(&raw);
    let status: u16 = text.split_whitespace().nth(1).and_then(|c| c.parse().ok()).ok_or_else(|| format!("{addr}: no status line in {:?}", text.chars().take(80).collect::<String>()))?;
    let body = text.split_once("\r\n\r\n").map(|(_, b)| b.to_string()).unwrap_or_default();
    Ok((status, body))
}

fn wait_port(addr: SocketAddr, budget: Duration) -> bool {
    let t0 = Instant::now();
    while t0.elapsed() < budget {
        if TcpStream::connect_timeout(&addr, Duration::from_millis(500)).is_ok() {
            return true;
        }
        std::thread::sleep(Duration::from_millis(250));
    }
    false
}

/// A child with its log file, stopped (TERM, then KILL) when dropped.
struct Daemon {
    child: Child,
    log: PathBuf,
}

impl Daemon {
    fn spawn(name: &'static str, cmd: &mut Command, log: &Path) -> Result<Daemon, String> {
        let out = std::fs::File::create(log).map_err(|e| format!("{}: {e}", log.display()))?;
        let err = out.try_clone().map_err(|e| e.to_string())?;
        let child = cmd.stdin(Stdio::null()).stdout(Stdio::from(out)).stderr(Stdio::from(err)).spawn().map_err(|e| format!("{name}: {e}"))?;
        Ok(Daemon { child, log: log.to_path_buf() })
    }
    fn stop(&mut self) {
        let pid = self.child.id();
        let _ = Command::new("kill").args(["-TERM", &pid.to_string()]).output();
        let t0 = Instant::now();
        while t0.elapsed() < Duration::from_secs(20) {
            if let Ok(Some(_)) = self.child.try_wait() {
                return;
            }
            std::thread::sleep(Duration::from_millis(200));
        }
        let _ = self.child.kill();
        let _ = self.child.wait();
    }
    fn log(&self) -> String {
        std::fs::read_to_string(&self.log).unwrap_or_default()
    }
}

impl Drop for Daemon {
    fn drop(&mut self) {
        self.stop();
    }
}

/// The ONE box's tick (`poll_minutes`): how often its jobs look at an order again.
pub const POLL_MINUTES: u64 = 1;
/// The box's install deadline (`install_deadline_mins`): an order `installing` this long with
/// a box not PAIRED is FAILED by the box, the installer's last pair status its reason.
pub const INSTALL_DEADLINE_MINS: u64 = 10;
/// The box's job deadline from the lay (`capture_within_secs`): an estate that has not answered
/// (called home, served, passed the sale check) this long after its lay began is FAILED by the
/// box, by name. The install deadline and the lay fit inside it.
pub const ANSWER_WITHIN_S: u64 = 900;

/// **How long the run waits for the ONE box's `ready`**, from the payment: never a bound of its
/// own. The box is given its deadlines in the declaration ([`ANSWER_WITHIN_S`],
/// [`INSTALL_DEADLINE_MINS`]) and FAILS the order by name when one passes; the run waits for
/// that word, so its bound is the box's deadline and one more of the box's ticks. A slow box
/// under load is waited for as long as the box itself would wait. A longer `--budget-s` is kept.
pub fn ready_budget(budget_s: u64) -> Duration {
    Duration::from_secs(budget_s.max(ANSWER_WITHIN_S + 2 * POLL_MINUTES * 60))
}

/// **The `podman ps` that counts the run's laid boxes**: every box the mock created and that
/// has not ended.
pub fn laid_boxes_argv(label_filter: &str) -> Vec<&str> {
    vec!["ps", "-a", "--filter", "status=running", "--filter", "status=paused", "--filter", label_filter, "--format", "{{.Names}}"]
}

/// A container's whole log: what it wrote to stdout, then to stderr (`podman logs` keeps them apart).
/// The utility address of this run's FRONT box: the container whose hostname has the front
/// medium's prefix.
fn front_ip(label: &str, prefix: &str) -> Option<std::net::Ipv4Addr> {
    let filter = format!("label=mock-upcloud-container={label}");
    let ids = podman(&["ps", "--filter", &filter, "--format", "{{.ID}}"]).ok()?;
    for id in ids.lines().map(str::trim).filter(|l| !l.is_empty()) {
        let seen = podman(&["inspect", "-f", "{{.Config.Hostname}} {{range .NetworkSettings.Networks}}{{.IPAddress}} {{end}}", id]).ok()?;
        let mut words = seen.split_whitespace();
        if words.next().is_some_and(|h| h.starts_with(prefix)) {
            if let Some(ip) = words.find_map(|w| w.parse().ok()) {
                return Some(ip);
            }
        }
    }
    None
}

fn logs_of(id: &str) -> String {
    match Command::new("podman").args(["logs", id]).output() {
        Ok(o) => format!("{}{}", String::from_utf8_lossy(&o.stdout), String::from_utf8_lossy(&o.stderr)),
        Err(e) => format!("podman logs {id}: {e}"),
    }
}

fn podman(args: &[&str]) -> Result<String, String> {
    let out = Command::new("podman").args(args).output().map_err(|e| format!("podman: {e}"))?;
    if out.status.success() {
        Ok(String::from_utf8_lossy(&out.stdout).trim().to_string())
    } else {
        Err(format!("podman {}: {}", args.join(" "), String::from_utf8_lossy(&out.stderr).trim()))
    }
}

/// Where a run's ONE box is reached: the utility network's gateway, the ONE box's own
/// address on it, and the slot's ports.
#[derive(Clone, Copy, Debug)]
pub struct RunNet<'a> {
    pub gateway: &'a str,
    pub one_ip: &'a str,
    pub ports: FastPorts,
}

/// Puts `from` at `dir/name`, the bin dir the ONE box's container runs from. Parallel runs of
/// one checkout share that dir, and another run's box may be executing `name`: the file is
/// copied beside it and renamed over it, so the running one keeps its own (a write into it is
/// `Text file busy`). A failure names the destination.
pub fn install_bin(from: &Path, dir: &Path, name: &str) -> Result<(), String> {
    let to = dir.join(name);
    let tmp = dir.join(format!(".{name}.{}.tmp", std::process::id()));
    let put = std::fs::copy(from, &tmp).and_then(|_| std::fs::rename(&tmp, &to));
    if put.is_err() {
        let _ = std::fs::remove_file(&tmp);
    }
    put.map_err(|e| format!("{} → {}: {e}", from.display(), to.display()))
}

/// The ONE box's `monetize.toml`, with every path as the container sees it.
pub fn declaration(product: &str, company: &str, net: &RunNet<'_>, fleet_ca_pem: &str, grants: &[String], media: &[(String, String, u64)]) -> String {
    let RunNet { gateway, one_ip, ports } = *net;
    let stripe = format!("http://{gateway}:{}", ports.stripe);
    let mock = format!("http://localhost:{}", ports.mock);
    let roots = "guest_trust_roots = [\"/data/monetize/trust/fast-root.der\"]";
    let vendor = vendor_of(product);
    let (key_secret, hook_secret) = stripe_secrets_of(product);
    let mut t = format!(
        r#"# GENERATED by monetize-fast (the fast test, A24 §8.2). The ONE box's declaration for one run.
grpc_addr = "0.0.0.0:{ONE_GRPC}"
data_dir = "/data/monetize/data"
poll_minutes = {POLL_MINUTES}
default_market = "se"

[products.{product}]
instance = "acme"
vendor = "{vendor}"
guest = "/data/monetize/guests/{product}.wasm"
{roots}
grants = {grants:?}

[prices.{product}.SE]
disk_gib_month = 1900

[vendors.stripe.{product}]
enabled = true
country = "IE"
guest = "/data/monetize/guests/stripe.wasm"
{roots}
grants = ["http", "hmac", "state"]
http_hosts = ["{stripe}"]
hmac_secrets = ["{hook_secret}"]
base_url = "{stripe}"
success_url = "https://acme.{product}.example/paid/{{reference}}"
cancel_url = "https://acme.{product}.example/cancel/{{reference}}"
livemode = false
webhook_secret = "{hook_secret}"

[[vendors.stripe.{product}.http_auth]]
host = "{stripe}"
prefix = "Bearer "
secret = "{key_secret}"

[clouds.upcloud]
enabled = true
guest = "/data/monetize/guests/upcloud.wasm"
{roots}
grants = ["http", "state"]
http_hosts = ["{mock}"]
api_base = "{mock}"
http_resolve = ["localhost={gateway}"]
zone = "se-sto1"
country = "FI"
cap = {{ monthly_minor = 50000, currency = "Eur" }}

[[clouds.upcloud.http_auth]]
host = "{mock}"
prefix = "Bearer "
secret = "upcloud_token"

[estate_orders]
product = "{product}"
cloud = "upcloud"
vendor = "{vendor}"
apex = "{product}.example"
zone = "se-sto1"
currency = "EUR"
pairing = "shop-pairing"
dns = "file:/data/monetize/bench-dns.json"
shop_door = "https://{ONE_NAME}"
spend_cap_monthly_minor = 50000
max_estates = 2
max_open = 2
install_deadline_mins = {INSTALL_DEADLINE_MINS}
capture_within_secs = {ANSWER_WITHIN_S}
installer_timeout_secs = 600

[estate_orders.term]
renew_url = "https://{{site}}/private?renew={{company}}"

# The operator's own site, laid by this box (a site order: the operator pays through the
# site's vendor, the box lays the site's apex itself).
[estates.{company}]
product = "{product}"
vendor = "{vendor}"
owner = "alice"
site = "{company}.{product}.example"
operator_site = true
terminable = true

[estate_orders.sale_feed]
"shop.reach" = "utility"
"shop.mint_certificate" = "true"
fleet_at = "{one_ip}:{ONE_TLS}"
fleet_ca = {ca:?}
"#,
        ca = fleet_ca_pem
    );
    // The account plans the site's /signup sells, for the owner's walk ([`crate::walk`]).
    t.push_str(&crate::walk::signup_block(product));
    for (kind, url, bytes) in media {
        let sha = url.rsplit('/').next().and_then(|n| n.strip_suffix(".json")).unwrap_or_default();
        t.push_str(&format!("\n[estate_orders.media_objects.\"{kind}\"]\nurl = \"{url}\"\nsha256 = \"{sha}\"\nbytes = {bytes}\n"));
    }
    t
}

fn write_secret(dir: &Path, name: &str, value: &str) -> Result<(), String> {
    use std::os::unix::fs::PermissionsExt as _;
    let p = dir.join(format!("secret.{name}"));
    std::fs::write(&p, value).map_err(|e| format!("{}: {e}", p.display()))?;
    std::fs::set_permissions(&p, std::fs::Permissions::from_mode(0o600)).map_err(|e| e.to_string())
}

/// The whole run on the real ONE box. Answers like [`crate::run`].
pub fn run(cfg: &Config, kit: &Kit) -> Result<(PathBuf, bool), String> {
    let r = Receipt::default();
    r.start();
    let product = cfg.product.as_str();
    let company = "acme";
    let label = crate::run_label();
    let network = format!("fast-{label}");
    let gateway = format!("{}.15.254", cfg.utility);
    let one_ip = format!("{}.{ONE_HOST}", cfg.utility);
    let ports = ports_of(cfg.slot).ok_or_else(|| format!("[fast-slot] slot {}: there are {}", cfg.slot, mock_upcloud::container::FAST_SLOTS))?;
    let work = cfg.out.join(work_dir_of(cfg.slot));
    let _ = std::fs::remove_dir_all(&work);
    for d in ["one/monetize/guests", "one/monetize/trust", "one/monetize/data/secrets", "one/edge", "mock", "media"] {
        std::fs::create_dir_all(work.join(d)).map_err(|e| format!("{}: {e}", work.join(d).display()))?;
    }
    let mut trees: BTreeMap<String, String> = cfg.trees.iter().map(|(n, d)| (n.clone(), head_of(d))).collect();
    trees.entry("monetize".into()).or_insert_with(|| head_of(Path::new(env!("CARGO_MANIFEST_DIR"))));
    let done = |r: &Receipt| -> Result<(PathBuf, bool), String> {
        let p = r.write(&cfg.out, product, &trees).map_err(|e| e.to_string())?;
        Ok((p, r.passed()))
    };
    let one_name = format!("fast-one-{label}");
    let mock_addr: SocketAddr = format!("127.0.0.1:{}", ports.mock).parse().unwrap();
    let control: SocketAddr = format!("127.0.0.1:{}", ports.control).parse().unwrap();
    let one_addr: SocketAddr = format!("{one_ip}:{ONE_GRPC}").parse().unwrap();
    let auth = ("Authorization", "Bearer fast-run");

    // ── the kit ───────────────────────────────────────────────────────────────────────────
    let have: Vec<&String> = kit.guests.keys().collect();
    r.step(
        "kit: the ONE box's pieces are built (monetize-admin, fast-edge, mock-upcloud, fake_stripe_serve, the three guests)",
        if ["upcloud", "stripe", product].iter().all(|g| kit.guests.contains_key(*g)) { Ok(format!("guests {have:?}")) } else { Err(format!("guests {have:?}: upcloud, stripe and {product} are needed")) },
    );
    if !r.passed() {
        return done(&r);
    }

    // ── the cloud: the mock with a container behind every machine ────────────────────────
    let mut mock_cmd = Command::new(&kit.mock_upcloud);
    mock_cmd
        .args(["--port", &ports.mock.to_string(), "--speed", MOCK_SPEED, "--listen", "0.0.0.0", "--engine", "container", "--label", &label, "--network", &network, "--utility", &cfg.utility, "--image", &cfg.image, "--root"])
        .arg(work.join("mock"))
        .arg("--bin-dir")
        .arg(&cfg.bin_dir);
    for (prefix, file) in &cfg.media {
        mock_cmd.arg("--by-hostname").arg(format!("{prefix}={}", file.display()));
    }
    let mock = Daemon::spawn("mock-upcloud", &mut mock_cmd, &cfg.out.join("mock.log"));
    let mock = match mock {
        Ok(m) => m,
        Err(e) => {
            r.step("cloud: mock-upcloud --engine container serves the UpCloud API", Err(e));
            return done(&r);
        }
    };
    let up = wait_port(mock_addr, Duration::from_secs(30));
    r.step("cloud: mock-upcloud --engine container serves the UpCloud API on the utility bridge", if up { Ok(format!("http://{gateway}:{} for the box, {mock_addr} here; network {network} over {}.8.0/21", ports.mock, cfg.utility)) } else { Err(format!("the mock never listened: {}", tail(&mock.log(), 8))) });
    if !up {
        return done(&r);
    }

    // ── the vendor: the fake Stripe ───────────────────────────────────────────────────────
    let mut stripe_cmd = Command::new(&kit.fake_stripe);
    stripe_cmd.args(["--port", &ports.stripe.to_string(), "--control", &ports.control.to_string(), "--key", STRIPE_KEY, "--webhook", STRIPE_HOOK, "--listen", "0.0.0.0", "--ids-like-stripe", "true"]);
    let stripe = match Daemon::spawn("fake-stripe", &mut stripe_cmd, &cfg.out.join("stripe.log")) {
        Ok(s) => s,
        Err(e) => {
            r.step("pay: the fake Stripe serves on the utility bridge", Err(e));
            return done(&r);
        }
    };
    let up = wait_port(control, Duration::from_secs(30));
    r.step("pay: the fake Stripe serves on the utility bridge, its control on loopback", if up { Ok(format!("http://{gateway}:{}; control {control}", ports.stripe)) } else { Err(format!("the fake never listened: {}", tail(&stripe.log(), 8))) });
    if !up {
        return done(&r);
    }

    // ── the run's test CA signs the guests ────────────────────────────────────────────────
    let signed: Result<String, String> = (|| {
        use guest_host::verify::sign::{self, dev};
        let (ca_key, ca_der) = dev::mint_ca("fast-test-plugin-root").map_err(|e| e.to_string())?;
        std::fs::write(work.join("one/monetize/trust/fast-root.der"), &ca_der).map_err(|e| e.to_string())?;
        let signer = dev::new_ed25519_signer(&ca_key, &ca_der, "fast-test-signing").map_err(|e| e.to_string())?;
        let mut names = Vec::new();
        for (name, from) in &kit.guests {
            let to = work.join("one/monetize/guests").join(format!("{name}.wasm"));
            std::fs::copy(from, &to).map_err(|e| format!("{}: {e}", from.display()))?;
            sign::sign_module_file(&to, &signer)?;
            names.push(name.clone());
        }
        Ok(format!("{} module(s) signed under the run's root: {names:?}", names.len()))
    })();
    // The product's names are its guest's facts (op 90), read from the module just signed.
    let mut grants: Vec<String> = Vec::new();
    let followed = signed.and_then(|w| {
        let g = work.join("one/monetize");
        let (line, asked) = follow_guest(product, &g.join("guests").join(format!("{product}.wasm")), &g.join("trust/fast-root.der"), &work.join("facts"))?;
        let words = format!("{w}; {line}; its grants {asked:?}");
        grants = asked;
        Ok(words)
    });
    if !r.step("the run's test CA signs the product, cloud and vendor guests (never the real signing root)", followed) {
        return done(&r);
    }
    let kinds = match media_kinds(product) {
        Ok(k) => k,
        Err(e) => {
            r.step("the product has a fast estate", Err(e));
            return done(&r);
        }
    };

    // ── the media: the product's container media in the mock's object store ───────────────
    let mut media_rows: Vec<(String, String, u64)> = Vec::new();
    let media: Result<String, String> = (|| {
        for (kind, prefix) in &kinds {
            let file = cfg.media.iter().find(|(p, _)| p == prefix).map(|(_, f)| f.clone()).ok_or_else(|| format!("no medium for the machines {prefix}* ({kind})"))?;
            let bytes = std::fs::read(&file).map_err(|e| format!("{}: {e}", file.display()))?;
            let sha = sha256_hex(&bytes);
            let key = format!("release/{kind}/{sha}.json");
            let (status, body) = http(mock_addr, "PUT", &format!("/objsto/{key}"), &[auth, ("Content-Type", "application/json")], &bytes)?;
            if status != 200 {
                return Err(format!("PUT /objsto/{key}: {status} {body}"));
            }
            media_rows.push((kind.to_string(), format!("http://127.0.0.1:{}/objsto/{key}", ports.mock), bytes.len() as u64));
        }
        Ok(media_rows.iter().map(|(k, _, b)| format!("{k} ({b} bytes)")).collect::<Vec<_>>().join(", "))
    })();
    if !r.step("media: the product's container media are objects in the mock's release bucket", media) {
        return done(&r);
    }

    // ── the ONE box's declaration, secrets, bearer and TLS door ───────────────────────────
    let one = work.join("one");
    let declared: Result<String, String> = (|| {
        let (cert, key) = monetize_shop_pairing::self_signed(&[ONE_NAME.to_string()])?;
        std::fs::write(one.join("edge/cert.pem"), &cert).map_err(|e| e.to_string())?;
        std::fs::write(one.join("edge/key.pem"), &key).map_err(|e| e.to_string())?;
        std::fs::write(one.join("monetize/monetize.toml"), declaration(product, company, &RunNet { gateway: &gateway, one_ip: &one_ip, ports }, &cert, &grants, &media_rows)).map_err(|e| e.to_string())?;
        let secrets = one.join("monetize/data/secrets");
        let (key_secret, hook_secret) = stripe_secrets_of(product);
        write_secret(&secrets, &key_secret, STRIPE_KEY)?;
        write_secret(&secrets, &hook_secret, STRIPE_HOOK)?;
        write_secret(&secrets, "upcloud_token", MOCK_TOKEN)?;
        write_secret(&secrets, "media_objsto", &serde_json::json!({ "access_key_id": "fast-release-access", "secret_access_key": "fast-release-secret", "region": "mock" }).to_string())?;
        use std::os::unix::fs::PermissionsExt as _;
        for (file, value) in [("token", BEARER), ("operator-token", OPERATOR)] {
            let p = one.join("monetize/data").join(file);
            std::fs::write(&p, value).map_err(|e| e.to_string())?;
            std::fs::set_permissions(&p, std::fs::Permissions::from_mode(0o600)).map_err(|e| e.to_string())?;
        }
        for (name, from) in [("monetize-admin", &kit.monetize_admin), ("fast-edge", &kit.fast_edge)] {
            install_bin(from, &cfg.bin_dir, name)?;
        }
        Ok(format!("monetize.toml ({} media objects, the site {company}), 4 secrets, the service and operator bearers, the edge's certificate for {ONE_NAME}", media_rows.len()))
    })();
    if !r.step("the ONE box's declaration: the three guests, the mock as its cloud, the fake as its vendor, the estate it sells", declared) {
        return done(&r);
    }
    // Both on stdout, so the box's log reads in the order it was written.
    let entry = format!("/opt/bin/fast-edge --listen 0.0.0.0:{ONE_TLS} --to 127.0.0.1:{ONE_GRPC} --cert /data/edge/cert.pem --key /data/edge/key.pem 2>&1 & exec /opt/bin/monetize-admin server --config /data/monetize/monetize.toml 2>&1");
    let _ = podman(&["rm", "-f", "-t", "0", &one_name]);
    let started = podman(&[
        "run", "-d", "--init", "--name", &one_name, "--label", &format!("mock-upcloud-container={label}"), "--hostname", "one", "--network", &network, "--ip", &one_ip,
        "--cpus", "2", "--memory", "4096m",
        "-v", &format!("{}:/data", one.display()), "-v", &format!("{}:/opt/bin:ro", cfg.bin_dir.display()),
        "-e", "MONETIZE_ADMIN_DATA=/data", "-e", "RUST_LOG=info", &cfg.image, "sh", "-c", &entry,
    ]);
    let one_log = || logs_of(&one_name);
    let up = started.is_ok() && wait_port(one_addr, Duration::from_secs(90));
    r.step(
        "the ONE box: monetize-admin server --config in its container, fast-edge's TLS door in front",
        match &started {
            Ok(_) if up => Ok(format!("{one_name} at {one_ip}: gRPC h2c :{ONE_GRPC}, TLS :{ONE_TLS} as {ONE_NAME}")),
            Ok(_) => Err(format!("the box never listened on {one_addr}: {}", tail(&one_log(), 15).replace('\n', " | "))),
            Err(e) => Err(e.clone()),
        },
    );
    let on_bridge = on_the_utility_bridge(&gateway);
    r.step("this run is the ONE side of the utility network", if on_bridge { Ok(format!("this process is {gateway} on {network}")) } else { Err("not on the utility bridge: run inside `podman unshare --rootless-netns`".into()) });
    let teardown = |r: &Receipt, mock: &mut Daemon, stripe: &mut Daemon| {
        let _ = std::fs::write(cfg.out.join("one.log"), one_log());
        let mut boxes = String::new();
        if let Ok(ids) = podman(&["ps", "-a", "--filter", &format!("label=mock-upcloud-container={label}"), "--format", "{{.ID}} {{.Names}}"]) {
            for line in ids.lines() {
                let id = line.split_whitespace().next().unwrap_or_default();
                boxes.push_str(&format!("\n──── {line} ────\n{}", logs_of(id)));
            }
        }
        let _ = std::fs::write(cfg.out.join("boxes.log"), &boxes);
        mock.stop();
        stripe.stop();
        // The mock tears its boxes down on its way out, but under load it can be stopped before
        // it is done (a box left `Stopping`). The run's own bounded sweep follows, the ONE box
        // with them: stop, kill, remove, each step timed; whatever is truly left fails the step.
        let swept = mock_upcloud::container::sweep_run("podman", &label, mock_upcloud::container::SWEEP_PATIENCE);
        let _ = podman(&["network", "rm", "-f", &network]);
        r.step("terminate (the run's own): no container and no network of the run is left", crate::terminate_verdict(&swept, crate::network_left(&network)));
    };
    let (mut mock, mut stripe) = (mock, stripe);
    if !up || !on_bridge {
        teardown(&r, &mut mock, &mut stripe);
        return done(&r);
    }
    // The guests: taken at start, or refused by name in the box's log.
    std::thread::sleep(Duration::from_secs(3));
    let log = one_log();
    let refused: Vec<&str> = log.lines().filter(|l| l.contains("REFUSED") || l.contains("refused-at-start") || l.contains("[guest-")).take(6).collect();
    r.step("the ONE box took the three signed guests at start (no refusal in its log)", if refused.is_empty() { Ok("no REFUSED line".into()) } else { Err(refused.join(" | ")) });

    // ── buy: EstateOrder.OrderSite, the page paid at the fake, the webhook to the callback door
    let rt = tokio::runtime::Builder::new_multi_thread().worker_threads(2).enable_all().build().map_err(|e| e.to_string())?;
    let channel = rt.block_on(async { tonic::transport::Channel::from_shared(format!("http://{one_addr}")).map_err(|e| e.to_string())?.connect_timeout(Duration::from_secs(10)).connect().await.map_err(|e| e.to_string()) });
    let channel = match channel {
        Ok(c) => c,
        Err(e) => {
            r.step("buy: the operator reaches the ONE box's gRPC door", Err(e));
            teardown(&r, &mut mock, &mut stripe);
            return done(&r);
        }
    };
    fn authed<T>(m: T) -> tonic::Request<T> {
        let mut req = tonic::Request::new(m);
        req.metadata_mut().insert("authorization", format!("Bearer {OPERATOR}").parse().expect("a bearer header"));
        req
    }
    let mut orders = monetize_proto::estate_order_client::EstateOrderClient::new(channel.clone());
    let started = rt.block_on(orders.order_site(authed(monetize_proto::EstateOrderSiteRequest { estate: company.into(), email: "ops@fast.invalid".into(), ..Default::default() })));
    let session = match &started {
        Ok(s) => {
            let s = s.get_ref();
            let cs = s.checkout_url.rsplit('/').next().unwrap_or_default().to_string();
            r.step("buy: the operator orders the site (EstateOrder.OrderSite): the quote and ONE payment page", Ok(format!("{} — {} — {} ({})", s.reference, s.price_words, s.words, s.checkout_url)));
            cs
        }
        Err(e) => {
            r.step("buy: the operator orders the site (EstateOrder.OrderSite): the quote and ONE payment page", Err(format!("{e} — the box's log: {}", tail(&one_log(), 12).replace('\n', " | "))));
            String::new()
        }
    };
    if session.is_empty() {
        teardown(&r, &mut mock, &mut stripe);
        return done(&r);
    }
    let paid: Result<String, String> = (|| {
        let (status, body) = http(control, "POST", &format!("/pay/{session}"), &[], b"")?;
        if status != 200 {
            return Err(format!("the fake's control refused the payment: {status} {body}"));
        }
        let v: serde_json::Value = serde_json::from_str(&body).map_err(|e| format!("the control's answer: {e}"))?;
        let (sig, event) = (v["signature"].as_str().unwrap_or_default().to_string(), v["body"].as_str().unwrap_or_default().to_string());
        let (status, body) = http(one_addr, "POST", &format!("/callback/stripe/{product}"), &[("Stripe-Signature", &sig), ("Content-Type", "application/json")], event.as_bytes())?;
        if status != 200 {
            return Err(format!("the ONE box's callback door answered {status}: {body}"));
        }
        Ok(format!("{session} paid at the fake; its checkout.session.completed webhook was taken by the box ({status})"))
    })();
    if !r.step("pay: the operator pays the page at the fake Stripe; its signed webhook reaches the box's callback door", paid) {
        teardown(&r, &mut mock, &mut stripe);
        return done(&r);
    }

    // ── lay → install → ready, on the ONE box's own code ──────────────────────────────────
    let t0 = Instant::now();
    let mut seen: Vec<(String, u64)> = Vec::new();
    let mut last = String::new();
    let mut final_words = String::new();
    let budget = ready_budget(cfg.budget_s);
    let mut laid_checked = false;
    while t0.elapsed() < budget {
        let st = rt.block_on(orders.status(authed(monetize_proto::EstateOrderStatusRequest { company: company.into(), actor_ticket: Vec::new() })));
        let (state, words) = match st {
            Ok(s) => {
                let s = s.get_ref();
                (if s.phase.is_empty() { s.state.clone() } else { format!("{}/{}", s.state, s.phase) }, if s.why.is_empty() { s.words.clone() } else { format!("{} [{}]", s.words, s.why) })
            }
            Err(e) => (format!("rpc-error {}", e.code()), e.message().to_string()),
        };
        if state != last {
            println!("fast: order {company}: {state} at {} s: {words}", t0.elapsed().as_secs());
            seen.push((state.clone(), t0.elapsed().as_secs()));
            last = state.clone();
        }
        final_words = words;
        if (state.starts_with("installing") || state.starts_with("ready")) && !laid_checked {
            laid_checked = true;
            let laid: Result<String, String> = (|| {
                let (status, body) = http(mock_addr, "GET", "/1.3/server", &[auth], b"")?;
                if status != 200 {
                    return Err(format!("GET /1.3/server: {status}"));
                }
                let v: serde_json::Value = serde_json::from_str(&body).map_err(|e| e.to_string())?;
                let hosts: Vec<String> = v["servers"]["server"].as_array().map(|a| a.iter().map(|s| s["hostname"].as_str().unwrap_or_default().to_string()).collect()).unwrap_or_default();
                let ours: Vec<&String> = hosts.iter().filter(|h| h.ends_with(&format!("-{company}"))).collect();
                let filter = format!("label=mock-upcloud-container={label}");
                let running = podman(&laid_boxes_argv(&filter)).map(|s| s.lines().filter(|l| l.starts_with("mu-")).count()).unwrap_or(0);
                if ours.len() == 3 && running == 3 {
                    Ok(format!("{ours:?} at the mock, {running} containers running"))
                } else {
                    Err(format!("servers of {company} at the mock: {ours:?}; containers running: {running}"))
                }
            })();
            r.step("lay: the ONE box laid exactly the plan's machines at the mock, each one running as a container", laid);
        }
        let word = state.split('/').next().unwrap_or_default();
        if word == "ready" || word == "failed" || state.starts_with("rpc-error") && t0.elapsed() > Duration::from_secs(60) {
            break;
        }
        std::thread::sleep(Duration::from_secs(2));
    }
    let phases = seen.iter().map(|(s, at)| format!("{s}@{at}s")).collect::<Vec<_>>().join(" → ");
    let ready = last.starts_with("ready");
    // `ready` is the capture's three holds passed, each on the box's own code: the call home
    // (the sold boxes reported on the pull channel, over the TLS door), the main's word that it
    // serves, and the sale check over the site's front.
    r.step(
        "ready: the ONE box laid and paired the site, heard its boxes call home, read the main's word and the sale check, and captured the payment (EstateOrder.Status = ready)",
        if ready {
            Ok(format!("{phases}: {final_words}"))
        } else {
            // Who ended the wait: the box's own word (`failed`, its reason), or — only if the box
            // broke its own deadlines — the run's bound.
            let ended = if last.starts_with("failed") { "the box FAILED the order".to_string() } else { format!("the box said neither ready nor failed within {} s (its deadlines and a tick)", budget.as_secs()) };
            Err(format!("{phases}; {ended}; last words: {final_words}; the box's log: {}", tail(&one_log(), 20).replace('\n', " | ")))
        },
    );
    // ── the owner's walk on the real front (T-OWNERFLOW): an account plan, bought on /signup ──
    if ready {
        let host = format!("{company}.{product}.example");
        let site: Result<crate::walk::Site<'_>, String> = (|| {
            let cert_path = crate::walk::front_cert_under(&work.join("one")).ok_or("the shop kept no certificate for the site's front")?;
            let cert = std::fs::read(&cert_path).map_err(|e| format!("{}: {e}", cert_path.display()))?;
            // The front's machines are named by its medium's kind (`front`, Holger's `holger-front`).
            let prefix = crate::walk::front_prefix(&kinds).ok_or_else(|| format!("the product names no front medium: {kinds:?}"))?;
            let ip = front_ip(&label, &prefix).ok_or_else(|| format!("no running container of this run named {prefix}*"))?;
            Ok(crate::walk::Site { product, host: host.clone(), front: SocketAddr::from((ip, 443)), cert, control, one: one_addr, vendor_instance: product })
        })();
        match site {
            Ok(site) => {
                crate::walk::run(&r, &site);
            }
            Err(e) => {
                r.step("walk: the site's front is reached for the owner's walk", Err(e));
            }
        }
        // ── the site refeed, end to end (RA5-18 + MAIL-RELAY): the order pulled and answered ──
        let asked = match rt.block_on(orders.refeed(authed(monetize_proto::EstateOrderRefeedRequest { estate: company.into(), only: vec![crate::refeed::GROUP.into()] }))) {
            Ok(a) => crate::refeed::Asked::Queued { asked: a.get_ref().asked, words: a.get_ref().words.clone() },
            Err(e) => crate::refeed::Asked::Refused(format!("{}: {}", e.code(), e.message())),
        };
        let t0 = Instant::now();
        let mut verdict = None;
        while verdict.is_none() {
            let (answered, kept, words) = match rt.block_on(orders.status(authed(monetize_proto::EstateOrderStatusRequest { company: company.into(), actor_ticket: Vec::new() }))) {
                Ok(s) => (s.get_ref().refeed_answered, s.get_ref().refeed_kept, s.get_ref().refeed_words.clone()),
                Err(e) => (0, false, format!("rpc-error {}: {}", e.code(), e.message())),
            };
            verdict = crate::refeed::verdict(&asked, answered, kept, &words);
            if verdict.is_none() {
                if t0.elapsed() > Duration::from_secs(crate::refeed::ANSWER_WITHIN_S) {
                    verdict = Some(Err(format!("the main did not answer the refeed order within {} s ({asked:?}); last status words: {words}", crate::refeed::ANSWER_WITHIN_S)));
                } else {
                    std::thread::sleep(Duration::from_secs(2));
                }
            }
        }
        r.step(crate::refeed::STEP, verdict.expect("judged"));
    }
    r.step("what is a double in this run (said, not judged)", Ok("the cloud (mock-upcloud, a container per machine), the medium (JSON, not the ISO), the seed's road (staged, not the metadata), the vendor (the fake Stripe), the DNS (the mock's file); the site's account sign-up is walked on its real front and its keys fed again (refeed); not yet run here: the private order on the real boxes (the trials walk it: g-owner-walk), renew, grow, update, terminate".into()));
    teardown(&r, &mut mock, &mut stripe);
    done(&r)
}

#[cfg(test)]
mod tests {

    /// ★ **Two parallel runs of one checkout share the bin dir the ONE box runs from**
    /// (2026-10-25, two Gunnar runs at once: "kit/fast-edge: Text file busy"): the second run
    /// puts its kit there while the first run's box executes it. The install replaces the file
    /// beside the running one, never writes into it, and names the destination when it fails.
    #[test]
    fn a_kit_binary_is_installed_over_one_that_is_running() {
        let dir = std::env::temp_dir().join(format!("fast-install-{}", std::process::id()));
        let _ = std::fs::remove_dir_all(&dir);
        std::fs::create_dir_all(&dir).unwrap();
        let sleep = Path::new("/bin/sleep");
        std::fs::copy(sleep, dir.join("box")).unwrap();
        let mut running = Command::new(dir.join("box")).arg("30").spawn().expect("the first run's box runs");
        let installed = install_bin(sleep, &dir, "box");
        let _ = running.kill();
        let _ = running.wait();
        installed.expect("installed beside the running binary, not into it");
        assert!(Command::new(dir.join("box")).arg("0").status().unwrap().success(), "the new file runs");
        assert!(install_bin(&dir.join("absent"), &dir, "box").unwrap_err().contains("box"), "a failure names the destination");
        let _ = std::fs::remove_dir_all(&dir);
    }
    /// ★ **Parallel fast runs**: a slot's mock, fake Stripe and its control listen on their own
    /// ports in the shared rootless namespace; slot 0 keeps today's.
    #[test]
    fn each_slot_has_its_own_ports_and_slot_zero_keeps_todays() {
        assert_eq!(ports_of(0), Some(FastPorts { mock: 8791, stripe: 12791, control: 12792 }));
        assert_eq!(ports_of(3), Some(FastPorts { mock: 8821, stripe: 12821, control: 12822 }));
        assert!(ports_of(mock_upcloud::container::FAST_SLOTS).is_none());
        let d = declaration("holger", "acme", &RunNet { gateway: "10.214.15.254", one_ip: "10.214.8.90", ports: ports_of(1).unwrap() }, "PEM", &["grpc".to_string()], &[]);
        assert!(d.contains("http://10.214.15.254:12801"), "the ONE box dials ITS slot's fake Stripe: {d}");
        assert!(!d.contains(":12791"), "never another slot's: {d}");
    }

    /// ★ Two runs at once take two slots; a slot held by a run is never handed to another.
    #[test]
    fn two_runs_at_once_take_two_slots() {
        let dir = std::env::temp_dir().join(format!("fast-slots-{}", std::process::id()));
        let _ = std::fs::remove_dir_all(&dir);
        let (a, _ga) = claim_slot(&dir, None).unwrap();
        let (b, _gb) = claim_slot(&dir, None).unwrap();
        assert_ne!(a, b, "two runs, two slots");
        assert!(claim_slot(&dir, Some(a)).is_err(), "a held slot is refused by name");
        drop(_ga);
        assert_eq!(claim_slot(&dir, Some(a)).unwrap().0, a, "a freed slot is free again");
        let _ = std::fs::remove_dir_all(&dir);
    }

    use super::*;

    /// ★ **The ready wait is the box's own deadlines, never a guess of its own** (FAST-REL,
    /// 2026-10-25): Holger's fast went red under load at a fixed 420 s from the payment
    /// (`budget_s.max(120) + 240`) while the box it watched still had its 10-minute install
    /// deadline, and a lay alone took 100 s at load 300. The declaration gives the box its job
    /// deadline from the lay (`capture_within_secs`) and its install deadline; the box FAILS the
    /// order by name when either passes, and the run waits for that word: its own bound is the
    /// box's deadline and one more of the box's ticks, whatever `--budget-s` says.
    #[test]
    fn the_ready_wait_outlasts_the_deadlines_the_box_is_given() {
        let d = declaration("holger", "acme", &RunNet { gateway: "10.213.15.254", one_ip: "10.213.8.90", ports: ports_of(0).unwrap() }, "PEM", &["grpc".to_string()], &[]);
        let num = |key: &str| -> u64 {
            let line = d.lines().find(|l| l.trim_start().starts_with(&format!("{key} ="))).unwrap_or_else(|| panic!("the declaration names {key}: {d}"));
            line.split('=').nth(1).unwrap().trim().parse().unwrap_or_else(|e| panic!("{line}: {e}"))
        };
        let tick = num("poll_minutes") * 60;
        let install = num("install_deadline_mins") * 60;
        let answer = num("capture_within_secs");
        assert!(answer > install, "the job's deadline from the lay ({answer} s) leaves the lay room before the install's ({install} s)");
        for given in [0, 180, 300] {
            let wait = ready_budget(given).as_secs();
            assert!(wait >= answer + tick, "--budget-s {given}: the run waits {wait} s, so the box's own word (its deadline {answer} s and one tick {tick} s) always comes first");
        }
        assert!(ready_budget(5_000).as_secs() >= 5_000, "a longer --budget-s is still honoured");
    }

    /// ★ **A box that boots late is laid** (FAST-REL, 2026-10-25): the lay step counted only
    /// RUNNING containers, so a machine the cloud had created that was still frozen in its boot
    /// (a paused container: a slow VM) failed "lay" though the mock held all three. A laid box is
    /// one that exists and has not ended: running or paused.
    #[test]
    fn a_box_that_boots_late_is_counted_as_laid() {
        let a = laid_boxes_argv("label=mock-upcloud-container=fast1").join(" ");
        assert!(a.starts_with("ps -a "), "every state is listed, then filtered: {a}");
        assert!(a.contains("--filter status=running") && a.contains("--filter status=paused"), "running or paused: {a}");
        assert!(a.contains("--filter label=mock-upcloud-container=fast1"), "only the run's own: {a}");
    }

    fn kinds(product: &str) -> Vec<(String, String)> {
        media_kinds(product).unwrap().iter().map(|(k, p)| (k.to_string(), p.to_string())).collect()
    }

    #[test]
    fn the_media_kinds_are_the_products_lifecycle_media() {
        monetize_server::testing::lifecycles::install();
        let s = |v: &[(&str, &str)]| v.iter().map(|(k, p)| (k.to_string(), p.to_string())).collect::<Vec<_>>();
        assert_eq!(kinds("holger"), s(&[("holger-front", "holger-web-ui-"), ("holger", "holger-server-"), ("holger-keep", "holger-server-"), ("holger-front-keep", "holger-web-ui-")]), "Holger's, as before");
        assert_eq!(kinds("gunnar"), s(&[("front", "gunnar-front-"), ("gunnar", "gunnar-appliance-"), ("gunnar-keep", "gunnar-appliance-"), ("front-keep", "gunnar-front-")]));
        assert!(media_kinds("zork").unwrap_err().contains("[fast-product]"));
    }

    #[test]
    fn a_guests_grants_are_what_its_imports_need() {
        use monetize_product_guest::imports;
        let v = |x: &[&str]| x.iter().map(|s| s.to_string()).collect::<Vec<_>>();
        assert_eq!(grants_for_imports(&v(&[imports::CLOCK, imports::LOG])).unwrap(), Vec::<String>::new(), "a product guest of the six-op contract (Gunnar's, Holger's) asks for none");
        assert_eq!(grants_for_imports(&v(&[imports::GRPC_UNARY])).unwrap(), v(&["grpc"]));
        assert_eq!(grants_for_imports(&v(&[imports::STATE_GET, imports::HTTP, imports::GRPC_UNARY, imports::ENDPOINT, imports::GRPC_STREAM_OPEN])).unwrap(), v(&["http", "grpc", "endpoint", "state"]), "in the vocabulary's order, once each");
        assert!(grants_for_imports(&v(&["socket_open"])).unwrap_err().contains("[fast-facts]"));
    }

    #[test]
    fn the_declaration_names_the_product_it_sells_and_no_other() {
        let g = |v: &[&str]| v.iter().map(|s| s.to_string()).collect::<Vec<_>>();
        let d = declaration("gunnar", "acme", &RunNet { gateway: "10.13.15.254", one_ip: "10.13.8.90", ports: ports_of(0).unwrap() }, "PEM", &g(&[]), &[]);
        assert!(d.contains("grants = []\n\n[prices.gunnar.SE]"), "the product's grants are its guest's (none): {d}");
        assert!(!d.contains("return_hosts"), "RA2-16: the retired key is never written: {d}");
        assert!(d.contains("[products.gunnar]") && d.contains("[vendors.stripe.gunnar]") && d.contains("vendor = \"stripe/gunnar\""), "{d}");
        assert!(d.contains("MONETIZE_STRIPE_GUNNAR_SECRET_KEY") && d.contains("MONETIZE_STRIPE_GUNNAR_WEBHOOK_SECRET"), "{d}");
        assert!(!d.to_lowercase().contains("holger"), "a Gunnar run's ONE box names no Holger: {d}");
        let h = declaration("holger", "acme", &RunNet { gateway: "10.13.15.254", one_ip: "10.13.8.90", ports: ports_of(0).unwrap() }, "PEM", &g(&["grpc"]), &[]);
        assert!(h.contains("[vendors.stripe.holger]") && h.contains("MONETIZE_STRIPE_HOLGER_SECRET_KEY"), "Holger's, as before: {h}");
    }
}