Skip to content

resource memberships#1478

Merged
swaroopAkkineniWorkos merged 17 commits intoENT-4372-base-authorization-branchfrom
ENT-4372-list-memberships-for-resource
Feb 13, 2026
Merged

resource memberships#1478
swaroopAkkineniWorkos merged 17 commits intoENT-4372-base-authorization-branchfrom
ENT-4372-list-memberships-for-resource

Conversation

@swaroopAkkineniWorkos
Copy link
Contributor

@swaroopAkkineniWorkos swaroopAkkineniWorkos commented Feb 11, 2026

linear: https://linear.app/workos/issue/ENT-4372/sdk-updates

I decided to break up the work for ENT-4372 into a smaller pr's that we can be easily reviewed and merge them into ENT-4372-base-authorization-branch. Then we can have one final merge that merges ENT-4372-base-authorization-branch into the main.

desc: the goal of this pr is to implement the following endpoints in the node sdk.

listResourcesForMembership() | GET /authorization/organization_memberships/{om_id}/resources
listMembershipsForResource() | GET /authorization/resources/{resource_id}/organization_memberships
listMembershipsForResourceByExternalId() | GET /authorization/organizations/{org_id}/resources/{type}/{external_id}/organization_memberships

listResourcesForMembership() ~ https://github.com/workos/workos/blob/main/packages/api/src/authorization/authorization.controller.ts#L221
listOrganizationMembershipsForResource() ~ https://github.com/workos/workos/blob/main/packages/api/src/authorization-resources/authorization-resources.controller.ts#L411
listOrganizationMembershipsForResourceByExternalId() ~ https://github.com/workos/workos/blob/main/packages/api/src/authorization-resources/authorization-resources-by-external-id.controller.ts#L135

@linear
Copy link

linear bot commented Feb 11, 2026

ENT-4372 SDK Updates

Base automatically changed from ENT-4372-Internal-ID to ENT-4372-base-authorization-branch February 11, 2026 19:12
@swaroopAkkineniWorkos swaroopAkkineniWorkos force-pushed the ENT-4372-list-memberships-for-resource branch from 7e6cf0e to 1740ace Compare February 12, 2026 16:56
@swaroopAkkineniWorkos
Copy link
Contributor Author

@greptile review plz

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.

12 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@workos workos deleted a comment from greptile-apps bot Feb 12, 2026
@workos workos deleted a comment from greptile-apps bot Feb 12, 2026
@swaroopAkkineniWorkos
Copy link
Contributor Author

@greptile re-review plz. Look at the api implementation linked in the description as part of your review. The sdk should implement calling them

@swaroopAkkineniWorkos swaroopAkkineniWorkos marked this pull request as ready for review February 12, 2026 20:12
@swaroopAkkineniWorkos swaroopAkkineniWorkos requested a review from a team as a code owner February 12, 2026 20:12
@swaroopAkkineniWorkos swaroopAkkineniWorkos requested review from atainter, csrbarber and hadihallak and removed request for a team February 12, 2026 20:12
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 12, 2026

Greptile Overview

Greptile Summary

Implements three new endpoints for querying relationships between organization memberships and resources:

  • listResourcesForMembership() - retrieves resources accessible to a membership with a specific permission
  • listMembershipsForResource() - retrieves memberships that have access to a resource with a specific permission (by internal resource ID)
  • listMembershipsForResourceByExternalId() - same as above but using external resource identifiers

Key Implementation Details:

  • All methods follow existing SDK patterns for pagination, serialization, and deserialization
  • Proper TypeScript typing with separate response and deserialized interfaces
  • Union type used for listResourcesForMembership to support either internal ID or external ID for parent resource
  • Comprehensive test coverage including pagination, edge cases, and optional parameters
  • Authorization-specific AuthorizationOrganizationMembership type introduced to handle simplified membership data (without role information)

Code Quality:

  • Consistent with existing codebase patterns and conventions
  • No security concerns (no SQL, CORS, or logging of sensitive data)
  • Proper null coalescing for optional fields like customAttributes

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation follows established SDK patterns precisely, includes comprehensive test coverage for all three new methods and their edge cases, and introduces no security concerns. The code is well-structured with proper TypeScript typing and consistent with the existing authorization module architecture.
  • No files require special attention

Important Files Changed

Filename Overview
src/authorization/authorization.ts Added three new list methods for querying resource-membership relationships. Implementation follows existing patterns correctly with proper serialization/deserialization.
src/authorization/authorization.spec.ts Comprehensive test coverage for all three new methods including edge cases, pagination, and optional parameters.
src/authorization/interfaces/organization-membership-list.interface.ts Defines authorization-specific organization membership types with proper response/deserialized pairs.
src/authorization/serializers/list-resources-for-membership-options.serializer.ts Correctly serializes options to API format, handling union type with proper conditional logic.
src/authorization/serializers/list-memberships-for-resource-options.serializer.ts Serializer shared between both membership query methods with proper optional field handling.

Sequence Diagram

sequenceDiagram
    participant Client as SDK Client
    participant SDK as Authorization Module
    participant API as WorkOS API

    Note over Client,API: listResourcesForMembership Flow
    Client->>SDK: listResourcesForMembership(organizationMembershipId, permissionSlug, parent...)
    SDK->>SDK: serializeListResourcesForMembershipOptions()
    SDK->>API: GET /authorization/organization_memberships/{om_id}/resources
    API-->>SDK: AuthorizationResourceListResponse
    SDK->>SDK: deserializeAuthorizationResource() for each item
    SDK-->>Client: AuthorizationResourceList

    Note over Client,API: listMembershipsForResource Flow
    Client->>SDK: listMembershipsForResource(resourceId, permissionSlug)
    SDK->>SDK: serializeListMembershipsForResourceOptions()
    SDK->>API: GET /authorization/resources/{resource_id}/organization_memberships
    API-->>SDK: AuthorizationOrganizationMembershipListResponse
    SDK->>SDK: deserializeAuthorizationOrganizationMembership() for each item
    SDK-->>Client: AuthorizationOrganizationMembershipList

    Note over Client,API: listMembershipsForResourceByExternalId Flow
    Client->>SDK: listMembershipsForResourceByExternalId(orgId, typeSlug, externalId, permissionSlug)
    SDK->>SDK: serializeListMembershipsForResourceOptions()
    SDK->>API: GET /authorization/organizations/{org_id}/resources/{type}/{external_id}/organization_memberships
    API-->>SDK: AuthorizationOrganizationMembershipListResponse
    SDK->>SDK: deserializeAuthorizationOrganizationMembership() for each item
    SDK-->>Client: AuthorizationOrganizationMembershipList
Loading

Last reviewed commit: 2eefd57

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.

12 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

};
}

export interface AuthorizationOrganizationMembership {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we already have types for organization membership because it's used with the organization memberships API. It uses the same JSON type so we should probably use the same interface.


export interface OrganizationMembershipList {
object: 'list';
data: OrganizationMembership[];
Copy link
Contributor

Choose a reason for hiding this comment

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

// test this
async removeRole(options: RemoveRoleOptions): Promise<void> {
await this.workos.delete(
await this.workos.deleteWithBody(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed to deleteWithBody because the delete role assignment API expects the identifying fields in the request body, and delete() doesn't send a body.

https://github.com/workos/workos/blob/1bf21e074e2cde476d83660ca41e05853fa081b8/packages/api/src/authorization/authorization-role-assignments.controller.ts#L205

AuthorizationOrganizationMembershipResponse,
} from '../interfaces/organization-membership-list.interface';

export const deserializeAuthorizationOrganizationMembership = (
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be in the userland package for base organization membership

}

export interface AuthorizationOrganizationMembershipResponse extends BaseOrganizationMembershipResponse {
organization_name?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should remove this because authz doesn't use it

options: ListResourcesForMembershipOptions,
): SerializedListResourcesForMembershipOptions => ({
permission_slug: options.permissionSlug,
...(options.limit !== undefined && { limit: options.limit }),
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a common helper for the pagination params?

}

export interface OrganizationMembershipResponse extends BaseOrganizationMembershipResponse {
organization_name: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be in the base

@swaroopAkkineniWorkos swaroopAkkineniWorkos merged commit bfc197d into ENT-4372-base-authorization-branch Feb 13, 2026
8 checks passed
@swaroopAkkineniWorkos swaroopAkkineniWorkos deleted the ENT-4372-list-memberships-for-resource branch February 13, 2026 15:12
swaroopAkkineniWorkos added a commit that referenced this pull request Feb 13, 2026
Adding these endpoints to the sdk
#1471
```
getResource()    ~ GET /authorization/resources/{resource_id}
createResource() ~ POST /authorization/resources
updateResource() ~ PATCH /authorization/resources/{resource_id}
deleteResource() ~ DELETE /authorization/resources/{resource_id}
```
#1473
```
check() | POST /authorization/organization_memberships/{om_id}/check
```
#1472
```
listResources()               | GET /authorization/organizations/{org_id}/resources

getResourceByExternalId()     | GET /authorization/organizations/{org_id}/resources/{type}/{external_id}
updateResourceByExternalId()  | PATCH /authorization/organizations/{org_id}/resources/{type}/{external_id}
deleteResourceByExternalId()  | DELETE /authorization/organizations/{org_id}/resources/{type}/{external_id}
```
#1474
```
listRoleAssignments() | GET /authorization/organization_memberships/{om_id}/role_assignments
assignRole() | POST /authorization/organization_memberships/{om_id}/role_assignments
removeRole() | DELETE /authorization/organization_memberships/{om_id}/role_assignments
removeRoleAssignment() | DELETE /authorization/organization_memberships/{om_id}/role_assignments/{ra_id}
```
#1478
```
listResourcesForMembership() | GET /authorization/organization_memberships/{om_id}/resources
listMembershipsForResource() | GET /authorization/resources/{resource_id}/organization_memberships
listMembershipsForResourceByExternalId() | GET /authorization/organizations/{org_id}/resources/{type}/{external_id}/organization_memberships
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants