-
Notifications
You must be signed in to change notification settings - Fork 1.9k
docs(migration): close guide gaps surfaced by real v1-to-v2 migrations #2382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+412
−184
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
30b47a9
docs(migration): close guide gaps surfaced by v1-to-v2 upgrade trials
felixweinberger f104fb1
docs(migration): fold in second-wave migration findings
felixweinberger ecbe8b2
docs(migration): correct five claims against the implementation
felixweinberger 91be7f3
Merge branch 'main' into fweinberger/migration-doc-findings
felixweinberger f47d25f
docs(migration): third-round corrections from review
felixweinberger File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| --- | ||
|
|
||
| Docs-only: migration-guide corrections from real v1-to-v2 migrations. No package changes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 The "strips its cache fields too" / "wire-only" claim here is only true at the type level: nothing at runtime removes
ttlMs/cacheScope— the probe path stores the wire-parse output verbatim andgetDiscoverResult()returns it with both fields still present (the client's own_freshness()reads them off that runtime body). Reword to scope the bullet to the public type surface (the fields are undeclared onDiscoverResult, readable via a cast, with the.catch()0/'private' defaults making absent-vs-default indistinguishable) — "must parse raw frames" overstates it.Extended reasoning...
What the bullet claims vs. what the code does. The new bullet (docs/migration/support-2026-07-28.md:305-308) says
DiscoverResult"strips its cache fields too", thatttlMs/cacheScopeare "wire-only — consumed by the client's response-cache layer", and that "tooling that displays the server's advertised cache policy must parse raw frames." Only the type-level half holds. Unlike theresultTypebullet directly above it (which describes a real runtime delete), nothing in the implementation removes the cache fields from the valuegetDiscoverResult()returns.The code path. The 2026 wire
DiscoverResultSchemaexplicitly declaresttlMs(.catch(0)) andcacheScope(.catch('private')) (packages/core-internal/src/wire/rev2026-07-28/schemas.ts:808-822), so the parse output carries both fields. The probe path stores that output verbatim:probeClassifier.tsclassifyResult()returns{ kind: 'modern', ..., discover: parsed.value }(packages/client/src/client/probeClassifier.ts:137-152),_connectNegotiatedassignsthis._discoverResult = result.discover(packages/client/src/client/client.ts:1093), andgetDiscoverResult()returns it as-is (client.ts:1290-1291). The codec's decode lift consumes onlyresultType(delete lifted['resultType'],codec.ts:258-261); there is no equivalent strip of the cache fields anywhere. Thediscover()typed-verb path validates with the neutralDiscoverResultSchema, which extends the looseResultSchema, so the runtime keys survive there too.Why "consumed by the client's response-cache layer" is the opposite of stripping.
Client._freshness()reads the cache hints off the runtime result body, and its JSDoc says exactly that: "The fields pass through the loose result schema, so they are read off the runtime body" (client.ts:~1660-1675). The SDK relies on the fields not being stripped — "consumed" here means "read", not "removed".Step-by-step proof. (1) A client with
versionNegotiation: { mode: 'auto' }connects to a 2026-capable server; theserver/discoverresponse body carriesttlMs: 30000, cacheScope: 'public'. (2)classifyResult()parses it with the 2026 wire codec —parsed.valueincludes both fields (the wire schema declares them; nothing deletes them). (3)client.ts:1093storesparsed.valueasthis._discoverResult. (4)client.getDiscoverResult()returns that exact object. (5)(client.getDiscoverResult() as Record<string, unknown>).ttlMsreads30000— no raw-frame parsing needed. A v2-alpha consumer auditing tooling against this bullet would conclude such reads stopped working at runtime; in fact they keep working (only the TypeScript declaration is gone).The accurate part, and the genuine caveat. The public neutral
DiscoverResultSchema(packages/core-internal/src/types/schemas.ts:577) does not declare the cache fields, andStripWireOnlyonly removesresultType(types/types.ts:211-218) — so the type-level claim ("absent from the publicDiscoverResulttype") is correct. There is also one real reason a faithful policy display might want raw frames: on the probe path the wire schema's.catch()fills0/'private'for absent or malformed hints, so a runtime read cannot distinguish "server advertised 0/private" from "server omitted the fields".Why it matters. This is a docs-only PR whose stated bar is that every claim was verified against the SDK source, and the bullet deliberately echoes the
resultTypebullet above it — which is a real runtime delete — making the over-claim more misleading. All three verifiers confirmed against current main; none refuted.How to fix. Reword to scope the claim to the type surface, e.g.: "
ttlMs/cacheScopeonserver/discoverare undeclared on the publicDiscoverResulttype returned bygetDiscoverResult()— the client reads them off the runtime body for its response cache, and they remain present on the returned object (readable via a cast). Note the wire schema's lenient defaults mean absent or malformed hints read back as0/'private'; tooling that must distinguish 'omitted' from 'advertised default' should parse raw frames." Drop the "strips" / "wire-only" wording.