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

nordisk/gunnar

crates/gunnar-front/tests/one_monetize.rs

//! **ONE monetize** (owner 2026-10-10 13:35Z, final): no estate runs a monetize — not
//! gunnar.rs, not test2, not a sold estate. Its tenants, signups, purchases and entitlements
//! live in the ONE ledger at `monetize.ignalina.dk`, and its boxes PULL from it
//! (`fleet`, `fleet_instance`, `monetize_pubkey`, offered by this front to every box).
//!
//! So the front EMBEDS no monetize in any build, the paid one included: no monetize-server,
//! no plugin door wire, nothing a shop runs on. What the paid front MAY link is the pull
//! channel's wire and signature — `monetize-proto` and `monetize` — as the SOLD estate's thin
//! `SoldEstate` client (F4's `recharge` under K3; tests/one_front_pull.rs holds that line).

const MANIFEST: &str = include_str!("../Cargo.toml");

/// The crates that ARE a per-estate monetize (or only exist to feed one). NOT here:
/// `monetize` and `monetize-proto`, the pull channel's signature and wire.
const A_MONETIZE: &[&str] = &[
    "monetize-server",
    "monetize-product-wasm",
    "monetize-front",
    "plugin-door-wire",
];

fn names_in(table: &toml::Table, key: &str) -> Vec<String> {
    table
        .get(key)
        .and_then(|d| d.as_table())
        .map(|d| d.keys().cloned().collect())
        .unwrap_or_default()
}

#[test]
fn the_front_links_no_monetize_in_any_build() {
    let m: toml::Table = toml::from_str(MANIFEST).expect("the front's Cargo.toml");
    let deps: Vec<String> = ["dependencies", "build-dependencies"]
        .iter()
        .flat_map(|k| names_in(&m, k))
        .collect();
    let linked: Vec<&String> = deps
        .iter()
        .filter(|d| A_MONETIZE.contains(&d.as_str()))
        .collect();
    assert!(linked.is_empty(), "the front links a monetize: {linked:?}");
    let features = m
        .get("features")
        .and_then(|f| f.as_table())
        .cloned()
        .unwrap_or_default();
    for (name, on) in &features {
        let on: Vec<&str> = on
            .as_array()
            .map(|a| a.iter().filter_map(|v| v.as_str()).collect())
            .unwrap_or_default();
        let named: Vec<&&str> = on
            .iter()
            .filter(|f| {
                A_MONETIZE
                    .iter()
                    .any(|c| f.trim_start_matches("dep:").split('/').next() == Some(c))
            })
            .collect();
        assert!(
            named.is_empty(),
            "feature `{name}` turns a monetize on: {named:?}"
        );
    }
}

/// The paid front is the console's paid half, the operator's door, and F4's thin pull side
/// (the estate's own installer: nordisk-pairing's wireguard link re-admits its boxes) — never
/// a shop's custody.
#[test]
fn the_paid_front_is_the_consoles_paid_half_and_nothing_more() {
    let m: toml::Table = toml::from_str(MANIFEST).unwrap();
    let metered: Vec<String> = m["features"]["metered"]
        .as_array()
        .unwrap()
        .iter()
        .filter_map(|v| v.as_str().map(String::from))
        .collect();
    assert!(
        metered.iter().any(|f| f == "gunnar-ui-server/metered"),
        "the console's paid half: {metered:?}"
    );
    assert!(
        !metered.iter().any(|f| f.contains("custody-ring")),
        "no shop custody: {metered:?}"
    );
    assert!(
        metered
            .iter()
            .any(|f| f == "nordisk-pairing/installer-wireguard"),
        "F4: the front IS the sold estate's installer: {metered:?}"
    );
}