feat: accept Next.js 16.4.4 on the native Node path
SO
1h ago+3037+3037+0123456789012345678901234567890123456789-263-263-012345678901234567890123456789
Stacked on #436. Native Node Functions accept Next.js 16.4.4 as well as 16.4.3.
Why
The native Node path qualified exact next@16.4.3 bytes and refused anything else. Since the scaffolder asks for ^16.4.x, a new native app now installs 16.4.4. Projects pinned to 16.4.3 must keep building, so both releases are supported.
What 16.4.4 changes for this path
Of every source the path pins, 16.4.4 changes only these:
package.json.- The twelve
next-serverruntimes. They requirenext/dist/compiled/fast-jwtwhere 16.4.3 requiredjsonwebtoken(#100885). build/templates/app-page-runtime.js. The resume now emits the Turbopack bootstrap (#100907).
Every other reviewed source is byte-identical between the two releases, which I checked against both installed packages: the route modules, route-module.js, load-components.js, the evaluator, the templates, request-meta.js, route-kind.js, pages-handler.js, require-hook.js and the ws bundle.
Two more changes affect the path:
- The Turbopack production runtime no longer installs a chunk's leading strict factory table (#100866).
- The JWT library is now fast-jwt, which needs a profile of its own.
Changes
- Per-release pins (
node-next-release.ts).- Each release carries its
package.json, runtime and template bytes. Lookups accept the reviewed bytes of either release. - Where the package is known, the bytes must be that package's own release. The Pages proof refuses a package that holds another release's copy of a runtime or of the template. The cache-policy rewrite, the app-page factory and the cache-write proof each check the release that
package.jsonnames. - The
wsand require-hook profiles accept either release's package, since their bytes are the same in both.
- Each release carries its
- Turbopack runtime.
- 16.4.4's three body fingerprints are computed from the release's own snapshot. Running the same computation on 16.4.3's snapshot reproduces the existing three fingerprints exactly.
- A runtime proof now reports whether the runtime installs strict factory tables. Next to a runtime that does not, a chunk that leads with such a table is refused.
- fast-jwt profile.
- The bundle has no
evaland noFunction. - Its one Node loader read is safer-buffer's
process.binding("buffer"), guarded by!o.kStringMaxLength. Node 24 and 26 exportkStringMaxLength, so that read never runs. - That one site is the only exemption granted to the closure walker. A test confirms the walker refuses nothing else in the bundle.
- The bootstrap guard accepts the record, answers the
node:builtins, and seals the crypto functions fast-jwt captures at load. - A CI-only test signs and verifies preview data through the guard.
- The bundle has no
- Producer per release. The independent Pages handler producer compiles with 16.4.4 under
--next=16.4.4. Its workflow now takes its pnpm version from the fixture: action-setup was refusing the pinned 12.15.0 next to the repository'spackageManager, so no producer job had been running. - CI and fixtures.
tools/native-addon-next-ci.mtsbuilds the official fixtures with a reviewed release named byUPWIND_NATIVE_NEXT(16.4.3 by default).fixtures/next-nativemoves to 16.4.4.
Still to come in this PR
- The Pages "proved" mode needs the 16.4.4 getHandler whole-factory references. They come from the producer's 16.4.4 artifacts, which cannot run until pnpm's one-day release-age default lets the fixture install 16.4.4 (after 2026-11-03 10:49 UTC).
- Until those references land, a Pages-only native build on 16.4.4 is still refused.
- App Router native Functions (the whole server output) build on 16.4.4 with this change.
- Once the references land, I'll add the 16.4.4 leg to the native fixture matrix.
Checks run locally
- 183 adapter and runtime suites around the native path pass, apart from three macOS-only environment failures (sharp's libvips and
/varvs/private/var). - The fast-jwt guard integration test passes on Node 24.22.1.
tsc, ESLint and oxfmt pass on every changed file, and so doknipandcheck:vocabulary.
Review notes
- Real fast-jwt qualification (Greptile, cubic). The unit suites never reach a positive JWT qualification, for jsonwebtoken either: that requires a completed route closure, which only a real native build produces. The official native fixture CI exercises it for 16.4.3, building
prerender-native-modulein the Pages "proved" mode with jsonwebtoken retained. The 16.4.4 leg of the same job will do it for fast-jwt once the getHandler references are in. Until then, the unit test refuses a fast-jwt route approval the same way it refuses a jsonwebtoken one, and the closure test shows the binding read is the bundle's only refusal. - Taken in ddfcad94.
- The Pages proof's package.json must match the release's exact bytes, not just its version.
- The nested-table probe is total, and the cohort reads the chunks for it once.
- The JWT builtin lists are frozen.
- The lock comparison allows integrity changes only in Next.js's own entries.
- The docs state the pending Pages-only limitation and the 16.4.3 CI fixture.
- The producer README is updated.
Summary by CodeRabbit
- New Features
- Added support for Next.js 16.4.4 alongside 16.4.3 in native integrations and Pages handler profiles.
- Pages handler profiles can be generated with server minification enabled or disabled, and can target either supported Next.js version.
- Added support for validating fast-jwt evaluation in the native integration environment.
- Documentation
- Updated compatibility and profile guidance for Next.js 16.4.4 and its JWT handling.