Skip to content

chore: resync the production spec (global volumes, organization) - #7

Merged
justinwlin merged 2 commits into
mainfrom
chore/spec-resync-2026-10-14
Oct 15, 2026
Merged

justinwlin merged 2 commits into
mainfrom
chore/spec-resync-2026-10-14

Conversation

@justinwlin

@justinwlin justinwlin commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Resyncs the vendored production spec and regenerates the types. Unblocks runpod-mcp, whose spec-drift check fails on the same upstream changes (runpod-mcp #121).

Why the daily update stopped

Daily production spec update has failed since the 2026-10-14 run, so no bot PR exists. Two patch-layer fixes:

  1. Mounts description edit. Upstream rewrote the sentence to cover global volumes, so the edit's anchor text no longer matched. Re-derived against the new text.
  2. Raw U+0085 in a regex. The new global-volume name pattern ends in a NEL character. YAML reads NEL as a line break, so the dumper's output folded it to a space on reload, and test_patch_layer_run_is_a_no_op failed. Strings containing NEL, LS or PS are now double-quoted, where PyYAML escapes them (\N). js-yaml reads the value back intact. Covered by a new round-trip test.

Upstream changes (minor bump)

  • New: global-volume CRUD (/v2/global-volumes), GET /v2/organization.
  • global mounts on pods (Mounts now extends BaseMounts; persistent/network unchanged).
  • mounts on endpoints (create, update, response).
  • pagination on the cluster and network-volume list responses. Types are additive, but listClusters and listNetworkVolumes now return one page (default limit 1000). The changeset tells callers to follow pagination.nextCursor.

BaseMounts and EndpointMount also get DESCRIPTION_EDITS entries. Upstream moved the dated mount wording ("enforced at the handler", "today", "not supported yet") into them, so it was reaching the published JSDoc.

Test plan

  • Locally, every step of the daily workflow: spec:pull, generate, generate:check, test:spec, test:scripts, typecheck, test, test:package, test:examples.
  • CI matrix (Node 20/22/24).

After merge

Merge the changesets "Version" PR to publish 0.3.0, then runpod-mcp takes the new SDK plus spec:pull and generate:tools.

Pulls the production OpenAPI and regenerates src/generated/schema.ts. The
daily update has failed since 2026-10-14 on two patch-layer issues:

- The Mounts description edit no longer matched: upstream rewrote the
  sentence to cover global volumes. Re-derived against the new text.
- The new global-volume name pattern ends in a raw U+0085. YAML reads NEL
  as a line break, so the dumper's plain/single-quoted output folded it to
  a space on reload and a second patch run rewrote the file. Strings
  containing NEL, LS or PS are now double-quoted, where they are escaped.

Upstream additions are additive: global-volume CRUD, GET
/v2/organization, global pod mounts, endpoint mounts, and pagination on
the cluster and network-volume lists.
@justinwlin
justinwlin marked this pull request as ready for review October 14, 2026 17:42

@OneAsterisk OneAsterisk left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude review, round 1

Verdict: Approved. The resync is clean and the NEL fix is correct; two Low follow-ups below.
Approval gate: 0 Critical, 0 High, 2 Medium+Low → approved.

Existing feedback

No prior reviews or comments.

PR description vs code

Claim Status Where
Mounts patch re-derived against new upstream text ✅ scripts/fix_spec.py:415-420, applied at spec/openapi.yaml Mounts
Strings with NEL/LS/PS are double-quoted, emitted as \N ✅ scripts/fix_spec.py:93,98-99; spec/openapi.yaml:2806,2823
Value reloads intact ✅ Loaded the vendored spec with SpecLoader: pattern is '[^\\p{Z}\\t-\\r\x85]'. js-yaml maps \N to U+0085.
New round-trip test ✅ scripts/test_fix_spec.py:63-80. allow_unicode=True in dump_spec, so without the fix the raw NEL would be emitted and folded. The test exercises the fix.
Global-volume CRUD, GET /v2/organization ✅ 5 global-volume ops plus getOrganization. All 66 ops carry x-runpod-scope.
Mounts extends BaseMounts, persistent/network unchanged ✅ src/generated/schema.ts:1452,1483
mounts on endpoint create, update, response ✅ EndpointMountsInput on create/update, EndpointMounts required on response
pagination on cluster and network-volume lists ✅ ListClustersResponse, ListNetworkVolumesResponse
"All additive, existing calls keep their current types" ⚠️ Types: true. Behavior: the two list calls now return one page (see Low 2).
CI matrix Node 20/22/24 ✅ All 6 verify jobs pass

Findings

Low

  • BaseMounts brings back the wording the old Mounts patch removed. spec/openapi.yaml:569-574 → src/generated/schema.ts:1445-1450. Upstream moved the old sentence ("enforced at the handler", "today", "eventual") into the new BaseMounts schema. It also added "Left open so that concrete schemas can extend it and close themselves." Only Mounts was re-patched, so the published JSDoc now carries what DESCRIPTION_EDITS exists to strip. Same family: EndpointMount "Custom paths are not supported yet" (spec/openapi.yaml:2843). Fix: add a DESCRIPTION_EDITS entry for BaseMounts (and optionally EndpointMount). Fine as a follow-up.
  • Changeset omits that listClusters and listNetworkVolumes now return one page. .changeset/production-spec-global-volumes.md:5. Both used to return "all" resources. They are now cursor-paginated with a default limit of 1000. A consumer that reads clusters or networkVolumes as the full list silently stops at 1000. docs/releases.md asks for compatibility impact in the changeset. Fix: add one sentence telling callers to follow pagination.nextCursor.

Simplification opportunities

None. The script change is 9 lines and the test is 19.

Verified clean

  • YAML_EXTRA_BREAKS check runs before the |/> branches, so a block scalar never receives a raw NEL. A NEL string inside a short flow list still goes through represent_str and gets quoted.
  • main() still verifies the round-trip under both SpecLoader and SafeLoader before writing, so any other unescaped break would fail loudly.
  • No hand-written code in src/, tests/, examples/ or the docs enumerates operations or list shapes that needed updating.
  • ClusterMounts generates the same type as the old Mounts, so cluster create input is unchanged. Mounts input only gains an optional global.
  • Version bump: minor (0.2.0 → 0.3.0) matches docs/releases.md for new endpoints in 0.x.
  • Clerk and X-Team-Id text in the security scheme stays in the vendored spec only. It does not reach schema.ts or dist.

Questions for the author

  • Endpoint responses now require mounts (network and global both required). Did you confirm the live API returns both arrays on every endpoint, including endpoints created before this change? Types that claim required fields the server omits are hard to walk back.

Reviewed by Claude (claude-opus-5-5) via the pr-review skill. Tokens: 32 in / 9,513 out / 938,272 cache read / 68,137 cache write = 1,015,954. Estimated cost: $2.07 per the skill's sum_usage.py rate card, cache writes priced at the 1-hour TTL. Round 1 of this PR. This is automated assistance; a human owns the final call.

Comment thread spec/openapi.yaml Outdated
Storage mounts attached to a pod. At most one of `persistent` or
`network` may be set: sending both is rejected with 400. The
`network` field is an array for forward compatibility with
The mount kinds every resource that takes `mounts` shares. At-most-one

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Low: This is the sentence the old Mounts entry in DESCRIPTION_EDITS rewrote ("enforced at the handler", "today", "eventual"). Upstream moved it here, plus "Left open so that concrete schemas can extend it and close themselves". Only Mounts was re-patched, so this text now ships in src/generated/schema.ts:1445-1450. Add a DESCRIPTION_EDITS entry for ("components", "schemas", "BaseMounts", "description") that keeps the contract half. EndpointMount "not supported yet" (line 2843) is the same kind of dated wording. Fine as a follow-up.

'@runpod/typescript-api-sdk': minor
---

Resync the vendored production spec and regenerate the types. Adds the global-volume operations (`/v2/global-volumes` list, create, get, update, delete) and `GET /v2/organization`, `global` mounts on pods, `mounts` on endpoints, and the `pagination` block on the cluster and network-volume list responses. All additive upstream, so existing calls keep their current types.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Low: "existing calls keep their current types" is true, but listClusters and listNetworkVolumes changed behavior. They used to return all resources and now return one page (default limit 1000). Callers that treat clusters / networkVolumes as the full list will silently stop at 1000. Suggest one more sentence, e.g. "listClusters and listNetworkVolumes now return one page; follow pagination.nextCursor until hasNextPage is false."

@OneAsterisk OneAsterisk left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Duplicate of Claude review, round 1, posted by a retry after GitHub returned a spurious 422. Please read that one.

…geset

Add DESCRIPTION_EDITS entries for BaseMounts and EndpointMount so the
handler/today/eventual/yet wording upstream moved into them stays out of
the published types. Tell callers that listClusters and listNetworkVolumes
now return one page.
@justinwlin
justinwlin merged commit 5f36649 into main Oct 15, 2026
6 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.

2 participants