Skip to content

Align service user and PAT org-level access with the user membership model #1544

@whoAbhishekSah

Description

@whoAbhishekSah

Problem

When a user is added to an org, they get both a policy (role binding — viewer/manager/owner) and an explicit relation (org#member or org#owner). This gives them role-based permissions and makes them visible in member listings.

Service users and PATs don't follow this model, creating inconsistencies.

Three principals, three different org-level role patterns

Principal RPC Roles Mode Relation path Policy Visible in listings
User SetOrganizationMemberRole 1 role Replace granted Yes Yes
PAT CreatePAT / UpdatePAT N roles via []PATScope Replace all pat_granted Yes N/A (separate listing)
Service User CreateServiceUser None N/A Direct member only No No

Service Users

  • On creation (CreateServiceUser), only gets a direct org#member relation — no policy, no role
  • The serviceuser.Service struct doesn't even have a PolicyService dependency
  • Invisible to policy-based member listing (e.g., ListOrganizationUsers won't show them with roles)
  • Has no org-level role permissions (can't manage projects, roles, billing via policy path)
  • Only gets basic get and membership via the direct member relation
  • Project-level access works fine via SetProjectMemberRole which already supports principalType: app/serviceuser

PATs

  • Access flows through pat_granted on the org (not granted) — a completely separate relation path
  • Accepts multiple roles via []PATScope — different from the user model which enforces single role
  • Project access is granted at the org level via pat_granted rolebindings, not at the project level
  • Different from both users and service users

SpiceDB schema

The schema already supports org-level policies for both service users and PATs — no changes needed:

definition app/rolebinding {
    relation bearer: app/user | app/group#member | app/serviceuser | app/pat
    relation role: app/role
}

Both app/serviceuser and app/pat can be bearers on rolebindings.

Proposed direction

Service users

  • Allow AddOrganizationMember and SetOrganizationMemberRole in the membership package to accept app/serviceuser as a principal type
  • Validate via serviceUserService.Get (check exists + check su.OrgID == orgID) instead of userService.GetByID
  • On CreateServiceUser, optionally call membership.AddOrganizationMember to create both policy + relation (instead of just the relation)
  • This brings service users into the same single-role replace model as users

PATs

  • PATs use pat_granted instead of granted on orgs — fundamentally different relation path
  • Accepts multiple roles per scope — different from the single-role model for users
  • Project access for PATs is granted at the org level (via org's synthetic project_* permissions), not at the project level
  • Needs separate analysis — may need a dedicated function rather than reusing the user membership functions

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions