Ultimate

25.x → 26.0.0, entry by entry

Six entries — CHANGELOG.md's 26.0.0 breaking entries in their order, grouped by package, lowest tier first. No legacy path, no codemod, no shim. Entry 1 can refuse sign-ins on a host whose egress cannot reach the provider's jwks_uri — check it before the deploy (upgrade step 2). A later slice appends its rows below the last one and never renumbers; each row's CHANGELOG.md line names it as (#N) after the dash.

The upgrade, top to bottom

#DoWhat you see until you doEntries
1pin every @ultimat3/* to the one new version, bun installnothing yet — a mixed install is untested—
2before the deploy, an app with an OIDC sign-in: from a production pod, curl -sS -m 5 https://www.googleapis.com/oauth2/v3/certs (or the jwks_uri of each provider you registered); where it cannot be reached, return 'token-endpoint-tls' for that provider only from oauthLogin(auth, { idTokenKeys }) (entry 1 shows the function)X_OAUTH_EXCHANGE_FAILED (stage jwks) on every sign-in through that provider1
3bun test — a test that feeds exchangeOAuthCode, completeOAuthLogin or oauthLogin an unsigned id token: sign it and serve the key set at the provider's jwksUri from the injected fetch, or pass keys / idTokenKeys: 'token-endpoint-tls'X_OAUTH_TOKEN_INVALID where the test signed in; an extra key-set URL in a recorded endpoint list1
4bun run typecheck for the removed exports: APPLE_PROVIDER, ServerHandle.describe(), AgentRecovery, Recovery, ROUTE_FILENAME.apiTS2305 / TS2339 at each site2, 3, 5
5find apps -path '*/api/*' \( -name route.ts -o -name page.tsx \) — move each into an action, or a plain route in runtime.routesX_ROUTE_FILE_INVALID at boot4
6grep -rnE "x (jobs (ls|rm)|(actions|queries|entities) describe|db branch (ls|drop))\b" .github scripts bin package.json docs and swap each for list, delete, showX_CLI_UNKNOWN_COMMAND naming the new verb6
7x verifygreen, or a finding whose fix: is the edit—

Entry by entry

Tier 2 — @ultimat3/auth (1–2), @ultimat3/http (3). Tier 4 — @ultimat3/render (4), @ultimat3/scraping (5). Tier 5 — @ultimat3/cli (6).

#SurfaceCosts you an edit if
1exchangeOAuthCode, completeOAuthLogin, oauthLogin — the id token's signatureyour egress cannot reach a provider's jwks_uri, or a test hands the exchange an unsigned id token. 25.x accepted any id token read off the token endpoint over TLS; 26.0.0 checks its signature against the provider's published key set whenever the provider has a jwksUri (providerJwks, cached per provider). X_OAUTH_TOKEN_INVALID for a bad signature, X_OAUTH_EXCHANGE_FAILED (stage jwks) for an unreachable key set. Opt one provider out with oauthLogin(auth, { idTokenKeys: (provider) => provider === 'bigco-sso' ? 'token-endpoint-tls' : undefined }) — undefined keeps the default; providerJwks(providerFor(id)) there throws for GitHub, which publishes no jwks_uri; completeOAuthLogin(auth, { idTokenKeys }) and exchangeOAuthCode(…, { keys }) take the value directly
2APPLE_PROVIDER, BUILTIN_OAUTH_PROVIDERS, BUILTIN_OAUTH_PROVIDER_IDSyou import APPLE_PROVIDER (TS2305) or list 'apple' in defineAuth({ providers }) (an unknown provider). Apple answers a form_post and the callback is a GET, so it never completed a login. Delete it, or registerOAuthProvider your own
3ServerHandle.describe()you call it. TS2339; read x routes --json, or call describeRoutes(table) from @ultimat3/http
4api/**/route.ts, ROUTE_FILENAME, RouteEntry.surfacea route file lives under api/: X_ROUTE_FILE_INVALID (was X_ROUTE_MODE_INVALID). Make it an action, or a plain route in runtime.routes. ROUTE_FILENAME is Record<RouteSurface, string>; type a surface with the new RouteSurface export of @ultimat3/render
5recover: 'agent', AgentRecovery, Recoverya scrape passes 'agent' (refused at scrape(); 25.x threw X_NOT_IMPLEMENTED on the first moved selector) or imports a removed type. Write a RecoveryHook function and call your own llm() from it; import type { Recovery } becomes RecoveryHook. @ultimat3/scraping is tier 4 now — nothing to edit in an app
6x jobs ls, x jobs rm, x actions|queries|entities describe, x db branch ls, x db branch dropa script runs an old verb: X_CLI_UNKNOWN_COMMAND with the new one in its fix. list, delete, show, list, delete; a bare x jobs still lists, and --json is unchanged

Edit this page on GitHubThis page as markdown