drop the manager socket, the no-op migrate branch and other ruth special cases
start_manager bound the same path register_agent binds. The migrate branch, hive-priv-sock::MANAGER_NAME and MANAGER_CONTAINER were no-ops or dead. The send allow-list docs promised a manager exemption the code never had. Tests that used ruth as the manager fixture use plain names.
This commit is contained in:
parent
df2394963a
commit
746c522f4e
16 changed files with 36 additions and 117 deletions
|
|
@ -1,11 +1,8 @@
|
|||
//! Unix-socket request server, shared by the per-agent sockets and the
|
||||
//! (pure-transport) manager socket. The socket file's existence on disk
|
||||
//! authenticates the caller: connecting to `<.../agents/foo/mcp.sock>` means
|
||||
//! you are `foo`; the manager socket simply serves as `ruth`. There is no
|
||||
//! privilege flag — both transports run the same [`serve`] / [`dispatch`]
|
||||
//! code, and authority derives uniformly from the caller's identity. An
|
||||
//! agent-targeting verb may name any agent, so `ruth` reaches every agent
|
||||
//! exactly the way every other agent does, not via any hardcoded name match.
|
||||
//! Unix-socket request server for the per-agent sockets. The socket file's
|
||||
//! existence on disk authenticates the caller: connecting to
|
||||
//! `<.../agents/foo/mcp.sock>` means you are `foo`. There is no privilege
|
||||
//! flag; [`serve`] / [`dispatch`] derive authority uniformly from the caller's
|
||||
//! identity. An agent-targeting verb may name any agent.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
|
@ -13,7 +10,6 @@ use std::sync::Arc;
|
|||
use anyhow::{Context, Result};
|
||||
use hive_core_agent_sock::{Request, Response};
|
||||
use hive_sh4re::inbox::Message;
|
||||
use hive_sh4re::manager::MANAGER_AGENT;
|
||||
use tokio::io::{AsyncBufRead, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader};
|
||||
use tokio::net::{UnixListener, UnixStream};
|
||||
use tokio::task::JoinHandle;
|
||||
|
|
@ -77,48 +73,6 @@ pub fn start(agent: &str, socket_path: &Path, coord: Arc<Coordinator>) -> Result
|
|||
Ok(AgentSocket { path, handle })
|
||||
}
|
||||
|
||||
/// Bind + serve the manager socket. This is now **pure transport**: it grants
|
||||
/// no authority of its own — it just serves requests as `agent = MANAGER_AGENT`
|
||||
/// ("ruth"), and ruth's reach comes entirely from the permissions it
|
||||
/// holds, identical to connecting on a per-agent socket — ruth
|
||||
/// uses the standard per-agent runtime dir + socket, with no dedicated helpers.
|
||||
pub fn start_manager(coord: Arc<Coordinator>) -> Result<()> {
|
||||
use std::os::unix::fs::PermissionsExt as _;
|
||||
let dir = crate::paths::agent_runtime_dir(crate::lifecycle::MANAGER_NAME);
|
||||
std::fs::create_dir_all(&dir)
|
||||
.with_context(|| format!("create manager dir {}", dir.display()))?;
|
||||
let socket = Coordinator::socket_path(crate::lifecycle::MANAGER_NAME);
|
||||
if socket.exists() {
|
||||
std::fs::remove_file(&socket).context("remove stale manager socket")?;
|
||||
}
|
||||
let listener = UnixListener::bind(&socket)
|
||||
.with_context(|| format!("bind manager socket {}", socket.display()))?;
|
||||
// 0666 so the in-container root user (non-root) can connect; the bind
|
||||
// source dir is manager-only on host (see the per-agent socket above).
|
||||
std::fs::set_permissions(&socket, std::fs::Permissions::from_mode(0o666))
|
||||
.with_context(|| format!("chmod manager socket {}", socket.display()))?;
|
||||
tracing::info!(socket = %socket.display(), "manager socket listening");
|
||||
|
||||
tokio::spawn(async move {
|
||||
let err = accept_until_fatal(
|
||||
MANAGER_AGENT,
|
||||
|| async { listener.accept().await.map(|(stream, _)| stream) },
|
||||
|stream| {
|
||||
let coord = coord.clone();
|
||||
tokio::spawn(async move {
|
||||
// Pure transport: serve as `ruth`, no privilege grant.
|
||||
if let Err(e) = serve(stream, MANAGER_AGENT.to_owned(), coord).await {
|
||||
tracing::warn!(error = ?e, "manager connection failed");
|
||||
}
|
||||
});
|
||||
},
|
||||
)
|
||||
.await;
|
||||
exit_on_dead_listener(MANAGER_AGENT, &err);
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Pause after an accept error that is not about a single connection. EMFILE
|
||||
/// and ENFILE leave the listener readable, so retrying at once would spin until
|
||||
/// some fd is closed. Same policy as axum's `serve`, which the dashboard runs.
|
||||
|
|
@ -164,9 +118,9 @@ where
|
|||
}
|
||||
|
||||
/// Exit on a listener that can no longer accept. A running hive-c0re re-binds
|
||||
/// an agent socket only on that agent's next start, and the manager socket
|
||||
/// never; on restart (`Restart = "on-failure"` on the unit) `start_manager` and
|
||||
/// `mcp_sockets::sync_on_start` re-bind every one.
|
||||
/// an agent socket only on that agent's next start; on restart
|
||||
/// (`Restart = "on-failure"` on the unit) `mcp_sockets::sync_on_start` re-binds
|
||||
/// every one.
|
||||
fn exit_on_dead_listener(agent: &str, e: &std::io::Error) -> ! {
|
||||
tracing::error!(
|
||||
%agent,
|
||||
|
|
@ -176,7 +130,7 @@ fn exit_on_dead_listener(agent: &str, e: &std::io::Error) -> ! {
|
|||
std::process::exit(1)
|
||||
}
|
||||
|
||||
/// Longest request line accepted on the agent and manager sockets, newline
|
||||
/// Longest request line accepted on the agent sockets, newline
|
||||
/// included. The largest request a client sends is an `OperatorMsg` from the
|
||||
/// agent web UI's `/send` (`hive-agent/src/web_ui/actions.rs:21`), whose body
|
||||
/// axum's default limit caps at 2 MiB; JSON escaping can roughly double that to
|
||||
|
|
@ -286,8 +240,7 @@ pub(crate) fn recv_timeout(wait_seconds: Option<u64>) -> std::time::Duration {
|
|||
}
|
||||
}
|
||||
|
||||
/// Unified dispatch for every socket connection — per-agent sockets and the
|
||||
/// (now pure-transport) manager socket alike. There is no privilege bit;
|
||||
/// Unified dispatch for every socket connection. There is no privilege bit;
|
||||
/// authority derives uniformly from the caller's identity.
|
||||
async fn dispatch(
|
||||
req: &hive_core_agent_sock::Request,
|
||||
|
|
|
|||
Loading…
Reference in a new issue