Files
pad/internal
xarmian 9b2234fce6 fix(workspaces): scope admin's personal workspace list to memberships (BUG-982) (#392)
handleListWorkspaces special-cased server admins, routing them through
an unfiltered store query that returned every non-deleted workspace
regardless of membership. The admin's "switcher" therefore showed
workspaces they had no member row in, labeled "shared with me" by the
frontend even though they weren't actually shared. Filed in BUG-982 by
the admin who saw the leak; the underlying mechanism would have leaked
workspace metadata to any future server admin.

The fix routes admins through the same GetUserWorkspaces path as every
other authenticated user. Cross-tenant visibility for admins is still
available via the admin-panel routes (/api/v1/admin/...), which call
ListWorkspaces() directly with the appropriate auth gate — that's the
correct surface for "see all workspaces on this server."

Drive-by cleanups along the way:

- Add ws.HydrateDerivedFields() to both branches of GetUserWorkspaces
  (member + guest) for parity with the admin path's previous behavior.
  Workspace context fields now hydrate consistently across all callers.
- Delete the unused ListWorkspacesForUser store function. Its name
  implied per-user filtering, its body returned every workspace — pure
  footgun for any future code that grepped by name. Inline the
  no-userID branch into ListWorkspaces() (still used by the admin
  panel and pre-auth bootstrap).

OUT OF SCOPE — handled by a follow-up Plan parented to PLAN-259
(Security Review):

  middleware_auth.go:449 still grants server admins implicit `owner`
  role on every workspace they navigate to. This PR closes the
  *listing* leak so admins no longer see workspaces in their switcher.
  It does NOT yet address the deeper concern in BUG-982's body — that
  on pad-cloud, admin access to other tenants should require an
  explicit auditable escalation flow (confirmation, audit log entry,
  owner notification, time-bound session, visible escalation banner).
  That's design-heavy and gets its own Plan.

Tests: new internal/server/handlers_workspaces_test.go verifies that
an admin who is NOT a member of a workspace does not see it in their
listing, and that adding them as an explicit member restores
visibility. Sister test confirms the existing non-admin behavior is
unchanged. Both pass on SQLite and on Postgres via make test-pg.
Full ./internal/server and ./internal/store suites stay green.
2026-05-03 00:35:31 -04:00
..
2026-03-26 01:52:36 +00:00