nordisk-pairing 0.5.2

The boxes of an estate find each other: a seed each box is installed with, a one-time join against the front, a tunnel (WireGuard by default) they meet inside, roles decided once, a pairing loop each box runs itself, and the signal it reports. Shared by gunnar and holger; the laptop's xtask only lays machines, writes seeds and reads the signal. Design: .nornir/pairing-design.md (2026-09-24).
Documentation
//! **What a collected log line may never carry** (0.3.0). The installer
//! stores every VM's boot log on the operator's machine; a line that carries
//! a secret is withheld there — replaced by its class and its size, never a
//! byte of the content. The rule moved here from private-gunnar-ops'
//! `xtask/src/bootnarr.rs` (the UDP boot narration's filter, retired with the
//! narration on 2026-09-24), so gunnar and holger share one filter.
//!
//! The classes, and why each one is here:
//!
//! * `cmdline` — the kernel command line carries `korp.args` with the
//!   monetize public key and `clock_key=` on it, so ONE echoed cmdline
//!   discloses the medium's whole configuration.
//! * `token` — any admin or API token, any `Bearer`, a password, a secret.
//! * `key` — any signing or private key material, and any SSH key line.
//! * `pubkey` — a PUBLIC verifying key. It discloses nothing; it is withheld
//!   anyway, on the owner's rule, because it is not progress.
//! * `env` — the shape of a secrets file being read out.
//! * `highentropy` — a long unbroken base64/hex run: what a key looks like
//!   when nobody labelled it.

/// The class a line must be withheld under, or `None` when it may be kept.
pub fn secret_class(line: &str) -> Option<&'static str> {
    let lower = line.to_ascii_lowercase();
    if lower.contains("kernel command line") || lower.contains("/proc/cmdline") || lower.contains("korp.args") || lower.contains("korp.log_udp=") || lower.contains("clock_key=") {
        return Some("cmdline");
    }
    if lower.contains("token") || lower.contains("bearer ") || lower.contains("password") || lower.contains("secret") {
        return Some("token");
    }
    if lower.contains("private key") || lower.contains("begin openssh") || lower.contains("ssh-ed25519") || lower.contains("ssh-rsa") || lower.contains("signing.key") || lower.contains("time_ed25519") {
        return Some("key");
    }
    if lower.contains("pubkey") || lower.contains("public key") || lower.contains("sha256:") {
        return Some("pubkey");
    }
    if lower.contains(".env") {
        return Some("env");
    }
    if longest_opaque_run(line) >= 40 {
        return Some("highentropy");
    }
    None
}

/// The longest unbroken run of base64/hex alphabet.
fn longest_opaque_run(line: &str) -> usize {
    let mut best = 0usize;
    let mut run = 0usize;
    for c in line.chars() {
        if c.is_ascii_alphanumeric() || c == '+' || c == '/' || c == '=' {
            run += 1;
            best = best.max(run);
        } else {
            run = 0;
        }
    }
    best
}

/// The text that stands in for a withheld line.
pub fn withheld(class: &str, bytes: usize) -> String {
    format!("<<WITHHELD: a {class}-class line of {bytes} bytes was not recorded>>")
}

/// **The line as it may be stored**: itself, or the withheld marker.
pub fn clean(line: &str) -> std::borrow::Cow<'_, str> {
    match secret_class(line) {
        None => std::borrow::Cow::Borrowed(line),
        Some(class) => std::borrow::Cow::Owned(withheld(class, line.len())),
    }
}

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

    #[test]
    fn progress_is_kept_and_every_secret_class_is_withheld_without_its_content() {
        assert_eq!(clean("korp-start: stage net up at 6.34 s"), "korp-start: stage net up at 6.34 s");
        for (line, class) in [
            ("[    0.000000] Kernel command line: korp.args=monetize_pubkey=abc", "cmdline"),
            ("GUNNAR_UI_ADMIN_TOKEN=xyz", "token"),
            ("-----BEGIN OPENSSH PRIVATE KEY-----", "key"),
            ("fed monetize pubkey eb16", "pubkey"),
            ("reading /etc/monetize/monetize.env", "env"),
            ("AAAAC3NzaC1lZDI1NTE5AAAAIGx8r8b4v8v5r7q2Zk1pQ3a", "highentropy"),
        ] {
            assert_eq!(secret_class(line), Some(class), "{line}");
            let c = clean(line);
            assert!(c.starts_with("<<WITHHELD: a ") && c.contains(class) && !c.contains(line), "{c}");
        }
    }
}