remove the get_host_journal MCP tool and its capability

swarm-logs covers every host-tier unit this tool could reach, so the
second, capability-gated path into host journald earns nothing and is
removed outright rather than disabled behind a flag.

Removed end to end: the MCP tool definition + handler, the
GetHostJournal/HostJournal wire variants, hive-c0re's
dispatch_host_journal handler, the ReadHostJournal capability, and the
harness-side capability->--allowedTools gate. get_host_journal was the
only capability that mapped to an MCP tool, so allowed_capability_tools
could only ever return an empty vec; it goes too rather than linger as a
function that provably does nothing.

capabilities::has_cap/caps_for stay: #4624 gave ManageRootAgent's
bind-mount enforcement (hive-c0re/src/lifecycle/host_config.rs) a
second caller of has_cap, so they're no longer callerless once this
lands on top of it.

hive-sh4re's journal module (JournalPriority) had no consumer outside
this tool and is deleted.

An existing capabilities.json still naming read_host_journal does not
error: capabilities::prune_unknown drops unrecognised names with a
warn!, and an agent left with no capabilities has its entry removed. No
migration step is needed.

Untouched: hive-c0re/src/dashboard/journal.rs's
read_host_journal_response, which matches the name but is the private
helper behind the operator-only GET /api/journal-host dashboard route
and carries no capability check.
This commit is contained in:
atlas 2026-09-21 19:20:05 +02:00
commit 11097ed336
18 changed files with 21 additions and 401 deletions

View file

@ -216,33 +216,3 @@ pub struct EditScheduleArgs {
#[serde(default)]
pub targets_remove: Option<Vec<String>>,
}
/// Arguments for `get_host_journal` (capability-gated: `read_host_journal`).
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
pub struct GetHostJournalArgs {
/// Systemd unit to filter (e.g. `hive-c0re.service`). Omit for all units.
#[serde(default)]
pub unit: Option<String>,
/// nspawn machine name verbatim (e.g. `h-iris`). Omit for host journal.
/// Agent containers use the `h-` prefix (e.g. `h-iris`); infrastructure
/// containers use their full name (e.g. `hive-ci`, `hive-forge`,
/// `hive-matrix`). The gateway has no machine — its nginx runs on the
/// host, so read it with `unit: nginx.service` and no `container`.
#[serde(default)]
pub container: Option<String>,
/// Number of lines to return (default 30, max 100).
#[serde(default)]
pub lines: Option<u32>,
/// Minimum syslog priority level.
#[serde(default)]
pub priority: Option<hive_sh4re::journal::JournalPriority>,
/// Regex to match against log message fields (journalctl --grep).
#[serde(default)]
pub grep: Option<String>,
/// Show entries on or newer than this timestamp (e.g. `-1h`).
#[serde(default)]
pub since: Option<String>,
/// Show entries on or older than this timestamp.
#[serde(default)]
pub until: Option<String>,
}

View file

@ -25,8 +25,8 @@ mod render;
pub use args::{
AckUntilArgs, CancelLooseEndArgs, CancelScheduleArgs, CompactArgs, CreateRepoArgs,
EditScheduleArgs, FireScheduleNowArgs, GetAgentMetaArgs, GetHostJournalArgs, MarkTodosDoneArgs,
RecvArgs, RemindArgs, RequestSchedulePromptArgs, SendArgs, SetStatusArgs,
EditScheduleArgs, FireScheduleNowArgs, GetAgentMetaArgs, MarkTodosDoneArgs, RecvArgs,
RemindArgs, RequestSchedulePromptArgs, SendArgs, SetStatusArgs,
};
pub use render::{annotate_retries, format_ack, format_agent_meta, format_recv};
@ -547,48 +547,6 @@ impl AgentServer {
.await
}
// IMPORTANT: this tool is capability-gated (`read_host_journal`).
// It is added to `--allowedTools` by `allowed_capability_tools` only
// when `HIVE_CAPABILITIES` contains `read_host_journal`. hive-c0re
// performs a second capability check server-side before running journalctl.
#[tool(
description = "Fetch recent lines from the host journal (requires `read_host_journal` \
capability). All filters are optional - omit to get the last N host journal lines. \
`unit`: filter to a systemd unit (e.g. `hive-c0re.service`). \
`container`: nspawn machine name verbatim (e.g. `h-iris`). Omit for host journal. \
Agent containers use the `h-` prefix (e.g. `h-iris`, `h-atlas`); \
infrastructure containers use their full name (e.g. `hive-ci`, `hive-forge`, \
`hive-matrix`). The gateway is not a container: its nginx logs are in \
the host journal, so omit `container` and pass `unit: nginx.service`. \
`lines`: how many lines (default 30, max 100). \
`priority`: minimum syslog level enum. \
`grep`: regex matched against log message fields (journalctl --grep). \
`since`: show entries on or newer than this (e.g. `-1h`, `2024-01-01 12:00:00`). \
`until`: show entries on or older than this."
)]
async fn get_host_journal(&self, Parameters(args): Parameters<GetHostJournalArgs>) -> String {
let log = format!("{args:?}");
run_tool_envelope("get_host_journal", log, async move {
let (resp, retries) = self
.dispatch(hive_core_agent_sock::Request::GetHostJournal {
unit: args.unit,
container: args.container,
lines: args.lines,
priority: args.priority,
grep: args.grep,
since: args.since,
until: args.until,
})
.await;
let result = match resp {
Ok(hive_core_agent_sock::Response::HostJournal { content }) => content,
other => reply_err(other, "get_host_journal"),
};
annotate_retries(result, retries)
})
.await
}
#[tool(
description = "Queue an approval to add a scheduled prompt — one body delivered to \
N agent inboxes at a target time, optionally recurring every `interval_seconds`. \