Return org _capabilities for UI permission checks
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 44.8k
- Forks
- 4.9k
- Avg merge
- 21h 23m
- Merged PRs (30d)
- 607
Description
Summary
The frontend recomputes permission decisions (for example project creation) from scopes, org flags, and team roles. That logic drifts from the API. A server-computed _capabilities map on the org payload would let the UI read one field instead of reimplementing access rules.
Current behavior
- Org serializers expose
accessas a flat scope list whenaccess=request.accessis passed (src/sentry/api/serializers/models/organization.py). - They also expose policy flags such as
allowMemberProjectCreation(org setting, not "this caller can create"). - Projects/teams already return computed
hasAccess+ per-objectaccess. - UI still stacks scopes + flags + team admin locally, e.g.
static/app/components/projects/canCreateProject.tsxviauseCanCreateProject. - Project create API rules live separately:
- Org create:
POSTscopesproject:read|write|admin, then deny when member creation is disabled unlessorg:write. - Team create:
POSTscopesproject:write|admin, with a per-teamteam:adminescape when member creation is disabled.
- Org create:
Gap
- UI and API permission models already diverge (scopes checked,
org:writebypass, team-admin path). - Every new org-level action risks another client-side recreation of server rules.
accessis the wrong place to extend: it is a public scope array, not a capability map.
Related work this would improve
- https://github.com/getsentry/sentry/pull/121727 — backend: stop requiring
organizations:team-rolesfor project create; default-allow member project creation for new orgs - https://github.com/getsentry/sentry/pull/121797 — frontend follow-up removing the same
team-rolesgate fromcanCreateProjectand the membership settings toggle - Both still leave create eligibility recomputed in the client from scopes/flags/teams
Proposed shape (discussion)
Add a private sibling field on the detailed/org session serializer (not inside access, not on the user endpoint):
{
"access": ["org:read", "project:read", "team:read"],
"allowMemberProjectCreation": true,
"_capabilities": {
"canCreateProject": true
}
}
Notes:
- Leading underscore marks it as UI/internal; also exclude from public OpenAPI if present on a documented endpoint.
- Compute with the same rules as the create endpoints so UI gating cannot drift.
- Start with
canCreateProject; grow the map only when another UI gate is re-encoding server policy. - Prefer the detailed org bootstrap payload the frontend already stores over the bare public summary.
Requested by David Cramer.
--
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src/sentry/api/serializers/models/organization.py and static/app/components/projects/canCreateProject.tsx, including useCanCreateProject. Compare the serializer's detailed org payload with the org and team project-create rules, then add the proposed _capabilities.canCreateProject value to the detailed bootstrap response so the UI can use it without recomputing permissions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, typescript
- Domain
- api, backend-api-design, frontend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100