holger-estate-front/tests/no_gunnar_in_the_graph.rs
//! **GUARD: holger has ZERO dependency on the gunnar repository** (owner
//! 2026-09-27: "why has HOLGER a dependency to gunnar now???"). holger follows
//! gunnar's PATTERN; it never links gunnar's code, never reads a gunnar
//! checkout.
//!
//! Read, not run (pure Rust, no `cargo metadata` subprocess): every lock holger
//! resolves — the root workspace's and this front's own — must name no package
//! `gunnar*`, and no manifest anywhere in the holger tree may point a `path`
//! dependency into a `gunnar` checkout (`../gunnar`, `…/gunnar-ui`, …). A
//! failure names the lock or manifest and the offending entry.
use std::path::{Path, PathBuf};
fn holger_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("..")
}
/// Does `path` step into a checkout of the gunnar repository (a component that
/// IS `gunnar` or starts `gunnar-`)?
fn into_gunnar(path: &str) -> bool {
Path::new(path).components().any(|c| {
c.as_os_str()
.to_str()
.is_some_and(|s| s == "gunnar" || s.starts_with("gunnar-") || s.starts_with("gunnar_"))
})
}
fn manifests(dir: &Path, out: &mut Vec<PathBuf>) {
let Ok(rd) = std::fs::read_dir(dir) else {
return;
};
for e in rd.flatten() {
let p = e.path();
let name = e.file_name().to_string_lossy().to_string();
if p.is_dir() {
if name != "target" && !name.starts_with('.') {
manifests(&p, out);
}
} else if name == "Cargo.toml" {
out.push(p);
}
}
}
/// Every `path = "…"` of every dependency table of a manifest.
fn dep_paths(doc: &toml::Value) -> Vec<String> {
let mut tables: Vec<&toml::Value> = Vec::new();
for key in ["dependencies", "dev-dependencies", "build-dependencies"] {
if let Some(t) = doc.get(key) {
tables.push(t);
}
}
if let Some(t) = doc.get("workspace").and_then(|w| w.get("dependencies")) {
tables.push(t);
}
if let Some(t) = doc.get("patch").and_then(toml::Value::as_table) {
tables.extend(t.values());
}
if let Some(t) = doc.get("target").and_then(toml::Value::as_table) {
for v in t.values() {
for key in ["dependencies", "dev-dependencies", "build-dependencies"] {
if let Some(d) = v.get(key) {
tables.push(d);
}
}
}
}
tables
.iter()
.filter_map(|t| t.as_table())
.flat_map(|t| t.values())
.filter_map(|d| d.get("path").and_then(toml::Value::as_str))
.map(str::to_string)
.collect()
}
#[test]
fn no_lock_holger_resolves_names_a_gunnar_package() {
let root = holger_root();
let mut offending = Vec::new();
for lock in [
root.join("Cargo.lock"),
root.join("holger-estate-front/Cargo.lock"),
] {
let text =
std::fs::read_to_string(&lock).unwrap_or_else(|e| panic!("{}: {e}", lock.display()));
let doc: toml::Table =
toml::from_str(&text).unwrap_or_else(|e| panic!("{}: {e}", lock.display()));
for p in doc
.get("package")
.and_then(toml::Value::as_array)
.into_iter()
.flatten()
{
let name = p
.get("name")
.and_then(toml::Value::as_str)
.unwrap_or_default();
if name.starts_with("gunnar") {
offending.push(format!("{}: package `{name}`", lock.display()));
}
}
}
assert!(
offending.is_empty(),
"holger resolves gunnar's crates: {offending:#?}"
);
}
#[test]
fn no_manifest_in_holger_points_into_a_gunnar_checkout() {
let root = holger_root();
let mut all = Vec::new();
manifests(&root, &mut all);
assert!(all.len() > 20, "the walk found the tree: {}", all.len());
let mut offending = Vec::new();
for m in &all {
let text = std::fs::read_to_string(m).unwrap();
let Ok(doc) = toml::from_str::<toml::Table>(&text).map(toml::Value::Table) else {
continue;
};
for p in dep_paths(&doc) {
if into_gunnar(&p) {
offending.push(format!("{}: path = {p:?}", m.display()));
}
}
}
assert!(
offending.is_empty(),
"a holger manifest points into a gunnar checkout: {offending:#?}"
);
}
#[test]
fn the_guard_sees_what_it_guards() {
assert!(into_gunnar("../../gunnar/crates/gunnar-front"));
assert!(into_gunnar("../gunnar-ui/crates/gunnar-ui-server"));
assert!(!into_gunnar(
"../../Skidbladnir/crates/installer/nordisk-pairing"
));
assert!(!into_gunnar("../../holger-ui/crates/holger-ui-server"));
let doc = toml::Value::Table(toml::from_str("[dependencies]\na = { path = \"../gunnar/x\" }\n[target.'cfg(unix)'.dev-dependencies]\nb = { path = \"../y\" }\n").unwrap());
assert_eq!(
dep_paths(&doc),
vec!["../gunnar/x".to_string(), "../y".to_string()]
);
}
// ── The PAYLOAD: what `holger-mvp-metered` actually links ─────────────────────
//
// Measured 2026-09-28 on the shipped payload (holger-mvp-metered, 63.4 MB,
// sha256 15aac30e…c449c): 9 byte runs spell "gunnar", and NONE of them is
// gunnar's code. Two classes are legitimate and are allowed BY NAME below:
//
// (a) data that enumerates products — `nordisk_pairing::seed::Kind
// { Front, Gunnar, Holger }` (Skidbladnir, seed.rs:66-72): its Debug
// names ("FrontGunnar…") and serde names ("front","gunnar","holger");
// (b) the git package format's frozen wire names in znippy-common
// (index.rs:328-357): `__gunnar_graph__`, `__gunnar_reach__`,
// `__gunnar_secrets__` as rodata, and `__gunnar_oid__` / `__gunnar_refs__`
// as 8-byte immediates of the inlined `is_reserved_module` compare
// (`48 b8 "__gunnar"` then `H3 …`/`H1 …` — hence "__gunnarH3"/"H1").
//
// Category (c) — gunnar's CODE linked in — is what these guards refuse: a
// package in the payload's closure that is gunnar's (by name, or one of
// gunnar's storage crates that carry a neutral name), and any "gunnar" byte run
// in a built payload that is not one of the classified ones above.
/// The root of the shipped payload (`--bin holger-mvp-metered`).
const PAYLOAD_ROOT: &str = "holger";
/// gunnar's own code published under names that do not start with `gunnar`.
/// Linking either is linking gunnar's git server storage.
const GUNNAR_CODE_UNDER_NEUTRAL_NAMES: &[&str] = &["storage-git-gix", "znippy-plugin-git"];
fn is_gunnar_code(package: &str) -> bool {
package.starts_with("gunnar") || GUNNAR_CODE_UNDER_NEUTRAL_NAMES.contains(&package)
}
/// Transitive closure of `root` over a Cargo.lock's `dependencies` edges (by
/// name — two versions of one name fold together, which can only widen it).
fn lock_closure(lock: &toml::Table, root: &str) -> std::collections::BTreeSet<String> {
let mut edges: std::collections::BTreeMap<String, Vec<String>> = Default::default();
for p in lock
.get("package")
.and_then(toml::Value::as_array)
.into_iter()
.flatten()
{
let name = p
.get("name")
.and_then(toml::Value::as_str)
.unwrap_or_default()
.to_string();
let deps = p
.get("dependencies")
.and_then(toml::Value::as_array)
.into_iter()
.flatten();
let deps = deps
.filter_map(toml::Value::as_str)
.filter_map(|d| d.split_whitespace().next())
.map(str::to_string);
edges.entry(name).or_default().extend(deps);
}
let mut seen = std::collections::BTreeSet::new();
let mut todo = vec![root.to_string()];
while let Some(n) = todo.pop() {
if seen.insert(n.clone()) {
todo.extend(edges.get(&n).into_iter().flatten().cloned());
}
}
seen
}
#[test]
fn the_payload_closure_links_no_gunnar_code() {
let lock_path = holger_root().join("Cargo.lock");
let lock: toml::Table = toml::from_str(&std::fs::read_to_string(&lock_path).unwrap()).unwrap();
let closure = lock_closure(&lock, PAYLOAD_ROOT);
// The walk reached the real graph (measured: 666 crates for the metered
// feature set via `cargo tree`; the lock closure is a superset of that).
assert!(
closure.len() > 300,
"the closure of {PAYLOAD_ROOT} is only {} crates — wrong root?",
closure.len()
);
for must in ["znippy-common", "nordisk-pairing"] {
assert!(
closure.contains(must),
"{must} is expected in the payload closure"
);
}
let offending: Vec<_> = closure.iter().filter(|p| is_gunnar_code(p)).collect();
assert!(
offending.is_empty(),
"{PAYLOAD_ROOT} links gunnar's code: {offending:?}"
);
}
/// Every "gunnar" (any case) in `bytes`, with the reason it is allowed, or
/// `Err(context)` for one that is not classified.
fn classify_gunnar_runs(bytes: &[u8]) -> Vec<Result<&'static str, String>> {
const WIRE: &[&[u8]] = &[b"_oid__", b"_graph__", b"_reach__", b"_refs__", b"_secrets"];
let mut out = Vec::new();
let mut i = 0;
while i + 6 <= bytes.len() {
if !bytes[i..i + 6].eq_ignore_ascii_case(b"gunnar") {
i += 1;
continue;
}
let before = &bytes[i.saturating_sub(5)..i];
let after = &bytes[i + 6..(i + 6 + 8).min(bytes.len())];
let verdict = if before.ends_with(b"__")
&& (WIRE.iter().any(|w| after.starts_with(w))
|| after.first().is_some_and(|b| *b != b'_'))
{
// `__gunnar_<section>__`, or the 8-byte immediate `__gunnar` of the
// inlined compare (the next byte is an opcode, never `_`).
Ok("(b) znippy-common git-format wire name")
} else if before.eq_ignore_ascii_case(b"front")
|| after.len() >= 6 && after[..6].eq_ignore_ascii_case(b"holger")
{
Ok("(a) nordisk_pairing::seed::Kind variant name")
} else {
let lo = i.saturating_sub(40);
let hi = (i + 46).min(bytes.len());
Err(String::from_utf8_lossy(&bytes[lo..hi])
.replace(|c: char| !c.is_ascii_graphic(), "."))
};
out.push(verdict);
i += 6;
}
out
}
#[test]
fn the_classifier_knows_every_measured_shape_and_refuses_a_new_one() {
let measured: &[&[u8]] = &[
b"BodyWriteAborted__gunnar_secretslastModifiedTime",
b"\0__gunnar_reach____\0",
b"_nest_tail_param__gunnar_graph__\0",
b"installer.FrontGunnarParseIntError",
b"TunnelKindwireguardtailscalemullvadfrontgunnarholgerFront",
b"\x48\xb8__gunnarH3\x07\x48\xb9ar_oid__",
b"\x48\xba__gunnarH1\xd1\x48\x8b",
];
for m in measured {
let v = classify_gunnar_runs(m);
assert_eq!(v.len(), 1, "{:?}", String::from_utf8_lossy(m));
assert!(v[0].is_ok(), "{v:?}");
}
for bad in [
&b"gunnar_server::serve"[..],
b"crates/gunnar-pack/src/lib.rs",
b"GunnarForge",
] {
assert!(
classify_gunnar_runs(bad).iter().any(Result::is_err),
"{:?} must be refused",
String::from_utf8_lossy(bad)
);
}
}
/// Scan a BUILT payload. The binary is not built by this test (a 5-minute
/// musl build is the Build Thing's job); point `HOLGER_PAYLOAD_BIN` at it, or
/// leave it where the Build Thing puts it. With neither present the test says
/// so on stderr and verifies nothing.
#[test]
fn a_built_payload_carries_no_unclassified_gunnar_bytes() {
let default = holger_root().join("target/x86_64-unknown-linux-musl/release/holger-mvp-metered");
let bin = std::env::var_os("HOLGER_PAYLOAD_BIN")
.map(PathBuf::from)
.unwrap_or(default);
let Ok(bytes) = std::fs::read(&bin) else {
eprintln!(
"NOT VERIFIED: no payload at {} (set HOLGER_PAYLOAD_BIN)",
bin.display()
);
return;
};
let verdicts = classify_gunnar_runs(&bytes);
let unclassified: Vec<_> = verdicts.iter().filter_map(|v| v.as_ref().err()).collect();
eprintln!(
"{}: {} gunnar run(s), {} unclassified",
bin.display(),
verdicts.len(),
unclassified.len()
);
assert!(
unclassified.is_empty(),
"{}: gunnar bytes that are neither (a) nor (b): {unclassified:#?}",
bin.display()
);
}