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

nordisk/monetize

crates/monetize-admin/tests/front_certs_cli.rs

//! ★ **A product front's REAL certificate report, said by `monetize front certs`** (A7).
//! Holger's front (`/front/certs`) and Gunnar's (`/api/front/certs`) answer with edda
//! estate-front's `web::status::report_json` (Gunnar's front a port of it); the CLI prints each
//! certificate's host, its names and every line the front wrote, and decides nothing. Here
//! the report is estate-front's own, over a data root where one name failed a validation, one
//! is waiting on DNS-free ACME, and one was never tried; the CLI's own test
//! (monetize-cli `tests/front_certs.rs`) drives the binary over TLS at both doors.

use std::time::SystemTime;

#[test]
fn the_fronts_real_report_is_said_by_the_cli_line_by_line() {
    let dir = tempfile::tempdir().unwrap();
    let now = SystemTime::now();
    estate_front::web::acme::failed_as(
        dir.path(),
        "holger.example",
        now,
        estate_front::web::acme::FailKind::Validation,
    );
    estate_front::web::acme::failed_as(
        dir.path(),
        "gunnar.example",
        now,
        estate_front::web::acme::FailKind::Acme,
    );
    let report = estate_front::web::status::report_json(dir.path(), now);
    let certs = report["certificates"]
        .as_array()
        .expect("the report lists certificates")
        .clone();
    assert!(certs.len() >= 2, "{report}");
    let out =
        monetize_cli::said(monetize_cli::What::BoxCerts, 200, &report.to_string()).expect("said");
    for c in &certs {
        let host = c["host"].as_str().unwrap();
        assert!(
            out.lines().any(|l| l.starts_with(host)),
            "{host} heads its block: {out}"
        );
        for l in c["lines"]
            .as_array()
            .into_iter()
            .flatten()
            .filter_map(|l| l.as_str())
        {
            assert!(
                out.contains(&format!("  {l}\n")),
                "the front's line {l:?} is said as it wrote it: {out}"
            );
        }
    }
    let none = estate_front::web::status::report_json(tempfile::tempdir().unwrap().path(), now);
    assert!(
        monetize_cli::said(monetize_cli::What::BoxCerts, 200, &none.to_string())
            .unwrap()
            .contains("no certificate is known"),
        "{none}"
    );
}

/// ★ **tls-alert** (owner 2026-11-03, the test2 ONE box console, Sites → Certificates): the
/// box's name before its first feed (`monetize-admin`) stayed in the list after the feed and
/// alerted `tls.no-certificate` beside a valid certificate for test2.monetize.ignalina.dk. A
/// fed box with a valid certificate for its real host and a stale placeholder lists only the
/// real host and raises no alert — on the page, in the CLI, or in the alert mail.
#[test]
fn a_fed_box_with_a_valid_cert_and_a_stale_placeholder_raises_no_alert() {
    use estate_front::web::{certs, status};
    let dir = tempfile::tempdir().unwrap();
    let root = dir.path();
    let now = SystemTime::now();
    let secs = now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
    // The placeholder as the front wrote it before the first feed, its clock five hours old.
    let mut pre = status::Record {
        hosts: vec!["monetize-admin".into()],
        ..Default::default()
    };
    pre.said(Some(status::KIND_UNFED), Some("tls: nothing valid to serve yet, and the installer has fed nothing — ACME is not asked before the first feed (it names the directory and the hosts)".into()));
    pre.no_certificate_since = Some(secs - 5 * 3600);
    pre.save(root, "monetize-admin").unwrap();
    let waiting = status::report_json(root, now);
    assert_eq!(
        waiting["certificates"][0]["alert"],
        serde_json::Value::Null,
        "before the first feed: no alert {waiting}"
    );
    assert_eq!(
        waiting["certificates"][0]["lines"],
        serde_json::json!(["waiting for the first feed"]),
        "one plain state"
    );
    // Fed: the real host's certificate is valid.
    let host = "test2.monetize.example";
    let (chain, key) = certs::self_signed(&[host], 90);
    let c = certs::Cert::parse(host, &chain, &key, now).unwrap();
    certs::keep(root, host, &c).unwrap();
    status::Record {
        hosts: vec![host.into()],
        ..Default::default()
    }
    .save(root, host)
    .unwrap();
    let report = status::report_json(root, now);
    let hosts: Vec<&str> = report["certificates"]
        .as_array()
        .unwrap()
        .iter()
        .filter_map(|c| c["host"].as_str())
        .collect();
    assert_eq!(hosts, vec![host], "the placeholder left the list: {report}");
    assert!(
        report["certificates"]
            .as_array()
            .unwrap()
            .iter()
            .all(|c| c["alert"].is_null()),
        "{report}"
    );
    let out = monetize_cli::said(monetize_cli::What::BoxCerts, 200, &report.to_string()).unwrap();
    assert!(
        !out.contains("ALERT") && !out.contains("monetize-admin") && !out.contains("unix "),
        "{out}"
    );
}