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.
This commit is contained in:
parent
6ab0757cc6
commit
4df286345a
3 changed files with 65 additions and 20 deletions
|
|
@ -115,6 +115,10 @@ pub async fn serve(port: u16, coord: Arc<Coordinator>) -> Result<()> {
|
|||
post(permissions::post_capabilities),
|
||||
)
|
||||
.route("/api/permissions", post(permissions::post_permissions))
|
||||
.route(
|
||||
"/api/permissions/stale",
|
||||
get(permissions::get_stale_permissions),
|
||||
)
|
||||
.route(
|
||||
"/api/permissions/{agent}",
|
||||
axum::routing::delete(permissions::delete_agent_permissions),
|
||||
|
|
|
|||
Loading…
Reference in a new issue