hivectl: collapse infra allowlist + restart/control ops onto SIBLING_CONTAINERS
Per review: RESTARTABLE_INFRA_CONTAINERS and the new CONTROLLABLE_INFRA_CONTAINERS
were near-identical subsets of SIBLING_CONTAINERS. Drop both and validate infra
lifecycle ops against SIBLING_CONTAINERS directly (all four infra containers;
hive-c0re is never in it, so it can't stop itself). This also makes hive-matrix
restartable, including via an infra_admin agent's restart tool.
Collapse the two priv ops too: RestartInfraContainer is gone; ControlInfraContainer
{ action } is the single op (restart = action: Restart). priv_client's
restart_infra_container is now a thin wrapper over control_infra_container.
This commit is contained in:
parent
c673dce73d
commit
0df9e40940
4 changed files with 46 additions and 109 deletions
|
|
@ -15,28 +15,16 @@ pub const MANAGER_NAME: &str = "ruth";
|
|||
/// Sub-agent container prefix. System container name = `h-<agent_name>`.
|
||||
pub const AGENT_PREFIX: &str = "h-";
|
||||
|
||||
/// Sibling service containers managed by hive-c0re.
|
||||
/// Sibling service containers managed by hive-c0re. This doubles as the
|
||||
/// authoritative allowlist for infra lifecycle ops
|
||||
/// ([`PrivRequest::ControlInfraContainer`]): any of these four may be
|
||||
/// started / stopped / restarted (by the hive-wide `hivectl stop`/`start`
|
||||
/// flow or an `infra_admin` agent's `restart`). `hive-c0re` is deliberately
|
||||
/// absent — stopping it would sever the very socket the request arrived on.
|
||||
/// hive-priv re-validates against this list root-side, so it's authoritative
|
||||
/// regardless of what the caller sends.
|
||||
pub const SIBLING_CONTAINERS: &[&str] = &["hive-forge", "hive-matrix", "hive-gateway", "hive-ci"];
|
||||
|
||||
/// Infra containers an agent holding the `infra_admin` capability may
|
||||
/// restart via the `restart` MCP tool. A deliberate subset of
|
||||
/// [`SIBLING_CONTAINERS`]: hive-matrix is excluded (kicking the matrix
|
||||
/// backend mid-sync is its own concern) and hive-c0re is excluded
|
||||
/// entirely (a self-restart would sever the very socket the request
|
||||
/// arrived on). hive-priv re-validates against this list root-side, so
|
||||
/// it is the authoritative allowlist regardless of what the caller sends.
|
||||
pub const RESTARTABLE_INFRA_CONTAINERS: &[&str] = &["hive-ci", "hive-gateway", "hive-forge"];
|
||||
|
||||
/// Infra containers hive-c0re may stop/start/restart hive-wide for the
|
||||
/// `hivectl stop` / `hivectl start` operator flow. Superset of
|
||||
/// [`RESTARTABLE_INFRA_CONTAINERS`]: it adds `hive-matrix`, because a full
|
||||
/// stop is a deliberate operator action (unlike the disruptive mid-sync
|
||||
/// *restart* the `infra_admin` MCP path forbids). `hive-c0re` is still
|
||||
/// excluded — it runs the daemon servicing the request and must never stop
|
||||
/// itself. hive-priv re-validates against this list root-side.
|
||||
pub const CONTROLLABLE_INFRA_CONTAINERS: &[&str] =
|
||||
&["hive-ci", "hive-gateway", "hive-forge", "hive-matrix"];
|
||||
|
||||
/// Lifecycle verb for [`PrivRequest::ControlInfraContainer`]. Maps directly
|
||||
/// to `systemctl <verb> container@<container>.service`.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
|
|
@ -336,24 +324,15 @@ pub enum PrivRequest {
|
|||
agent_name: String,
|
||||
},
|
||||
|
||||
/// Restart a hive infrastructure container on the host via
|
||||
/// `systemctl restart container@<container>.service`. hive-priv
|
||||
/// validates `container` against [`RESTARTABLE_INFRA_CONTAINERS`]
|
||||
/// before acting — the root-side allowlist is authoritative. Used
|
||||
/// by hive-c0re to service a `restart` request from an agent that
|
||||
/// holds the `infra_admin` capability.
|
||||
RestartInfraContainer {
|
||||
/// Infra container name (e.g. `hive-ci`); must be in
|
||||
/// [`RESTARTABLE_INFRA_CONTAINERS`].
|
||||
container: String,
|
||||
},
|
||||
|
||||
/// Start/stop/restart a hive infrastructure container on the host via
|
||||
/// `systemctl <action> container@<container>.service`. hive-priv
|
||||
/// validates `container` against [`CONTROLLABLE_INFRA_CONTAINERS`]
|
||||
/// root-side. Generalises [`PrivRequest::RestartInfraContainer`] for the
|
||||
/// hive-wide `hivectl stop` / `hivectl start` operator flow.
|
||||
/// Start / stop / restart a hive infrastructure container on the host
|
||||
/// via `systemctl <action> container@<container>.service`. hive-priv
|
||||
/// validates `container` against [`SIBLING_CONTAINERS`] root-side (the
|
||||
/// authoritative allowlist; `hive-c0re` is never in it). Serves both the
|
||||
/// hive-wide `hivectl stop` / `hivectl start` flow and an `infra_admin`
|
||||
/// agent's `restart` (with `action = Restart`).
|
||||
ControlInfraContainer {
|
||||
/// Infra container name (e.g. `hive-ci`); must be in
|
||||
/// [`SIBLING_CONTAINERS`].
|
||||
container: String,
|
||||
action: InfraAction,
|
||||
},
|
||||
|
|
@ -414,21 +393,15 @@ pub enum PrivEvent {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{RESTARTABLE_INFRA_CONTAINERS, SIBLING_CONTAINERS};
|
||||
use super::SIBLING_CONTAINERS;
|
||||
|
||||
#[test]
|
||||
fn restartable_infra_is_a_safe_subset_of_siblings() {
|
||||
// Every restartable infra container must be a known sibling.
|
||||
for c in RESTARTABLE_INFRA_CONTAINERS {
|
||||
assert!(
|
||||
SIBLING_CONTAINERS.contains(c),
|
||||
"{c} is not a managed sibling container"
|
||||
);
|
||||
}
|
||||
// hive-matrix and hive-c0re are deliberately excluded: kicking the
|
||||
// matrix backend mid-sync is its own concern, and a self-restart of
|
||||
// c0re would sever the request socket.
|
||||
assert!(!RESTARTABLE_INFRA_CONTAINERS.contains(&"hive-matrix"));
|
||||
assert!(!RESTARTABLE_INFRA_CONTAINERS.contains(&"hive-c0re"));
|
||||
fn infra_control_allowlist_excludes_c0re_includes_matrix() {
|
||||
// SIBLING_CONTAINERS is the authoritative allowlist for infra
|
||||
// lifecycle ops. hive-c0re must NEVER be in it — stopping the daemon
|
||||
// would sever the socket the request arrived on.
|
||||
assert!(!SIBLING_CONTAINERS.contains(&"hive-c0re"));
|
||||
// hive-matrix IS controllable (operator can stop/start/restart it).
|
||||
assert!(SIBLING_CONTAINERS.contains(&"hive-matrix"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue