Watch
0
0
Fork
You've already forked hyperhive
0

agent permissions: one set, tool groups included, set at agent creation

mara on #5170: "dont split caps and perms. its all perms. / dont include
the now empty tool groups / nothing set -> default / also add perms to
agent creation screen".

- hive-sh4re: one `Permission` enum (messaging, meta, inbox, execution,
  web_tools, manage_root_agent) replaces `ToolGroup` and `Capability`;
  `lifecycle`/`forge` are gone. `Permission::default_for` is the default
  for an agent the swarm sets nothing for.
- The record is `{ "permissions": [...] }`. Missing key, unset field or
  no successful read yet = default; `[]` = none; a failed read after a
  good one keeps the last value.
- hive-agent reads its own key every 10s and builds each turn's --tools,
  --allowedTools and MCP config (rewritten before every turn) from it;
  the subagent daemon reads it on each start/continue. Agents get a
  read-only grant on their own key.
- hive-c0re restarts an agent only when its manage_root_agent changes.
  The import now merges meta/capabilities.json and meta/tool-groups.json
  into one list per agent and deletes both; the "import pending, don't
  read" decision is `ImportOutcome::read_allowed`, table-tested.
- swarm-controller: `GET /api/permissions` (names + default) and an
  optional `permissions` on `POST /api/agents`, stored before the job is
  queued. swarm-ui's create-agent form gets a permissions field.
- Deleted: HIVE_TOOL_GROUPS and its forward to the subagent daemon,
  tool_groups.rs, ruth's tool-group seed, the permissions rebuild job
  (PermPayload/WritePermFile/perm_change), the dashboard permissions tab
  and its stale-entries panel.

Part of #5170.
This commit is contained in:
atlas 2026-10-15 04:09:53 +02:00 • committed by mara
commit f0844f6da3
73 changed files with 1578 additions and 2742 deletions

View file

@ -23,7 +23,6 @@ use anyhow::Result;
use crate::coordinator::Coordinator;
use crate::lifecycle::{self, AGENT_PREFIX, MANAGER_NAME};
use crate::tool_groups;
/// Resolve the current rev of `hyperhive_flake`. For a path on disk we
/// canonicalize (following symlinks) so a /etc/hyperhive → /nix/store/...
@ -200,7 +199,6 @@ pub async fn ensure_root_agent(coord: &Arc<Coordinator>) -> Result<()> {
let hive = coord.hive_env();
let paths = Coordinator::agent_paths(MANAGER_NAME, runtime)?;
lifecycle::spawn(MANAGER_NAME, &hive, &paths).await?;
seed_manager_tool_groups();
if let Err(e) = coord.power.set(MANAGER_NAME, crate::power::Wanted::Up) {
tracing::warn!(error = ?e, "agent_power: set manager wanted=up failed");
}
@ -212,47 +210,6 @@ pub async fn ensure_root_agent(coord: &Arc<Coordinator>) -> Result<()> {
Ok(())
}
/// Give ruth her privileged tool groups on the one path that creates her.
///
/// `effective_tool_groups()` has no manager-flavour fallback, so an agent
/// with no entry in `tool-groups.json` is an agent with no privileged
/// tools. Ruth needs hers from her first turn, and this is the only place
/// she is brought into existence — so it is written once, here, rather
/// than re-checked on every hive-c0re boot.
///
/// Skips a name that already has an entry: a destroy+recreate under the
/// same name must not silently reset an operator's chosen group set back
/// to the default. An unreadable file is logged and left alone: ruth has
/// already been spawned, and seeding stays best-effort like the write
/// below.
fn seed_manager_tool_groups() {
match tool_groups::groups_for(MANAGER_NAME) {
Ok(groups) if groups.is_empty() => {}
Ok(_) => {
tracing::debug!("manager tool groups already set — leaving as-is");
return;
}
Err(e) => {
tracing::warn!(
error = ?e,
"tool-groups file unreadable — not seeding ruth's tool groups"
);
return;
}
}
let all_groups: Vec<String> = hive_sh4re::permissions::ToolGroup::MANAGER_DEFAULT
.iter()
.map(|g| <&str>::from(*g).to_owned())
.collect();
match tool_groups::set_groups(MANAGER_NAME, &all_groups) {
Ok(()) => tracing::info!("seeded ruth's tool groups to MANAGER_DEFAULT (all groups)"),
Err(e) => tracing::warn!(
error = ?e,
"failed to seed ruth's tool groups — she will start without privileged tools"
),
}
}
/// Boot reconcile (see the module doc): classify every agent by rev
/// freshness + persisted `wanted` intent, submit one `Boot` DAG
/// (hyperhive lock bump growing an in-DAG rebuild subgraph per stale