feat: implement SetProjectMemberRole RPC#1481
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a server-side RPC to set a project member's role and implements end-to-end support: service logic, Connect handler, interface/mocks, tests, domain errors, authorization entry, and updates Makefile PROTON_COMMIT. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 1 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/project/service_test.go (1)
23-35:⚠️ Potential issue | 🟠 MajorAdd direct unit tests for
SetMemberRolebehavior (currently missing).This update wires new dependencies, but the new project-member role mutation path is not covered here. Please add focused tests for role validation, non-member handling, and last-owner protection to reduce regression risk in the new RPC path.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 56252940-859b-4c10-83dd-9b50d88a457e
⛔ Files ignored due to path filters (3)
proto/v1beta1/frontier.pb.gois excluded by!**/*.pb.go,!proto/**proto/v1beta1/frontier.pb.validate.gois excluded by!proto/**proto/v1beta1/frontierv1beta1connect/frontier.connect.gois excluded by!proto/**
📒 Files selected for processing (12)
Makefilecmd/serve.gocore/project/errors.gocore/project/mocks/policy_service.gocore/project/mocks/role_service.gocore/project/service.gocore/project/service_test.gointernal/api/v1beta1connect/errors.gointernal/api/v1beta1connect/interfaces.gointernal/api/v1beta1connect/mocks/project_service.gointernal/api/v1beta1connect/project.gopkg/server/connect_interceptors/authorization.go
Pull Request Test Coverage Report for Build 23882133908Details
💛 - Coveralls |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
core/project/service.go (1)
360-363:⚠️ Potential issue | 🟠 MajorThe last-owner invariant is gone.
Demoting the only direct owner now succeeds and leaves the project with zero project-scoped owners. That regresses the owner-constraint behavior this RPC is supposed to preserve; if org-level fallback is intentionally replacing that invariant, the contract/tests need to change too.
Also applies to: 377-390
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7a3f72ab-6cdf-4e25-beb2-3c66806bc560
📒 Files selected for processing (3)
core/project/errors.gocore/project/service.gointernal/api/v1beta1connect/project.go
🚧 Files skipped from review as they are similar to previous changes (2)
- core/project/errors.go
- internal/api/v1beta1connect/project.go
There was a problem hiding this comment.
♻️ Duplicate comments (1)
core/project/service.go (1)
362-402:⚠️ Potential issue | 🟠 MajorUse the resolved project ID (
prj.ID) consistently.Lines 380 and 396 use the raw
projectIDparameter instead ofprj.ID. Sinces.Get()at line 366 resolves both UUIDs and names, passing a project name will cause the policy filter and create operations to use the name string instead of the canonical UUID.🐛 Proposed fix
existingPolicies, err := s.policyService.List(ctx, policy.Filter{ - ProjectID: projectID, + ProjectID: prj.ID, PrincipalID: principalID, PrincipalType: principalType, }) @@ _, err = s.policyService.Create(ctx, policy.Policy{ RoleID: newRoleID, - ResourceID: projectID, + ResourceID: prj.ID, ResourceType: schema.ProjectNamespace, PrincipalID: principalID, PrincipalType: principalType, })
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: c2d62ec5-29b5-4805-9f36-2c26ab203e72
⛔ Files ignored due to path filters (2)
proto/v1beta1/frontier.pb.gois excluded by!**/*.pb.go,!proto/**proto/v1beta1/frontier.pb.validate.gois excluded by!proto/**
📒 Files selected for processing (9)
Makefilecore/project/errors.gocore/project/mocks/group_service.gocore/project/mocks/serviceuser_service.gocore/project/service.gocore/project/service_test.gointernal/api/v1beta1connect/interfaces.gointernal/api/v1beta1connect/mocks/project_service.gointernal/api/v1beta1connect/project.go
🚧 Files skipped from review as they are similar to previous changes (3)
- Makefile
- internal/api/v1beta1connect/project.go
- core/project/errors.go
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
core/project/service_test.go (1)
59-60: Remove redundant_ = roleServiceno-op assignments.These lines add noise and can be dropped since
roleServiceis passed toproject.NewService(...)in the same scope.Also applies to: 77-78, 122-123, 140-141
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d83355dc-3728-44ea-b279-794bb4b06969
📒 Files selected for processing (3)
core/project/service.gocore/project/service_test.gopkg/server/connect_interceptors/authorization.go
✅ Files skipped from review due to trivial changes (1)
- pkg/server/connect_interceptors/authorization.go
🚧 Files skipped from review as they are similar to previous changes (1)
- core/project/service.go
E2E Test Results — 29/29 PASSTested on a clean database (fresh Frontier + SpiceDB) with users at different permission levels. Happy Path — 9/9 PASS
Authorization — 7/7 PASS
A2: Org admin (app_organization_manager) is correctly allowed — the role has cascading project update permission via the authz model. A3/A6: Project viewer correctly denied on a clean SpiceDB instance. Previous local testing showed false positives due to stale SpiceDB permission relations from the additive-only Validation — 13/13 PASS
|
d48a848 to
606a863
Compare
c0191e0 to
790192f
Compare
790192f to
2d16d2d
Compare
2d16d2d to
273767e
Compare
273767e to
ff832b5
Compare
Add handler, service, and authorization for atomically setting a principal's role in a project. Supports user, service user, and group principals. - Validates principal exists and belongs to the project's org - Validates role has project scope (app/project) - Authorization checks update permission on the project - No minimum-owner constraint (project access can come from org-level) - 14 unit tests covering all validation and success paths Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ff832b5 to
d2048ff
Compare
Summary
SetProjectMemberRoleRPC for atomic role assignment on project membersprincipal_id+principal_typeapp/project)updatepermission on the project (consistent withCreatePolicyForProject)Closes #1461 (partially —
RemoveProjectMemberwill be a separate PR)Proton PR: raystack/proton#456
Test plan
🤖 Generated with Claude Code