refactor: extract organization-workspace-access role#25929
Conversation
665e852 to
39cfee3
Compare
3aa1a66 to
79be71f
Compare
39cfee3 to
c23f308
Compare
79be71f to
989d98f
Compare
c23f308 to
a75eca2
Compare
989d98f to
5253fe8
Compare
23745e1 to
8dc7f14
Compare
8dc7f14 to
e62737a
Compare
e62737a to
6aef7c0
Compare
| // orgWorkspaceAccess grants the workspace-operations | ||
| // capabilities org members need to use their workspaces. | ||
| // See OrgWorkspaceAccessMemberPerms for the perm set. | ||
| orgWorkspaceAccess: func(organizationID uuid.UUID) Role { | ||
| return Role{ | ||
| Identifier: RoleIdentifier{Name: orgWorkspaceAccess, OrganizationID: organizationID}, | ||
| DisplayName: "Organization Workspace Access", | ||
| Site: []Permission{}, | ||
| User: []Permission{}, | ||
| ByOrgID: map[string]OrgPermissions{ | ||
| organizationID.String(): { | ||
| Org: []Permission{}, | ||
| Member: OrgWorkspaceAccessMemberPerms(), | ||
| }, | ||
| }, | ||
| } | ||
| }, |
There was a problem hiding this comment.
This role will be viewable once this merges. Even though it's a subset of member today.
Hiding it until the split feels like a lot of work for what will likely ship in the same release.
And regardless, having it available early could be useful to configure before the split is adopted. As the split will have to be some opt-in behavior.
…Accounts Adds the column that drives per-org Gateway Accounts behavior. Effective roles for an org member at request time are now the union of organization_members.roles and organizations.default_org_member_roles, so changes to the org default propagate to every member on the next request. The deployment-wide default is 'organization-workspace-access', matching today's effective behavior. The PATCH organization handler accepts the new field but rejects deviations from the deployment default unless the minimum-implicit-member experiment is enabled. The experiment constant ships in this PR so the write-gating has something to check; the floor shrink behavior lands in a follow-up. Refs #25936. Stacks on #25929.
…Accounts Adds the column that drives per-org Gateway Accounts behavior. Effective roles for an org member at request time are now the union of organization_members.roles and organizations.default_org_member_roles, so changes to the org default propagate to every member on the next request. The deployment-wide default is 'organization-workspace-access', matching today's effective behavior. The PATCH organization handler accepts the new field but rejects deviations from the deployment default unless the minimum-implicit-member experiment is enabled. The experiment constant ships in this PR so the write-gating has something to check; the floor shrink behavior lands in a follow-up. Refs #25936. Stacks on #25929.
…Accounts Adds the column that drives per-org Gateway Accounts behavior. Effective roles for an org member at request time are now the union of organization_members.roles and organizations.default_org_member_roles, so changes to the org default propagate to every member on the next request. The deployment-wide default is 'organization-workspace-access', matching today's effective behavior. The PATCH organization handler accepts the new field but rejects deviations from the deployment default unless the minimum-implicit-member experiment is enabled. The experiment constant ships in this PR so the write-gating has something to check; the floor shrink behavior lands in a follow-up. Refs #25936. Stacks on #25929.
…Accounts Adds the column that drives per-org Gateway Accounts behavior. Effective roles for an org member at request time are now the union of organization_members.roles and organizations.default_org_member_roles, so changes to the org default propagate to every member on the next request. The deployment-wide default is 'organization-workspace-access', matching today's effective behavior. The PATCH organization handler accepts the new field but rejects deviations from the deployment default unless the minimum-implicit-member experiment is enabled. The experiment constant ships in this PR so the write-gating has something to check; the floor shrink behavior lands in a follow-up. Refs #25936. Stacks on #25929.
…Accounts Adds the column that drives per-org Gateway Accounts behavior. Effective roles for an org member at request time are now the union of organization_members.roles and organizations.default_org_member_roles, so changes to the org default propagate to every member on the next request. The deployment-wide default is 'organization-workspace-access', matching today's effective behavior. The PATCH organization handler accepts the new field but rejects deviations from the deployment default unless the minimum-implicit-member experiment is enabled. The experiment constant ships in this PR so the write-gating has something to check; the floor shrink behavior lands in a follow-up. Refs #25936. Stacks on #25929.
6aef7c0 to
fb33230
Compare
5253fe8 to
f1ebc42
Compare
eafa7f5 to
0d366d9
Compare
0d366d9 to
fa7e9f9
Compare
|
/coder-agents-review |
|
Chat: Review in progress | View chat deep-review v0.6.1 | Round 1 | Last posted: Round 1, 10 findings (1 P2, 3 P3, 1 P4, 3 Nit, 2 Note), COMMENT. Review Finding inventoryFindings
Round logRound 1Panel (19 reviewers: bisky, chopper, ging-go, gon, hisoka, kite, knov, kurapika, leorio, luffy, mafu-san, mafuuu, melody, meruem, pariston, razor, robin, ryosuke, zoro). Netero first pass clean (1 P4, 1 Note). Panel: 1 P2, 3 P3, 3 Nit, 2 Note. CRF-1 not posted (P4, pre-panel). Reviewed against b9c3eea..fa7e9f9. About deep-reviewCRF = Coder Review Finding (P0-P4, Nit, Note)
|
There was a problem hiding this comment.
Clean role extraction. OrgWorkspaceAccessMemberPerms() is defined once and consumed by all three callers (standalone role, OrgMemberPermissions, OrgServiceAccountPermissions). Permission equivalence verified: slices.Concat(elevation, floor) produces the same 42 permissions across 12 resource types as the pre-refactor flat memberPerms. Assignment matrix correctly expanded for system, owner, userAdmin, orgAdmin, orgUserAdmin. All RBAC tests pass.
1 P2, 3 P3, 3 Nit, 2 Note.
"Just a function that returns permissions. That's it. That's the whole feature." Luffy
PS. Commit scope coderd/rbac doesn't contain all changed files (codersdk/rbacroles.go, enterprise/coderd/roles_test.go). Per project convention, omit the scope for cross-cutting changes.
🤖 This review was automatically generated with Coder Agents.
e9a3bd8 to
15e4f90
Compare
32809ee to
ecdc5f1
Compare
| // Should be able to add the prebuilds system user as a member to any organization that needs prebuilds. | ||
| rbac.ResourceOrganizationMember.Type: { | ||
| policy.ActionRead, | ||
| policy.ActionCreate, | ||
| }, | ||
| // Needs to be able to assign roles to the system user in order to make it a member of an organization. | ||
| rbac.ResourceAssignOrgRole.Type: { | ||
| policy.ActionAssign, | ||
| }, |
There was a problem hiding this comment.
This is unfortunate, but with default roles, we need to escalate to the System context when making the prebuild user.
ecdc5f1 to
b7ec31f
Compare
c746ace to
eeadd81
Compare
Introduce the organization-workspace-access role and split the member and service-account perms into a floor plus an elevation set. The elevation lives in the new OrgWorkspaceAccessMemberPerms helper and is mirrored onto the new role; both OrgMemberPermissions and OrgServiceAccountPermissions compose floor + elevation today, so this PR is behavior-preserving. A future PR will gate the elevation on the minimum-implicit-member experiment so a user without organization-workspace-access has only the floor. Org admins, owners, user admins, and the system role can assign the new role. The helper carries the same "Intentionally omitted at Member scope" rationale as the prior enumeration so that owner-less resources (e.g. ResourceTemplate, ResourceWorkspaceProxy) are not re-added by mistake. TestRolePermissions adds an org_workspace_access subject to requiredSubjects so the role's coverage is asserted in every test case. This catches accidental Org/Member swaps in the role wiring (e.g. attaching the perm set to Org instead of Member). The prebuilds membership reconciler now wraps its InsertOrganizationMember call with dbauthz.AsSystemRestricted instead of relying on the AsPrebuildsOrchestrator context. The prebuilds system user does not log in or act with its assigned roles; the membership row only exists so prebuilt workspaces have a valid owner. Routing the assignment check through the system actor keeps the call working when the experiment splits workspace ops off organization-member, and removes the dependency on prebuildsOrchestrator's assignable role map.
eeadd81 to
010e350
Compare

Refs PLAT-217.
Extracts an
organization-workspace-accessrole so workspace elevation can be split off the organization-member floor without changing behavior.organization-member.MinimumImplicitMemberfloor preserves the existing behavior until feat(coderd): gate org-member workspace elevation behind experiment #26027 shrinks it.dbauthz.AsSystemRestrictedand no longer needsOrganizationMemberorAssignOrgRolegrants.Agent context
coderd/rbac/roles.go:OrgWorkspaceAccessMemberPerms()grantsWorkspace,WorkspaceDormant,File(Create+Read),ProvisionerDaemon(Create+Read), andTask. Deliberate omissions (Template,Group,WorkspaceProxy, etc.) are documented inline.coderd/rbac/roles_test.go:orgWorkspaceAccessUseris added torequiredSubjects.UserProvisionerDaemonsis split intoUserProvisionerDaemonsCreateandUserProvisionerDaemonsUpdateDeletebecause the new role grants Create+Read only and the test framework requires uniform pass/fail per case.codersdk/rbacroles.go: exposesRoleOrganizationWorkspaceAccess.enterprise/coderd/prebuilds/membership.go:InsertOrganizationMemberruns underdbauthz.AsSystemRestricted. The orchestrator never acts with the elevation role; the membership row only exists so prebuilt workspaces have a valid owner.coderd/database/dbauthz/dbauthz.go: drops the now-deadOrganizationMemberandAssignOrgRolepermissions from the prebuilds-orchestrator role and the orchestrator's entry inassignRoles.Coder Agents on behalf of @Emyrk.