feat(#1004,#1006): capability system + read_host_journal / get_host_journal MCP tool
This commit is contained in:
parent
6c75030420
commit
dc8a4e2baf
7 changed files with 345 additions and 3 deletions
|
|
@ -428,6 +428,25 @@ pub enum Request {
|
|||
/// crashed-mid-turn sessions. See
|
||||
/// `docs/conventions.md::Broker delivery + ack cycle`.
|
||||
RequeueInflight,
|
||||
/// *(capability-gated: `read_host_journal`)* Fetch recent lines
|
||||
/// from the host journal. Filters are all optional; omitting all
|
||||
/// returns the last `lines` entries from the global journal.
|
||||
GetHostJournal {
|
||||
/// Filter to a specific systemd unit (e.g. `hive-c0re.service`).
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
unit: Option<String>,
|
||||
/// Filter to a specific nspawn container by logical agent name
|
||||
/// (e.g. `"iris"` → machine `h-iris`). Adds `-M` flag.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
container: Option<String>,
|
||||
/// Number of journal lines to return (default 100, max 500).
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
lines: Option<u32>,
|
||||
/// Minimum syslog priority level: `err`, `warning`, `info`, `debug`.
|
||||
/// Corresponds to journalctl `-p LEVEL`.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
priority: Option<String>,
|
||||
},
|
||||
|
||||
// ---- privileged (manager socket only for now) ---------------------------
|
||||
|
||||
|
|
@ -556,6 +575,10 @@ pub enum Response {
|
|||
/// `GetLogs` result: journal lines for the requested container.
|
||||
/// Returned on the manager socket only.
|
||||
Logs { content: String },
|
||||
/// `GetHostJournal` result: host journal lines matching the
|
||||
/// requested filters. Returned on the agent socket when the agent
|
||||
/// holds the `read_host_journal` capability.
|
||||
HostJournal { content: String },
|
||||
/// `ListSchedules` result. Snapshot of every schedule.
|
||||
/// Returned on the manager socket only.
|
||||
Schedules { schedules: Vec<WireSchedule> },
|
||||
|
|
@ -821,6 +844,43 @@ impl ToolGroup {
|
|||
}
|
||||
}
|
||||
|
||||
/// Per-agent capability grants. Stored in `meta/capabilities.json`
|
||||
/// (same shape as `tool-groups.json`: `{ "alice": ["read_host_journal"] }`).
|
||||
/// Capabilities control system-level access that hive-c0re enforces
|
||||
/// at dispatch time; they are orthogonal to tool groups (which control
|
||||
/// which MCP tools the harness exposes to claude).
|
||||
///
|
||||
/// Injected into containers as `HIVE_CAPABILITIES` (comma-separated
|
||||
/// snake_case) via `meta::render_flake`. The harness reads this to
|
||||
/// conditionally register capability-gated MCP tools so claude only
|
||||
/// sees tools it can actually invoke. See `docs/conventions.md::Capabilities`.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Capability {
|
||||
/// Agent can lifecycle-manage the root agent (kill/start/restart)
|
||||
/// on behalf of the hive when the root has crashed. Named capability
|
||||
/// for the existing manager privilege — future topology enforcement
|
||||
/// will gate this via the capability system instead of the hardcoded
|
||||
/// `container == MANAGER_CONTAINER` check.
|
||||
ManageRootAgent,
|
||||
/// Agent can read the full host journal via `GetHostJournal`.
|
||||
/// hive-c0re checks this capability before running journalctl.
|
||||
/// MCP tool `get_host_journal` is only registered in the harness
|
||||
/// when this capability is present.
|
||||
ReadHostJournal,
|
||||
}
|
||||
|
||||
impl Capability {
|
||||
/// Canonical snake_case name for this capability (matches serde).
|
||||
#[must_use]
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::ManageRootAgent => "manage_root_agent",
|
||||
Self::ReadHostJournal => "read_host_journal",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Schedule row shape on the wire — mirror of
|
||||
/// `scheduled_prompts::Schedule` but in the public crate so the
|
||||
/// dashboard and agent surfaces can deserialize without depending
|
||||
|
|
|
|||
Loading…
Reference in a new issue