Skip to content

fix: Validate every paginated request like the original request - #1009

Open
razor-x wants to merge 5 commits into
mainfrom
claude/js-sdk-audit-6x115l-m11a-paginator-validation
Open

fix: Validate every paginated request like the original request#1009
razor-x wants to merge 5 commits into
mainfrom
claude/js-sdk-audit-6x115l-m11a-paginator-validation

Conversation

@razor-x

@razor-x razor-x commented Aug 24, 2026

Copy link
Copy Markdown
Member

Problem

SDK audit finding M11a (medium): SeamPaginator rebuilt each page request with only pathname, method, responseKey, and the data — dropping parameters, hasRequiredParameters, and requiredParameterNames. Every paginated fetch, including the first page, skipped the required-parameter validation that the direct call performs, so an invalid paginated request fired a wasted real network request instead of failing locally. The field-by-field copy is also exactly the hand-copied-signature drift trap the PHP audit notes warn about — any new request-config field would be silently dropped by the paginator.

Fix

Add SeamHttpRequest.withPageCursor(pageCursor): returns a copy of the request with the entire configuration carried over and the page cursor merged into the params or body chosen by the request method. The paginator builds every page through it. New config fields now travel to page requests automatically.

Note: because withPageCursor builds the request data unconditionally, this also covers the no-arguments cursor-drop fixed minimally in #1003 — the two branches overlap on SeamPaginator.#fetch and whichever merges second is a trivial rebase (this version is a superset).

Tests

  • paginating accessCodes.list({}) rejects locally with At least one parameter is required for /access_codes/list and zero requests hit the wire (on reverted source, the request goes to the network — the audit's symptom)
  • paginating a valid accessCodes.list({ device_id }) fetches normally

Full suite (127 tests), lint, typecheck green.

Part of applying the rev-3 SDK audit (one PR per finding). Related: #1002#1008, overlaps #1003.

🤖 Generated with Claude Code

https://claude.ai/code/session_01B8xeJm2Hd923k8uo6eoFd2


Generated by Claude Code

The paginator rebuilt each page request with only the pathname, method,
response key, and data, dropping the request parameters and validation
configuration, so required parameter checks were skipped for every
paginated fetch including the first page. A cursor was also dropped
entirely when the original request had no params or body.

Build each page through a new SeamHttpRequest.withPageCursor, which
copies the entire request configuration and merges the page cursor into
the params or body chosen by the request method. New configuration
fields now travel to page requests automatically instead of being
hand-copied in the paginator.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B8xeJm2Hd923k8uo6eoFd2
Comment thread src/lib/seam-paginator.ts Outdated
…lidation

Resolves the conflict with the malformed response guards and completes
the removal of the unused paginator constructor parameter: the
generated createPaginator methods now construct SeamPaginator with the
request only, and the unused parent interface is gone. The fake does
not return a pagination object for /access_codes/list, so the valid
parameters test now pins that endpoint with a mock.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B8xeJm2Hd923k8uo6eoFd2
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B8xeJm2Hd923k8uo6eoFd2
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.

2 participants