hive-c0re: stop naming nix implementation files in env-var prose
Six diagnostics and eight comments explained where an environment variable comes from by naming the module file that sets it. The reader of a panic is an operator, who does not edit that file; the reader of the comment is already in the code. Neither can act on a filename, and a filename in prose is checked by nothing. Each one now names what the reader can act on: the option where there is one (services.hyperhive.network.bridgeName, .bridgeIp, .bridgePrefixLength, c0re.assets, c0re.orgAvatarPng), otherwise the unit the process is expected to run under. Two of the six diagnostics had a real option available; the other four have none, so they name the unit rather than an invented path. Four of them pointed at hive-c0re.nix, which is a directory. Two of those spelled it nix/modules/hive-c0re.nix — a directory that does not exist either, and one of the two was wrapped across a line break, so no grep for the whole path could have found it. That is the argument for the change: prose naming a file rots silently because nothing compiles it. Scope here is the four files around those diagnostics. The same pattern still matches elsewhere in the tree; that sweep follows.
This commit is contained in:
parent
f4bfd2f816
commit
ca4b56c006
4 changed files with 41 additions and 33 deletions
|
|
@ -39,7 +39,8 @@ use users::{
|
|||
const FORGE_CONTAINER: &str = "hive-forge";
|
||||
|
||||
/// Base HTTP URL for the local Forgejo instance, from `HIVE_FORGE_URL`
|
||||
/// (set unconditionally by `hive-c0re.nix` to `http://<forge.domain>`).
|
||||
/// (set unconditionally by the hyperhive NixOS module on the `hive-c0re`
|
||||
/// unit, to `http://<forge.domain>`).
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
|
|
@ -54,8 +55,9 @@ pub(crate) fn forge_http_base() -> &'static str {
|
|||
static BASE: OnceLock<String> = OnceLock::new();
|
||||
BASE.get_or_init(|| {
|
||||
std::env::var("HIVE_FORGE_URL").expect(
|
||||
"HIVE_FORGE_URL is unset — hive-c0re.nix sets it unconditionally, \
|
||||
so this process was started outside the NixOS module",
|
||||
"HIVE_FORGE_URL is unset — the hyperhive NixOS module sets it \
|
||||
unconditionally on the hive-c0re unit, so this process was \
|
||||
started outside that unit",
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@ use crate::paths::FORGE_CORE_TOKEN as CORE_TOKEN_PATH;
|
|||
/// package to change it.
|
||||
fn core_avatar_png_path() -> std::path::PathBuf {
|
||||
let dir = std::env::var("HIVE_ASSETS_DIR").expect(
|
||||
"HIVE_ASSETS_DIR is unset — hive-c0re.nix sets it unconditionally, \
|
||||
so this process was started outside the NixOS module",
|
||||
"HIVE_ASSETS_DIR is unset — the hyperhive NixOS module sets it from \
|
||||
services.hyperhive.c0re.assets on the hive-c0re unit, so this \
|
||||
process was started outside that unit",
|
||||
);
|
||||
std::path::PathBuf::from(dir).join("branding/hyperhive.png")
|
||||
}
|
||||
|
|
@ -51,9 +52,10 @@ fn core_avatar_png_path() -> std::path::PathBuf {
|
|||
/// `assets` package.
|
||||
fn config_org_avatar_png_path() -> std::path::PathBuf {
|
||||
std::path::PathBuf::from(std::env::var("HIVE_ORG_AVATAR_PNG").expect(
|
||||
"HIVE_ORG_AVATAR_PNG is unset — hive-c0re.nix sets it unconditionally \
|
||||
(from services.hyperhive.c0re.orgAvatarPng or the bundled default), \
|
||||
so this process was started outside the NixOS module",
|
||||
"HIVE_ORG_AVATAR_PNG is unset — the hyperhive NixOS module sets it \
|
||||
unconditionally on the hive-c0re unit (from \
|
||||
services.hyperhive.c0re.orgAvatarPng or the bundled default), so \
|
||||
this process was started outside that unit",
|
||||
))
|
||||
}
|
||||
/// Per-agent token scopes (broad-but-not-admin) for tokens hive-c0re
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@ pub fn bridge_gateway_ip(subnet_cidr: &str) -> Option<String> {
|
|||
}
|
||||
|
||||
/// Build the network-isolation settings every container is configured
|
||||
/// with, from the variables `hive-network.nix` sets on the `hive-c0re`
|
||||
/// unit.
|
||||
/// with, from the variables the hyperhive NixOS module derives from
|
||||
/// `services.hyperhive.network.*` onto the `hive-c0re` unit.
|
||||
///
|
||||
/// Isolation is the only supported mode: the on/off toggle is gone, so
|
||||
/// there is no non-isolated branch to fall back to and a missing or
|
||||
|
|
@ -143,12 +143,14 @@ pub fn network_isolation_from_vars(
|
|||
subnet: Option<&str>,
|
||||
) -> Result<hive_priv_sock::NetworkIsolation> {
|
||||
let bridge = bridge.filter(|s| !s.is_empty()).context(
|
||||
"HIVE_NETWORK_BRIDGE is unset or empty — hive-network.nix sets it on the \
|
||||
hive-c0re unit, so this means the daemon is running outside its unit or \
|
||||
with a broken module evaluation",
|
||||
"HIVE_NETWORK_BRIDGE is unset or empty — the hyperhive NixOS module sets it \
|
||||
from services.hyperhive.network.bridgeName on the hive-c0re unit, so this \
|
||||
means the daemon is running outside its unit or with a broken module \
|
||||
evaluation",
|
||||
)?;
|
||||
let subnet = subnet.filter(|s| !s.is_empty()).context(
|
||||
"HIVE_NETWORK_SUBNET is unset or empty — hive-network.nix sets it on the \
|
||||
"HIVE_NETWORK_SUBNET is unset or empty — the hyperhive NixOS module sets it \
|
||||
from services.hyperhive.network.bridgeIp and .bridgePrefixLength on the \
|
||||
hive-c0re unit, so this means the daemon is running outside its unit or \
|
||||
with a broken module evaluation",
|
||||
)?;
|
||||
|
|
|
|||
|
|
@ -716,8 +716,8 @@ const FORWARDED_VARS: &[&str] = &[
|
|||
/// which is how a hive ends up with two disagreeing answers for one value.
|
||||
///
|
||||
/// The hive/swarm display names are here for exactly that reason, learned the
|
||||
/// hard way: they were forwarded as runtime env only, while
|
||||
/// `claude-settings.nix` read them from the container's `environment.variables`
|
||||
/// hard way: they were forwarded as runtime env only, while the agent's
|
||||
/// claude-settings module read them from the container's `environment.variables`
|
||||
/// at *eval* time — where they were never set. Every agent baked
|
||||
/// `hive=unknown,swarm=unknown` into its OTEL resource attributes and shipped
|
||||
/// that label on every metric, while the same process's env held the right
|
||||
|
|
@ -757,9 +757,9 @@ fn push_forwarded_var_options(out: &mut String, vars: &[(&'static str, String)])
|
|||
|
||||
/// Service URLs a running hive must always supply, checked before rendering.
|
||||
///
|
||||
/// The forge is not optional on a real hive: `hive-c0re.nix` sets
|
||||
/// The forge is not optional on a real hive: the hyperhive NixOS module sets
|
||||
/// `HIVE_FORGE_URL` unconditionally, so its absence means this daemon was
|
||||
/// started outside the NixOS module. The agent option is nullable — `null`
|
||||
/// started outside its unit. The agent option is nullable — `null`
|
||||
/// legitimately means "no forge" when the modules are evaluated on their own —
|
||||
/// which is exactly why the hive has to assert its own requirement here rather
|
||||
/// than leaning on the module to reject the empty case.
|
||||
|
|
@ -780,17 +780,19 @@ const REQUIRED_SERVICE_URL_VARS: &[&str] = &["HIVE_FORGE_URL"];
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When a required var is missing. `hive-c0re.nix` sets it unconditionally, so
|
||||
/// this means the daemon is running outside the NixOS module; refusing to
|
||||
/// When a required var is missing. The hyperhive NixOS module sets it
|
||||
/// unconditionally, so this means the daemon is running outside its unit;
|
||||
/// refusing to
|
||||
/// write the flake beats writing one whose agents would silently all lack a
|
||||
/// forge.
|
||||
fn require_service_urls(vars: &[(&'static str, String)]) -> Result<()> {
|
||||
for required in REQUIRED_SERVICE_URL_VARS {
|
||||
if !vars.iter().any(|(name, _)| name == required) {
|
||||
anyhow::bail!(
|
||||
"{required} is unset — hive-c0re.nix sets it unconditionally, so this process \
|
||||
was started outside the NixOS module. Refusing to write a meta flake whose \
|
||||
agents would every one of them have no forge configured."
|
||||
"{required} is unset — the hyperhive NixOS module sets it unconditionally on \
|
||||
the hive-c0re unit, so this process was started outside that unit. Refusing \
|
||||
to write a meta flake whose agents would every one of them have no forge \
|
||||
configured."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -816,7 +818,7 @@ fn forwarded_env_vars() -> Vec<(&'static str, String)> {
|
|||
const HIVE_CA_FILE: &str = "hive-ca.pem";
|
||||
|
||||
/// Host path of the hive's TLS trust anchors, when self-signed TLS is
|
||||
/// active. `hive-tls.nix` sets `HIVE_TLS_CA_PATH` in hive-c0re's service env
|
||||
/// active. The hyperhive TLS module sets `HIVE_TLS_CA_PATH` in hive-c0re's env
|
||||
/// (to `<tls.stateDir>/trust-bundle.pem`) whenever the gateway serves a
|
||||
/// self-signed, hive-CA-signed leaf. The file holds one *or more* certs —
|
||||
/// the hive CA plus the swarm root it is issued under — and is copied
|
||||
|
|
@ -834,8 +836,8 @@ fn hive_ca_source() -> Option<String> {
|
|||
}
|
||||
|
||||
/// Hive-wide OTEL config injected into every agent's build, read off
|
||||
/// hive-c0re's own unit env (set from `services.hyperhive.otel.*` in
|
||||
/// `nix/modules/hive-c0re.nix`). A present, non-empty
|
||||
/// hive-c0re's own unit env (set from `services.hyperhive.otel.*`). A
|
||||
/// present, non-empty
|
||||
/// `HYPERHIVE_OTEL_ENDPOINT` is the enable signal — the host module
|
||||
/// asserts the endpoint is set whenever `otel.enable` is true, so
|
||||
/// "endpoint present" == "OTEL on". The optional fields map to the
|
||||
|
|
@ -887,9 +889,9 @@ fn otel_config() -> Option<OtelConfig> {
|
|||
/// `(filename, host_source_path)` — now just the hive's own trust
|
||||
/// anchors as `hive-ca.pem`, when self-signed TLS is active.
|
||||
///
|
||||
/// That single file already carries the swarm root (`hive-tls.nix`
|
||||
/// writes the hive CA *and* the root it is issued under into the trust
|
||||
/// bundle), so every hive under the swarm root validates from it. Which
|
||||
/// That single file already carries the swarm root (the hyperhive TLS
|
||||
/// module writes the hive CA *and* the root it is issued under into the
|
||||
/// trust bundle), so every hive under the swarm root validates from it. Which
|
||||
/// is why the per-peer CAs this used to append are gone: they said the
|
||||
/// same thing once per peer.
|
||||
///
|
||||
|
|
@ -1313,8 +1315,8 @@ where
|
|||
);
|
||||
}
|
||||
// Forwarded env vars — picked up from hive-c0re's own systemd unit
|
||||
// env (`services.hyperhive.*` options flow through nix/modules/
|
||||
// hive-c0re.nix into the host process). We copy whatever's set into
|
||||
// env (`services.hyperhive.*` options flow through the hyperhive
|
||||
// NixOS module into the host process). We copy whatever's set into
|
||||
// each sub-agent's harness service env so the in-container surfaces
|
||||
// (`identity.rs`, `forge_notify`) see a consistent view across the
|
||||
// whole hive. Absent host-side env (option not set) → skip emission
|
||||
|
|
@ -1379,7 +1381,7 @@ where
|
|||
};
|
||||
// Effective `MemoryMax=` for this agent (per-agent override, else
|
||||
// the hive-wide default), turned into a raw byte count so
|
||||
// `claude-settings.nix` can derive a JSC heap ceiling from it
|
||||
// the agent's claude-settings module can derive a JSC heap ceiling
|
||||
// (see `hyperhive.claudeMemoryMaxBytes`). `null` when the
|
||||
// effective value is `"infinity"` or a RAM percentage — no
|
||||
// byte count to derive, dependent env var stays unset, same as
|
||||
|
|
@ -2127,7 +2129,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn render_flake_embeds_hive_ca_when_signalled() {
|
||||
// When hive-tls.nix signals a self-signed hive CA via
|
||||
// When the hyperhive TLS module signals a self-signed hive CA via
|
||||
// HIVE_TLS_CA_PATH (and the cert exists), the agent module must
|
||||
// trust it at build time via security.pki.certificateFiles. Absent
|
||||
// the signal, no reference is emitted (so the flake doesn't point at
|
||||
|
|
|
|||
Loading…
Reference in a new issue