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

nordisk/edda

crates/nornir-build-thing/src/capability_probe.rs

//! **The hollow-binary gate: does a DEPLOYED artifact carry the capability its
//! feature promised?**
//!
//! The feature-rot gate ([`crate::feature_axis`]) catches the DECLARATION side — an
//! offered feature no variant builds. This module catches the OTHER end of the same
//! failure: a binary that built green but was compiled WITHOUT its real feature, so
//! it runs hollow. That is exactly what a `required-features` bin does when
//! `cargo build --all-targets` silently skips it, and what `dwarves-full` did when it
//! embedded nornir's `full-server` with no embedder — a green build, a dead runtime.
//!
//! ## How it proves capability without running anything
//!
//! A compiled-in capability leaves LITERALS in the binary — a model registry string,
//! a SQL engine name, a boot primitive. A compiled-OUT one often leaves the honest
//! "not built in" STUB string instead. So we can read the verdict off the binary's
//! own bytes with a `strings`-style scan — done here as a pure in-process byte search
//! (ROOT LAW: no shelling out to `strings`/`nm`), so it runs in CI on any platform.
//!
//! * a [`Capability`] declares the literals that PROVE it present ([`Capability::proof_any`])
//!   and, optionally, the [`Capability::stub_marker`] that proves it compiled OUT;
//! * [`probe`] reads one capability off a byte slice into a [`Presence`];
//! * [`gate_binary`] fails LOUD ([`HollowBinary`]) when a binary is missing a
//!   capability its deployment requires.
//!
//! ## What this cannot do — stated, not buried
//!
//! It reads bytes, not behaviour. A literal can survive dead-code the linker didn't
//! strip (a false PRESENT), and a capability with no distinctive literal cannot be
//! proven at all (a [`Presence::Unknown`], never silently "present"). It is a cheap,
//! high-value FLOOR — "this artifact provably still contains its embedder" — not an
//! execution test.

use std::collections::BTreeMap;
use std::path::Path;

use serde::{Deserialize, Serialize};

/// One capability a deployed binary must actually carry — the feature that compiles
/// it in, the literals that prove it did, and (when there is one) the stub string
/// that proves it did NOT.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Capability {
    /// Human name of the capability (`"embeddings"`, `"vm-boot"`).
    pub name: &'static str,
    /// The cargo feature that must be enabled to compile it in — the fix a failure
    /// names (`"embed-ort"`, `"vm-boot"`, `"dataview-sql"`).
    pub feature: &'static str,
    /// ANY of these literal substrings present in the binary proves the capability
    /// is compiled in. Pick strings that ONLY the real feature emits (a model id, an
    /// engine type name), never a word that also occurs in unrelated code.
    pub proof_any: &'static [&'static str],
    /// The DISABLED-STUB marker: an honest "feature not built in" string the code
    /// emits only when the capability is compiled OUT. When present AND no
    /// `proof_any` literal is found, the binary is provably [`Presence::Hollow`].
    /// `None` when the feature ships no such stub (then absence of proof is only
    /// [`Presence::Unknown`], never asserted hollow).
    pub stub_marker: Option<&'static str>,
}

/// The verdict for one capability against one binary's bytes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum Presence {
    /// A `proof_any` literal was found — the capability is compiled in.
    Present,
    /// No proof literal, and the `stub_marker` WAS found — provably compiled out.
    Hollow,
    /// Neither proof nor stub found — cannot attest either way. Never reported as
    /// present, so an unmeasurable capability can never pass silently.
    Unknown,
}

impl Presence {
    pub fn label(self) -> &'static str {
        match self {
            Presence::Present => "present",
            Presence::Hollow => "hollow",
            Presence::Unknown => "unknown",
        }
    }
}

/// **The pure byte scan** — is `needle` present as an ASCII substring of `haystack`?
/// A `strings | grep -F` done in-process (no external tool), matching bytes directly
/// so it works on any object format. Empty needle is never a match.
pub fn contains_literal(haystack: &[u8], needle: &str) -> bool {
    let n = needle.as_bytes();
    if n.is_empty() || n.len() > haystack.len() {
        return false;
    }
    haystack.windows(n.len()).any(|w| w == n)
}

/// Probe one capability against a binary's bytes.
pub fn probe(bin: &[u8], cap: &Capability) -> Presence {
    if cap.proof_any.iter().any(|lit| contains_literal(bin, lit)) {
        return Presence::Present;
    }
    match cap.stub_marker {
        Some(stub) if contains_literal(bin, stub) => Presence::Hollow,
        _ => Presence::Unknown,
    }
}

/// Probe one capability against a binary on disk.
pub fn probe_file(path: &Path, cap: &Capability) -> std::io::Result<Presence> {
    let bytes = std::fs::read(path)?;
    Ok(probe(&bytes, cap))
}

/// The full reading of one binary against a list of required capabilities.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProbeReport {
    pub binary: String,
    /// capability name → verdict.
    pub results: BTreeMap<String, Presence>,
    /// capability name → the feature that would compile it in (for the fix line).
    pub features: BTreeMap<String, String>,
}

impl ProbeReport {
    /// The capabilities that are provably compiled OUT — the hollow ones.
    pub fn hollow(&self) -> Vec<&str> {
        self.results
            .iter()
            .filter(|(_, p)| **p == Presence::Hollow)
            .map(|(n, _)| n.as_str())
            .collect()
    }
    /// The capabilities that could not be attested either way.
    pub fn unknown(&self) -> Vec<&str> {
        self.results
            .iter()
            .filter(|(_, p)| **p == Presence::Unknown)
            .map(|(n, _)| n.as_str())
            .collect()
    }
    /// `true` ⇔ no capability is provably hollow. (Unknowns do not fail — they cannot
    /// be measured — but they are reported so a caller may treat them stricter.)
    pub fn is_intact(&self) -> bool {
        self.hollow().is_empty()
    }
}

/// **The gate.** Probe `caps` against the binary at `path` and FAIL with a
/// [`HollowBinary`] naming every capability that is provably compiled out, with the
/// feature to rebuild with. The reusable "deployed bin has its declared capability"
/// assertion the release / CI path runs after an install.
pub fn gate_binary(path: &Path, caps: &[Capability]) -> Result<ProbeReport, HollowBinary> {
    let bytes = match std::fs::read(path) {
        Ok(b) => b,
        Err(e) => {
            return Err(HollowBinary {
                binary: path.display().to_string(),
                hollow: Vec::new(),
                read_error: Some(e.to_string()),
            })
        }
    };
    let mut results = BTreeMap::new();
    let mut features = BTreeMap::new();
    let mut hollow = Vec::new();
    for cap in caps {
        let p = probe(&bytes, cap);
        if p == Presence::Hollow {
            hollow.push((cap.name.to_string(), cap.feature.to_string()));
        }
        results.insert(cap.name.to_string(), p);
        features.insert(cap.name.to_string(), cap.feature.to_string());
    }
    let report = ProbeReport { binary: path.display().to_string(), results, features };
    if hollow.is_empty() {
        Ok(report)
    } else {
        Err(HollowBinary { binary: path.display().to_string(), hollow, read_error: None })
    }
}

/// A deployed binary that built green but is missing a capability it must carry.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HollowBinary {
    pub binary: String,
    /// `(capability, feature to rebuild with)` for each provably-out capability.
    pub hollow: Vec<(String, String)>,
    /// Set when the binary could not even be read (then `hollow` is empty).
    pub read_error: Option<String>,
}

impl std::fmt::Display for HollowBinary {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if let Some(e) = &self.read_error {
            return write!(f, "capability probe could not read `{}`: {e}", self.binary);
        }
        writeln!(f, "HOLLOW BINARY `{}` — green build, dead runtime:", self.binary)?;
        for (cap, feat) in &self.hollow {
            writeln!(
                f,
                "  · `{cap}` is compiled OUT — rebuild with `--features {feat}` (the binary \
                 carries the disabled-stub marker and none of the capability's proof literals)."
            )?;
        }
        Ok(())
    }
}

impl std::error::Error for HollowBinary {}

/// **The known deployable → required-capability registry**, encoding the exact
/// hollow cases this session hit, with literals VERIFIED against the installed
/// binaries (`strings`-probed 2026-07-24). Keyed by binary FILE-name so a probe can
/// look a deployed artifact up by `path.file_name()`.
///
/// This is a documented default, not the whole world: a caller may probe with its own
/// [`Capability`] list. It exists so a release/CI step can assert the constellation's
/// fat nodes are intact with one lookup.
pub const DEPLOYABLES: &[(&str, &[Capability])] = &[
    // dwarves-full embeds nornir; its whole reason to exist is the embedder + the
    // nornir gRPC stack. With nornir pulled `full-server` (no embedder) the embeddings
    // table stays empty — the model-registry ids prove the embedder is really in.
    (
        "dwarves-full",
        &[
            Capability {
                name: "embeddings",
                feature: "embed-nornir nornir/embed-ort",
                proof_any: &[
                    "sentence-transformers/all-MiniLM",
                    "minilm-l6-v2",
                    "onnx/model.onnx",
                ],
                stub_marker: None,
            },
            Capability {
                name: "embedded-nornir-server",
                feature: "embed-nornir",
                proof_any: &["server_grpc"],
                stub_marker: None,
            },
        ],
    ),
    // dwarves-gui: the boot smoke leg and the SQL dataview both ship an honest stub
    // string when their feature is off — so these are provable BOTH ways.
    (
        "dwarves-gui",
        &[
            Capability {
                name: "vm-boot",
                feature: "vm-boot",
                proof_any: &["boot_test", "qemu-system"],
                stub_marker: Some("vm-boot feature is not"),
            },
            Capability {
                name: "dataview-sql",
                feature: "dataview-sql",
                proof_any: &["MemTable", "SessionContext"],
                stub_marker: Some("SQL engine not built in"),
            },
        ],
    ),
    // korp-server / korp: the S3/MinIO ingest leg (aegir is korp's ingest engine) and
    // the Spark 4.1 source.
    (
        "korp-server",
        &[Capability {
            name: "s3-minio-ingest",
            feature: "containers",
            proof_any: &["minio", "aegir"],
            stub_marker: None,
        }],
    ),
    (
        "korp",
        &[Capability {
            name: "spark41",
            feature: "spark41",
            proof_any: &["SparkConnect", "lake.knut_demo"],
            stub_marker: None,
        }],
    ),
];

/// The required capabilities for a deployed binary looked up by its file name, or an
/// empty slice if the binary is not in [`DEPLOYABLES`].
pub fn capabilities_for(bin_file_name: &str) -> &'static [Capability] {
    DEPLOYABLES.iter().find(|(n, _)| *n == bin_file_name).map(|(_, c)| *c).unwrap_or(&[])
}

#[cfg(test)]
mod tests {
    use super::*;

    const EMBED: Capability = Capability {
        name: "embeddings",
        feature: "embed-ort",
        proof_any: &["sentence-transformers/all-MiniLM", "minilm-l6-v2"],
        stub_marker: Some("no embedder compiled in"),
    };

    #[test]
    fn a_present_literal_reads_present() {
        let bin = b"....sentence-transformers/all-MiniLM-L6-v2....other bytes";
        assert_eq!(probe(bin, &EMBED), Presence::Present);
    }

    #[test]
    fn the_stub_marker_with_no_proof_reads_hollow() {
        // the exact green-build-dead-runtime shape: only the disabled stub is present.
        let bin = b"....no embedder compiled in - rebuild with --features embed-ort....";
        assert_eq!(probe(bin, &EMBED), Presence::Hollow);
    }

    #[test]
    fn neither_proof_nor_stub_is_unknown_never_present() {
        let bin = b"an unrelated binary with none of the literals";
        assert_eq!(probe(bin, &EMBED), Presence::Unknown);
    }

    #[test]
    fn contains_literal_is_a_plain_substring_scan() {
        assert!(contains_literal(b"aXboot_testYc", "boot_test"));
        assert!(!contains_literal(b"short", "a much longer needle"));
        assert!(!contains_literal(b"anything", ""));
    }

    /// RED→GREEN on a synthetic file: a hollow binary FAILS the gate naming the
    /// capability + the feature to rebuild with; the same file with the proof literal
    /// PASSES.
    #[test]
    fn gate_binary_fails_on_hollow_and_passes_once_the_capability_is_present() {
        let dir = tempfile::tempdir().unwrap();
        let caps = capabilities_for("dwarves-gui");
        assert!(!caps.is_empty(), "dwarves-gui is a known deployable");

        // A hollow build: both features off — each ships its stub, no proof literal.
        let hollow = dir.path().join("dwarves-gui");
        std::fs::write(
            &hollow,
            b"binary...the `vm-boot feature is not` wired...SQL engine not built in ...",
        )
        .unwrap();
        let err = gate_binary(&hollow, caps).expect_err("hollow build must fail the gate");
        let msg = err.to_string();
        assert!(msg.contains("HOLLOW BINARY"), "{msg}");
        assert!(msg.contains("vm-boot") && msg.contains("--features vm-boot"), "{msg}");
        assert!(msg.contains("dataview-sql") && msg.contains("--features dataview-sql"), "{msg}");

        // The real (intact) build carries the proof literals for both.
        let intact = dir.path().join("dwarves-gui-full");
        std::fs::write(&intact, b"binary...boot_test...qemu-system...MemTable...SessionContext...")
            .unwrap();
        let report = gate_binary(&intact, caps).expect("intact build passes the gate");
        assert!(report.is_intact());
        assert_eq!(report.results["vm-boot"], Presence::Present);
        assert_eq!(report.results["dataview-sql"], Presence::Present);
    }

    #[test]
    fn an_unreadable_path_is_a_failure_not_a_pass() {
        let missing = Path::new("/no/such/binary/anywhere");
        let err = gate_binary(missing, capabilities_for("korp")).expect_err("missing file fails");
        assert!(err.read_error.is_some());
        assert!(err.to_string().contains("could not read"));
    }
}