refactor(#2285): inline remaining 1:1 path wrappers (meta_dir, marker fns, host_conf_path)

This commit is contained in:
damocles 2026-07-10 20:30:01 +02:00 committed by mara
commit 556a213320
11 changed files with 39 additions and 72 deletions

View file

@ -28,7 +28,7 @@ const CAPABILITIES_FILE: &str = "capabilities.json";
#[must_use] #[must_use]
pub fn capabilities_path() -> PathBuf { pub fn capabilities_path() -> PathBuf {
crate::meta::meta_dir().join(CAPABILITIES_FILE) crate::paths::meta_root().join(CAPABILITIES_FILE)
} }
/// Read the per-agent capability map. Returns an empty map when the /// Read the per-agent capability map. Returns an empty map when the

View file

@ -30,7 +30,7 @@ const TOOL_GROUPS_FILE: &str = "tool-groups.json";
#[must_use] #[must_use]
pub fn tool_groups_path() -> PathBuf { pub fn tool_groups_path() -> PathBuf {
crate::meta::meta_dir().join(TOOL_GROUPS_FILE) crate::paths::meta_root().join(TOOL_GROUPS_FILE)
} }
/// Read the per-agent tool-group map. Returns an empty map when the /// Read the per-agent tool-group map. Returns an empty map when the

View file

@ -34,7 +34,7 @@ const TOPOLOGY_FILE: &str = "topology.json";
#[must_use] #[must_use]
pub fn topology_path() -> PathBuf { pub fn topology_path() -> PathBuf {
crate::meta::meta_dir().join(TOPOLOGY_FILE) crate::paths::meta_root().join(TOPOLOGY_FILE)
} }
/// Snapshot of the topology map. Read on every `container_view::build_all` /// Snapshot of the topology map. Read on every `container_view::build_all`
@ -451,7 +451,7 @@ const ROLES_FILE: &str = "roles.json";
#[must_use] #[must_use]
pub fn roles_path() -> std::path::PathBuf { pub fn roles_path() -> std::path::PathBuf {
crate::meta::meta_dir().join(ROLES_FILE) crate::paths::meta_root().join(ROLES_FILE)
} }
/// Read the roles map from disk. Returns an empty map when absent or /// Read the roles map from disk. Returns an empty map when absent or

View file

@ -7,7 +7,6 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use std::fmt::Write as _; use std::fmt::Write as _;
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
@ -31,17 +30,6 @@ static LAST_FAILED_RELOAD: AtomicU64 = AtomicU64::new(0);
/// Minimum gap between retry attempts after a reload failure (30 s). /// Minimum gap between retry attempts after a reload failure (30 s).
const RELOAD_RETRY_SECS: u64 = 30; const RELOAD_RETRY_SECS: u64 = 30;
/// Host-side path where c0re writes the generated nginx include file.
/// The gateway container bind-mounts `/var/lib/hyperhive/gateway/`
/// (not the whole parent dir) at `/run/hive-state/` so nginx inside
/// can read it at `/run/hive-state/agents.conf`. Subdirectory scoping
/// avoids exposing the rest of `/var/lib/hyperhive/` (which may contain
/// forge tokens or other credentials) to the gateway container.
#[must_use]
pub fn host_conf_path() -> PathBuf {
crate::paths::gateway_agents_conf()
}
/// Nginx proxy headers present in every per-agent location block. /// Nginx proxy headers present in every per-agent location block.
/// `$connection_upgrade` is defined in the http context by the NixOS /// `$connection_upgrade` is defined in the http context by the NixOS
/// nginx module when `recommendedProxySettings = true` (which the /// nginx module when `recommendedProxySettings = true` (which the
@ -162,7 +150,7 @@ fn render(names: &[String], frontend_dir: Option<&str>) -> String {
} }
/// Atomically write the nginx include file for `names` to /// Atomically write the nginx include file for `names` to
/// [`host_conf_path()`]. Skips the write + reload when the rendered /// [`crate::paths::gateway_agents_conf()`]. Skips the write + reload when the rendered
/// body matches what's already on disk (idempotent; avoids spurious /// body matches what's already on disk (idempotent; avoids spurious
/// gateway reloads on a quiet tick). /// gateway reloads on a quiet tick).
/// ///
@ -184,7 +172,7 @@ pub async fn write(names: &[String]) -> Result<()> {
.ok() .ok()
.filter(|s| !s.is_empty()); .filter(|s| !s.is_empty());
let body = render(names, frontend_dir.as_deref()); let body = render(names, frontend_dir.as_deref());
let path = host_conf_path(); let path = crate::paths::gateway_agents_conf();
if std::fs::read_to_string(&path).ok().as_deref() == Some(&body) { if std::fs::read_to_string(&path).ok().as_deref() == Some(&body) {
return Ok(()); return Ok(());
} }

View file

@ -120,7 +120,7 @@ async fn run_prebuild(
} }
} }
ctx.step("nix build"); ctx.step("nix build");
let flake_ref = format!("{}#{name}", crate::meta::meta_dir().display()); let flake_ref = format!("{}#{name}", crate::paths::meta_root().display());
crate::lifecycle::prebuild_toplevel(name, &flake_ref, &|log_id| ctx.build_log(log_id)).await?; crate::lifecycle::prebuild_toplevel(name, &flake_ref, &|log_id| ctx.build_log(log_id)).await?;
Ok(NodeOutput::default()) Ok(NodeOutput::default())
} }
@ -145,7 +145,7 @@ async fn run_swap(coord: &Arc<Coordinator>, claim: &Claim, ctx: &Ctx<'_>) -> Res
match &result { match &result {
Ok(()) => { Ok(()) => {
if let Some(rev) = crate::auto_update::current_flake_rev(&coord.hyperhive_flake) if let Some(rev) = crate::auto_update::current_flake_rev(&coord.hyperhive_flake)
&& let Err(e) = std::fs::write(crate::auto_update::rev_marker_path(name), rev) && let Err(e) = std::fs::write(crate::paths::applied_rev_marker(name), rev)
{ {
tracing::warn!(%name, error = ?e, "write rev marker failed"); tracing::warn!(%name, error = ?e, "write rev marker failed");
} }

View file

@ -49,7 +49,7 @@ pub fn restart(coord: &Arc<Coordinator>, agent: &str, source: Source, reason: St
/// — the old fast-lane `run_start` upgrade, moved to submit time. /// — the old fast-lane `run_start` upgrade, moved to submit time.
pub fn start(coord: &Arc<Coordinator>, agent: &str, source: Source, reason: String) -> u64 { pub fn start(coord: &Arc<Coordinator>, agent: &str, source: Source, reason: String) -> u64 {
set_wanted(coord, agent, Wanted::Up); set_wanted(coord, agent, Wanted::Up);
let stored = std::fs::read_to_string(crate::auto_update::rev_marker_path(agent)).ok(); let stored = std::fs::read_to_string(crate::paths::applied_rev_marker(agent)).ok();
let stale = crate::auto_update::current_flake_rev(&coord.hyperhive_flake) let stale = crate::auto_update::current_flake_rev(&coord.hyperhive_flake)
.is_some_and(|rev| stored.as_deref() != Some(rev.as_str())); .is_some_and(|rev| stored.as_deref() != Some(rev.as_str()));
if stale { if stale {

View file

@ -635,7 +635,7 @@ pub async fn rebuild_no_meta(
on_build_log_id: &(dyn Fn(i64) + Send + Sync), on_build_log_id: &(dyn Fn(i64) + Send + Sync),
) -> Result<bool> { ) -> Result<bool> {
prepare_rebuild_dirs(name, paths).await?; prepare_rebuild_dirs(name, paths).await?;
let flake_ref = format!("{}#{name}", crate::meta::meta_dir().display()); let flake_ref = format!("{}#{name}", crate::paths::meta_root().display());
if container_exists(name).await { if container_exists(name).await {
// Rebuild strategy: stop-before-update + pre-build. // Rebuild strategy: stop-before-update + pre-build.
// See `docs/coordinator.md::Container lifecycle`. // See `docs/coordinator.md::Container lifecycle`.

View file

@ -4,7 +4,7 @@
//! `finalize_deploy` / `abort_deploy`, `lock_update_hyperhive`): //! `finalize_deploy` / `abort_deploy`, `lock_update_hyperhive`):
//! `docs/approvals.md::Meta flake`. //! `docs/approvals.md::Meta flake`.
use std::path::{Path, PathBuf}; use std::path::Path;
use anyhow::{Context, Result, bail}; use anyhow::{Context, Result, bail};
use tokio::process::Command; use tokio::process::Command;
@ -56,11 +56,6 @@ pub struct AgentSpec {
pub port: u16, pub port: u16,
} }
#[must_use]
pub fn meta_dir() -> PathBuf {
crate::paths::meta_root()
}
/// Idempotently reconcile the meta repo with the current agent set. /// Idempotently reconcile the meta repo with the current agent set.
/// First call inits the git repo, runs `nix flake lock`, and lands a /// First call inits the git repo, runs `nix flake lock`, and lands a
/// seed commit. Subsequent calls only touch `flake.nix` when the /// seed commit. Subsequent calls only touch `flake.nix` when the
@ -68,7 +63,7 @@ pub fn meta_dir() -> PathBuf {
/// no-op. /// no-op.
pub async fn sync_agents(hive: &HiveEnv, agents: &[AgentSpec]) -> Result<()> { pub async fn sync_agents(hive: &HiveEnv, agents: &[AgentSpec]) -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
let dir = meta_dir(); let dir = crate::paths::meta_root();
std::fs::create_dir_all(&dir).with_context(|| format!("create {}", dir.display()))?; std::fs::create_dir_all(&dir).with_context(|| format!("create {}", dir.display()))?;
let new_flake = render_flake( let new_flake = render_flake(
@ -241,7 +236,7 @@ pub async fn sync_agents(hive: &HiveEnv, agents: &[AgentSpec]) -> Result<()> {
/// meta history only carries successful deploys. /// meta history only carries successful deploys.
pub async fn prepare_deploy(name: &str) -> Result<()> { pub async fn prepare_deploy(name: &str) -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
let dir = meta_dir(); let dir = crate::paths::meta_root();
let input = format!("agent-{name}"); let input = format!("agent-{name}");
nix(&dir, &["flake", "update", &input]).await?; nix(&dir, &["flake", "update", &input]).await?;
// Stage the new lock — git+file://'s dirty-tree fetcher reads // Stage the new lock — git+file://'s dirty-tree fetcher reads
@ -255,7 +250,7 @@ pub async fn prepare_deploy(name: &str) -> Result<()> {
/// place (nothing staged → nothing to commit). /// place (nothing staged → nothing to commit).
pub async fn finalize_deploy(name: &str, sha: &str, tag: &str) -> Result<()> { pub async fn finalize_deploy(name: &str, sha: &str, tag: &str) -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
let dir = meta_dir(); let dir = crate::paths::meta_root();
if !paths_dirty(&dir, &["flake.lock"]).await? { if !paths_dirty(&dir, &["flake.lock"]).await? {
return Ok(()); return Ok(());
} }
@ -273,7 +268,7 @@ pub async fn finalize_deploy(name: &str, sha: &str, tag: &str) -> Result<()> {
/// captured in `applied/<n>`'s annotated `failed/<id>` tag. /// captured in `applied/<n>`'s annotated `failed/<id>` tag.
pub async fn abort_deploy() -> Result<()> { pub async fn abort_deploy() -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
let dir = meta_dir(); let dir = crate::paths::meta_root();
git(&dir, &["restore", "--staged", "flake.lock"]).await?; git(&dir, &["restore", "--staged", "flake.lock"]).await?;
git(&dir, &["restore", "flake.lock"]).await git(&dir, &["restore", "flake.lock"]).await
} }
@ -284,7 +279,7 @@ pub async fn abort_deploy() -> Result<()> {
/// semantics — it always wants the latest main. /// semantics — it always wants the latest main.
pub async fn lock_update_for_rebuild(name: &str) -> Result<()> { pub async fn lock_update_for_rebuild(name: &str) -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
let dir = meta_dir(); let dir = crate::paths::meta_root();
let input = format!("agent-{name}"); let input = format!("agent-{name}");
nix(&dir, &["flake", "update", &input]).await?; nix(&dir, &["flake", "update", &input]).await?;
if !paths_dirty(&dir, &["flake.lock"]).await? { if !paths_dirty(&dir, &["flake.lock"]).await? {
@ -325,7 +320,7 @@ fn agent_input_override(applied_dir: &Path, sha: &str) -> String {
/// actual apply, so this is the right "would this apply" gate. /// actual apply, so this is the right "would this apply" gate.
pub async fn verify_commit(name: &str, applied_dir: &Path, sha: &str) -> Result<()> { pub async fn verify_commit(name: &str, applied_dir: &Path, sha: &str) -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
let dir = meta_dir(); let dir = crate::paths::meta_root();
let input = format!("agent-{name}"); let input = format!("agent-{name}");
let over = agent_input_override(applied_dir, sha); let over = agent_input_override(applied_dir, sha);
let attr = format!(".#nixosConfigurations.{name}.config.system.build.toplevel.drvPath"); let attr = format!(".#nixosConfigurations.{name}.config.system.build.toplevel.drvPath");
@ -355,7 +350,7 @@ pub async fn verify_commit(name: &str, applied_dir: &Path, sha: &str) -> Result<
/// file) when targeting specific inputs. /// file) when targeting specific inputs.
pub async fn lock_update(inputs: &[String]) -> Result<()> { pub async fn lock_update(inputs: &[String]) -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
let dir = meta_dir(); let dir = crate::paths::meta_root();
let mut args: Vec<&str> = vec!["flake", "update"]; let mut args: Vec<&str> = vec!["flake", "update"];
for i in inputs { for i in inputs {
args.push(i.as_str()); args.push(i.as_str());
@ -380,7 +375,7 @@ pub async fn lock_update(inputs: &[String]) -> Result<()> {
/// because the per-agent inputs aren't touched. /// because the per-agent inputs aren't touched.
pub async fn lock_update_hyperhive() -> Result<()> { pub async fn lock_update_hyperhive() -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
let dir = meta_dir(); let dir = crate::paths::meta_root();
nix(&dir, &["flake", "update", "hyperhive"]).await?; nix(&dir, &["flake", "update", "hyperhive"]).await?;
if !paths_dirty(&dir, &["flake.lock"]).await? { if !paths_dirty(&dir, &["flake.lock"]).await? {
return Ok(()); return Ok(());
@ -396,7 +391,7 @@ pub async fn lock_update_hyperhive() -> Result<()> {
pub async fn commit_tool_groups(agent: &str, groups: &[String]) -> Result<()> { pub async fn commit_tool_groups(agent: &str, groups: &[String]) -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
crate::tool_groups::set_groups(agent, groups)?; crate::tool_groups::set_groups(agent, groups)?;
let dir = meta_dir(); let dir = crate::paths::meta_root();
if crate::tool_groups::tool_groups_path().exists() { if crate::tool_groups::tool_groups_path().exists() {
git(&dir, &["add", "tool-groups.json"]).await?; git(&dir, &["add", "tool-groups.json"]).await?;
} }
@ -417,7 +412,7 @@ pub async fn commit_capabilities(agent: &str, caps: &[String]) -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
crate::capabilities::set_caps(agent, caps) crate::capabilities::set_caps(agent, caps)
.map_err(|e| anyhow::anyhow!("set capabilities for {agent}: {e}"))?; .map_err(|e| anyhow::anyhow!("set capabilities for {agent}: {e}"))?;
let dir = meta_dir(); let dir = crate::paths::meta_root();
if crate::capabilities::capabilities_path().exists() { if crate::capabilities::capabilities_path().exists() {
git(&dir, &["add", "capabilities.json"]).await?; git(&dir, &["add", "capabilities.json"]).await?;
} }
@ -450,7 +445,7 @@ pub async fn commit_perms(
caps: Option<&[String]>, caps: Option<&[String]>,
) -> Result<()> { ) -> Result<()> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
let dir = meta_dir(); let dir = crate::paths::meta_root();
let mut parts: Vec<&str> = Vec::new(); let mut parts: Vec<&str> = Vec::new();
if let Some(groups) = groups { if let Some(groups) = groups {
crate::tool_groups::set_groups(agent, groups)?; crate::tool_groups::set_groups(agent, groups)?;
@ -492,7 +487,7 @@ pub async fn commit_topology(
) -> std::result::Result<(), String> { ) -> std::result::Result<(), String> {
let _guard = META_LOCK.lock().await; let _guard = META_LOCK.lock().await;
crate::topology::set_parent(child, new_parent)?; crate::topology::set_parent(child, new_parent)?;
let dir = meta_dir(); let dir = crate::paths::meta_root();
let stage = async { let stage = async {
git(&dir, &["add", "topology.json"]).await?; git(&dir, &["add", "topology.json"]).await?;
if paths_dirty(&dir, &["topology.json"]).await? { if paths_dirty(&dir, &["topology.json"]).await? {
@ -554,7 +549,7 @@ pub async fn bulk_commit_topology(
crate::topology::write(&next).map_err(|e| format!("{e:#}"))?; crate::topology::write(&next).map_err(|e| format!("{e:#}"))?;
} }
// Commit the whole batch as one git operation. // Commit the whole batch as one git operation.
let dir = meta_dir(); let dir = crate::paths::meta_root();
let commit_msg = if moves.len() == 1 { let commit_msg = if moves.len() == 1 {
let (child, new_parent) = moves[0]; let (child, new_parent) = moves[0];
format!("topology: {}{}", child, new_parent.unwrap_or("<root>")) format!("topology: {}{}", child, new_parent.unwrap_or("<root>"))

View file

@ -4,7 +4,7 @@
//! Kill-switch: `HIVE_SKIP_META_MIGRATION=1`. Full migration sequence //! Kill-switch: `HIVE_SKIP_META_MIGRATION=1`. Full migration sequence
//! and phase details: `docs/approvals.md::Migration from the pre-tag`. //! and phase details: `docs/approvals.md::Migration from the pre-tag`.
use std::path::{Path, PathBuf}; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
@ -17,18 +17,6 @@ use crate::tool_groups;
const KILL_SWITCH: &str = "HIVE_SKIP_META_MIGRATION"; const KILL_SWITCH: &str = "HIVE_SKIP_META_MIGRATION";
/// Marker for phase 4. Once present, container repoint is skipped on
/// future restarts.
fn repoint_marker() -> PathBuf {
crate::paths::meta_migration_marker()
}
/// Marker for phase 5. Once present, root→h-root container rename is
/// skipped on future restarts.
fn hroot_rename_marker() -> PathBuf {
crate::paths::hroot_rename_marker()
}
/// Substring that identifies the *current* agent flake boilerplate. /// Substring that identifies the *current* agent flake boilerplate.
/// Bumped whenever the template changes so the startup migration /// Bumped whenever the template changes so the startup migration
/// re-renders existing agents onto the new shape. Today the marker /// re-renders existing agents onto the new shape. Today the marker
@ -83,7 +71,7 @@ pub async fn run(coord: &Arc<Coordinator>) -> Result<()> {
} }
// Phase 4: container repoint, guarded by marker. // Phase 4: container repoint, guarded by marker.
if repoint_marker().exists() { if crate::paths::meta_migration_marker().exists() {
tracing::debug!("migration: phase 4 marker present, skipping repoint"); tracing::debug!("migration: phase 4 marker present, skipping repoint");
return Ok(()); return Ok(());
} }
@ -104,7 +92,7 @@ pub async fn run(coord: &Arc<Coordinator>) -> Result<()> {
} }
if all_ok if all_ok
&& !names.is_empty() && !names.is_empty()
&& let Err(e) = std::fs::write(repoint_marker(), b"done\n") && let Err(e) = std::fs::write(crate::paths::meta_migration_marker(), b"done\n")
{ {
tracing::warn!(error = ?e, "migration: write repoint marker failed"); tracing::warn!(error = ?e, "migration: write repoint marker failed");
} }
@ -169,20 +157,20 @@ fn migrate_harness_files(name: &str) {
/// conf files present; on the next hive-c0re start the marker is /// conf files present; on the next hive-c0re start the marker is
/// absent so the phase retries. /// absent so the phase retries.
async fn rename_manager_container(coord: &Arc<Coordinator>) { async fn rename_manager_container(coord: &Arc<Coordinator>) {
if hroot_rename_marker().exists() { if crate::paths::hroot_rename_marker().exists() {
return; return;
} }
let old_conf = std::path::PathBuf::from("/etc/nixos-containers/root.conf"); let old_conf = std::path::PathBuf::from("/etc/nixos-containers/root.conf");
let new_conf = std::path::PathBuf::from("/etc/nixos-containers/h-root.conf"); let new_conf = std::path::PathBuf::from("/etc/nixos-containers/h-root.conf");
if !old_conf.exists() { if !old_conf.exists() {
// Fresh install — root container was never created under the old name. // Fresh install — root container was never created under the old name.
let _ = std::fs::write(hroot_rename_marker(), b"done\n"); let _ = std::fs::write(crate::paths::hroot_rename_marker(), b"done\n");
return; return;
} }
if new_conf.exists() { if new_conf.exists() {
// Already renamed (but marker was lost — write it and return). // Already renamed (but marker was lost — write it and return).
tracing::info!("migration phase 5: h-root.conf already present, marking done"); tracing::info!("migration phase 5: h-root.conf already present, marking done");
let _ = std::fs::write(hroot_rename_marker(), b"done\n"); let _ = std::fs::write(crate::paths::hroot_rename_marker(), b"done\n");
return; return;
} }
tracing::info!("migration phase 5: renaming root container to h-root"); tracing::info!("migration phase 5: renaming root container to h-root");
@ -243,7 +231,7 @@ async fn rename_manager_container(coord: &Arc<Coordinator>) {
} }
tracing::info!("migration phase 5: root container renamed to h-root"); tracing::info!("migration phase 5: root container renamed to h-root");
let _ = std::fs::write(hroot_rename_marker(), b"done\n"); let _ = std::fs::write(crate::paths::hroot_rename_marker(), b"done\n");
// Clean up the old conf file so `nixos-container list` doesn't show // Clean up the old conf file so `nixos-container list` doesn't show
// a stale stopped `root` entry. Best-effort; a failure here is // a stale stopped `root` entry. Best-effort; a failure here is
// harmless — h-root is already running and the marker is written. // harmless — h-root is already running and the marker is written.
@ -312,7 +300,7 @@ async fn migrate_applied_repo(name: &str) -> Result<()> {
async fn repoint_container(name: &str) -> Result<()> { async fn repoint_container(name: &str) -> Result<()> {
let container = lifecycle::container_name(name); let container = lifecycle::container_name(name);
let flake_ref = format!("{}#{name}", meta::meta_dir().display()); let flake_ref = format!("{}#{name}", crate::paths::meta_root().display());
let out = Command::new("nixos-container") let out = Command::new("nixos-container")
.args(["update", &container, "--flake", &flake_ref]) .args(["update", &container, "--flake", &flake_ref])
.output() .output()

View file

@ -224,6 +224,10 @@ pub fn shared_root() -> PathBuf {
pub const KNOWLEDGE_DIR: &str = "/var/lib/hyperhive/knowledge"; pub const KNOWLEDGE_DIR: &str = "/var/lib/hyperhive/knowledge";
/// `gateway/` — generated nginx include fragments for the gateway vhost. /// `gateway/` — generated nginx include fragments for the gateway vhost.
/// The gateway container bind-mounts *this subdir only* (not the whole
/// state root) at `/run/hive-state/`, so nginx can read `agents.conf`
/// without the rest of `/var/lib/hyperhive/` (forge/matrix tokens, etc.)
/// being exposed to the gateway container.
// nix: bind-mounted into the gateway container (hive-gateway.nix) — must match. // nix: bind-mounted into the gateway container (hive-gateway.nix) — must match.
#[must_use] #[must_use]
pub fn gateway_dir() -> PathBuf { pub fn gateway_dir() -> PathBuf {

View file

@ -16,7 +16,7 @@
//! Booting with no config change performs no meta commit — only //! Booting with no config change performs no meta commit — only
//! reconciles. See `docs/coordinator.md::Boot reconcile`. //! reconciles. See `docs/coordinator.md::Boot reconcile`.
use std::path::{Path, PathBuf}; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use anyhow::Result; use anyhow::Result;
@ -24,14 +24,6 @@ use anyhow::Result;
use crate::coordinator::Coordinator; use crate::coordinator::Coordinator;
use crate::lifecycle::{self, AGENT_PREFIX, MANAGER_NAME}; use crate::lifecycle::{self, AGENT_PREFIX, MANAGER_NAME};
/// Marker file recording the hyperhive rev a sub-agent's container was last
/// built against. Sibling of `applied/<name>/` (rather than inside it) to
/// keep it out of the applied repo's git history. Uses a leading dot so a
/// glob over `applied/*` doesn't include it.
pub fn rev_marker_path(name: &str) -> PathBuf {
crate::paths::applied_rev_marker(name)
}
/// Resolve the current rev of `hyperhive_flake`. For a path on disk we /// Resolve the current rev of `hyperhive_flake`. For a path on disk we
/// canonicalize (following symlinks) so a /etc/hyperhive → /nix/store/... /// canonicalize (following symlinks) so a /etc/hyperhive → /nix/store/...
/// update yields a different string. For anything else we return None. /// update yields a different string. For anything else we return None.
@ -159,7 +151,7 @@ pub async fn ensure_root_agent(coord: &Arc<Coordinator>) -> Result<()> {
tracing::warn!(error = ?e, "agent_power: set manager wanted=up failed"); tracing::warn!(error = ?e, "agent_power: set manager wanted=up failed");
} }
if let Some(rev) = current_rev { if let Some(rev) = current_rev {
let _ = std::fs::write(rev_marker_path(MANAGER_NAME), &rev); let _ = std::fs::write(crate::paths::applied_rev_marker(MANAGER_NAME), &rev);
} }
Ok(()) Ok(())
} }
@ -248,7 +240,7 @@ pub async fn run(coord: Arc<Coordinator>) -> Result<()> {
} }
}; };
let fresh = current_rev.as_ref().is_some_and(|rev| { let fresh = current_rev.as_ref().is_some_and(|rev| {
std::fs::read_to_string(rev_marker_path(name)) std::fs::read_to_string(crate::paths::applied_rev_marker(name))
.is_ok_and(|stored| stored == rev.as_str()) .is_ok_and(|stored| stored == rev.as_str())
}); });
if fresh { if fresh {