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
- 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.
- 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.
- Types: drop
role from the user/session TS types; add groups: string[] (the API field is groups, no omitempty).
- 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).
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(theusers.role/sessions.rolecolumns are dropped by migration000057). The frontend still gates oncurrentUser.role(seefrontend/src/auth.tsisAdmin()~L20/L921/L934,frontend/src/permissions.tsgetRolePermissions()/isAdmin()), so admin UI gating and permission derivation will break against the new API.Scope
groups: string[]instead ofrole.isAdmin()and viewer/operator gating to derive from the user's effective group permissions (membership in the Administrators group, fixed UUID00000000-0000-5000-8000-000000000001, or the{admin, *}capability) instead ofuser.role.rolefrom the user/session TS types; addgroups: string[](the API field isgroups, noomitempty).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).