Skip to content

Frontend: replace role selector with required group multi-select + permission-derived gating (follow-up to #907) #913

Description

@cristim

Follow-up to #907 / PR #912 (backend group-membership-only authorization).

The backend now derives all authorization from group membership and no longer returns user.role (the users.role / sessions.role columns are dropped by migration 000057). The frontend still gates on currentUser.role (see frontend/src/auth.ts isAdmin() ~L20/L921/L934, frontend/src/permissions.ts getRolePermissions() / isAdmin()), so admin UI gating and permission derivation will break against the new API.

Scope

  1. Create/edit-user form: replace the role selector with a required group multi-select (>= 1 group, sensible default preselected; cannot submit empty). Submit groups: string[] instead of role.
  2. Permission-derived UI gating: switch isAdmin() and viewer/operator gating to derive from the user's effective group permissions (membership in the Administrators group, fixed UUID 00000000-0000-5000-8000-000000000001, or the {admin, *} capability) instead of user.role.
  3. Types: drop role from the user/session TS types; add groups: string[] (the API field is groups, no omitempty).
  4. Tests: update frontend/src/__tests__/users.test.ts, auth.test.ts, permissions-related and recommendations-permissions tests to the group/permission model; keep coverage flat or better.

Deployment ordering (important)

PR #912 must not be deployed to an environment whose frontend still reads user.role. Ship this follow-up together with #912 (or merge #912 then this, and deploy only after both land).

Backend reference for the effective-permission contract: internal/auth/service_group.go (HasPermission, UserHasAdminCapability), internal/api/types.go (User.Groups), internal/auth/service_api.go (APIUser.Groups).

Activity

  1. cristim commented on Jul 27, 2026

    @cristim
    MemberAuthor

    Verification sweep against main (101f099fb) on 2026-07-27 finds this already resolved.
    The role selector has been replaced by a required groups multi-select, and isAdmin() now derives from group membership.
    Evidence: commit fa1603f (#914).
    Recommending close.

  2. cristim commented on Sep 2, 2026

    @cristim
    MemberAuthor

    Verified resolved at 3c0f8ac: the create/edit-user form uses a required multi-select of groups, isAdmin() and permission gating derive from Administrators-group membership or the admin capability rather than user.role, and the user/session TS types no longer carry a role field. Evidence: frontend/src/permissions.ts:144-204, frontend/src/auth.ts:21, frontend/src/index.html:1060 (#914). Residual axes checked: remaining user.role reads in frontend/src (none outside comments), role field in TS types (none), getRolePermissions callers (test-only). Closing as completed; reopen if the behaviour recurs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions