screentinker/server
ScreenTinker 2872b883c7 feat(admin): manage a user's workspace memberships (multi + per-workspace role)
The Workspace column on the platform Users page could only move a 0/1-workspace
user and showed a dead "N workspaces" label for multi-membership users. Replace
it with a "Manage workspaces" modal that handles the full picture.

Backend (routes/admin.js, requirePlatformAdmin):
- GET    /api/admin/users/:id/workspaces            list memberships (+org/ws names, role)
- POST   /api/admin/users/:id/workspaces            add to a workspace (upsert role)
- PUT    /api/admin/users/:id/workspaces/:wsId      change role in a workspace
- DELETE /api/admin/users/:id/workspaces/:wsId      remove (last one allowed -> unassigned)
Roles validated against WORKSPACE_ROLES; each mutation writes an audit row.

Frontend:
- Workspace cell is now a summary (Unassigned / <name> / N workspaces /
  "Platform (all)" for staff) + a Manage button.
- New admin-user-workspaces-modal: lists every membership with an inline role
  dropdown + Remove, plus a type-to-filter "Add to workspace" picker (org-grouped,
  excludes current memberships) with a role select. Staff get a note that they
  already have platform-wide access. Refreshes the table on close if changed.
- Removed the old single-select inline move control (superseded by the modal).

Tests: 6 added (add to multiple workspaces, per-workspace role change, upsert,
remove incl. last->unassigned, validation 400/404, non-platform-admin 403).
Full suite 33/33. Verified headless: Manage opens, lists memberships, filtered
picker, add/role-change/remove round-trips persist (throwaway user, cleaned up).
2026-06-08 16:24:52 -05:00
..
config fix: log real client IPs through Cloudflare instead of CF edge 2026-05-07 15:26:37 -05:00
db fix(db): cascade tenant resources on workspace/org delete (#18 follow-up) 2026-06-08 16:01:52 -05:00
lib fix(db): cascade tenant resources on workspace/org delete (#18 follow-up) 2026-06-08 16:01:52 -05:00
middleware feat(admin): admin-provisioned user creation + first-login gate (#10) 2026-06-05 11:03:56 -05:00
player security(widgets): add sandbox="allow-scripts" to widget iframes 2026-05-28 12:28:34 -05:00
routes feat(admin): manage a user's workspace memberships (multi + per-workspace role) 2026-06-08 16:24:52 -05:00
services feat(signup): T+3 activation nudge for users with zero paired screens 2026-05-30 20:28:24 -05:00
test feat(admin): manage a user's workspace memberships (multi + per-workspace role) 2026-06-08 16:24:52 -05:00
ws fix(proof-of-play): throttle play_logs writes to prevent runaway bloat 2026-06-02 09:52:22 -05:00
.gitignore feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
config.js feat(signup): optional org-on-create for self-service signups (#12) 2026-06-05 11:16:27 -05:00
package-lock.json feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
package.json test(admin): node:test coverage for Add User + role gating 2026-06-05 11:23:06 -05:00
server.js feat(admin): admin-provisioned user creation + first-login gate (#10) 2026-06-05 11:03:56 -05:00