diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index cb5660c3..d73131d9 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -276,19 +276,19 @@ The current capabilities are: Each row is one agent. Columns are the capability names returned by `GET /api/capabilities` as `caps: Vec`. Checking or unchecking -boxes changes only the in-browser state; the `S4V3` button on the -right edge POSTs the full capability set for that agent to -`POST /api/capabilities/{agent}` as `{ caps: ["name", …] }` and -queues a rebuild. Absent agents in the assignment map have no extra -capabilities. +boxes only stages the change in-browser; nothing is written until the +page-level **save all** button (described below) is clicked. The +checkboxes reflect the *effective* set (explicit grant or role default), +so a default-perms agent shows its real grants rather than blank; absent +agents in the assignment map have no extra capabilities. **T00L GR0UPS** — per-agent tool-group permissions. Tool groups are named buckets of MCP tools; each agent starts with a role default (agents: `messaging`, `meta`, `inbox`, `execution`; manager: all -groups). Checking / unchecking and saving changes which groups are -active for the agent. Backed by `GET /api/tool-groups` (columns) and -`POST /api/tool-groups/{agent}` (save). A rebuild is queued after -each save so `HIVE_TOOL_GROUPS` takes effect. +groups). Checking / unchecking stages which groups are active for the +agent; the page-level **save all** button (below) commits it. Columns +come from `GET /api/tool-groups`. A rebuild is queued so +`HIVE_TOOL_GROUPS` takes effect. The current tool groups are: `messaging`, `meta`, `inbox`, `lifecycle`, `approvals`, `scheduling`, `diagnostics`, `execution`, `web_tools`. All @@ -300,9 +300,26 @@ agent session. Both tables share the same visual shape: `.cap-table-wrap` / `.tg-table-wrap` outer scroll container, `thead` with a label column (`.cap-agent-col` / `.tg-agent-col`) + one column per permission -(`.cap-col` / `.tg-group-col`) + a save column (`.cap-save-col` / -`.tg-save-col`). Each tbody row is one agent: a name cell, checkbox -cells, and the `S4V3` button. +(`.cap-col` / `.tg-group-col`). Each tbody row is one agent: a name cell +and its checkbox cells, where each checkbox carries `data-baseline` (its +render-time state) and the row carries `data-agent` for dirty-tracking. + +**Saving — one button for the whole page.** There are no per-row save +buttons. A single page-level `.perm-save-bar` with a **save all (N +agents)** button sits at the bottom of the pane, enabled only when some +checkbox diverges from its baseline. Clicking it diffs every checkbox +across *both* matrices and POSTs one batch to `POST /api/permissions` as +`{ changes: [ { agent, tool_groups?, capabilities? } ] }` — only the +perm-types that actually changed for each agent are included (an omitted +field leaves that file untouched; an included array fully replaces it). +The backend coalesces an agent's capabilities + tool-groups into a +single rebuild, so changing both for one agent is one rebuild, not two. +The batch is atomic: it validates every change first and on any error +rejects the whole POST (`{error}`, nothing applied); a clean 200 (`ok`) +flips the bar to a queued→rebuilding state and re-fetches both tables. +Live `capabilities_changed` / `tool_groups_changed` events re-render the +matrices unless the section has unsaved edits, so an in-progress edit set +isn't clobbered. ## SCH3DUL3S tab