From cce35c20e626f6198202eee3cc87a8b6684153a3 Mon Sep 17 00:00:00 2001 From: damocles Date: Wed, 15 Jul 2026 21:58:03 +0200 Subject: [PATCH] refactor(#2352): move hivectl-shared layout consts to hive-host-sock --- hive-c0re/src/lifecycle/mod.rs | 17 +++++++------- hive-c0re/src/paths.rs | 33 ++++++-------------------- hive-host-sock/src/lib.rs | 42 ++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/hive-c0re/src/lifecycle/mod.rs b/hive-c0re/src/lifecycle/mod.rs index 29ea64f8..acfa722a 100644 --- a/hive-c0re/src/lifecycle/mod.rs +++ b/hive-c0re/src/lifecycle/mod.rs @@ -25,10 +25,14 @@ use tokio::process::Command; use crate::coordinator::{AgentPaths, HiveEnv}; -/// Sub-agent container prefix. `nixos-container` caps the total container name -/// at 11 chars (it gets encoded into network interface names), so the agent -/// name itself can be at most `MAX_AGENT_NAME` chars. -pub const AGENT_PREFIX: &str = "h-"; +// `AGENT_PREFIX` (`h-`) + `container_name` are shared with the host-side +// `hivectl` CLI, so they live in `hive-host-sock`; re-exported here so this +// module stays the daemon's facade for its own callsites. +pub use hive_host_sock::{AGENT_PREFIX, container_name}; + +/// Max agent-name length. `nixos-container` caps the total container name at +/// 11 chars (it gets encoded into network interface names) and `AGENT_PREFIX` +/// (`h-`) takes 2, so the agent name itself is at most `MAX_AGENT_NAME` chars. pub const MAX_AGENT_NAME: usize = 9; /// Logical name of the manager agent (broker recipient, state-dir key, /// meta flake attribute). All persistent state lives under `ruth/`. @@ -124,11 +128,6 @@ pub fn bridge_gateway_ip(subnet_cidr: &str) -> Option { Some(ip_str.to_owned()) } -#[must_use] -pub fn container_name(name: &str) -> String { - format!("{AGENT_PREFIX}{name}") -} - /// Read the agent user's `(uid, gid)` from the container's nixos-managed /// `/etc/passwd`. Returns `None` when the container hasn't been built /// yet, the passwd file is unparseable, or the agent user is missing diff --git a/hive-c0re/src/paths.rs b/hive-c0re/src/paths.rs index 045d4761..4c5a2d7b 100644 --- a/hive-c0re/src/paths.rs +++ b/hive-c0re/src/paths.rs @@ -24,6 +24,12 @@ use std::path::{Path, PathBuf}; +// Layout facts shared with the host-side `hivectl` CLI live in +// `hive-host-sock` (the crate hivectl links instead of the whole daemon); +// re-exported here so this module stays the daemon's single-source facade for +// its own callsites. +pub use hive_host_sock::{AGENTS_ROOT, GATEWAY_HTPASSWD, HOST_SOCKET, agent_state_dir}; + /// Root of all hive-c0re persistent state. // nix: bind-mount source `services.hyperhive.c0re.statePath` (hive-c0re.nix) — must match. pub const STATE_ROOT: &str = "/var/lib/hyperhive"; @@ -35,11 +41,6 @@ pub const STATE_ROOT: &str = "/var/lib/hyperhive"; // stay in sync; the privsep boundary prevents importing across the crate. pub const RUNTIME_ROOT: &str = "/run/hyperhive"; -/// Default host admin socket (`/run/hyperhive/host.sock`). Exposed as a -/// `&str` for the `--socket` / `--host-socket` clap `default_value` in -/// `main.rs` (hive-c0re) and `bin/hivectl.rs`. -pub const HOST_SOCKET: &str = "/run/hyperhive/host.sock"; - /// `/run/hive-agent` — per-agent runtime socket dir root (web + bound /// markers), one subdir per agent. // nix: agent container bind-mount / `RuntimeDirectory` (the harness nix modules) — must match. @@ -158,26 +159,12 @@ pub fn agent_sockets_file() -> PathBuf { // single Rust-side source. // --------------------------------------------------------------------------- -/// `agents/` — per-agent persistent state root (one subdir per agent, -/// bind-mounted into each container as `/agents/`). A `&str` (the -/// dashboard state-file allow-list uses it for `strip_prefix` / -/// `starts_with` checks), so it stays a const; [`agents_root`] wraps it. -// nix: agent container bind-mount source (harness modules / agent.nix template) — must match. -// priv-sock: `hive_priv_sock::AGENT_STATE_ROOT` is the same value and must stay in sync; -// the privsep boundary prevents importing across the crate. -pub const AGENTS_ROOT: &str = "/var/lib/hyperhive/agents"; - +/// `agents/` root (`AGENTS_ROOT`) as an owned `PathBuf`. #[must_use] pub fn agents_root() -> PathBuf { PathBuf::from(AGENTS_ROOT) } -/// `agents/` — one agent's persistent state root. -#[must_use] -pub fn agent_state_dir(name: &str) -> PathBuf { - agents_root().join(name) -} - /// `applied/` — per-agent *applied* (deployed) config repos + rev markers, /// distinct from the proposed configs under `agents//config`. // nix: read by hive-c0re only, but paired with `agents/` in the deploy flow. @@ -253,12 +240,6 @@ pub fn gateway_agents_conf() -> PathBuf { gateway_dir().join("agents.conf") } -/// `gateway/gateway.htpasswd` — nginx basic-auth credential store for the -/// operator dashboard vhost. A `&str` (used as a `hivectl` clap -/// `default_value`), so it stays a const rather than a `PathBuf` fn. -// nix: read by the gateway container's nginx (hive-gateway.nix) — must match. -pub const GATEWAY_HTPASSWD: &str = "/var/lib/hyperhive/gateway/gateway.htpasswd"; - /// `forge-core-token` — the hive-c0re forge account API token. A `&str` /// (used in `Path::new` + user-facing `format!` messages), so it stays a /// const rather than a `PathBuf` fn. diff --git a/hive-host-sock/src/lib.rs b/hive-host-sock/src/lib.rs index 1833c8f7..b4c9a15a 100644 --- a/hive-host-sock/src/lib.rs +++ b/hive-host-sock/src/lib.rs @@ -6,9 +6,51 @@ //! payload types it references (`Approval`, `AgentStatusRow`, `jobs::DagView`) //! stay in `hive-sh4re`. +use std::path::PathBuf; + use hive_sh4re::{AgentStatusRow, Approval, jobs}; use serde::{Deserialize, Serialize}; +// ── Shared hive layout facts ────────────────────────────────────────────── +// Paths + names both the `hive-c0re` daemon and the host-side `hivectl` CLI +// must agree on. Homed here (the protocol crate both sides already depend on) +// so a standalone `hivectl` can reach them without linking the whole daemon +// crate. `hive-c0re`'s `paths` / `lifecycle` modules re-export these, staying +// the daemon's single-source facade for its own callsites. + +/// Default host admin socket (`/run/hyperhive/host.sock`). Used as the +/// `--socket` / `--host-socket` clap `default_value` in the daemon and +/// `hivectl`. +pub const HOST_SOCKET: &str = "/run/hyperhive/host.sock"; + +/// `agents/` — per-agent persistent state root (one subdir per agent, +/// bind-mounted into each container as `/agents/`). +// nix: agent container bind-mount source (harness modules / agent.nix template) — must match. +// priv-sock: `hive_priv_sock::AGENT_STATE_ROOT` is the same value and must stay in sync; +// the privsep boundary prevents importing across the crate. +pub const AGENTS_ROOT: &str = "/var/lib/hyperhive/agents"; + +/// `agents/` — one agent's persistent state root. +#[must_use] +pub fn agent_state_dir(name: &str) -> PathBuf { + PathBuf::from(AGENTS_ROOT).join(name) +} + +/// `gateway/gateway.htpasswd` — nginx basic-auth credential store for the +/// operator dashboard vhost. `hivectl`'s `--htpasswd-file` clap default. +// nix: read by the gateway container's nginx (hive-gateway.nix) — must match. +pub const GATEWAY_HTPASSWD: &str = "/var/lib/hyperhive/gateway/gateway.htpasswd"; + +/// nspawn machine-name prefix for agent containers (`h-`). A single +/// `starts_with(AGENT_PREFIX)` filter enumerates managed containers. +pub const AGENT_PREFIX: &str = "h-"; + +/// Map an agent's logical name to its nspawn machine name (`h-`). +#[must_use] +pub fn container_name(name: &str) -> String { + format!("{AGENT_PREFIX}{name}") +} + /// Requests on the host admin socket. /// /// Wire format: one JSON object per line.