hivectl: add hive-wide start/stop verbs

`hivectl stop` brings the whole hive down in one operator action — all
sub-agents plus the ci/forge/gateway/matrix infra containers — and
`hivectl start` brings it back up. Scope flags (--agents, --agent <name>,
--ci, --forge, --gateway, --matrix) narrow the set; a bare invocation
targets everything. hive-c0re never stops itself.

- hive-sh4re: HostRequest::{Stop,Start} + LifecycleScope wire type;
  priv_proto InfraAction + ControlInfraContainer + the
  CONTROLLABLE_INFRA_CONTAINERS allowlist (adds hive-matrix, excludes
  hive-c0re).
- hive-priv: control_infra_container handler (systemctl <verb>
  container@<name>, allowlist-validated root-side).
- hive-c0re: handle_stop / handle_start fan out agents via lifecycle and
  infra via hive-priv; per-target failures are aggregated. Infra
  systemctl routes through hive-priv (the privsep boundary).
- The --graceful flag is threaded through Stop now; the per-agent quiesce
  itself lands with the graceful-agent-stop work.
This commit is contained in:
atlas 2026-06-19 00:30:37 +02:00 committed by mara
commit fbb48ed3ce
6 changed files with 407 additions and 7 deletions

View file

@ -27,6 +27,37 @@ pub const SIBLING_CONTAINERS: &[&str] = &["hive-forge", "hive-matrix", "hive-gat
/// 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)]
#[serde(rename_all = "snake_case")]
pub enum InfraAction {
Start,
Stop,
Restart,
}
impl InfraAction {
/// The `systemctl` subcommand this action maps to.
pub fn systemctl_verb(self) -> &'static str {
match self {
InfraAction::Start => "start",
InfraAction::Stop => "stop",
InfraAction::Restart => "restart",
}
}
}
/// Host path of the meta flake. The flake ref for agent `<name>` is
/// `{META_DIR}#{name}`, derived by `hive-priv` — never passed over the wire.
pub const META_DIR: &str = "/var/lib/hyperhive/meta";
@ -316,6 +347,16 @@ pub enum PrivRequest {
/// [`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.
ControlInfraContainer {
container: String,
action: InfraAction,
},
}
/// Response from the privileged helper.