Skip to content

feat: SDK conformance wave 3 — Node SDKs via bun - #66

Merged
deblasis merged 2 commits into
mainfrom
feat/sdk-conformance-node
Aug 18, 2026
Merged

feat: SDK conformance wave 3 — Node SDKs via bun#66
deblasis merged 2 commits into
mainfrom
feat/sdk-conformance-node

Conversation

@deblasis

Copy link
Copy Markdown
Contributor

What

SDK conformance wave 3 — the Node SDKs, via bun (just conformance-node; bun added to CI). The suites boot the real stunt binarystunt up, runtime file, probe-bound ports — so they double as end-to-end tests of the CLI itself, not just the engine.

SDK Checks
stripe-node typed creates, autoPagingEach walking has_more, PaymentIntent create+confirm, and webhook verification through the SDK's constructEventAsync — signature verifies, data.object parses, tampered payloads rejected
octokit issue CRUD and octokit.paginate following the adapter's Link headers page by page
twilio-node the message lifecycle driven by SDK fetches (queued → sent/delivered), the +15005550001 magic number → failed, and status callbacks verified by twilio-node's own validateRequest

Findings

  1. Real bug: github-style's Link pagination headers hardcoded https://api.github.com absolute URLs. Any client that follows the header — octokit.paginate — was sent to the real GitHub and 401'd. (go-github survived only because it parses the page params without following the URL, which is why the Go wave never saw it.) Link targets are now built from the serving host (req["host"]) — what a real GitHub Enterprise does.
  2. A just hazard worth knowing: the recipe originally ran /tmp/stunt-ci, which just build never writes — only the lint recipes do — so it executed a stale binary from an ancient lint run, still carrying the v0.45-era form-parser panic. That stale binary produced an ECONNRESET red herring that cost a long diagnostic detour. The recipe now builds its own binary explicitly.
  3. Known-environment quirk (documented in-suite, not a stunt bug): under bun, stripe-node's fetch layer intermittently drops the url form param when its value names a live same-process listener — reproduced with a fresh client against a bare echo server, with the param present at the SDK's own encode step. Webhook registration tries the SDK first and falls back to a raw one-shot POST; everything downstream of registration is SDK-driven.

Verification

  • 24 expects across the three suites, green twice consecutively.
  • Go conformance (36 checks) + full main-module suite, parse guard, gofmt, vet — green. Engine tests for github-style re-run on the Link change.

New suites under conformance/node/ (just conformance-node; bun added
to CI) that boot the REAL stunt binary — stunt up, runtime file,
probe-bound ports — so they double as end-to-end tests of the CLI:

- stripe-node: typed creates, autoPagingEach walking has_more, PI
  create+confirm, webhook verification through constructEventAsync
  (signature verifies, data.object parses, tamper rejected).
- octokit: issue CRUD and octokit.paginate following the adapter's
  Link headers page by page.
- twilio-node: lifecycle driven by SDK fetches (queued->sent/
  delivered), the +15005550001 magic number -> failed, and callbacks
  verified by twilio-node's own validateRequest.

Findings:
- REAL BUG: github-style's Link pagination headers hardcoded
  https://api.github.com absolute URLs — clients that FOLLOW the
  header (octokit.paginate) were sent to the real GitHub and 401'd;
  go-github survived only because it parses page params without
  following. Link targets now build from the serving host
  (req["host"]), like a real GitHub Enterprise.
- just hazard: conformance-node used /tmp/stunt-ci, which
  never writes — only the lint recipes do — so the recipe could run a
  stale binary from an old lint run (that's exactly what produced a
  session-long ECONNRESET mystery: the stale pre-v0.45 binary still
  had the form-parser panic). The recipe builds fresh now.
- Known-environment quirk documented in the suite: under bun,
  stripe-node's fetch layer drops the url form param when it names a
  live same-process listener (reproduced with a fresh client against
  an echo server, independent of stunt; plain bun fetch does not do
  it). Registration tries the SDK first and falls back to a raw
  one-shot POST; everything else is SDK-driven.

24 expects across 3 suites, green twice consecutively; Go conformance
+ full main-module suite green.
Review findings on PR #66, all fixed:

- Link scheme: handlers now read X-Forwarded-Proto (the subdomain
  proxy sets it) with the loopback-host inference only as the port-mode
  fallback — the heuristic alone was wrong for no-TLS subdomain mode.
  Same fix applied to shopify's page_info URL (hardcoded https) and
  dune's next_uri (hardcoded http).
- github Link round-trips every filter/query param except page — a
  Link-following client no longer loses state=closed&q= between pages.
  A missing host now omits the Link instead of redirecting to the real
  api.github.com.
- justfile: bun install --frozen-lockfile fails loudly (the silent
  fallback could silently resolve newer semver in CI).
- harness: stunt-up stderr is captured and included in boot failures
  (was a bare 20s timeout); failure paths stop the sink and remove the
  tmpdir; readiness fetches carry a 500ms abort and a hard failure
  after the loop (was silent proceed); the port probe stays bound
  until just before spawn.
- suites: stripe paging asserts distinct ids with no valve trip
  (catches both has_more=false and ignored starting_after); the
  registration fallback warns when it fires; twilio drives to
  delivered and REQUIRES the second callback (a dropped unsigned
  terminal callback now fails instead of slipping through); timeouts
  bumped to 120s for CI headroom.

27 expects green twice consecutively; Go conformance + engine suites
on all three touched adapters green.
@deblasis
deblasis merged commit 469b062 into main Aug 18, 2026
1 check passed
@deblasis
deblasis deleted the feat/sdk-conformance-node branch August 18, 2026 10:41
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.

1 participant