dashboard: single save-all button for the permissions page

Replace the per-row save buttons on the P3RM1SS10NS tab with one
page-level "save all (N agents)" button covering both the capabilities
and tool-groups matrices.

Toggling cells stages edits in the DOM; each checkbox carries its
render-time baseline (data-baseline). On save we diff against the
baseline and POST only the perm-types that actually changed per agent
to the new combined endpoint:

  POST /api/permissions { changes: [ { agent, tool_groups?, capabilities? } ] }

An omitted field leaves that perm-type untouched (no commit, no diff);
an included array fully replaces it. The backend coalesces caps + groups
for one agent into a single rebuild — no more double-rebuild when an
operator changes both for the same agent. The batch is atomic: on a
clean 200 the bar shows queued -> rebuilding and re-fetches (resetting
baselines); on any validation error nothing is applied and an error note
is shown.

Live capabilities_changed / tool_groups_changed re-renders are skipped
while the section has unsaved edits so a half-finished edit set is not
clobbered; the tab-activation and post-save re-fetches are the recovery
paths.

Pairs with the hive-c0re combined-PermPayload half (damocles).
This commit is contained in:
iris 2026-06-17 17:53:03 +02:00 committed by mara
commit 4297436d94
4 changed files with 208 additions and 91 deletions

View file

@ -27,6 +27,7 @@ import { fmtAgo, truncate, fmtElapsed, fmtDuration } from './util.js';
import {
applyCapabilitiesChanged, applyToolGroupsChanged,
fetchAndRenderCapabilities, fetchAndRenderToolGroups,
initPermissions,
} from './permissions.js';
import {
applySchedulesChanged, applyRemindersChanged,
@ -1524,6 +1525,7 @@ window.marked = marked;
// activation as a safety net for any gap between SSE events and
// the cold-load snapshot.
if (target === 'permissions') {
initPermissions();
fetchAndRenderCapabilities();
fetchAndRenderToolGroups();
}