refactor(membership): stop writing org owner/member relations - #1812
Conversation
Since the schema stopped reading the owner and member relations on organizations (#1809), writing them on every membership change is dead work. Stop writing them: - AddOrganizationMember and SetOrganizationMemberRole no longer write or replace org relations. The service user identity link (serviceuser#org@organization) is still written — the schema reads it to resolve the manage permission. - Groups always write the member relation now, never owner. The member relation stays because role grants to a group flow through group#member. This also fixes a real bug: a role granted to a group never reached the group's own owner, because owners got an owner relation instead of member. Group owners now receive group-granted roles like every other member. - Group role changes migrate a legacy owner relation to member. - linkGroupToOrg no longer writes organization#member@group#member; it granted nothing after the schema change. The removal paths still delete it (and the org owner/member relations) so members and groups from before this change leave no stale data behind. - Delete the orgRoleToRelation/groupRoleToRelation mapping helpers. The relations stay declared in the schema until the existing tuples are cleaned up; SpiceDB cannot drop a relation while data references it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Tested live on a local Frontier (Postgres + SpiceDB) running this branch, using a real org with users covering each path. All checks via 1. Adding an org member writes no links. Added a fresh user as org viewer. The Relations API shows zero 2. Group owners now receive group-granted roles (the bug fix). New group, made the user its Team Owner, granted the group 3. Org role change works with no link step. Promoted a viewer to owner — policy replaced, nothing else written, access correct. 4. Group role change works with no link step. The 5. Removal cleans up fully. Removed the user from the org: group member link, role bindings, everything gone; org and project access denied afterwards. Also reproduced the bug itself end to end: with the old-style Unit tests updated to match: no expectations on org link writes, group add asserts a |
|
Warning Review limit reached
Next review available in: 11 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughOrganization membership flows now update policies without organization relation writes. Group memberships consistently use member relations, migrate legacy owner tuples, and simplify group-to-organization linking. Tests update relation expectations and rollback coverage. ChangesMembership relation changes
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
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.
🧹 Nitpick comments (1)
core/membership/service.go (1)
1316-1401: 🚀 Performance & Scalability | 🔵 TrivialGroup member relation migration looks correct.
Always writing
schema.MemberRelationNameon add, and migrating only the legacyOwnerRelationNametoMemberRelationNameon role change, matches the PR's stated intent that all group members (including owners) carry the member relation while cleaning up legacy owner tuples.One minor note: on the promotion path (member → owner),
replaceRelationwill unconditionally re-Createthe member relation even though the principal already holds it (only the owner relation is inoldRelations). This is presumably harmless if the underlyingRelationService.Createis idempotent/touch-semantics against SpiceDB (which the tests assume), but worth a quick sanity check ifCreateever surfaces a "duplicate relationship" error.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: cde9e66c-340d-4508-9156-ab4a2a9c9ee8
📒 Files selected for processing (2)
core/membership/service.gocore/membership/service_test.go
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Coverage Report for CI Build 30350730670Coverage decreased (-0.04%) to 46.901%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
The member relation is created when the principal joins the group and never changes shape after that, so a role change has no relation work. Existing owner relations get converted to member in the data cleanup, not lazily per request. Delete the now-unused replaceRelation helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Tested this live on a local server built from this branch, with a fresh org and SpiceDB tuples checked directly in the datastore after each step.
Listing calls exercised: One pre-existing quirk (not from this PR): 🤖 Generated with Claude Code |
What this is
Part 2 of removing relation-based ownership, following #1809. That PR made the schema stop reading the
ownerandmemberlinks on orgs and groups; this one makes the membership paths stop writing them. The split was planned from the start: reading had to stop first so that a rollback of either PR never leaves anyone without access.Changes
managepermission.)memberlink, whatever the role. That link is not a permission grant — it is how roles granted to the group (e.g. a project role) fan out to the people in it, which is why it stays. A role change inside the group touches only the policy.ownerlink instead ofmember, so roles granted to the group never reached the group's own owner. Group owners now receive group-granted roles like every other member.Behavior change to be aware of: group owners gain access through roles granted to their group. They were wrongly excluded before.
🤖 Generated with Claude Code