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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions