Watch
0
0
Fork
You've already forked hyperhive
0

build agents only from internal/meta; delete the hive's local meta flake

The hive no longer renders, locks or commits a meta flake. A rebuild's
MetaSync node picks the internal/meta commit and records it with the
hyperhive and config pins it holds; Prebuild, Swap and Create build from it,
and a head that does not pin the agent's current config fails the build
naming the agent. hive-priv's meta_rev is required.

Removed: meta.rs sync/lock/render, the manual-rebuild relock, the boot
sweep's hyperhive bump (MetaLock), the update-meta-inputs form and its
panel, MetaWindow, the hive's hyperhive_rev setting.

Kept: agent_set::refresh holds what sync_agents also did (topology.json, the
gateway's agent-socket map and nginx include), called from spawn, destroy,
rebuild and the migration.

The boot reconcile and the stale-start upgrade compare the agent's marker
with the hyperhive pin of internal/meta; the dashboard's deployed chip reads
the config marker a successful build writes.
This commit is contained in:
atlas 2026-10-25 13:33:15 +01:00
commit 4aa11b3a94
64 changed files with 1042 additions and 3793 deletions

View file

@ -101,13 +101,6 @@ impl std::str::FromStr for InfraContainer {
}
}
/// Host path of the meta flake a hive renders itself. The flake ref for agent
/// `<name>` is `{META_DIR}#{name}`, derived by `hive-priv` — never passed over
/// the wire. Must stay in sync with `hive-c0re::paths::meta_root()`
/// (`STATE_ROOT + "/meta"`); the privsep boundary prevents importing across
/// the crate.
pub const META_DIR: &str = "/var/lib/hyperhive/meta";
/// Whether `rev` is a git commit id: 40 lowercase hex digits. The only part of
/// the `internal/meta` flake ref that crosses the wire (`meta_rev` on
/// `PrivRequest::UpdateContainer` and `CreateContainer`), so `hive-priv` checks
@ -251,20 +244,18 @@ pub enum PrivRequest {
KillContainer { name: String },
/// `nixos-container update <name> --flake <flake_ref>`
/// The flake ref is derived from `name` by hive-priv: the hive's own meta
/// flake, or `internal/meta` at `meta_rev` when that is set (the forge URL
/// is hive-priv's own and never on the wire).
/// The flake ref is derived from `name` and `meta_rev` by hive-priv: the
/// swarm's `internal/meta` at that commit (the forge URL is hive-priv's
/// own and never on the wire).
/// When `stream` is `true`, hive-priv sends `PrivEvent::Line` messages
/// as the process runs, then a terminal `PrivEvent::Done`.
UpdateContainer {
name: String,
#[serde(default)]
stream: bool,
/// A commit of `internal/meta` to build from, checked by
/// `valid_meta_rev`. `serde(default)` so a request from a hive-c0re
/// that predates the field builds from the hive's own flake.
#[serde(default)]
meta_rev: Option<String>,
/// The commit of `internal/meta` to build from, checked by
/// `valid_meta_rev`.
meta_rev: String,
},
/// `nixos-container create <name> --flake <flake_ref>`
@ -276,8 +267,7 @@ pub enum PrivRequest {
name: String,
#[serde(default)]
stream: bool,
#[serde(default)]
meta_rev: Option<String>,
meta_rev: String,
},
/// `nixos-container destroy <name>`
@ -746,29 +736,20 @@ mod tests {
);
}
/// A hive-c0re that predates `meta_rev` sends neither field.
/// `meta_rev` is required: there is no local flake to fall back to.
#[test]
fn a_request_without_meta_rev_builds_from_the_hives_own_flake() {
fn a_request_without_meta_rev_is_refused() {
for op in ["update_container", "create_container"] {
let req: PrivRequest =
serde_json::from_str(&format!(r#"{{"op":"{op}","name":"atlas"}}"#)).unwrap();
match req {
PrivRequest::UpdateContainer { meta_rev, .. }
| PrivRequest::CreateContainer { meta_rev, .. } => assert_eq!(meta_rev, None),
other => panic!("{other:?}"),
}
let without = format!(r#"{{"op":"{op}","name":"atlas"}}"#);
assert!(
serde_json::from_str::<PrivRequest>(&without).is_err(),
"{op}"
);
let with = format!(
r#"{{"op":"{op}","name":"atlas","meta_rev":"{}"}}"#,
"b".repeat(40)
);
assert!(serde_json::from_str::<PrivRequest>(&with).is_ok(), "{op}");
}
let with: PrivRequest = serde_json::from_str(&format!(
r#"{{"op":"update_container","name":"atlas","meta_rev":"{}"}}"#,
"b".repeat(40)
))
.unwrap();
assert!(matches!(
with,
PrivRequest::UpdateContainer {
meta_rev: Some(_),
..
}
));
}
}