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

nordisk/holger

holger-recipe/tests/feature_honesty.rs

//! RULE 1 and RULE 2 as plain Rust tests.
//!
//! Written in `.nornir/stinky/09-mvp-line-and-feature-honesty.md` §4.1 and §4.2
//! and homeless until 2026-09-20. They are tests, not a separate mechanism, so
//! they run wherever holger's tests run. `cargo xtask gate --rules` calls the
//! same two functions directly for an operator who wants the finding list
//! without compiling the workspace.
//!
//! Both are expected to be RED on `main` at `542e296`, and that is the point:
//! the first commit that makes each one green is the commit that decides
//! something nobody has decided yet. The failure text names the variant, the
//! package and the feature, so the decision is stated rather than guessed.

use holger_recipe::honesty::{self, Workspace};
use std::path::{Path, PathBuf};

fn root() -> PathBuf {
    honesty::find_workspace_root(Path::new(env!("CARGO_MANIFEST_DIR")))
        .expect("holger's [workspace] Cargo.toml above holger-recipe")
}

fn workspace() -> Workspace {
    Workspace::load(&root()).expect("parse every workspace member's Cargo.toml")
}

/// A rule that parses nothing passes everything. This asserts the engine really
/// sees holger's workspace before any verdict below is believed.
#[test]
fn the_engine_is_not_vacuous() {
    let ws = workspace();
    assert!(
        ws.members.len() > 20,
        "only {} workspace members parsed; the member glob expansion is broken",
        ws.members.len()
    );
    assert!(ws.get("holger").is_some(), "holger not parsed");
    assert!(
        ws.get("holger-server-lib").is_some(),
        "holger-server-lib not parsed"
    );

    let rows = honesty::shipped_rows();
    assert!(!rows.is_empty(), "no shipped rows to judge");
    assert!(
        rows.iter().any(|r| r.variant == "mvp-server-musl"),
        "mvp-server-musl is a declared exe row and must be judged"
    );
}

/// The rule must discriminate, or it is noise: a feature the ROW ITSELF
/// declares can never be reported as a rider on that row.
///
/// Note what this does NOT say. `full` IS reported as shipping
/// `holger-server-lib` feature `mini`, and that is correct: `full`'s own
/// declaration does not name `mini`; it arrives through the bench-scenarios
/// edge, which is the mechanism of feature leak 1. The rule is per row, not per
/// feature name.
#[test]
fn a_feature_the_row_itself_declares_is_never_a_rider() {
    let riders = honesty::rule1_riders(&workspace());
    for row in honesty::shipped_rows() {
        for r in riders.iter().filter(|r| r.variant == row.variant) {
            assert!(
                !row.features.contains(&r.feature),
                "row '{}' declares \"{}\" and it was still reported as a rider",
                row.variant,
                r.feature
            );
        }
    }
}

/// **RULE 1 — every feature in a shipped artifact must be NAMED by its variant.**
///
/// MEASURED RED at `542e296`: `sign` and the `znippy-common` feature it pulls
/// ride into all five server rows from `server/cli/Cargo.toml:71`
/// (`server-lib = { …, default-features = false, features = ["sign"] }`), and no
/// variant declares either. This is the oldest of the four instances of the same
/// shape and the only one nobody had been told about.
///
/// Going green requires a decision, not a code change: either the server rows
/// declare `sign`, or `server/cli` stops enabling it on the edge. Owner question
/// 1 in `.nornir/stinky/09-mvp-line-and-feature-honesty.md` §5.
#[test]
fn every_shipped_feature_is_named_by_its_variant() {
    let riders = honesty::rule1_riders(&workspace());
    assert!(
        riders.is_empty(),
        "{} feature rider(s):\n  {}",
        riders.len(),
        riders
            .iter()
            .map(|r| r.to_string())
            .collect::<Vec<_>>()
            .join("\n  ")
    );
}

/// **RULE 2 — no shipped binary may normal-depend on a bench/test/fixture crate.**
///
/// RULE 1 catches a leak once it exists; RULE 2 forbids the edge that makes the
/// class possible. MEASURED RED at `542e296` on three `nornir-testmatrix` edges:
/// `server/cli/Cargo.toml:106`, `server/lib/Cargo.toml:199`,
/// `agent/cli/Cargo.toml:75`. All three are `optional = true`, which is not
/// protection: `bench` was optional too and was in `default`, and that is how
/// `front`, `auth-passkey` and `auth-oidc` each reached a shipped binary.
#[test]
fn no_shipped_binary_normal_depends_on_a_bench_or_test_crate() {
    let edges = honesty::rule2_bench_edges(&workspace());
    assert!(
        edges.is_empty(),
        "{} bench/test edge(s) in a shipped graph:\n  {}",
        edges.len(),
        edges
            .iter()
            .map(|e| e.to_string())
            .collect::<Vec<_>>()
            .join("\n  ")
    );
}

// ── W17: the provenance gate's compile census ────────────────────────────────

/// ★ **Every row that can promote carries the `provenance` gate.**
///
/// MEASURED on `main` at `bb0302e`: **none of them did.** `catalog_from_config`
/// registered `osv` unconditionally and `attested` only when
/// `promotion.require_attestation` named a predicate type; there was no gate
/// called `provenance` in any build. A config writing `gates: ["provenance"]`
/// was therefore a BOOT FAILURE (HOL-GUN-007) on all five server rows —
/// `embedded`, `mini`, `full`, `mvp-server`, `mvp-server-metered` (and
/// `mvp-server-musl`, the same features on another target) — and the unit test
/// in `promote/gate.rs` used `"provenance"` as its stock example of a name no
/// build carries.
///
/// This is a census in the shape of the other honesty guards: it reads the real
/// declaration and the real source, and it can fail. Three claims, each
/// falsifiable:
///
/// 1. every shipped row that builds `holger` is named, so the set
///    cannot shrink silently;
/// 2. `promote` and `promote::gate` are unconditional modules — nothing in the
///    path from `lib.rs` to `ProvenanceGate` is behind a `#[cfg(feature …)]`,
///    so there is no feature a row could omit to lose the gate; and
/// 3. `catalog_from_config` registers `ProvenanceGate` on the SAME unconditional
///    chain as `OsvGate`, rather than inside an `if let` the way `AttestedGate`
///    is registered.
///
/// If any one of those stops being true, a row promotes with no provenance gate
/// and, per this module's founding complaint, *"a promotion with no gate looks
/// exactly like one that passed every gate."*
#[test]
fn the_gate_is_compiled_into_every_row_that_promotes() {
    // (1) The rows. `holger` is the package every promoting binary is
    // built from — the gRPC `PromoteArtifact` RPC and the `holger-server
    // promote` CLI verb both resolve through `HolgerConfig::promotion_engine`.
    let promoting: Vec<String> = honesty::shipped_rows()
        .into_iter()
        .filter(|r| r.package == "holger")
        .map(|r| r.variant)
        .collect();
    assert!(
        promoting.len() >= 4,
        "only {} row(s) build holger ({promoting:?}); the census has gone blind, \
         which is how a gate stops shipping without anything failing",
        promoting.len()
    );
    for expected in [
        "holger",
        "mvp-server-musl",
        "mvp-server-metered",
        "mvp-server-musl-metered",
    ] {
        assert!(
            promoting.iter().any(|v| v == expected),
            "row '{expected}' no longer builds holger; it promoted at \
             bb0302e and this census must be told, not surprised. Rows found: {promoting:?}"
        );
    }

    // (2) The path from the crate root to the gate carries no feature gate.
    let lib_rs = std::fs::read_to_string(root().join("server/lib/src/lib.rs"))
        .expect("read server/lib/src/lib.rs");
    assert!(
        lib_rs.contains("\npub mod promote;"),
        "`promote` must be an unconditional module of holger-server-lib: a `#[cfg]` above \
         it would take the whole promotion boundary out of some row"
    );
    let mod_rs = std::fs::read_to_string(root().join("server/lib/src/promote/mod.rs"))
        .expect("read server/lib/src/promote/mod.rs");
    assert!(
        mod_rs.contains("\npub mod gate;") || mod_rs.contains("\nmod gate;"),
        "`promote::gate` must be an unconditional module: {}",
        "found no bare `mod gate;` declaration"
    );
    // `meter_gate` IS feature-gated, deliberately — so this assertion has to be
    // about `gate` specifically and not about the file holding no cfg at all.
    let gate_decl = mod_rs
        .lines()
        .position(|l| l.trim_start().starts_with("pub mod gate;"))
        .expect("`pub mod gate;` in promote/mod.rs");
    let preceding: Vec<&str> = mod_rs.lines().take(gate_decl).collect();
    assert!(
        !preceding
            .last()
            .map(|l| l.trim_start().starts_with("#[cfg"))
            .unwrap_or(false),
        "a #[cfg] attribute now guards `pub mod gate;` — the promotion gate seam would \
         vanish from any row that did not enable it"
    );

    // (3) The registration is unconditional, beside OsvGate and NOT inside the
    //     `if let Some(pt)` that guards `AttestedGate`.
    let gate_rs = std::fs::read_to_string(root().join("server/lib/src/promote/gate.rs"))
        .expect("read server/lib/src/promote/gate.rs");
    assert!(
        gate_rs.contains("pub struct ProvenanceGate"),
        "`ProvenanceGate` has left promote/gate.rs; this census no longer measures anything"
    );
    assert!(
        !gate_rs.contains("#[cfg(feature")
            || !gate_rs[..gate_rs.find("pub struct ProvenanceGate").unwrap()]
                .rsplit('\n')
                .take(3)
                .any(|l| l.trim_start().starts_with("#[cfg")),
        "`ProvenanceGate` is now behind a feature; a row that omits it promotes ungated"
    );
    let body_start = gate_rs
        .find("pub fn catalog_from_config")
        .expect("catalog_from_config in promote/gate.rs");
    let body = &gate_rs[body_start..];
    let end = body
        .find("\n}\n")
        .map(|i| body_start + i)
        .unwrap_or(gate_rs.len());
    let body = &gate_rs[body_start..end];
    let reg = body
        .find("ProvenanceGate::new")
        .expect("catalog_from_config must register ProvenanceGate");
    let guard = body.find("if let Some(pt)").unwrap_or(usize::MAX);
    assert!(
        reg < guard,
        "ProvenanceGate is registered INSIDE the conditional that guards AttestedGate. \
         It must be registered unconditionally, like OsvGate: a gate that exists only \
         when it was configured cannot be named by a rung on a build that could have \
         carried it, and HOL-GUN-007 then refuses the boot for the wrong reason."
    );
}