Watch
0
0
Fork
You've already forked hyperhive
0

download an agent's cached closure in prebuild, building locally when that fails

This commit is contained in:
atlas 2026-10-28 02:02:29 +01:00
commit c16cf1756f

View file

@ -110,6 +110,33 @@ pub fn valid_meta_rev(rev: &str) -> bool {
rev.len() == 40 && rev.bytes().all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'f'))
}
/// Whether `path` is a store path in the shape nix prints one: `/nix/store/`,
/// 32 lowercase letters or digits, `-`, then a name of the characters store
/// names allow. The path crosses the wire in [`PrivRequest::RealiseClosure`],
/// so `hive-priv` checks it before it hands it to nix.
#[must_use]
pub fn valid_closure_path(path: &str) -> bool {
let Some(rest) = path.strip_prefix("/nix/store/") else {
return false;
};
let Some((hash, name)) = rest.split_once('-') else {
return false;
};
hash.len() == 32
&& hash
.bytes()
.all(|b| b.is_ascii_lowercase() || b.is_ascii_digit())
&& !name.is_empty()
&& name.bytes().all(|b| {
b.is_ascii_alphanumeric() || matches!(b, b'+' | b'-' | b'.' | b'_' | b'?' | b'=')
})
}
/// What a failed [`PrivRequest::RealiseClosure`] says when nix refused a path
/// because no trusted key signed it, so a caller can tell that apart from a
/// cache that is down.
pub const SIGNATURE_REFUSED: &str = "no signature by the swarm cache's key";
/// The flake the swarm publishes at `internal/meta`, at `rev`:
/// `git+<forge_base>/internal/meta.git?rev=<rev>`. `forge_base` is the forge's
/// `http` origin, which the hive's git credential helper answers for.
@ -270,6 +297,18 @@ pub enum PrivRequest {
meta_rev: String,
},
/// `nix-store --realise <store_path>` from the swarm's binary cache, never
/// building: the closure the swarm built for `agent`, downloaded into the
/// store ahead of the update that applies it.
///
/// The request names no cache and no key: hive-priv takes the cache's
/// address from its own unit's environment and the key and the pull token
/// from files only root can write, and nix accepts the path only with a
/// signature by that key. `store_path` is checked by
/// [`valid_closure_path`]. A path nix could not substitute answers with an
/// error that starts `not available: `.
RealiseClosure { agent: String, store_path: String },
/// `nixos-container destroy <name>`
DestroyContainer { name: String },
@ -661,7 +700,7 @@ pub enum PrivEvent {
#[cfg(test)]
mod tests {
use super::{InfraContainer, PrivRequest, meta_flake_url, valid_meta_rev};
use super::{InfraContainer, PrivRequest, meta_flake_url, valid_closure_path, valid_meta_rev};
#[test]
fn infra_control_names_no_c0re_or_swarm_service() {
@ -717,6 +756,46 @@ mod tests {
);
}
#[test]
fn only_a_store_path_is_a_closure_path() {
let hash = "0123456789abcdfghijklmnpqrsvwxyz";
for good in [
format!("/nix/store/{hash}-nixos-system-atlas-26.05.20261026.718f670"),
format!("/nix/store/{hash}-a"),
] {
assert!(valid_closure_path(&good), "{good}");
}
for bad in [
String::new(),
"/nix/store/".to_owned(),
format!("/nix/store/{hash}"),
format!("/nix/store/{hash}-"),
format!("/nix/store/{}-x", &hash[1..]),
format!("/nix/store/{hash}a-x"),
format!("/nix/store/{}-x", hash.to_uppercase()),
format!("/tmp/{hash}-x"),
format!("/nix/store/{hash}-x/bin/sh"),
format!("/nix/store/{hash}-../x"),
format!("/nix/store/{hash}-x y"),
format!("/nix/store/{hash}-x\n"),
format!("/nix/store/../../etc/{hash}-x"),
format!("/nix/store/{hash}-x;id"),
] {
assert!(!valid_closure_path(&bad), "{bad:?}");
}
}
#[test]
fn a_closure_request_names_an_agent_and_a_path() {
let line = r#"{"op":"realise_closure","agent":"atlas","store_path":"/nix/store/x"}"#;
assert!(matches!(
serde_json::from_str::<PrivRequest>(line),
Ok(PrivRequest::RealiseClosure { .. })
));
let without = r#"{"op":"realise_closure","agent":"atlas"}"#;
assert!(serde_json::from_str::<PrivRequest>(without).is_err());
}
/// `meta_rev` is required: there is no local flake to fall back to.
#[test]
fn a_request_without_meta_rev_is_refused() {