Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/swarm-queue-client/Cargo.toml
atlas f0844f6da3 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.
2026-10-15 18:01:40 +02:00

100 lines
4.9 KiB
TOML

[package]
name = "swarm-queue-client"
version.workspace = true
readme = "README.md"
edition.workspace = true
[features]
# OFF by default, and that default is the point: the auth-callout responder
# consumes this crate for the connect alone and speaks neither `jetstream`
# nor `kv`. A consumer that needs the status bucket says so in its own
# Cargo.toml, so the requirement stays visible where it is incurred.
#
# What is behind the flag is deliberately narrow - the *name and shape* of
# one bucket two crates open from opposite ends (`src/status.rs`), not a
# general "KV support" surface. The crate's job still ends at a connected
# client; the exception exists because an agreement between two crates has
# to live in one of them, and neither end of that bucket is senior to the
# other.
kv = ["async-nats/kv"]
# 🩸 `jetstream` is NOT in async-nats's default feature set here — the
# workspace-level dependency turns default features off entirely (see
# root `Cargo.toml`: `server_2_14`/`nkeys`/`ring` only). `kv` above works
# standalone only because async-nats's own `kv` feature pulls `jetstream`
# in transitively; `notices.rs` uses `async_nats::jetstream` directly and
# needs the same request explicitly, or it only compiles by accident when
# something else in the same build happens to also enable `kv` (which is
# exactly how this went unnoticed: `cargo test` at the workspace level
# unifies features across every crate being built, so `hive-c0re`'s own
# `kv` request silently carried `notices.rs` until a single-crate
# `cargo check -p swarm-nats-auth` — no `kv` anywhere in that build —
# surfaced it as `cannot find jetstream in async_nats`).
notices = ["async-nats/jetstream"]
# `subagent_term::open_or_create`, for swarm-controller, which creates every
# agent's subagent stream. Explicit for the same reason as `notices`.
subagent-term = ["async-nats/jetstream"]
# `agent_term::open_or_create` and the replay consumer, for swarm-controller,
# which creates every agent's terminal stream and replays it to swarm-ui.
# Explicit for the same reason as `notices`.
agent-term = ["async-nats/jetstream"]
# `agent_schedules::read_own`, for the agent harness, which reads its own
# schedule key without opening the bucket. Explicit for the same reason as
# `notices`.
agent-schedules = ["async-nats/jetstream"]
# `agent_inference::read_own`, for the agent harness, which reads its own
# inference key the same way. Explicit for the same reason as `notices`.
agent-inference = ["async-nats/jetstream"]
# `ToSchema` on the review classifier's shared types, for swarm-controller,
# whose HTTP API serves the same shapes the queue carries.
schema = ["dep:utoipa"]
# `agent_limits::read`, for hive-c0re, which reads the key of each agent it
# runs the same way. Explicit for the same reason as `notices`.
agent-limits = ["async-nats/jetstream"]
# `agent_permissions::AgentPermissions` and `read`, for hive-c0re, the agent
# harness, the subagent daemon and swarm-controller. Pulls `hive-sh4re` for the
# `Permission` names, so the crates that only need the bucket name do not link
# it.
agent-permissions = ["dep:hive-sh4re", "async-nats/jetstream"]
[dependencies]
# Bare (no `kv`/`jetstream`) unless a consumer opts into the `kv` feature
# above - the connect itself needs none of them.
async-nats.workspace = true
# `Shared`, so every caller refused while a secret re-read runs waits on that
# one read (`stored_secret`).
futures-util.workspace = true
hive-sh4re = { workspace = true, optional = true }
# `blocking` on top of the workspace default (`form`/`json`/`rustls`) —
# `mint_token_for_blocking` needs `reqwest::blocking::Client` for a caller
# with no tokio reactor to `.await` an async request on (an OTLP exporter's
# `HttpClient` impl, see that function's doc). Declared here rather than
# left to arrive transitively from a consumer that happens to pull in
# `reqwest`'s blocking feature some other way — this crate already has a
# recorded case of exactly that kind of accidental compile (see the `kv`
# feature's comment above), and `cargo check -p swarm-queue-client` alone
# must not depend on what else is in the build.
reqwest = { workspace = true, features = ["blocking"] }
rustls.workspace = true
serde.workspace = true
serde_json.workspace = true
strum.workspace = true
# A library, so its errors are a matchable enum rather than an opaque
# `anyhow::Error`. The binaries that consume this keep anyhow; `?` converts.
thiserror.workspace = true
tokio.workspace = true
tracing.workspace = true
utoipa = { workspace = true, optional = true }
[dev-dependencies]
# A loopback stand-in token endpoint for the client secret re-read tests.
axum.workspace = true
data-encoding.workspace = true
# `test-util` for `#[tokio::test(start_paused = true)]`: the re-read backoff
# tests run on paused time.
tokio = { workspace = true, features = ["test-util"] }
# Capturing what a re-read logs, to check it names the client and never the
# secret.
tracing-subscriber.workspace = true
[lints]
workspace = true