Backend:
- _list_groups(): reads /etc/group, returns groups with gid >= 1000
plus a small whitelist (root, staff, sambashare, www-data)
- GET/POST /api/groups: list and create groups (groupadd)
- DELETE /api/groups/<name>: delete group (groupdel)
- POST /api/groups/<name>/members: add user to group (gpasswd -a)
- DELETE /api/groups/<name>/members/<user>: remove user (gpasswd -d)
Frontend:
- Users tab now has a Groups section: table with GID, member badges
with × remove buttons, per-row "add member" select populated with
users not already in the group, delete group button
- loadUsers() caches result in _cachedUsers for groups table to use
- openEditModal is now async; fetches /api/users + /api/groups before
rendering so Owner and Group inputs have datalist autocomplete
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>