Commit graph hyperhive/hive-c0re/src/dashboard/permissions.rs
Author SHA1 Message Date
damocles
84b750fba5 refactor(#2302): type socket wire fields as ident, validated by serde on deserialize 2026-07-20 21:46:18 +02:00
damocles
bf644cc126 feat(#2302): thread &Ident through agent path builders 2026-07-20 21:46:18 +02:00
damocles
1286029947 feat(#2302): migrate dashboard to the single hive-host-sock Ident newtype 2026-07-20 21:46:18 +02:00
damocles
cfac917b4d feat(#2302): parse agent names into AgentName newtype at dashboard boundary 2026-07-20 21:46:18 +02:00
müde
7946e03fde feat(hive-c0re): replace rebuild queue with generic job-DAG queue
jobs are now DAGs of primitive nodes (prebuild, stop-for-update, swap,
reconcile, signal, drain, ...) driven by one scheduler with N build
slots + per-agent lifecycle leases. per-agent power intent (wanted
up/offline) is durable in agent_power.sqlite; Reconcile nodes converge
observed state to it. kills the graceful-stop watcher thread, the
deferred-start follow-up, and the cascade pre-enqueue (fan-out on
MetaLock completion instead). tracker: #2166
2026-07-06 20:36:57 +02:00
iris
75e49f7752 fix(permissions): clarify kept_state_names comment in get_stale_permissions
The variable was misleadingly named `tombstones` and commented as
'any name here is a tombstone', but kept_state_names() returns ALL
agents with a state dir on disk — both live containers and soft-deleted
tombstones. The logic was always correct (union with the live roster
filters both), but the comment would mislead future readers.

Rename the variable to `kept` and update comments to accurately
describe the contents.
2026-06-28 23:29:51 +02:00
iris
cffe645197 fix(permissions): collapse known-set assignment to one line (rustfmt) 2026-06-28 23:29:51 +02:00
iris
4df286345a refactor(permissions): move ghost-perm detection server-side
Add GET /api/permissions/stale endpoint that returns agent names with
explicit capability/tool-group JSON entries but no live container AND
no kept-state tombstone. Ghost detection is now entirely server-side —
one authoritative call, no client-side roster cache, no staleness window.

The previous client-side approach in core.js made three parallel API
calls (GET /api/capabilities, GET /api/tool-groups, GET /api/state) and
filtered the result against a module-level `liveContainerNames` Set
populated only on cold load and form submits. Any container lifecycle
event (spawn, destroy) while core.html was open left `liveContainerNames`
stale, risking a false-positive ghost entry for a live container.

Changes:
- permissions.rs: add `get_stale_permissions` handler + `StalePermsResponse`
  struct. Computes live roster (containers_snapshot), tombstone set
  (Coordinator::kept_state_names), explicit perm names (capabilities::read
  + tool_groups::read), then returns the difference sorted.
- dashboard.rs: register GET /api/permissions/stale.
- core.js: replace the three-call client-side logic in
  `fetchAndRenderStalePerms` with a single fetch to /api/permissions/stale.
  Remove `liveContainerNames` state + its syncFromSnapshot population.
2026-06-28 23:29:51 +02:00
iris
31433da3aa fix(permissions): propagate I/O errors as 500 from delete_agent_permissions
Both remove_agent() calls now run unconditionally for maximum partial
cleanup, but any I/O error is returned as HTTP 500 instead of silently
200-ing — so the frontend's !resp.ok path fires and the operator sees a
meaningful error rather than the stale row reappearing unchanged.

Also add a clarifying comment on isStale in permissions.js explaining
that containersState is keyed from nixos-container list (which includes
stopped-but-configured containers), so a temporarily-stopped agent is
not treated as stale — only destroyed/renamed agents are absent.
2026-06-27 13:44:11 +02:00
iris
a8fb33e2ee fix(permissions): mark stale agents and allow removing their explicit entries
The P3RM1SS10NS tab showed agents that no longer exist in the live
container roster — e.g. an agent named 'root' that was renamed or
destroyed but still had explicit entries in tool-groups.json and/or
capabilities.json. The roster-union behaviour is intentional for
temporarily-stopped agents, but stale entries from renamed/destroyed
agents are confusing.

Backend (dashboard/permissions.rs):
- New DELETE /api/permissions/{agent} handler that bypasses the live-
  roster guard (intentionally — that's the point). Calls
  tool_groups::remove_agent + capabilities::remove_agent to clear both
  JSON files, then emits live SSE snapshots so the tab updates without
  a page reload. Format-checks the agent name but does not require it to
  be in the containers snapshot.

Frontend (permissions.js):
- renderCapabilities / renderToolGroups now cross-reference agentNames
  against containersState (the live roster, already imported). Agents
  not in the live roster get an isStale flag.
- Stale rows get a '(not running)' label and a '✕ remove' button that
  calls clearStaleAgent() — a new async helper that DELETEs the stale
  entry and re-fetches both perm tables.
- Non-stale agents without explicit assignments still get '(default)'.

CSS (dashboard.css):
- .perm-row-stale (reduced opacity), .perm-stale-label (muted small
  text), .perm-remove-btn (small red-bordered button) + disabled state.
2026-06-27 13:44:11 +02:00
damocles
65ad994c85 dashboard: return problem details directly from client-error handlers 2026-06-22 16:04:22 +02:00
damocles
2b0c51badf inline problem_details builder at call sites; drop the one-caller wrapper 2026-06-22 16:04:22 +02:00
damocles
5dc1b3933a return accurate http status codes for dashboard client errors 2026-06-22 16:04:22 +02:00
damocles
8e24814efe feat(dashboard): batch POST /api/permissions for save-all perms (#1719) 2026-06-17 18:21:56 +02:00
damocles
789ecd86f6 fix(#1661): show default-perms agents with effective values in perms tab 2026-06-14 21:20:03 +02:00
damocles
7ade5f27ea refactor(#1456): extract dashboard permission endpoints into dashboard/permissions.rs 2026-06-09 00:12:15 +02:00