fn sh_squote(s: &str) -> String {
format!("'{}'", s.replace('\'', r"'\''"))
}
pub const INSTALL_SCRIPT_TEMPLATE: &str = include_str!("control_plane_install.sh");
pub fn build_install_script(version: &str, url: &str, sha256: &str, sudo: bool) -> String {
let sudo_kw = if sudo { "sudo" } else { "" };
format!(
"SUDO={sudo_kw}\nURL={url}\nSHA={sha}\nVER={ver}\n{body}",
sudo_kw = sudo_kw,
url = sh_squote(url),
sha = sh_squote(sha256),
ver = sh_squote(version),
body = INSTALL_SCRIPT_TEMPLATE,
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn script_embeds_the_signed_digest_and_url() {
let url = "https://cdn.yah.dev/yubaba/0.8.19/yubaba-0.8.19-x86_64-unknown-linux-musl.tar.gz";
let sha = "abc123def456";
let s = build_install_script("0.8.19", url, sha, false);
assert!(s.contains(sha), "script must carry the manifest sha256");
assert!(s.contains(url), "script must carry the manifest url");
assert!(s.contains("sha256sum -c -"), "script must verify the digest");
}
#[test]
fn script_is_atomic_and_installs_the_whole_pair() {
let s = build_install_script("0.8.19", "u", "d", false);
assert!(s.contains("mv -f"), "install must be an atomic rename");
assert!(s.contains(".roll-new.$$"), "install must stage to a temp name");
for target in [
"/usr/local/bin/yubaba",
"/usr/local/bin/kamaji",
"/usr/local/bin/yah-scryer",
"/usr/local/bin/passway",
"/usr/local/bin/passway-demux",
"/etc/systemd/system/yubaba.slice",
"/etc/systemd/system/kamaji.service",
"/etc/systemd/system/yubaba.service",
"/etc/systemd/system/yah-scryer.service",
] {
assert!(s.contains(target), "script must install {target}");
}
let k = s.find("restart kamaji.service").unwrap();
let y = s.find("restart yubaba.service").unwrap();
assert!(k < y, "kamaji must restart before yubaba");
assert!(s.contains("daemon-reload"));
}
#[test]
fn scryer_install_is_conditional_on_the_tarball_carrying_it() {
let s = build_install_script("0.8.32", "u", "d", true);
assert!(
s.contains(r#"if [ -e "$D/yah-scryer" ]; then"#),
"scryer install must be gated on the tarball carrying the binary"
);
assert!(
s.contains(r#"assert_installed_bytes "$D/yah-scryer" /usr/local/bin/yah-scryer"#),
"installed scryer bytes must be content-asserted like the pair"
);
assert!(s.contains("enable yah-scryer.service"));
assert!(
s.find("restart yubaba.service").unwrap()
< s.find("restart yah-scryer.service").unwrap(),
"scryer restarts after the supervision pair"
);
}
#[test]
fn passway_installs_conditionally_and_never_restarts_the_front_door() {
let s = build_install_script("0.8.33", "u", "d", true);
assert!(
s.contains(r#"if [ -e "$D/passway" ]; then"#),
"passway install must be gated on the tarball carrying the binary"
);
for bin in ["passway", "passway-demux"] {
assert!(
s.contains(&format!(
r#"assert_installed_bytes "$D/{bin}" /usr/local/bin/{bin}"#
)) || s.contains(&format!(
r#"assert_installed_bytes "$D/{bin}" /usr/local/bin/{bin}"#
)),
"installed {bin} bytes must be content-asserted like the pair"
);
}
let exec = executable_lines(&s);
for unit in [
"passway.service",
"passway-test.service",
"passway-demux.service",
] {
assert!(
!exec.contains(unit),
"a roll must not name {unit} — see R870-T3 for the graceful path"
);
}
}
fn executable_lines(script: &str) -> String {
script
.lines()
.filter(|l| !l.trim_start().starts_with('#'))
.collect::<Vec<_>>()
.join("\n")
}
#[test]
fn script_never_touches_durable_state() {
let s = executable_lines(&build_install_script("0.8.19", "u", "d", true));
assert!(!s.contains("identity.json"), "must not touch host identity");
assert!(!s.contains("/var/lib/yah-cloud"), "must not touch state dir");
assert!(!s.contains("raft"), "must not touch the raft log dir");
assert!(!s.contains("rm -rf /"), "must not wipe system paths");
assert!(
!s.contains("/var/lib/yah/scryer"),
"must not touch the scryer event store"
);
}
#[test]
fn script_anchors_every_file_it_replaces_before_replacing_it() {
let s = build_install_script("0.8.19", "u", "d", true);
let first_anchor = s.find("anchor /usr/local/bin/yubaba").expect("anchors");
let first_install = s.find("install_atomic \"$D/yubaba\"").expect("installs");
assert!(
first_anchor < first_install,
"anchors must be written before anything is replaced"
);
assert!(s.contains(r#"STAMP="$(date -u +%Y%m%d)""#));
for target in [
"/usr/local/bin/yubaba",
"/usr/local/bin/kamaji",
"/usr/local/bin/yah-scryer",
"/usr/local/bin/passway",
"/usr/local/bin/passway-demux",
"/etc/systemd/system/yubaba.slice",
"/etc/systemd/system/kamaji.service",
"/etc/systemd/system/yubaba.service",
"/etc/systemd/system/yah-scryer.service",
] {
assert!(
s.contains(&format!("anchor {target}\n")),
"every installed path needs a rollback anchor, missing {target}"
);
}
}
#[test]
fn anchoring_is_idempotent_within_a_day() {
let s = build_install_script("0.8.19", "u", "d", true);
assert!(
s.contains(r#"if [ ! -e "$1.rollback-$STAMP" ]; then"#),
"anchor must refuse to overwrite an existing same-day anchor"
);
}
#[test]
fn success_is_asserted_by_content_not_by_version_string() {
let s = build_install_script("0.8.19", "u", "d", true);
for pair in [
r#"assert_installed_bytes "$D/yubaba" /usr/local/bin/yubaba"#,
r#"assert_installed_bytes "$D/kamaji" /usr/local/bin/kamaji"#,
] {
assert!(s.contains(pair), "missing content assertion: {pair}");
}
let body = &s[s.find("assert_installed_bytes() {").expect("assert fn")..];
assert!(
body.contains("content assertion FAILED") && body.contains("exit 1"),
"a content mismatch must exit nonzero so the caller sees a failed roll"
);
assert!(
s.find("assert_installed_bytes \"$D/yubaba\"").unwrap()
< s.find("systemctl restart kamaji.service").unwrap(),
"content must be proved before the supervision tree restarts"
);
}
#[test]
fn the_template_is_the_only_copy_of_the_body() {
let s = build_install_script("0.8.19", "u", "d", false);
assert!(
s.ends_with(INSTALL_SCRIPT_TEMPLATE),
"the built script must be prologue + the shared template, verbatim"
);
let prologue = &s[..s.len() - INSTALL_SCRIPT_TEMPLATE.len()];
assert_eq!(
prologue.lines().count(),
4,
"the prologue is exactly URL/SHA/VER/SUDO — anything else belongs in the template"
);
}
#[test]
fn sudo_prefix_tracks_the_caller() {
let s = build_install_script("0.8.19", "u", "d", true);
assert!(s.contains("SUDO=sudo"));
let s = build_install_script("0.8.19", "u", "d", false);
assert!(s.contains("SUDO=\n") || s.contains("SUDO="));
}
}