Skip to content

feat(api): new membership API for org and suborgs groups#5472

Merged
IgorHorta merged 56 commits intomainfrom
igor/paltfrm-198-new-behaviour
Feb 18, 2026
Merged

feat(api): new membership API for org and suborgs groups#5472
IgorHorta merged 56 commits intomainfrom
igor/paltfrm-198-new-behaviour

Conversation

@IgorHorta
Copy link
Contributor

@IgorHorta IgorHorta commented Feb 13, 2026

Context

Sub-organization groups and project groups previously used legacy group endpoints (e.g. POST/DELETE /groups/:id/link for org link/unlink). We're moving to the new membership API shape {scope}/memberships/{actor-type}/{actor-id} so org and project group membership is consistent and easier to extend.

Before: Org/project groups used a mix of legacy group routes; link/unlink used POST/DELETE /groups/:id/link.
After: Org groups use GET/POST/PATCH/DELETE /api/v1/organizations/memberships/groups (and .../groups/:groupId for PATCH/DELETE). Project groups use .../projects/:projectId/memberships/groups. Link/unlink use the new create/delete org group membership endpoints. Legacy /:id/link routes are removed. Group service fetches membership + group in parallel where both are needed.

Related: PLATFRM-198

Screenshots

Steps to verify the change

  1. Org groups list – In an org (or sub-org), open Groups. Confirm list loads and shows owned + inherited groups.
  2. Org group create/edit/delete – Create a group, rename it, delete it. Confirm all work and list refreshes.
  3. Org group link/unlink – In a sub-org, link an existing group and set role; then unlink. Confirm list and detail update and cache invalidates for the current org.
  4. Project groups – In a project, open Groups. Add a group, change role, remove group. Confirm list and behaviour match expectations.
  5. Sub-org inherited group – In a sub-org, open an inherited group. Confirm name/slug are read-only; only role in this org can be updated.

Type

  • Fix
  • Feature
  • Improvement
  • Breaking
  • Docs
  • Chore

Checklist

  • Title follows the conventional commit format: type(scope): short description (scope is optional, e.g., fix: prevent crash on sync or fix(api): handle null response).
  • Tested locally
  • Updated docs (if needed)
  • Read the contributing guide

@maidul98
Copy link
Collaborator

maidul98 commented Feb 13, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 13, 2026

Greptile Summary

This PR introduces a new membership API shape for org and project group memberships, enabling groups from a parent organization to be linked into sub-organizations. The key changes are:

  • New API endpoints: GET/POST/PATCH/DELETE /api/v1/organizations/memberships/groups and /api/v1/projects/:projectId/memberships/groups for consistent group membership CRUD
  • Linked groups: Sub-orgs can now link groups from their parent org, with proper permission enforcement via a new LinkRootGroup action on the SubOrganization permission subject
  • Effective membership resolution: A new findEffectiveOrgMembership function checks both direct and group-based org access, used across auth login, token validation, SCIM provisioning, and identity services
  • Sub-org cleanup: When unlinking a group or removing a member from a group, project memberships in sub-orgs are cleaned up for actors who no longer have effective access
  • Legacy deprecation: Existing /groups/:id project routes are marked deprecated with pointers to new endpoints; backward compatibility is maintained
  • Frontend: UI updated with "Create New" / "Assign Existing" wizard for sub-org group management, "Managed By" badges, and read-only enforcement for linked groups

Key observations:

  • The permission-dal.ts group subqueries had their orgId filter removed to support linked groups. While functionally correct (outer queries scope correctly), the subqueries now return all groups globally rather than org-scoped, which may affect query performance at scale
  • The cleanUpSubOrgProjectMemberships function runs in a separate transaction from the main group member removal, creating a potential inconsistency window if the cleanup fails
  • Legacy routes are properly deprecated but preserved for backward compatibility — no breaking API changes detected

Confidence Score: 3/5

  • This PR is a large, well-structured feature addition with no breaking API changes, but the complexity of group-linked membership cleanup and permission query broadening warrants thorough integration testing before merge.
  • Score of 3 reflects: (1) no security vulnerabilities or data exposure issues found — OR queries are correctly grouped, permission checks are thorough; (2) one transaction isolation concern in cleanUpSubOrgProjectMemberships that could leave stale data on failure; (3) permission-dal subqueries are unnecessarily broad after orgId filter removal; (4) the 86-file scope with complex multi-org membership logic benefits from comprehensive integration testing to validate edge cases.
  • Pay close attention to backend/src/ee/services/group/group-service.ts (transaction isolation in cleanup), backend/src/ee/services/permission/permission-dal.ts (broadened subqueries), and backend/src/services/org/org-dal.ts (new effective membership resolution).

Important Files Changed

Filename Overview
backend/src/ee/services/group/group-service.ts Major expansion: adds linked-group support, sub-org cleanup, and refactors update/delete logic. Transaction isolation concern with cleanUpSubOrgProjectMemberships running outside the main operation's tx.
backend/src/ee/services/permission/permission-dal.ts Removes orgId filter from group subqueries to support linked groups from parent orgs. Safe due to outer query scoping, but subqueries are now overly broad (returning ALL groups globally instead of org-scoped).
backend/src/server/routes/v1/organization-memberships-router.ts New router for org group memberships (CRUD). Well-structured with proper auth, rate limiting, and Zod validation. Minor: create/update handlers make two service calls without shared atomicity.
backend/src/server/routes/v1/project-group-memberships-router.ts New router for project group memberships. Clean implementation with proper auth modes and validation schemas.
backend/src/services/membership-group/membership-group-dal.ts Adds findEffectiveInOrg query and exposes group orgId in membership queries. The orWhereIn usage in findEffectiveInOrg is correctly grouped within a .where callback.
backend/src/services/membership-group/org/org-membership-group-factory.ts Enables org group membership create/delete for sub-orgs with proper permission checks (LinkRootGroup, privilege boundary validation).
backend/src/services/org/org-dal.ts Adds findEffectiveOrgMembership/s with group-based access resolution. Sub-org listing now considers group-based access. OR queries are correctly grouped in callbacks.
backend/src/ee/services/scim/scim-service.ts Properly updated to use findEffectiveOrgMembership with correct handling of three cases: no membership, direct membership, and group-only access (creates direct membership for SCIM compatibility).
backend/src/ee/services/group/group-dal.ts Adds listAvailableGroups and getGroupsReferencingGroup. findByOrgId correctly scopes by membership rather than group.orgId to support linked groups.
backend/src/services/auth/auth-login-service.ts Switches to findEffectiveOrgMembership for sub-org login and org-slug resolution. Now correctly checks isActive for slug-based org selection.
backend/src/services/auth-token/auth-token-service.ts Switches to findEffectiveOrgMembership for token validation. Correctly adds status filter for accepted memberships.
backend/src/services/identity-access-token/identity-access-token-service.ts Switches to findEffectiveOrgMembership for identity access token validation. Clean refactor.
backend/src/services/user/user-service.ts Properly handles group-only membership edge cases for project favorites (returns empty array for group-only access, blocks updates).
backend/src/services/group-project/group-project-dal.ts Updated to use membership-based group visibility. Changed join to leftJoin for orgMembership with null-safe isActive fallback.
backend/src/ee/services/permission/org-permission.ts Adds LinkRootGroup action to SubOrganization permissions. Granted to admin by default. Clean addition.
frontend/src/hooks/api/organization/queries.tsx Switches to new /organizations/memberships/groups endpoint with proper response mapping. organizationId parameter now used only for cache keying.
frontend/src/hooks/api/projects/mutations.tsx Switches to new /projects/:id/memberships/groups endpoints. Clean URL migration.
backend/src/server/routes/v1/group-project-router.ts Existing routes correctly marked as deprecated with pointers to new endpoints. Backward compatible.

Last reviewed commit: 58ea679

@IgorHorta IgorHorta changed the title Igor/paltfrm 198 new behaviour feat(api): new membership API for org and project groups Feb 13, 2026
@IgorHorta IgorHorta requested a review from akhilmhdh February 13, 2026 01:33
Copy link
Member

@akhilmhdh akhilmhdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pending: Application testing

@IgorHorta
Copy link
Contributor Author

@greptile please review this again

@IgorHorta IgorHorta requested a review from akhilmhdh February 13, 2026 23:27
@akhilmhdh
Copy link
Member

Application testing feedbacks

  • Would be great like identity in sub-org group section we have Managed By section in table that says this group is managed by which scope. Like wise in detail view of a group as well.
image
  • Projects are not visible. I have created group with engineering and assign to suborg and then connected to project in suborg. But that project is not listed when i login to that suborg via the user of the group
Screenshot 2026-02-16 at 2 50 14 PM
  • I am not visible in All Projects section as well. This part it's not saying i am part of the project
Screenshot 2026-02-16 at 2 51 51 PM

Please test the sub-org project flow for both user and identity as well. I am able to do the operations but the list ones are broken. I was able to do operations on the project - so it seems only the list is broken. Do it test for identity as well. Do a complete workflow - of creating this, adding groups, consuming operations in a project for both user and identity.

@IgorHorta IgorHorta requested a review from akhilmhdh February 16, 2026 20:45
@IgorHorta IgorHorta changed the title feat(api): new membership API for org and project groups feat(api): new membership API for org and suborgs groups Feb 16, 2026
@akhilmhdh
Copy link
Member

Application Testing Feedback

1. Sub-org project visibility leak from root

Users in a sub-org should not see projects belonging to the root org. Currently, if a group has a project in root, members can see it when viewing the sub-org.

Screenshot

Screenshot

2. Machine identity – missing project listing fix

The project listing fix was not applied to machine identities. They still show the old behavior.

Screenshot

Screenshot

3. Empty membership list for group-created projects in sub-org

When a project is created in a sub-org where access comes solely through group membership, the project's member listing appears empty — no users are shown.

Screenshot

Screenshot

4. Group deletion failing

Deleting a group throws an error. The use of raw in the query is unclear, and there appears to be a reference to a non-existent column.

Screenshot

Screenshot

5. Group re-linking restores previously removed project access

Steps to reproduce: Link a group from root → add a project → remove the group → re-add the group.
Result: All previously removed projects reappear.
Expected: Project membership cleanup should persist through group removal/re-addition.

Screenshot

Screenshot

6. User retains direct project membership after losing suborg access

When a user's only link to a sub-org (via a group) is removed, their direct project memberships in that sub-org are not cleaned up. When the group is re-added, those memberships resurface. Project membership should be revoked when the user's last access path to the org/sub-org is removed.

Also ensure this cleanup happens for identities as well as it's not happening for the same reason

Screenshot

Screenshot

IgorHorta and others added 15 commits February 17, 2026 14:10
- Phase 1: Org/project group list includes orgId; frontend hides edit for inherited groups
- Cache: useUpdateGroup/useDeleteGroup accept organizationId to invalidate current org list
- Phase 2: Frontend uses new membership endpoints (org + project)
- Deprecate legacy routes in docs; new routes note restructure + retrocompatibility
- Fix ESLint unused destructuring in group mutations
- Backend: project-group-memberships allows optional group.orgId

Co-authored-by: Cursor <cursoragent@cursor.com>
@IgorHorta IgorHorta force-pushed the igor/paltfrm-198-new-behaviour branch from ad35ce6 to 516bf92 Compare February 17, 2026 17:19
@IgorHorta IgorHorta requested a review from akhilmhdh February 17, 2026 17:55
IgorHorta and others added 2 commits February 17, 2026 23:36
- Add findEffectiveInOrg to membership-group-dal for checking remaining
  org access (direct + group-based) after excluding specific memberships
- Rewrite unlinkGroupFromSubOrg to collect all membership IDs and delete
  in a single batch instead of incremental deletes
- Fix missing scope=Organization filter that caused project memberships
  to be counted as effective org access, preventing cleanup
- Extract deleteOwnedGroup and unlinkGroupFromSubOrg as separate methods
  for readability
- Remove unused ActorType import and findEffectiveOrgMembership from
  orgDAL Pick type

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… from group

When a user or identity is removed from a group that is linked to sub-orgs,
their direct project memberships in those sub-orgs are now cleaned up if they
no longer have effective org access (direct or through another linked group).
@akhilmhdh
Copy link
Member

@greptile this pr has made a lot of changes from your last review. Do a complete review once more

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

86 files reviewed, 8 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 18, 2026

Additional Comments (2)

backend/src/ee/services/permission/permission-dal.ts
Same over-broad subquery issue for identity groups

Same concern as getProjectUserPermissions: after removing the orgId filter, the identityGroupSubquery now returns ALL group IDs in the database. While the outer query still scopes correctly, consider narrowing this subquery to groups with an org-level membership in the target org for better query performance.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!


backend/src/services/group-project/group-project-dal.ts
Changed join to leftJoin for orgMembership — verify isActive null handling

Changing from join to leftJoin means users who access via linked groups (no direct org membership) will now have isActive = NULL. At line 200, the code defaults this to true (isOrgMembershipActive: isActive ?? true), which is correct. However, other consumers of this data should also handle the null case gracefully. Same change at project-membership-dal.ts:21 — make sure all downstream code handling isOrgMembershipActive tolerates a nulltrue fallback.

@akhilmhdh
Copy link
Member

Good job @IgorHorta

@IgorHorta IgorHorta merged commit bbd1842 into main Feb 18, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants