hive-c0re: drop the dead manager exclusion from the agent web-port map

This commit is contained in:
damocles 2026-06-21 23:19:03 +02:00 committed by mara
commit 0df52806f9
2 changed files with 17 additions and 18 deletions

View file

@ -131,11 +131,11 @@ logical agent name → TCP web port:
Written alongside `agents.conf` on every topology change. Ports come from
`lifecycle::agent_web_port(name)` — a pure FNV-1a hash of the name,
reproducible from the name alone. The manager is excluded: it always
uses a unix socket (`HIVE_WEB_SOCKET` is unconditionally set for the
manager role), so its TCP port never appears in the fallback map.
The gateway routes `/agent/root/` to the manager's unix socket via
`agents.conf` alongside sub-agents.
reproducible from the name alone. Every agent gets an entry — no name is
special-cased. Note this TCP map is now a fallback the gateway no longer
reaches: all agents bind a unix-socket web UI (`HIVE_WEB_SOCKET`) and the
gateway routes via `agent-sockets.json`, picking the socket upstream
whenever one exists. The root agent's UI is routed at `/agent/root/`.
The file doubles as a human-readable audit artifact — `cat agent-ports.json`
shows every registered sub-agent and its deterministic port assignment. TCP

View file

@ -1,23 +1,24 @@
//! `/var/lib/hyperhive/run/agent-ports.json` writer — flat map of
//! agent name → TCP web port. Written alongside `agents.conf` on
//! every topology change. JSON shape, port derivation (FNV-1a hash),
//! atomicity, and manager exclusion: `docs/gateway.md::Agent port map`.
//! and atomicity: `docs/gateway.md::Agent port map`.
use std::collections::BTreeMap;
use std::path::PathBuf;
use anyhow::{Context, Result};
use crate::lifecycle::{self, MANAGER_NAME};
use crate::lifecycle;
#[must_use]
pub fn host_ports_path() -> PathBuf {
crate::paths::agent_ports_file()
}
/// Compute the agent-port map for the given logical agent names.
/// Sub-agents only — manager is filtered out at the call boundary
/// because the gateway doesn't surface per-agent routing for it.
/// Compute the agent-port map for the given logical agent names. Every
/// agent gets an entry — no name is special-cased. (All agents now bind
/// a unix-socket web UI via `HIVE_WEB_SOCKET`, so this TCP map is a
/// fallback the gateway no longer reaches; tracked for removal.)
///
/// `BTreeMap` keeps the JSON output sorted by key so a re-emit
/// without churn produces byte-identical output (helpful when the
@ -26,7 +27,6 @@ pub fn host_ports_path() -> PathBuf {
pub fn build_map(names: &[String]) -> BTreeMap<String, u16> {
names
.iter()
.filter(|n| n.as_str() != MANAGER_NAME)
.map(|n| (n.clone(), lifecycle::agent_web_port(n)))
.collect()
}
@ -77,17 +77,16 @@ mod tests {
use super::*;
#[test]
fn build_map_filters_manager() {
// Use MANAGER_NAME in the input so the assert below actually
// exercises the filter path — a literal `"root"` would pass
// trivially if the constant ever changed and the filter
// silently became a no-op.
let names: Vec<String> = ["iris", MANAGER_NAME, "argus"]
fn build_map_includes_every_agent() {
// No name is special-cased: the bootstrap/root container gets a
// port entry like any other agent. Use the bootstrap name in the
// input so this guards against re-introducing an exclusion.
let names: Vec<String> = ["iris", lifecycle::MANAGER_NAME, "argus"]
.iter()
.map(|s| (*s).to_owned())
.collect();
let map = build_map(&names);
assert!(!map.contains_key(MANAGER_NAME));
assert!(map.contains_key(lifecycle::MANAGER_NAME));
assert!(map.contains_key("iris"));
assert!(map.contains_key("argus"));
}