fix(api): add project create and codeowners scopes#113122
fix(api): add project create and codeowners scopes#113122dcramer wants to merge 1 commit intodcramer/fix/api-write-scope-mutationsfrom
Conversation
Model project creation and ownership management as dedicated project leaf scopes. Previously, project creation and code ownership flows either relied on broader project scopes or mixed readonly access into write endpoints. Add project:create and project:codeowners, wire them through the bitfield and scope hierarchy, and move the create-project and ownership endpoints to those scopes so the public API contract is explicit. Co-Authored-By: OpenAI Codex <noreply@openai.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 70087ed. Configure here.
| "project:read", | ||
| "project:write", | ||
| "project:admin", | ||
| "project:codeowners", |
There was a problem hiding this comment.
Missing project:create scope breaks non-member role project creation
High Severity
The admin (retired), manager, and owner org roles all have project:write/project:admin but lack explicit project:create in their scopes. The member role is the only one with project:create. Since add_scope_hierarchy is only applied to token scopes and scopes_upper_bound, but NOT to member role scopes (via RpcBackedAccess.scopes), these roles lose the ability to create projects. For session auth, scopes_upper_bound is None so member scopes are used directly. For token auth, the intersection of unexpanded member scopes with the expanded upper bound still excludes project:create. Both TeamProjectPermission and OrgProjectPermission now require project:create for POST, so admins/managers/owners get 403s.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 70087ed. Configure here.
| if request.method == "POST" and request.access.has_scope("project:create"): | ||
| return request.access.has_team_access(team) | ||
|
|
||
| return super().has_object_permission(request, view, team) |
There was a problem hiding this comment.
Early return check uses uninitialized access object
Medium Severity
The has_object_permission override checks request.access.has_scope("project:create") before determine_access has been called. At this point request.access is the default NoAccess() set during request initialization, so has_scope always returns False and this early-return path is unreachable dead code. The determine_access call that properly initializes request.access only happens inside OrganizationPermission.has_object_permission, which is reached via the super() fallthrough.
Reviewed by Cursor Bugbot for commit 70087ed. Configure here.
| "org:read", | ||
| "member:read", | ||
| "project:read", | ||
| "project:codeowners", |
There was a problem hiding this comment.
Team admin role also missing project:create scope
Medium Severity
The team admin role in SENTRY_TEAM_ROLES has project:write and project:admin but lacks project:create. When has_team_scope is checked as a fallback in the permission chain, team-level scopes also won't contain project:create, closing off the last path that could grant project creation access to users whose org-level check already failed.
Reviewed by Cursor Bugbot for commit 70087ed. Configure here.
Backend Test FailuresFailures on
|


Introduce leaf project scopes for project creation and code ownership management.
Previously, project creation and code ownership flows did not have a clean public API scope model. Project creation was either tied to broader project write access or allowed through readonly project access on some flows, and ownership / CODEOWNERS management relied on broader project scopes even when we wanted a narrower capability.
After this change, project creation is modeled as
project:createand ownership / CODEOWNERS management is modeled asproject:codeowners. The standard project creation endpoint and the member bootstrap flow both useproject:create, and the ownership / CODEOWNERS endpoints useproject:codeowners.project:writeandproject:adminimply these leaf scopes through the scope hierarchy, so existing broader tokens continue to work. Member and team role behavior is preserved by granting the new scopes where the session model already allows these actions.This PR also centralizes scope hierarchy handling during permission evaluation so endpoints can name the leaf scope they actually need instead of repeating every parent scope in
scope_map.Refs getsentry/getsentry#19897