Skip to content

feat!: standardize authorization list endpoint pagination#1553

Merged
gjtorikian merged 9 commits intomainfrom
node-sdk-authorization-list-fix
Apr 17, 2026
Merged

feat!: standardize authorization list endpoint pagination#1553
gjtorikian merged 9 commits intomainfrom
node-sdk-authorization-list-fix

Conversation

@swaroopAkkineniWorkos
Copy link
Copy Markdown
Contributor

@swaroopAkkineniWorkos swaroopAkkineniWorkos commented Apr 15, 2026

Description

Authorization endpoints weren’t using the shared pagination types, which automatically set order='desc'. Because of this, the authorization methods defaulted to PaginationOrder=normal, causing the next page to return a before cursor instead of after.

Also adds listEffectivePermissions methods.

Summary by CodeRabbit

  • Refactor
    • List endpoints now use a unified paginated flow; legacy list response types removed.
  • New Features
    • Added paginated effective-permissions listing, including lookup by external identifier.
  • Bug Fixes / Tests
    • Expanded test coverage for list endpoints, pagination, and explicit order behavior (defaults to descending).
  • Chores
    • Added fixtures and request-serialization support for the new listing options.

@swaroopAkkineniWorkos
Copy link
Copy Markdown
Contributor Author

@greptile review plz

@swaroopAkkineniWorkos swaroopAkkineniWorkos changed the title moar node sdk stuff feat: standardize authorization list endpoint pagination Apr 15, 2026
@workos workos deleted a comment from greptile-apps bot Apr 15, 2026
@workos workos deleted a comment from greptile-apps bot Apr 15, 2026
@swaroopAkkineniWorkos
Copy link
Copy Markdown
Contributor Author

@greptile re-review plz

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 15, 2026

Greptile Summary

This PR standardizes authorization list endpoints to use the shared AutoPaginatable / fetchAndDeserialize pattern, which automatically applies order: 'desc' as the default (fixing the bug where endpoints defaulted to a normal pagination order that returned before cursors instead of after). It also removes legacy bespoke list types and adds two new paginated methods: listEffectivePermissions and listEffectivePermissionsByExternalId.

The implementation is correct: path parameters are properly extracted into endpoint URLs, and only pagination options flow through to query strings. Test coverage is thorough across all refactored methods.

Confidence Score: 5/5

Safe to merge — the pagination bug fix is correctly implemented and all findings are minor style suggestions.

No P0 or P1 issues found. The core fix (defaulting to desc order via fetchAndDeserialize/setDefaultOptions) is correct, path params are properly isolated to endpoint URLs, and the new listEffectivePermissions methods follow the established pattern correctly. All remaining observations are P2.

No files require special attention.

Important Files Changed

Filename Overview
src/authorization/authorization.ts Refactors all list methods to use AutoPaginatable/fetchAndDeserialize and adds listEffectivePermissions + listEffectivePermissionsByExternalId; path params correctly extracted into endpoint URLs, serialized options carry only pagination fields.
src/authorization/serializers/list-effective-permissions-options.serializer.ts New thin serializer delegating entirely to serializePaginationOptions; correct since path params are consumed by endpoint construction in authorization.ts.
src/authorization/interfaces/list-effective-permissions-options.interface.ts New interface extending PaginationOptions with organizationMembershipId and resourceId; correctly typed.
src/authorization/interfaces/list-effective-permissions-by-external-id-options.interface.ts New interface extending PaginationOptions with organizationMembershipId, organizationId, resourceTypeSlug, externalId; correctly typed.
src/authorization/authorization.spec.ts Extensive test additions covering default desc order, explicit asc/desc order for all refactored list methods; listEffectivePermissionsByExternalId tests are slightly less thorough (missing explicit asc/desc order tests).
src/authorization/interfaces/permission.interface.ts Removes legacy PermissionList and PermissionListResponse in favour of the shared AutoPaginatable pattern.
src/authorization/interfaces/role-assignment.interface.ts Removes legacy RoleAssignmentList and RoleAssignmentListResponse; clean deletion.
src/authorization/interfaces/authorization-resource.interface.ts Removes legacy AuthorizationResourceList and AuthorizationResourceListResponse; clean deletion.
src/user-management/interfaces/organization-membership.interface.ts Removes AuthorizationOrganizationMembershipList and AuthorizationOrganizationMembershipListResponse; clean deletion with correct retention of the response type alias.
src/authorization/fixtures/list-effective-permissions.json New test fixture for effective permissions list; matches the Permission interface structure correctly.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant Authorization
    participant fetchAndDeserialize
    participant setDefaultOptions
    participant WorkOS API

    Caller->>Authorization: listEffectivePermissions(options)
    Authorization->>Authorization: extract path params → endpoint URL
    Authorization->>Authorization: serializeListEffectivePermissionsOptions(options) → pagination-only Record
    Authorization->>fetchAndDeserialize: (workos, endpoint, deserializePermission, serializedOptions)
    fetchAndDeserialize->>setDefaultOptions: options (may lack order)
    setDefaultOptions-->>fetchAndDeserialize: { ...options, order: options.order || 'desc' }
    fetchAndDeserialize->>WorkOS API: GET endpoint?order=desc&...
    WorkOS API-->>fetchAndDeserialize: ListResponse<PermissionResponse>
    fetchAndDeserialize-->>Authorization: List<Permission>
    Authorization->>Caller: AutoPaginatable<Permission>

    Note over Caller,WorkOS API: autoPagination() calls apiCall({...options, limit:100, after:cursor}), captured endpoint closure reuses same URL
Loading

Reviews (6): Last reviewed commit: "prettier" | Re-trigger Greptile

@atainter atainter marked this pull request as ready for review April 15, 2026 21:18
@atainter atainter requested review from a team as code owners April 15, 2026 21:18
@atainter atainter requested a review from cmatheson April 15, 2026 21:18
@gjtorikian gjtorikian changed the title feat: standardize authorization list endpoint pagination feat!: standardize authorization list endpoint pagination Apr 15, 2026
@gjtorikian gjtorikian changed the title feat!: standardize authorization list endpoint pagination fix!: standardize authorization list endpoint pagination Apr 17, 2026
…ce tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 17, 2026

📝 Walkthrough

Walkthrough

Refactors authorization list APIs to return AutoPaginatable, adds two effective-permissions list endpoints and their serializers/options interfaces, removes several list-specific interfaces, adds a fixture for effective permissions, and updates tests to use a unified result response and assert pagination/order behavior.

Changes

Cohort / File(s) Summary
Authorization implementation & tests
src/authorization/authorization.ts, src/authorization/authorization.spec.ts
List endpoints refactored to fetchAndDeserialize + AutoPaginatable<T>; added listEffectivePermissions and listEffectivePermissionsByExternalId; tests updated to consume a single result object and assert default/explicit order and pagination/search behavior.
New option interfaces
src/authorization/interfaces/list-effective-permissions-options.interface.ts, src/authorization/interfaces/list-effective-permissions-by-external-id-options.interface.ts, src/authorization/interfaces/index.ts
Added ListEffectivePermissionsOptions and ListEffectivePermissionsByExternalIdOptions and re-exported them from the interfaces index.
New serializer & re-export
src/authorization/serializers/list-effective-permissions-options.serializer.ts, src/authorization/serializers/index.ts
Added serializeListEffectivePermissionsOptions and re-exported it from the serializers index.
Removed list interfaces
src/authorization/interfaces/permission.interface.ts, src/authorization/interfaces/role-assignment.interface.ts, src/authorization/interfaces/authorization-resource.interface.ts, src/user-management/interfaces/organization-membership.interface.ts
Deleted deprecated list-specific interfaces and response variants (e.g., *List, *ListResponse) for permissions, role assignments, authorization resources, and organization memberships.
Test fixture
src/authorization/fixtures/list-effective-permissions.json
Added fixture containing a serialized list response for effective permissions (two permission objects and list_metadata).
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is brief but adequately conveys the core issue (pagination cursor defaults) and the fix (standardizing to shared pagination types). However, it is missing the Documentation section required by the template. Add the Documentation section from the template to indicate whether WorkOS Docs (API Reference or code snippets) require updates for the new listEffectivePermissions methods.
✅ Passed checks (2 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title 'feat!: standardize authorization list endpoint pagination' directly and clearly describes the main change—refactoring authorization list endpoints to use standardized pagination, which is the core objective of the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch node-sdk-authorization-list-fix

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/authorization/authorization.ts`:
- Around line 444-529: The helpers listResourcesForMembership,
listMembershipsForResource, and listMembershipsForResourceByExternalId currently
pass the full options bag (including path identifiers) into their serializer
functions (serializeListResourcesForMembershipOptions,
serializeListMembershipsForResourceOptions); update each function to destructure
and remove path params first—organizationMembershipId, resourceId,
organizationId, resourceTypeSlug, externalId—and then call the corresponding
serializer with only the remaining query options so path identifiers cannot be
encoded into the query string.
- Around line 239-257: The AutoPaginatable change made list responses
non-enumerable and breaks callers expecting a plain { object, data, listMetadata
} shape; update listPermissions (and other authz list methods) to return a plain
enumerable object instead of exposing AutoPaginatable internals: either (A)
convert the AutoPaginatable instance into a plain object before returning (e.g.,
construct and return { object: 'list', data: autoPaginatable.list, listMetadata:
autoPaginatable.listMetadata, ...options }), or (B) modify AutoPaginatable in
src/common/utils/pagination.ts to expose enumerable data and listMetadata (or
implement a toJSON()/toPlainObject() that returns the original shape) and call
that from listPermissions; reference the listPermissions function and the
AutoPaginatable class in pagination.ts when making the change so the returned
value preserves the old enumerable shape.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f9a3fcec-848f-4477-94a1-949c6865ea50

📥 Commits

Reviewing files that changed from the base of the PR and between c7a5804 and c1497e2.

📒 Files selected for processing (6)
  • src/authorization/authorization.spec.ts
  • src/authorization/authorization.ts
  • src/authorization/interfaces/authorization-resource.interface.ts
  • src/authorization/interfaces/permission.interface.ts
  • src/authorization/interfaces/role-assignment.interface.ts
  • src/user-management/interfaces/organization-membership.interface.ts
💤 Files with no reviewable changes (4)
  • src/authorization/interfaces/authorization-resource.interface.ts
  • src/authorization/interfaces/permission.interface.ts
  • src/authorization/interfaces/role-assignment.interface.ts
  • src/user-management/interfaces/organization-membership.interface.ts

Comment on lines 239 to 257
async listPermissions(
options?: ListPermissionsOptions,
): Promise<PermissionList> {
const { data } = await this.workos.get<PermissionListResponse>(
'/authorization/permissions',
{ query: options },
): Promise<AutoPaginatable<Permission>> {
return new AutoPaginatable(
await fetchAndDeserialize<PermissionResponse, Permission>(
this.workos,
'/authorization/permissions',
deserializePermission,
options,
),
(params) =>
fetchAndDeserialize<PermissionResponse, Permission>(
this.workos,
'/authorization/permissions',
deserializePermission,
params,
),
options,
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

AutoPaginatable changes the runtime shape of these list responses.

This no longer returns a plain { object, data, listMetadata } object. In src/common/utils/pagination.ts:1-63, AutoPaginatable stores list, apiCall, and options as own instance fields, while data and listMetadata are prototype getters. So spreads, Object.keys(), and JSON serialization will behave differently for listPermissions() and the other converted authz list methods, which is a broader breaking change than the pagination fix itself. Please preserve the old enumerable shape or hide the internal fields before shipping this conversion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/authorization/authorization.ts` around lines 239 - 257, The
AutoPaginatable change made list responses non-enumerable and breaks callers
expecting a plain { object, data, listMetadata } shape; update listPermissions
(and other authz list methods) to return a plain enumerable object instead of
exposing AutoPaginatable internals: either (A) convert the AutoPaginatable
instance into a plain object before returning (e.g., construct and return {
object: 'list', data: autoPaginatable.list, listMetadata:
autoPaginatable.listMetadata, ...options }), or (B) modify AutoPaginatable in
src/common/utils/pagination.ts to expose enumerable data and listMetadata (or
implement a toJSON()/toPlainObject() that returns the original shape) and call
that from listPermissions; reference the listPermissions function and the
AutoPaginatable class in pagination.ts when making the change so the returned
value preserves the old enumerable shape.

Comment on lines 444 to +529
async listResourcesForMembership(
options: ListResourcesForMembershipOptions,
): Promise<AuthorizationResourceList> {
): Promise<AutoPaginatable<AuthorizationResource>> {
const { organizationMembershipId } = options;
const { data } = await this.workos.get<AuthorizationResourceListResponse>(
`/authorization/organization_memberships/${organizationMembershipId}/resources`,
{
query: serializeListResourcesForMembershipOptions(options),
},
const endpoint = `/authorization/organization_memberships/${organizationMembershipId}/resources`;
const serializedOptions =
serializeListResourcesForMembershipOptions(options);
return new AutoPaginatable(
await fetchAndDeserialize<
AuthorizationResourceResponse,
AuthorizationResource
>(
this.workos,
endpoint,
deserializeAuthorizationResource,
serializedOptions,
),
(params) =>
fetchAndDeserialize<
AuthorizationResourceResponse,
AuthorizationResource
>(this.workos, endpoint, deserializeAuthorizationResource, params),
serializedOptions,
);
return {
object: 'list',
data: data.data.map(deserializeAuthorizationResource),
listMetadata: {
before: data.list_metadata.before,
after: data.list_metadata.after,
},
};
}

async listMembershipsForResource(
options: ListMembershipsForResourceOptions,
): Promise<AuthorizationOrganizationMembershipList> {
): Promise<AutoPaginatable<AuthorizationOrganizationMembership>> {
const { resourceId } = options;
const { data } =
await this.workos.get<AuthorizationOrganizationMembershipListResponse>(
`/authorization/resources/${resourceId}/organization_memberships`,
{
query: serializeListMembershipsForResourceOptions(options),
},
);
return {
object: 'list',
data: data.data.map(deserializeAuthorizationOrganizationMembership),
listMetadata: {
before: data.list_metadata.before,
after: data.list_metadata.after,
},
};
const endpoint = `/authorization/resources/${resourceId}/organization_memberships`;
const serializedOptions =
serializeListMembershipsForResourceOptions(options);
return new AutoPaginatable(
await fetchAndDeserialize<
AuthorizationOrganizationMembershipResponse,
AuthorizationOrganizationMembership
>(
this.workos,
endpoint,
deserializeAuthorizationOrganizationMembership,
serializedOptions,
),
(params) =>
fetchAndDeserialize<
AuthorizationOrganizationMembershipResponse,
AuthorizationOrganizationMembership
>(
this.workos,
endpoint,
deserializeAuthorizationOrganizationMembership,
params,
),
serializedOptions,
);
}

async listMembershipsForResourceByExternalId(
options: ListMembershipsForResourceByExternalIdOptions,
): Promise<AuthorizationOrganizationMembershipList> {
): Promise<AutoPaginatable<AuthorizationOrganizationMembership>> {
const { organizationId, resourceTypeSlug, externalId } = options;
const { data } =
await this.workos.get<AuthorizationOrganizationMembershipListResponse>(
`/authorization/organizations/${organizationId}/resources/${resourceTypeSlug}/${externalId}/organization_memberships`,
{
query: serializeListMembershipsForResourceOptions(options),
},
);
return {
object: 'list',
data: data.data.map(deserializeAuthorizationOrganizationMembership),
listMetadata: {
before: data.list_metadata.before,
after: data.list_metadata.after,
},
};
const endpoint = `/authorization/organizations/${organizationId}/resources/${resourceTypeSlug}/${externalId}/organization_memberships`;
const serializedOptions =
serializeListMembershipsForResourceOptions(options);
return new AutoPaginatable(
await fetchAndDeserialize<
AuthorizationOrganizationMembershipResponse,
AuthorizationOrganizationMembership
>(
this.workos,
endpoint,
deserializeAuthorizationOrganizationMembership,
serializedOptions,
),
(params) =>
fetchAndDeserialize<
AuthorizationOrganizationMembershipResponse,
AuthorizationOrganizationMembership
>(
this.workos,
endpoint,
deserializeAuthorizationOrganizationMembership,
params,
),
serializedOptions,
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Strip path identifiers before serializing query options.

These helpers encode organizationMembershipId, resourceId, organizationId, resourceTypeSlug, and externalId into the URL, but still pass the full options bag to the serializers. That makes correctness depend on each serializer silently ignoring non-query fields. Destructure the path params first and serialize only the remaining query options so a later serializer change cannot start leaking duplicate query params.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/authorization/authorization.ts` around lines 444 - 529, The helpers
listResourcesForMembership, listMembershipsForResource, and
listMembershipsForResourceByExternalId currently pass the full options bag
(including path identifiers) into their serializer functions
(serializeListResourcesForMembershipOptions,
serializeListMembershipsForResourceOptions); update each function to destructure
and remove path params first—organizationMembershipId, resourceId,
organizationId, resourceTypeSlug, externalId—and then call the corresponding
serializer with only the remaining query options so path identifiers cannot be
encoded into the query string.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/authorization/authorization.ts`:
- Around line 559-581: The function listEffectivePermissionsByExternalId has a
long single-line destructuring that breaks Prettier rules; split the
destructuring across multiple lines (or extract the incoming options to a named
variable before destructuring) to satisfy line-length formatting and re-run
Prettier. Update the const { organizationMembershipId, organizationId,
resourceTypeSlug, externalId } = options; in
listEffectivePermissionsByExternalId so each property sits on its own line (or
perform const opts = options; const organizationId = opts.organizationId; etc.),
then ensure endpoint, serializedOptions (from
serializeListEffectivePermissionsOptions) and the AutoPaginatable call remain
unchanged functionally and pass lint/format checks.

In
`@src/authorization/interfaces/list-effective-permissions-by-external-id-options.interface.ts`:
- Around line 1-9: Prettier formatting errors are present in the
ListEffectivePermissionsByExternalIdOptions interface; run the formatter
(prettier --write) on this file or reformat so import and interface declarations
meet project style (ensure import spacing, line breaks, and indentation around
the export interface ListEffectivePermissionsByExternalIdOptions and its members
organizationMembershipId, organizationId, resourceTypeSlug, externalId follow
Prettier rules).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a8517858-93dc-412c-9e1d-c7081dc3ea6d

📥 Commits

Reviewing files that changed from the base of the PR and between c1497e2 and ab60468.

📒 Files selected for processing (8)
  • src/authorization/authorization.spec.ts
  • src/authorization/authorization.ts
  • src/authorization/fixtures/list-effective-permissions.json
  • src/authorization/interfaces/index.ts
  • src/authorization/interfaces/list-effective-permissions-by-external-id-options.interface.ts
  • src/authorization/interfaces/list-effective-permissions-options.interface.ts
  • src/authorization/serializers/index.ts
  • src/authorization/serializers/list-effective-permissions-options.serializer.ts

Comment thread src/authorization/authorization.ts
@atainter atainter changed the title fix!: standardize authorization list endpoint pagination feat!: standardize authorization list endpoint pagination Apr 17, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
src/authorization/authorization.ts (2)

535-556: 🧹 Nitpick | 🔵 Trivial

Strip path identifiers before serializing effective-permissions query options.

Both helpers embed the identifiers in endpoint, then still pass the full options bag into serializeListEffectivePermissionsOptions(...). That currently works only because the serializer ignores non-pagination fields; a later serializer change could start leaking organizationMembershipId, organizationId, resourceTypeSlug, or externalId into the query string. Destructure ...queryOptions first and serialize only those.

♻️ Proposed fix
   async listEffectivePermissions(
     options: ListEffectivePermissionsOptions,
   ): Promise<AutoPaginatable<Permission>> {
-    const { organizationMembershipId, resourceId } = options;
+    const { organizationMembershipId, resourceId, ...queryOptions } = options;
     const endpoint = `/authorization/resources/${resourceId}/organization_memberships/${organizationMembershipId}/permissions`;
-    const serializedOptions = serializeListEffectivePermissionsOptions(options);
+    const serializedOptions =
+      serializeListEffectivePermissionsOptions(queryOptions);
     return new AutoPaginatable(
       await fetchAndDeserialize<PermissionResponse, Permission>(
         this.workos,
         endpoint,
         deserializePermission,
@@
   async listEffectivePermissionsByExternalId(
     options: ListEffectivePermissionsByExternalIdOptions,
   ): Promise<AutoPaginatable<Permission>> {
     const {
       organizationMembershipId,
       organizationId,
       resourceTypeSlug,
       externalId,
+      ...queryOptions
     } = options;
     const endpoint = `/authorization/organizations/${organizationId}/resources/${resourceTypeSlug}/${externalId}/organization_memberships/${organizationMembershipId}/permissions`;
-    const serializedOptions = serializeListEffectivePermissionsOptions(options);
+    const serializedOptions =
+      serializeListEffectivePermissionsOptions(queryOptions);
     return new AutoPaginatable(
       await fetchAndDeserialize<PermissionResponse, Permission>(
         this.workos,
         endpoint,
         deserializePermission,

Also applies to: 559-585

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/authorization/authorization.ts` around lines 535 - 556, The serializer is
being passed the full options bag including path identifiers which may leak into
the query string; in listEffectivePermissions, destructure options to remove
organizationMembershipId and resourceId (e.g., const { organizationMembershipId,
resourceId, ...queryOptions } = options) and call
serializeListEffectivePermissionsOptions(queryOptions) so only query parameters
are serialized; apply the same pattern to the other similar method referenced
(the block around lines 559-585) and keep endpoint construction using the
extracted identifiers (endpoint =
`/authorization/resources/${resourceId}/organization_memberships/${organizationMembershipId}/permissions`).

242-260: ⚠️ Potential issue | 🟠 Major

Returning AutoPaginatable here is a breaking runtime shape change.

AutoPaginatable is a class instance, not the previous plain list object. In src/common/utils/pagination.ts, list/options are own fields while data and listMetadata are prototype getters, so spreads, Object.keys(), and JSON.stringify() no longer preserve the old { object, data, listMetadata } shape for this and the other converted authz list methods.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/authorization/authorization.ts` around lines 242 - 260, The method
listPermissions currently returns a new AutoPaginatable instance (in function
listPermissions), which changes the runtime shape; instead return the original
plain list object shape produced by fetchAndDeserialize (so consumers still get
{ object, data, listMetadata, ... } and spreads/JSON.stringify behave the same).
Replace the new AutoPaginatable(...) return with the raw result from
fetchAndDeserialize<PermissionResponse, Permission>(this.workos,
'/authorization/permissions', deserializePermission, options) (and ensure
subsequent paginated caller wrapper uses that raw result or provides a
.toPlainObject() helper), and apply the same pattern to the other converted
authorization list methods to preserve the previous plain-object API shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/authorization/authorization.ts`:
- Around line 535-556: The serializer is being passed the full options bag
including path identifiers which may leak into the query string; in
listEffectivePermissions, destructure options to remove organizationMembershipId
and resourceId (e.g., const { organizationMembershipId, resourceId,
...queryOptions } = options) and call
serializeListEffectivePermissionsOptions(queryOptions) so only query parameters
are serialized; apply the same pattern to the other similar method referenced
(the block around lines 559-585) and keep endpoint construction using the
extracted identifiers (endpoint =
`/authorization/resources/${resourceId}/organization_memberships/${organizationMembershipId}/permissions`).
- Around line 242-260: The method listPermissions currently returns a new
AutoPaginatable instance (in function listPermissions), which changes the
runtime shape; instead return the original plain list object shape produced by
fetchAndDeserialize (so consumers still get { object, data, listMetadata, ... }
and spreads/JSON.stringify behave the same). Replace the new
AutoPaginatable(...) return with the raw result from
fetchAndDeserialize<PermissionResponse, Permission>(this.workos,
'/authorization/permissions', deserializePermission, options) (and ensure
subsequent paginated caller wrapper uses that raw result or provides a
.toPlainObject() helper), and apply the same pattern to the other converted
authorization list methods to preserve the previous plain-object API shape.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5116ea1c-f78a-49a6-bd7d-b252f61337ee

📥 Commits

Reviewing files that changed from the base of the PR and between ab60468 and d249bf5.

📒 Files selected for processing (2)
  • src/authorization/authorization.ts
  • src/authorization/interfaces/list-effective-permissions-by-external-id-options.interface.ts

@gjtorikian gjtorikian merged commit 7a91d74 into main Apr 17, 2026
11 checks passed
@gjtorikian gjtorikian deleted the node-sdk-authorization-list-fix branch April 17, 2026 20:34
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.

4 participants