Role permission saves and bulk download counts fixed (QA)
Executive summary
Promotes two correctness fixes from development into the QA environment. The first stops the admin Roles screen from silently discarding a role's permissions when its permission list spans multiple pages, and makes the Roles grid refresh immediately after any change. The second corrects the bulk-download progress counter, which was showing "NaN files updated" instead of the actual count of files downloaded.
Why this was needed
Two distinct defects reached users on development. In Admin, editing a role with more than one page of assigned permissions rebuilt the permission list from only the visible page and sent it as a full replacement, so every permission on other pages was silently dropped on save; separately, the Roles grid kept showing stale rows after a save until a hard page refresh. In Mail, the bulk ZIP download progress panel displayed "NaN files updated" on success because the completion event omits count fields and the copy always said "updated" regardless of operation.
Client / user impact
- Admin users can edit roles with many permissions across multiple pages without accidentally losing assignments on pages they did not view.
- The Roles grid now reflects create, edit, delete, and permission changes immediately, no manual refresh needed.
- The bulk download progress panel shows an accurate count with the correct wording ("N files downloaded"), instead of the confusing "NaN files updated".
- Bulk status updates and batch uploads continue to read "updated" and "processed" respectively.
Technical scope
Scope is small and frontend-only (8 files, +89/-45), covering two feature PRs:
PR #974 — admin role permissions + grid staleness:
RoleFormDialognow sends the backend's incremental{ add_permission_ids, remove_permission_ids }payload instead of reconstructing a fullpermission_idslist from one paginated page.AssignRolePermissionsRequesttype and the Zod schema were narrowed to the incremental shape so the unsafe full-replacement payload is no longer representable.- Introduced a 2-segment
ROLES_LIST_KEY(["admin", "roles-list"]) prefix and routed all role mutations (create/update/delete/assign) through it, fixing a TanStack Query key mismatch ("roles"vs"roles-list") that left the grid stale; removed the dialog's redundant invalidation calls. - Removed an unused export and refreshed stale JSDoc/route comments.
PR #971 — bulk ZIP download count:
useJobProgressSocketnow guards count fields so only finite numeric values overwrite state, preventing a partial WebSocket completion event from cachingNaN.BulkOperationProgressderives an explicitactionVerbper operation type (downloaded/processed/updated) for both the counter and the minimized summary.
Risk & mitigation
Low. Changes are confined to the admin Roles dialog/mutations and the Mail bulk-progress UI; no backend or shared-package changes. The permission payload switch depends on the backend supporting the incremental add/remove fields (verified against the dev API per the commit notes). A separate, unrelated backend issue (DSM_Backend_dev#144) — the bulk ZIP endpoint not honoring the workspace-tenant header for enterprise-filtered downloads — is out of scope and unaffected by this UI fix.
QA validation focus
- Roles (Admin): Edit a role with permissions spanning more than one page, toggle some on/off across pages, save; confirm no page's assignments are silently dropped and the count is correct.
- Confirm the Roles grid updates without a hard refresh after edit, create, delete, and permission changes.
- Confirm the "cannot remove admin access if no other admin role exists" guard still triggers.
- Bulk download (Mail): On /inbox apply an Enterprise filter, select-all, Download; confirm the counter reads "N files downloaded" (not "NaN files updated") and the minimized summary reads "Download complete — file downloaded".
- Regression: bulk status update still reads "N mails updated"; batch upload still reads "N files processed".