Skip to content

fix(spec): DestinationUpdate discriminator, drop pagination overlay, event.data oneOf#924

Merged
alexluong merged 4 commits into
mainfrom
fix/spec-sdk-fixes
May 29, 2026
Merged

fix(spec): DestinationUpdate discriminator, drop pagination overlay, event.data oneOf#924
alexluong merged 4 commits into
mainfrom
fix/spec-sdk-fixes

Conversation

@leggetter
Copy link
Copy Markdown
Collaborator

@leggetter leggetter commented May 28, 2026

Summary

Bundles three spec/SDK fixes that landed sequentially on the fix/spec-sdk-fixes umbrella. The combined effect: PATCH semantics are spec-correct, TS list endpoints return flat results again, and event.data is no longer dropped on listAttempts with include=event.data.

What's in this PR

PR Title Effect
#920 fix(openapi): add type discriminator to DestinationUpdate union Restores the missing discriminator; introduces 17 *ConfigUpdate/*CredentialsUpdate companion schemas so partial PATCH bodies are typeable. Fixes a silent wire-serialization bug where the SDK was routing partial-config PATCH through Hookdeck's permissive variant and sending camelCase keys the server didn't recognize.
#917 fix(spec): expose event.data on Attempt when include=event.data Swaps oneOf order so EventFull comes before EventSummary. Zod's z.union matches first-success and was dropping data to EventSummary.
#919 chore(sdks): drop x-speakeasy-pagination overlay from all SDK sources Removes the cross-SDK pagination annotation. In TS this means list endpoints no longer return a PageIterator wrapper — back to a flat Promise<EventPaginatedResult> with result.models / result.pagination. Net DX improvement; the Python auto-pagination upside that originally motivated the overlay didn't pan out symmetrically.

Consumer impact (after SDK regen lands)

Surface Impact
Typed SDK update() Breaking. Must include type: '<destination>'. Compile error otherwise. Discriminated narrowing means IDE autocomplete now suggests only fields valid for the chosen type.
Typed SDK list() Breaking. No more PageIterator. Promise<XPaginatedResult> — read from result.models / result.pagination. No for await iteration helper.
Typed SDK listAttempts({include: ['event.data']}) attempt.event now includes data instead of dropping it silently.
Raw HTTP Server still accepts PATCH without type (lenient). All other changes are wire-compatible.
API ref docs / code samples / MCP server Regenerated as part of the SDK regen PR.

Test plan

  • Spec validates (swagger-cli validate).
  • Acceptance tests pass locally — 153 passing / 0 failing / 15 pending against managed Outpost with fresh TS SDK regen on the umbrella state. Paginator accessor revert committed (4675bc9c).
  • SDK regen PRs (TS / Go / Python) created and merged after this lands.
  • CI workflow for acceptance tests — tracked in Add CI workflow for spec-sdk-tests (SDK acceptance testing) #921.

Notes

🤖 Generated with Claude Code

leggetter and others added 3 commits May 28, 2026 12:04
Trigger: the DestinationUpdate union lost its discriminator in 8be278c
(May 2025), when `type` wasn't on PATCH. Server has since added `type`
acceptance and RFC 7396 merge-patch (bd7701b), making the missing
discriminator an active bug — Hookdeck's permissive `config: {}` variant
greedily matched any partial-config payload, the SDK sent it through
with no field remap (camelCase reached the server), and merge-patch
silently no-op'd. All non-Webhook partial config updates affected.

Spec: `type` becomes a required, enum-locked discriminator on every
DestinationUpdate* variant; 17 new `*ConfigUpdate`/`*CredentialsUpdate`
companions model the now-explicit partial PATCH shape; Hookdeck's
`config: {}` removed.

Impact:
  * Breaking for typed SDK consumers: `update()` must include `type`
    after regen. Server is more lenient (still accepts PATCH without
    `type`), so raw HTTP callers keep working but are spec-noncompliant.
  * SDK regen left to the bot — separate PR. CI compile-check on this
    PR will fail until that lands; tests were validated locally
    against a 1.4.1 regen.

spec-sdk-tests (knock-on): `type` added to 46 update sites; paginator
shape fixed (supersedes fix/spec-sdk-tests-paginator-shape); SDK retries
enabled; cleanup parallelized; cleanup-error logging hardened.

Test status (managed Outpost, local regen'd SDK): 133→152 passing,
14→0 failing. spec-sdk-tests have no CI today; follow-up PR will add one.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(spec-sdk): fix paginator response shape (response.result.models)

Speakeasy CLI 1.741.7 → 1.753.0 (commit 3f311e0, 2026-03-13) changed
the generated TS SDK return type for list operations from the flat
paginated body to a PageIterator wrapper: ListEventsResponse now wraps
the body in `result`, so callers access `response.result.models` instead
of `response.models`. The shape change was a side-effect of the
Speakeasy version bump and wasn't surfaced in the SDK regen PR changelog
(which only flagged the unrelated `request` query-param restyle).

Tests in spec-sdk-tests/tests/{events,tenants}.test.ts still used the
pre-bump accessor and failed to compile against the current SDK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(spec-sdk): assert event.data is exposed when include=event.data

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(spec): order EventFull before EventSummary in Attempt.event oneOf

Speakeasy's TS generator emits zod unions in declaration order. The
non-strict EventSummary matched first and silently stripped event.data
from the parsed attempt — losing the payload added by include=event.data.
Declaring EventFull first lets it match when data is present, with
EventSummary as the fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…#919)

The shared pagination-config-overlay added x-speakeasy-pagination to list
endpoints, which Speakeasy then converted into PageIterator wrappers (TS),
res.Next() helpers (Go), and res.next() chaining (Python).

In TS the wrapper changed the response shape to response.result.models,
which is a noisy regression for the common single-page case. In Go and
Python the helper saves one line at the cost of hiding which request
params get carried across the cursor call.

Drop the overlay from all three sources for symmetric, explicit DX:
callers paginate manually using res.pagination.next on the flat response.

SDK regeneration is intentionally left out of this commit so the workflow
change can be reviewed in isolation.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@leggetter leggetter changed the title fix/spec sdk fixes fix(spec): DestinationUpdate discriminator, drop pagination overlay, event.data oneOf May 28, 2026
…verlay drop

Trigger: #919 (merged into umbrella) drops the x-speakeasy-pagination
overlay, so the TS SDK no longer wraps list responses in PageIterator.
events.list()/tenants.list() return EventPaginatedResult/TenantPaginatedResult
directly — accessor is `response.models`, not `response.result.models`.

Tests in #920 had been adapted to the wrapper shape; this realigns them
back to the flat shape post-regen. Local run after fresh TS SDK regen:
153 passing / 0 failing / 15 pending.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@alexluong alexluong merged commit bf55998 into main May 29, 2026
3 checks passed
@alexluong alexluong deleted the fix/spec-sdk-fixes branch May 29, 2026 08:37
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