@timber-js/app 0.2.0-alpha.185 → 0.2.0-alpha.187

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (570) hide show
  1. package/dist/_chunks/{actions-O_LsyCE4.js → actions-35jnMdeJ.js} +4 -3
  2. package/dist/_chunks/{actions-O_LsyCE4.js.map → actions-35jnMdeJ.js.map} +1 -1
  3. package/dist/_chunks/als-registry-C6kcfprT.js +41 -0
  4. package/dist/_chunks/als-registry-C6kcfprT.js.map +1 -0
  5. package/dist/_chunks/als-slots-BEEIPKYm.js +26 -0
  6. package/dist/_chunks/als-slots-BEEIPKYm.js.map +1 -0
  7. package/dist/_chunks/base-path-DaQrzbez.js +80 -0
  8. package/dist/_chunks/base-path-DaQrzbez.js.map +1 -0
  9. package/dist/_chunks/build-manifest-DWppEdLB.js +86 -0
  10. package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
  11. package/dist/_chunks/build-output-helper-C3DrfzZR.js +369 -0
  12. package/dist/_chunks/build-output-helper-C3DrfzZR.js.map +1 -0
  13. package/dist/_chunks/{cache-api-B-lhk9p4.js → cache-api-DjNrIWRR.js} +8 -14
  14. package/dist/_chunks/cache-api-DjNrIWRR.js.map +1 -0
  15. package/dist/_chunks/cli-check-CpmN7Nh-.js +256 -0
  16. package/dist/_chunks/cli-check-CpmN7Nh-.js.map +1 -0
  17. package/dist/_chunks/cli-schema-sync-CGMp_Psg.js +298 -0
  18. package/dist/_chunks/cli-schema-sync-CGMp_Psg.js.map +1 -0
  19. package/dist/_chunks/{cloudflare-CnT5Lr7U.js → cloudflare-CGP6BZKO.js} +92 -14
  20. package/dist/_chunks/{cloudflare-CnT5Lr7U.js.map → cloudflare-CGP6BZKO.js.map} +1 -1
  21. package/dist/_chunks/convention-lint-kXsgc_-7.js +784 -0
  22. package/dist/_chunks/convention-lint-kXsgc_-7.js.map +1 -0
  23. package/dist/_chunks/error-boundary-D-ODYX41.js +353 -0
  24. package/dist/_chunks/error-boundary-D-ODYX41.js.map +1 -0
  25. package/dist/_chunks/{fast-hash-D6hIVt1Y.js → fast-hash-C-tVYrLb.js} +6 -1
  26. package/dist/_chunks/fast-hash-C-tVYrLb.js.map +1 -0
  27. package/dist/_chunks/file-cache-DmX7OqZP.js +454 -0
  28. package/dist/_chunks/file-cache-DmX7OqZP.js.map +1 -0
  29. package/dist/_chunks/fs-identity-D7vb6GdI.js +208 -0
  30. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +1 -0
  31. package/dist/_chunks/{logger-AWfuX-KJ.js → logger-D8xJZXIN.js} +34 -51
  32. package/dist/_chunks/logger-D8xJZXIN.js.map +1 -0
  33. package/dist/_chunks/mdx-file-C005ay-P.js +25 -0
  34. package/dist/_chunks/mdx-file-C005ay-P.js.map +1 -0
  35. package/dist/_chunks/{plugin-context---kTF5v8.js → plugin-context-rCinWLiE.js} +8 -2
  36. package/dist/_chunks/plugin-context-rCinWLiE.js.map +1 -0
  37. package/dist/_chunks/purge-store-Byr8XOjU.js +14 -0
  38. package/dist/_chunks/purge-store-Byr8XOjU.js.map +1 -0
  39. package/dist/_chunks/{resolve-schema-Dz3fcFUo.js → resolve-schema-5ma5pp1b.js} +2 -2
  40. package/dist/_chunks/{resolve-schema-Dz3fcFUo.js.map → resolve-schema-5ma5pp1b.js.map} +1 -1
  41. package/dist/_chunks/{router-ref-CtmF-aPv.js → router-ref-DuYuV_0Q.js} +2 -2
  42. package/dist/_chunks/router-ref-DuYuV_0Q.js.map +1 -0
  43. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js +243 -0
  44. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js.map +1 -0
  45. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js +40 -0
  46. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js.map +1 -0
  47. package/dist/_chunks/rsc-media-type-DRqE_lD_.js +46 -0
  48. package/dist/_chunks/rsc-media-type-DRqE_lD_.js.map +1 -0
  49. package/dist/_chunks/rsc-payload-path-B_LBodc2.js +48 -0
  50. package/dist/_chunks/rsc-payload-path-B_LBodc2.js.map +1 -0
  51. package/dist/_chunks/scanner-C8b0Gcw3.js +1564 -0
  52. package/dist/_chunks/scanner-C8b0Gcw3.js.map +1 -0
  53. package/dist/_chunks/schema-bridge-Cc2Gngu1.js +199 -0
  54. package/dist/_chunks/schema-bridge-Cc2Gngu1.js.map +1 -0
  55. package/dist/_chunks/{segment-classify-Byy425ng.js → segment-classify-C539Pa2O.js} +23 -2
  56. package/dist/_chunks/segment-classify-C539Pa2O.js.map +1 -0
  57. package/dist/_chunks/segment-context-CjOlyB8Y.js +97 -0
  58. package/dist/_chunks/segment-context-CjOlyB8Y.js.map +1 -0
  59. package/dist/_chunks/{canonicalize-DQHyFClh.js → segment-keys-BawYuNFO.js} +61 -2
  60. package/dist/_chunks/segment-keys-BawYuNFO.js.map +1 -0
  61. package/dist/_chunks/slot-params-BCTmZkQB.js +76 -0
  62. package/dist/_chunks/slot-params-BCTmZkQB.js.map +1 -0
  63. package/dist/_chunks/{ssr-data-BOWsq18U.js → ssr-data-14MXm7Pj.js} +17 -2
  64. package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -0
  65. package/dist/_chunks/{use-query-states-DFvWd-EA.js → use-query-states-BbU5Ge1V.js} +74 -26
  66. package/dist/_chunks/use-query-states-BbU5Ge1V.js.map +1 -0
  67. package/dist/_chunks/use-segment-params-C4r4BD9T.js +398 -0
  68. package/dist/_chunks/use-segment-params-C4r4BD9T.js.map +1 -0
  69. package/dist/_chunks/walkers-RzN6AFjr.js +141 -0
  70. package/dist/_chunks/walkers-RzN6AFjr.js.map +1 -0
  71. package/dist/adapters/build-output-helper.d.ts +37 -0
  72. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  73. package/dist/adapters/cloudflare-dev.js +1 -1
  74. package/dist/adapters/cloudflare-kv-cache.js +1 -1
  75. package/dist/adapters/cloudflare.d.ts.map +1 -1
  76. package/dist/adapters/cloudflare.js +1 -1
  77. package/dist/adapters/compress-module.d.ts +12 -0
  78. package/dist/adapters/compress-module.d.ts.map +1 -1
  79. package/dist/adapters/fs-identity.d.ts +64 -0
  80. package/dist/adapters/fs-identity.d.ts.map +1 -0
  81. package/dist/adapters/nitro.d.ts.map +1 -1
  82. package/dist/adapters/nitro.js +56 -5
  83. package/dist/adapters/nitro.js.map +1 -1
  84. package/dist/adapters/shared.d.ts +57 -1
  85. package/dist/adapters/shared.d.ts.map +1 -1
  86. package/dist/adapters/types.d.ts +13 -1
  87. package/dist/adapters/types.d.ts.map +1 -1
  88. package/dist/cache/fast-hash.d.ts +5 -0
  89. package/dist/cache/fast-hash.d.ts.map +1 -1
  90. package/dist/cache/index.js +1 -1
  91. package/dist/cdn/cloudflare-purge.js +30 -0
  92. package/dist/cdn/cloudflare-purge.js.map +1 -0
  93. package/dist/cdn/fastly-purge.js +33 -0
  94. package/dist/cdn/fastly-purge.js.map +1 -0
  95. package/dist/cdn/index.js +94 -0
  96. package/dist/cdn/index.js.map +1 -0
  97. package/dist/cdn/workers-cache-purge.js +35 -0
  98. package/dist/cdn/workers-cache-purge.js.map +1 -0
  99. package/dist/cli-check.d.ts +153 -0
  100. package/dist/cli-check.d.ts.map +1 -0
  101. package/dist/cli.d.ts +34 -8
  102. package/dist/cli.d.ts.map +1 -1
  103. package/dist/cli.js +46 -21
  104. package/dist/cli.js.map +1 -1
  105. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  106. package/dist/client/browser-entry/hydrate.d.ts +20 -9
  107. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  108. package/dist/client/browser-entry/index.d.ts +1 -1
  109. package/dist/client/browser-entry/index.d.ts.map +1 -1
  110. package/dist/client/browser-entry/post-hydration.d.ts +4 -1
  111. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  112. package/dist/client/browser-entry/router-init.d.ts +3 -0
  113. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  114. package/dist/client/browser-entry/rsc-stream.d.ts +8 -0
  115. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -1
  116. package/dist/client/error-boundary.d.ts +7 -0
  117. package/dist/client/error-boundary.d.ts.map +1 -1
  118. package/dist/client/error-boundary.js +1 -162
  119. package/dist/client/history.d.ts +13 -6
  120. package/dist/client/history.d.ts.map +1 -1
  121. package/dist/client/index.d.ts +1 -0
  122. package/dist/client/index.d.ts.map +1 -1
  123. package/dist/client/index.js +42 -41
  124. package/dist/client/index.js.map +1 -1
  125. package/dist/client/internal.d.ts +4 -3
  126. package/dist/client/internal.d.ts.map +1 -1
  127. package/dist/client/internal.js +877 -311
  128. package/dist/client/internal.js.map +1 -1
  129. package/dist/client/link.d.ts +1 -7
  130. package/dist/client/link.d.ts.map +1 -1
  131. package/dist/client/navigation-api.d.ts +2 -2
  132. package/dist/client/navigation-commit.d.ts +87 -0
  133. package/dist/client/navigation-commit.d.ts.map +1 -0
  134. package/dist/client/navigation-context.d.ts +37 -20
  135. package/dist/client/navigation-context.d.ts.map +1 -1
  136. package/dist/client/navigation-root.d.ts +63 -23
  137. package/dist/client/navigation-root.d.ts.map +1 -1
  138. package/dist/client/params-context.d.ts +81 -0
  139. package/dist/client/params-context.d.ts.map +1 -0
  140. package/dist/client/router-effects.d.ts +129 -0
  141. package/dist/client/router-effects.d.ts.map +1 -0
  142. package/dist/client/router-lifecycle.d.ts +55 -0
  143. package/dist/client/router-lifecycle.d.ts.map +1 -0
  144. package/dist/client/router-pipeline.d.ts +84 -0
  145. package/dist/client/router-pipeline.d.ts.map +1 -0
  146. package/dist/client/router-ref.d.ts +1 -1
  147. package/dist/client/router-ref.d.ts.map +1 -1
  148. package/dist/client/router-skew.d.ts +21 -0
  149. package/dist/client/router-skew.d.ts.map +1 -0
  150. package/dist/client/router-types.d.ts +207 -0
  151. package/dist/client/router-types.d.ts.map +1 -0
  152. package/dist/client/router.d.ts +1 -182
  153. package/dist/client/router.d.ts.map +1 -1
  154. package/dist/client/rsc-fetch.d.ts +47 -26
  155. package/dist/client/rsc-fetch.d.ts.map +1 -1
  156. package/dist/client/segment-cache.d.ts +87 -34
  157. package/dist/client/segment-cache.d.ts.map +1 -1
  158. package/dist/client/ssr-data.d.ts +6 -0
  159. package/dist/client/ssr-data.d.ts.map +1 -1
  160. package/dist/client/stale-client.d.ts +69 -0
  161. package/dist/client/stale-client.d.ts.map +1 -0
  162. package/dist/client/state.d.ts +10 -1
  163. package/dist/client/state.d.ts.map +1 -1
  164. package/dist/client/top-loader.d.ts +2 -1
  165. package/dist/client/top-loader.d.ts.map +1 -1
  166. package/dist/client/unload-guard.d.ts +5 -0
  167. package/dist/client/unload-guard.d.ts.map +1 -1
  168. package/dist/client/use-cookie.d.ts.map +1 -1
  169. package/dist/client/use-query-states.d.ts +9 -3
  170. package/dist/client/use-query-states.d.ts.map +1 -1
  171. package/dist/client/use-router.d.ts +1 -1
  172. package/dist/client/use-segment-params.d.ts +18 -8
  173. package/dist/client/use-segment-params.d.ts.map +1 -1
  174. package/dist/codec.js +1 -1
  175. package/dist/cookies/define-cookie.d.ts.map +1 -1
  176. package/dist/cookies/index.js +5 -5
  177. package/dist/cookies/index.js.map +1 -1
  178. package/dist/index.d.ts +4 -1
  179. package/dist/index.d.ts.map +1 -1
  180. package/dist/index.js +1009 -759
  181. package/dist/index.js.map +1 -1
  182. package/dist/params/index.js +1 -1
  183. package/dist/plugin-context.d.ts +46 -0
  184. package/dist/plugin-context.d.ts.map +1 -1
  185. package/dist/plugins/adapter-build.d.ts.map +1 -1
  186. package/dist/plugins/build-manifest.d.ts +1 -1
  187. package/dist/plugins/build-manifest.d.ts.map +1 -1
  188. package/dist/plugins/entries.d.ts.map +1 -1
  189. package/dist/plugins/fonts.d.ts.map +1 -1
  190. package/dist/plugins/request-dep/analysis.d.ts +106 -0
  191. package/dist/plugins/request-dep/analysis.d.ts.map +1 -0
  192. package/dist/plugins/request-dep/index.d.ts +75 -0
  193. package/dist/plugins/request-dep/index.d.ts.map +1 -0
  194. package/dist/plugins/request-dep/origin.d.ts +61 -0
  195. package/dist/plugins/request-dep/origin.d.ts.map +1 -0
  196. package/dist/plugins/routing.d.ts.map +1 -1
  197. package/dist/plugins/shims.d.ts.map +1 -1
  198. package/dist/plugins/static-build.d.ts +160 -8
  199. package/dist/plugins/static-build.d.ts.map +1 -1
  200. package/dist/routing/codegen-shared.d.ts +3 -44
  201. package/dist/routing/codegen-shared.d.ts.map +1 -1
  202. package/dist/routing/codegen-types.d.ts +28 -31
  203. package/dist/routing/codegen-types.d.ts.map +1 -1
  204. package/dist/routing/codegen-write.d.ts +51 -0
  205. package/dist/routing/codegen-write.d.ts.map +1 -0
  206. package/dist/routing/codegen.d.ts.map +1 -1
  207. package/dist/routing/collision-probe.d.ts +104 -0
  208. package/dist/routing/collision-probe.d.ts.map +1 -0
  209. package/dist/routing/collision-spaces.d.ts +26 -0
  210. package/dist/routing/collision-spaces.d.ts.map +1 -0
  211. package/dist/routing/convention-lint.d.ts +18 -4
  212. package/dist/routing/convention-lint.d.ts.map +1 -1
  213. package/dist/routing/export-detect.d.ts +16 -0
  214. package/dist/routing/export-detect.d.ts.map +1 -1
  215. package/dist/routing/index.js +4 -3
  216. package/dist/routing/interception.d.ts +235 -6
  217. package/dist/routing/interception.d.ts.map +1 -1
  218. package/dist/routing/link-codegen.d.ts +19 -4
  219. package/dist/routing/link-codegen.d.ts.map +1 -1
  220. package/dist/routing/manifest-codegen.d.ts +1 -7
  221. package/dist/routing/manifest-codegen.d.ts.map +1 -1
  222. package/dist/routing/scanner.d.ts.map +1 -1
  223. package/dist/routing/segment-classify.d.ts +33 -0
  224. package/dist/routing/segment-classify.d.ts.map +1 -1
  225. package/dist/routing/segment-keys.d.ts +95 -0
  226. package/dist/routing/segment-keys.d.ts.map +1 -0
  227. package/dist/routing/slot-placement.d.ts +48 -0
  228. package/dist/routing/slot-placement.d.ts.map +1 -0
  229. package/dist/routing/types.d.ts +0 -6
  230. package/dist/routing/types.d.ts.map +1 -1
  231. package/dist/routing/walkers.d.ts +6 -0
  232. package/dist/routing/walkers.d.ts.map +1 -1
  233. package/dist/schema-bridge.d.ts +60 -9
  234. package/dist/schema-bridge.d.ts.map +1 -1
  235. package/dist/search-params/define.d.ts +62 -14
  236. package/dist/search-params/define.d.ts.map +1 -1
  237. package/dist/search-params/index.d.ts +0 -1
  238. package/dist/search-params/index.d.ts.map +1 -1
  239. package/dist/search-params/index.js +221 -10
  240. package/dist/search-params/index.js.map +1 -1
  241. package/dist/search-params/parse-total.d.ts +70 -0
  242. package/dist/search-params/parse-total.d.ts.map +1 -0
  243. package/dist/search-params/wrappers.d.ts +26 -3
  244. package/dist/search-params/wrappers.d.ts.map +1 -1
  245. package/dist/server/access-gate.d.ts +19 -8
  246. package/dist/server/access-gate.d.ts.map +1 -1
  247. package/dist/server/action-handler.d.ts.map +1 -1
  248. package/dist/server/actions.d.ts +6 -3
  249. package/dist/server/actions.d.ts.map +1 -1
  250. package/dist/server/als-registry.d.ts +18 -1
  251. package/dist/server/als-registry.d.ts.map +1 -1
  252. package/dist/server/build-manifest.d.ts +13 -1
  253. package/dist/server/build-manifest.d.ts.map +1 -1
  254. package/dist/server/chain-url-parts.d.ts +82 -0
  255. package/dist/server/chain-url-parts.d.ts.map +1 -0
  256. package/dist/server/children-interception.d.ts +49 -0
  257. package/dist/server/children-interception.d.ts.map +1 -0
  258. package/dist/server/compress.d.ts.map +1 -1
  259. package/dist/server/default-status-page.d.ts +45 -0
  260. package/dist/server/default-status-page.d.ts.map +1 -0
  261. package/dist/server/deny-boundary.d.ts +148 -15
  262. package/dist/server/deny-boundary.d.ts.map +1 -1
  263. package/dist/server/deny-renderer.d.ts +15 -4
  264. package/dist/server/deny-renderer.d.ts.map +1 -1
  265. package/dist/server/error-boundary-wrapper.d.ts +85 -15
  266. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  267. package/dist/server/head-response.d.ts +35 -0
  268. package/dist/server/head-response.d.ts.map +1 -0
  269. package/dist/server/index.d.ts +0 -1
  270. package/dist/server/index.d.ts.map +1 -1
  271. package/dist/server/index.js +3 -2
  272. package/dist/server/index.js.map +1 -1
  273. package/dist/server/internal.d.ts +3 -1
  274. package/dist/server/internal.d.ts.map +1 -1
  275. package/dist/server/internal.js +712 -418
  276. package/dist/server/internal.js.map +1 -1
  277. package/dist/server/metadata-collector.d.ts +52 -0
  278. package/dist/server/metadata-collector.d.ts.map +1 -0
  279. package/dist/server/param-coercion.d.ts +22 -6
  280. package/dist/server/param-coercion.d.ts.map +1 -1
  281. package/dist/server/pipeline-helpers.d.ts +0 -18
  282. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  283. package/dist/server/pipeline-interception.d.ts +59 -9
  284. package/dist/server/pipeline-interception.d.ts.map +1 -1
  285. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  286. package/dist/server/pipeline-phases.d.ts.map +1 -1
  287. package/dist/server/pipeline.d.ts +11 -0
  288. package/dist/server/pipeline.d.ts.map +1 -1
  289. package/dist/server/primitives.d.ts +23 -0
  290. package/dist/server/primitives.d.ts.map +1 -1
  291. package/dist/server/publish-params.d.ts +33 -0
  292. package/dist/server/publish-params.d.ts.map +1 -0
  293. package/dist/server/request-context.d.ts +48 -0
  294. package/dist/server/request-context.d.ts.map +1 -1
  295. package/dist/server/route-element-builder.d.ts +22 -3
  296. package/dist/server/route-element-builder.d.ts.map +1 -1
  297. package/dist/server/route-handler.d.ts.map +1 -1
  298. package/dist/server/route-matcher.d.ts +13 -0
  299. package/dist/server/route-matcher.d.ts.map +1 -1
  300. package/dist/server/rsc-cache-key-guard.d.ts +78 -0
  301. package/dist/server/rsc-cache-key-guard.d.ts.map +1 -0
  302. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  303. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  304. package/dist/server/rsc-entry/error-renderer.d.ts +15 -3
  305. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  306. package/dist/server/rsc-entry/helpers.d.ts +2 -17
  307. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  308. package/dist/server/rsc-entry/index.d.ts +0 -1
  309. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  310. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  311. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  312. package/dist/server/rsc-entry/rsc-payload.d.ts +1 -2
  313. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  314. package/dist/server/rsc-entry/rsc-stream.d.ts +15 -2
  315. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  316. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  317. package/dist/server/skippable-prefix.d.ts +23 -0
  318. package/dist/server/skippable-prefix.d.ts.map +1 -0
  319. package/dist/server/slot-interception.d.ts +80 -0
  320. package/dist/server/slot-interception.d.ts.map +1 -0
  321. package/dist/server/slot-resolver.d.ts +70 -8
  322. package/dist/server/slot-resolver.d.ts.map +1 -1
  323. package/dist/server/ssr-bridge-types.d.ts +17 -0
  324. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  325. package/dist/server/ssr-entry.d.ts +0 -1
  326. package/dist/server/ssr-entry.d.ts.map +1 -1
  327. package/dist/server/ssr-wrappers.d.ts +24 -13
  328. package/dist/server/ssr-wrappers.d.ts.map +1 -1
  329. package/dist/server/state-tree-diff.d.ts +6 -27
  330. package/dist/server/state-tree-diff.d.ts.map +1 -1
  331. package/dist/server/static-generator.d.ts +6 -0
  332. package/dist/server/static-generator.d.ts.map +1 -1
  333. package/dist/server/static-not-found.d.ts +52 -0
  334. package/dist/server/static-not-found.d.ts.map +1 -0
  335. package/dist/server/status-code-resolver.d.ts +8 -1
  336. package/dist/server/status-code-resolver.d.ts.map +1 -1
  337. package/dist/server/tree-builder.d.ts +28 -36
  338. package/dist/server/tree-builder.d.ts.map +1 -1
  339. package/dist/server/types.d.ts +12 -7
  340. package/dist/server/types.d.ts.map +1 -1
  341. package/dist/server/utils/element-type.d.ts +40 -0
  342. package/dist/server/utils/element-type.d.ts.map +1 -0
  343. package/dist/shared/als-slots.d.ts +41 -0
  344. package/dist/shared/als-slots.d.ts.map +1 -0
  345. package/dist/shared/base-path.d.ts +56 -0
  346. package/dist/shared/base-path.d.ts.map +1 -0
  347. package/dist/shared/param-value.d.ts +80 -0
  348. package/dist/shared/param-value.d.ts.map +1 -0
  349. package/dist/shared/payload-root.d.ts +108 -0
  350. package/dist/shared/payload-root.d.ts.map +1 -0
  351. package/dist/shared/rsc-cache-key.d.ts +163 -0
  352. package/dist/shared/rsc-cache-key.d.ts.map +1 -0
  353. package/dist/shared/rsc-error-envelope.d.ts +25 -0
  354. package/dist/shared/rsc-error-envelope.d.ts.map +1 -0
  355. package/dist/shared/rsc-manifest.d.ts +28 -0
  356. package/dist/shared/rsc-manifest.d.ts.map +1 -0
  357. package/dist/shared/rsc-media-type.d.ts +40 -0
  358. package/dist/shared/rsc-media-type.d.ts.map +1 -0
  359. package/dist/shared/rsc-payload-path.d.ts +42 -0
  360. package/dist/shared/rsc-payload-path.d.ts.map +1 -0
  361. package/dist/shared/segment-info.d.ts +59 -0
  362. package/dist/shared/segment-info.d.ts.map +1 -0
  363. package/dist/shared/slot-params.d.ts +51 -0
  364. package/dist/shared/slot-params.d.ts.map +1 -0
  365. package/dist/shared/static-platform-files.d.ts +71 -0
  366. package/dist/shared/static-platform-files.d.ts.map +1 -0
  367. package/docs/api/30-api-server.mdx +1 -1
  368. package/docs/api/31-api-client.mdx +4 -2
  369. package/docs/api/33-api-search-params.mdx +38 -16
  370. package/docs/api/35-api-typescript.mdx +3 -3
  371. package/docs/api/36-cli.mdx +34 -7
  372. package/docs/learn/00-introduction.mdx +1 -1
  373. package/docs/learn/02-pages-and-layouts.mdx +2 -2
  374. package/docs/learn/05-typed-params.mdx +8 -8
  375. package/docs/learn/07-typed-routes.mdx +12 -7
  376. package/docs/learn/11-error-handling.mdx +18 -0
  377. package/docs/learn/12-client-navigation.mdx +2 -2
  378. package/docs/learn/14-deploying.mdx +23 -0
  379. package/docs/more/01-advanced-routing.mdx +173 -3
  380. package/docs/more/03-coming-from-nextjs.mdx +2 -2
  381. package/docs/more/04-metadata-and-fonts.mdx +1 -1
  382. package/docs/more/50-ai-agent-instructions.mdx +6 -4
  383. package/package.json +9 -6
  384. package/src/adapters/build-output-helper.ts +116 -3
  385. package/src/adapters/cloudflare.ts +90 -12
  386. package/src/adapters/compress-module.ts +79 -1
  387. package/src/adapters/fs-identity.ts +156 -0
  388. package/src/adapters/nitro.ts +6 -6
  389. package/src/adapters/shared.ts +196 -21
  390. package/src/adapters/types.ts +13 -1
  391. package/src/cache/fast-hash.ts +5 -0
  392. package/src/cli-check.ts +458 -0
  393. package/src/cli.ts +59 -24
  394. package/src/client/browser-entry/action-dispatch.ts +11 -5
  395. package/src/client/browser-entry/hydrate.ts +40 -29
  396. package/src/client/browser-entry/index.ts +15 -6
  397. package/src/client/browser-entry/post-hydration.ts +10 -9
  398. package/src/client/browser-entry/router-init.ts +104 -48
  399. package/src/client/browser-entry/rsc-stream.ts +11 -2
  400. package/src/client/error-boundary.tsx +85 -16
  401. package/src/client/history.ts +13 -6
  402. package/src/client/index.ts +14 -3
  403. package/src/client/internal.ts +4 -3
  404. package/src/client/link.tsx +120 -72
  405. package/src/client/navigation-api.ts +3 -3
  406. package/src/client/navigation-commit.ts +197 -0
  407. package/src/client/navigation-context.ts +40 -67
  408. package/src/client/navigation-root.tsx +326 -101
  409. package/src/client/params-context.ts +192 -0
  410. package/src/client/router-effects.ts +231 -0
  411. package/src/client/router-lifecycle.ts +288 -0
  412. package/src/client/router-pipeline.ts +393 -0
  413. package/src/client/router-ref.ts +1 -1
  414. package/src/client/router-skew.ts +30 -0
  415. package/src/client/router-types.ts +230 -0
  416. package/src/client/router.ts +243 -707
  417. package/src/client/rsc-fetch.ts +183 -106
  418. package/src/client/segment-cache.ts +129 -44
  419. package/src/client/ssr-data.ts +6 -0
  420. package/src/client/stale-client.ts +191 -0
  421. package/src/client/state.ts +14 -1
  422. package/src/client/top-loader.tsx +2 -1
  423. package/src/client/unload-guard.ts +34 -2
  424. package/src/client/use-cookie.ts +9 -2
  425. package/src/client/use-query-states.ts +102 -39
  426. package/src/client/use-router.ts +1 -1
  427. package/src/client/use-segment-params.ts +41 -18
  428. package/src/cookies/define-cookie.ts +6 -1
  429. package/src/index.ts +25 -4
  430. package/src/plugin-context.ts +58 -0
  431. package/src/plugins/adapter-build.ts +4 -0
  432. package/src/plugins/build-manifest.ts +34 -13
  433. package/src/plugins/entries.ts +4 -0
  434. package/src/plugins/fonts.ts +11 -8
  435. package/src/plugins/request-dep/analysis.ts +447 -0
  436. package/src/plugins/request-dep/index.ts +376 -0
  437. package/src/plugins/request-dep/origin.ts +310 -0
  438. package/src/plugins/routing.ts +97 -102
  439. package/src/plugins/shims.ts +0 -1
  440. package/src/plugins/static-build.ts +391 -95
  441. package/src/routing/codegen-shared.ts +3 -79
  442. package/src/routing/codegen-types.ts +28 -31
  443. package/src/routing/codegen-write.ts +139 -0
  444. package/src/routing/codegen.ts +86 -172
  445. package/src/routing/collision-probe.ts +438 -0
  446. package/src/routing/collision-spaces.ts +281 -0
  447. package/src/routing/convention-lint.ts +139 -40
  448. package/src/routing/export-detect.ts +151 -7
  449. package/src/routing/interception.ts +896 -50
  450. package/src/routing/link-codegen.ts +32 -65
  451. package/src/routing/manifest-codegen.ts +6 -62
  452. package/src/routing/scanner.ts +117 -92
  453. package/src/routing/segment-classify.ts +57 -0
  454. package/src/routing/segment-keys.ts +146 -0
  455. package/src/routing/slot-placement.ts +97 -0
  456. package/src/routing/types.ts +0 -6
  457. package/src/routing/walkers.ts +8 -0
  458. package/src/schema-bridge.ts +180 -58
  459. package/src/search-params/define.ts +108 -66
  460. package/src/search-params/index.ts +0 -1
  461. package/src/search-params/parse-total.ts +78 -0
  462. package/src/search-params/wrappers.ts +60 -11
  463. package/src/server/access-gate.tsx +60 -40
  464. package/src/server/action-handler.ts +4 -5
  465. package/src/server/actions.ts +6 -3
  466. package/src/server/als-registry.ts +18 -1
  467. package/src/server/build-manifest.ts +14 -1
  468. package/src/server/chain-url-parts.ts +163 -0
  469. package/src/server/children-interception.ts +115 -0
  470. package/src/server/compress.ts +9 -1
  471. package/src/server/default-status-page.ts +127 -0
  472. package/src/server/deny-boundary.ts +269 -41
  473. package/src/server/deny-renderer.ts +111 -39
  474. package/src/server/error-boundary-wrapper.ts +166 -79
  475. package/src/server/head-response.ts +54 -0
  476. package/src/server/index.ts +1 -3
  477. package/src/server/internal.ts +2 -2
  478. package/src/server/metadata-collector.ts +115 -0
  479. package/src/server/param-coercion.ts +51 -69
  480. package/src/server/pipeline-helpers.ts +2 -47
  481. package/src/server/pipeline-interception.ts +81 -32
  482. package/src/server/pipeline-outcome.ts +4 -5
  483. package/src/server/pipeline-phases.ts +77 -25
  484. package/src/server/pipeline.ts +57 -10
  485. package/src/server/prebuilt-runtime.ts +4 -4
  486. package/src/server/primitives.ts +25 -0
  487. package/src/server/publish-params.ts +42 -0
  488. package/src/server/request-context.ts +97 -18
  489. package/src/server/route-element-builder.ts +241 -253
  490. package/src/server/route-handler.ts +8 -8
  491. package/src/server/route-matcher.ts +21 -9
  492. package/src/server/rsc-cache-key-guard.ts +164 -0
  493. package/src/server/rsc-entry/api-handler.ts +6 -8
  494. package/src/server/rsc-entry/deny-fallback.ts +3 -2
  495. package/src/server/rsc-entry/error-renderer.ts +94 -35
  496. package/src/server/rsc-entry/helpers.ts +33 -28
  497. package/src/server/rsc-entry/index.ts +36 -33
  498. package/src/server/rsc-entry/render-route.ts +18 -10
  499. package/src/server/rsc-entry/revalidate-renderer.ts +3 -2
  500. package/src/server/rsc-entry/rsc-payload.ts +113 -40
  501. package/src/server/rsc-entry/rsc-stream.ts +29 -5
  502. package/src/server/rsc-entry/ssr-renderer.ts +38 -22
  503. package/src/server/skippable-prefix.ts +92 -0
  504. package/src/server/slot-interception.ts +168 -0
  505. package/src/server/slot-resolver.ts +263 -158
  506. package/src/server/ssr-bridge-types.ts +18 -0
  507. package/src/server/ssr-entry.ts +20 -10
  508. package/src/server/ssr-wrappers.tsx +33 -32
  509. package/src/server/state-tree-diff.ts +14 -55
  510. package/src/server/static-generator.ts +68 -29
  511. package/src/server/static-not-found.ts +134 -0
  512. package/src/server/status-code-resolver.ts +28 -11
  513. package/src/server/tree-builder.ts +35 -218
  514. package/src/server/types.ts +12 -7
  515. package/src/server/utils/element-type.ts +72 -0
  516. package/src/shared/als-slots.ts +72 -0
  517. package/src/shared/base-path.ts +80 -0
  518. package/src/shared/param-value.ts +244 -0
  519. package/src/shared/payload-root.ts +151 -0
  520. package/src/shared/rsc-cache-key.ts +269 -0
  521. package/src/shared/rsc-error-envelope.ts +31 -0
  522. package/src/shared/rsc-manifest.ts +29 -0
  523. package/src/shared/rsc-media-type.ts +43 -0
  524. package/src/shared/rsc-payload-path.ts +45 -0
  525. package/src/shared/segment-info.ts +60 -0
  526. package/src/shared/slot-params.ts +111 -0
  527. package/src/shared/static-platform-files.ts +75 -0
  528. package/dist/_chunks/build-output-helper-DOGYFb_X.js +0 -196
  529. package/dist/_chunks/build-output-helper-DOGYFb_X.js.map +0 -1
  530. package/dist/_chunks/cache-api-B-lhk9p4.js.map +0 -1
  531. package/dist/_chunks/canonicalize-DQHyFClh.js.map +0 -1
  532. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js +0 -668
  533. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js.map +0 -1
  534. package/dist/_chunks/define-COtkxMRT.js +0 -191
  535. package/dist/_chunks/define-COtkxMRT.js.map +0 -1
  536. package/dist/_chunks/define-c4au4I9R.js +0 -82
  537. package/dist/_chunks/define-c4au4I9R.js.map +0 -1
  538. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +0 -1
  539. package/dist/_chunks/logger-AWfuX-KJ.js.map +0 -1
  540. package/dist/_chunks/navigation-root-bUDZLw74.js +0 -124
  541. package/dist/_chunks/navigation-root-bUDZLw74.js.map +0 -1
  542. package/dist/_chunks/plugin-context---kTF5v8.js.map +0 -1
  543. package/dist/_chunks/registry-DbJPKoBp.js +0 -20
  544. package/dist/_chunks/registry-DbJPKoBp.js.map +0 -1
  545. package/dist/_chunks/router-ref-CtmF-aPv.js.map +0 -1
  546. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +0 -119
  547. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +0 -1
  548. package/dist/_chunks/segment-classify-Byy425ng.js.map +0 -1
  549. package/dist/_chunks/segment-context-ZDnXDkbz.js +0 -34
  550. package/dist/_chunks/segment-context-ZDnXDkbz.js.map +0 -1
  551. package/dist/_chunks/ssr-data-BOWsq18U.js.map +0 -1
  552. package/dist/_chunks/use-query-states-DFvWd-EA.js.map +0 -1
  553. package/dist/_chunks/use-segment-params-D1CzlgBo.js +0 -151
  554. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +0 -1
  555. package/dist/_chunks/walkers-_6zKFlch.js +0 -1002
  556. package/dist/_chunks/walkers-_6zKFlch.js.map +0 -1
  557. package/dist/client/error-boundary.js.map +0 -1
  558. package/dist/plugins/request-dep.d.ts +0 -32
  559. package/dist/plugins/request-dep.d.ts.map +0 -1
  560. package/dist/search-params/registry.d.ts +0 -20
  561. package/dist/search-params/registry.d.ts.map +0 -1
  562. package/dist/segment-params/define.d.ts +0 -89
  563. package/dist/segment-params/define.d.ts.map +0 -1
  564. package/dist/segment-params/index.d.ts +0 -3
  565. package/dist/segment-params/index.d.ts.map +0 -1
  566. package/dist/segment-params/index.js +0 -2
  567. package/src/plugins/request-dep.ts +0 -499
  568. package/src/search-params/registry.ts +0 -31
  569. package/src/segment-params/define.ts +0 -249
  570. package/src/segment-params/index.ts +0 -9
@@ -30,6 +30,8 @@ import { checkVersionSkew, applyReloadHeaders } from './version-skew.js';
30
30
  import { serveStaticMetadataFile, serializeSitemap } from './pipeline-metadata.js';
31
31
  import { loadModule } from './safe-load.js';
32
32
  import { findInterceptionMatch } from './pipeline-interception.js';
33
+ import { computeSegmentTreePaths } from '../routing/segment-keys.js';
34
+ import { parseClientStateTree } from './state-tree-diff.js';
33
35
  import { applyCookieJar, cloneWithMutableHeaders, type ProxyResolver } from './pipeline-helpers.js';
34
36
  import { coerceSegmentParams } from './param-coercion.js';
35
37
  import { outcomeToResponse, type PhaseOutcome } from './pipeline-outcome.js';
@@ -37,6 +39,7 @@ import type { InterceptionContext, PipelineConfig, RouteMatch } from './pipeline
37
39
  import type { MetadataHandler, MetadataRoute, MiddlewareContext } from './types.js';
38
40
  import { swallow } from './logger.js';
39
41
  import { isDebug } from './debug.js';
42
+ import { isRscRequest } from '../shared/rsc-media-type.js';
40
43
 
41
44
  interface RenderContext {
42
45
  canonicalPathname: string;
@@ -293,17 +296,6 @@ export async function handleRequest(
293
296
  // outer Server-Timing writer can append without hitting an
294
297
  // immutable header bag (e.g. user returns Response.redirect()).
295
298
  if (handlerResult instanceof Response) {
296
- if (method === 'HEAD') {
297
- const headHeaders = new Headers(handlerResult.headers);
298
- if (handlerResult.ok && !headHeaders.has('Cache-Control')) {
299
- headHeaders.set('Cache-Control', 'public, max-age=14400, must-revalidate');
300
- }
301
- return new Response(null, {
302
- status: handlerResult.status,
303
- statusText: handlerResult.statusText,
304
- headers: headHeaders,
305
- });
306
- }
307
299
  const res = cloneWithMutableHeaders(handlerResult);
308
300
  if (res.ok && !res.headers.has('Cache-Control')) {
309
301
  res.headers.set('Cache-Control', 'public, max-age=14400, must-revalidate');
@@ -376,8 +368,8 @@ export async function handleRequest(
376
368
  // deployment ID matches the current build. On mismatch, signal the
377
369
  // client to do a full page reload instead of returning an RSC payload
378
370
  // that references mismatched module IDs.
379
- const isRscRequest = (req.headers.get('Accept') ?? '').includes('text/x-component');
380
- if (isRscRequest) {
371
+ const isRsc = isRscRequest(req);
372
+ if (isRsc) {
381
373
  const skewCheck = checkVersionSkew(req);
382
374
  if (!skewCheck.ok) {
383
375
  const reloadHeaders = new Headers();
@@ -395,20 +387,81 @@ export async function handleRequest(
395
387
  // to prevent spoofing from plain HTML navigations or raw HTTP clients.
396
388
  // The header value must be a valid relative pathname — reject schemes,
397
389
  // authority, and control characters. Canonicalize before matching.
398
- if (isRscRequest && config.interceptionRewrites?.length) {
390
+ if (isRsc && config.interceptionRewrites?.length) {
399
391
  const rawSourceUrl = req.headers.get('X-Timber-URL');
400
392
  const validatedSourceUrl = rawSourceUrl
401
393
  ? validateInterceptionHeader(rawSourceUrl, stripTrailingSlash)
402
394
  : null;
403
395
  if (validatedSourceUrl) {
404
- const intercepted = findInterceptionMatch(
396
+ // The scope of an interception is the segment that owns the intercepting
397
+ // slot, so the guard asks whether the route the user is LEAVING renders
398
+ // that segment. Two independent answers to "what is on screen?", tried in
399
+ // order — deferred behind a thunk so neither runs unless a rewrite's
400
+ // target pattern matches.
401
+ //
402
+ // 1. What the client says it has mounted (X-Timber-State-Tree
403
+ // `treePaths`). Authoritative about tree shape and nothing else.
404
+ // 2. What re-matching X-Timber-URL implies. Correct while the address bar
405
+ // still holds the source page, which stops being true the moment a
406
+ // modal is open — the address is then the *intercepted* URL and
407
+ // re-matching it resolves through whichever group owns the canonical
408
+ // page (TIM-1282).
409
+ //
410
+ // Neither is trusted: both are client-supplied, and satisfying the scope
411
+ // only selects which build-time rewrite applies. The rendered pathname is
412
+ // always the rewrite's own `interceptingPrefix`, the server re-derives the
413
+ // rendered chain from it below, and every access.ts runs regardless.
414
+ //
415
+ // They are handed over as two sets in that order rather than one union:
416
+ // each describes a single rendered chain, and only within one chain does
417
+ // "the deepest scope" name the innermost owner (TIM-1318). Unioned, a
418
+ // deeper scope from the address-implied canonical branch — which after
419
+ // (2) may be a route group the client never mounted — would outrank the
420
+ // owner actually on screen.
421
+ const resolveSourceScopes = () => {
422
+ const mounted = new Set(parseClientStateTree(req)?.treePaths ?? []);
423
+ const sourceRoute = config.matchRoute(validatedSourceUrl);
424
+ const addressed = new Set(sourceRoute ? computeSegmentTreePaths(sourceRoute.segments) : []);
425
+ const scopes = [mounted, addressed].filter((scope) => scope.size > 0);
426
+ // Neither channel produced a tree — no scope can contain anything, and
427
+ // an origin that matches no route is not a legitimate soft navigation.
428
+ return scopes.length > 0 ? scopes : null;
429
+ };
430
+ const rewrite = findInterceptionMatch(
405
431
  canonicalPathname,
406
- validatedSourceUrl,
432
+ resolveSourceScopes,
407
433
  config.interceptionRewrites
408
434
  );
409
- if (intercepted) {
410
- const sourceMatch = config.matchRoute(intercepted.sourcePathname);
411
- if (sourceMatch) {
435
+ if (rewrite?.mode === 'children') {
436
+ // Sibling layout swap (TIM-1280). Nothing is re-matched: the resolver
437
+ // addresses the owner directory by tree path and returns the chain
438
+ // `[…owner ancestors, interceptingNode, …descendants]`, which renders
439
+ // as an ordinary route. `interception` stays unset — there is no slot
440
+ // to intercept into, and setting it would additionally arm the modal
441
+ // path for every slot in the tree we are about to render.
442
+ //
443
+ // A null here means the scope named nothing in this manifest, or no
444
+ // intercepting child matched the target. Both fall through to the
445
+ // canonical route, which is what a hard navigation renders.
446
+ const interceptedMatch = config.matchInterceptedRoute?.(
447
+ canonicalPathname,
448
+ rewrite.interceptingScope
449
+ );
450
+ if (interceptedMatch) match = interceptedMatch;
451
+ } else if (rewrite) {
452
+ const sourceMatch = config.matchRoute(rewrite.interceptingPrefix);
453
+ // The scope test above was about the route the user is LEAVING. The
454
+ // route we are about to render is a different one —
455
+ // `interceptingPrefix` is URL-derived, and route groups are
456
+ // URL-invisible, so `/` can resolve into a sibling group that does not
457
+ // own the slot. Rendering that would reproduce the TIM-1278 failure on
458
+ // a valid tree: the rewrite hijacks the navigation and no slot exists
459
+ // to render the intercepting page. Fall through to the canonical
460
+ // target route instead.
461
+ const rendersTheSlot =
462
+ sourceMatch !== null &&
463
+ computeSegmentTreePaths(sourceMatch.segments).includes(rewrite.interceptingScope);
464
+ if (rendersTheSlot) {
412
465
  match = sourceMatch;
413
466
  interception = { targetPathname: canonicalPathname };
414
467
  }
@@ -459,7 +512,7 @@ export async function handleRequest(
459
512
  | { route?: unknown; page?: unknown }
460
513
  | undefined;
461
514
  const isApiRoute = leafSegment?.route && !leafSegment?.page;
462
- if (config.earlyHints && !isRscRequest && !isApiRoute) {
515
+ if (config.earlyHints && !isRsc && !isApiRoute) {
463
516
  try {
464
517
  await config.earlyHints(match, req, responseHeaders);
465
518
  } catch (err) {
@@ -468,8 +521,8 @@ export async function handleRequest(
468
521
  }
469
522
 
470
523
  // Stage 2c: Param coercion (before middleware)
471
- // Load params.ts modules from matched segments and coerce raw string
472
- // params through defineSegmentParams codecs. Coercion failure → 404
524
+ // Coerce raw string params through the app/schema.ts codecs.
525
+ // Coercion failure → 404
473
526
  // (middleware never runs). See design/07-routing.md §"Where Coercion Runs"
474
527
  //
475
528
  // Snapshot raw params before coercion — slot resolution needs the
@@ -488,9 +541,8 @@ export async function handleRequest(
488
541
  `[timber] Param coercion failed for ${method} ${canonicalPathname} — responding with 404\n` +
489
542
  ` Matched segments: ${segmentChain}\n` +
490
543
  ` Error: ${error.message}\n` +
491
- ` This usually means a params.ts codec rejected the URL params.\n` +
492
- ` Check that all fields in defineSegmentParams() are optional for params\n` +
493
- ` that don't appear at every route depth (e.g. year, month, day).`
544
+ ` This usually means a codec in app/schema.ts rejected the URL value.\n` +
545
+ ` Check the codec for the bracket key of the segment named above.`
494
546
  );
495
547
  }
496
548
  // For API routes (route.ts), return a bare 404 — not an HTML page.
@@ -35,6 +35,9 @@ import { makeProxyResolver } from './pipeline-helpers.js';
35
35
  import { handleRequest, runProxyPhase } from './pipeline-phases.js';
36
36
  import { outcomeToResponse } from './pipeline-outcome.js';
37
37
  import { canonicalize } from './canonicalize.js';
38
+ import { enforceRscCacheKey, hardenRscPayloadResponse } from './rsc-cache-key-guard.js';
39
+ import { stripHeadBody } from './head-response.js';
40
+ import { RSC_KEY_HEADERS } from '../shared/rsc-cache-key.js';
38
41
  import { isDebug } from './debug.js';
39
42
 
40
43
  // ─── Route Match Result ────────────────────────────────────────────────────
@@ -142,6 +145,17 @@ export interface PipelineConfig {
142
145
  * See design/07-routing.md §"Intercepting Routes"
143
146
  */
144
147
  interceptionRewrites?: import('../routing/interception.js').InterceptionRewrite[];
148
+ /**
149
+ * Resolver for children-path interceptions — the sibling layout swap.
150
+ *
151
+ * Separate from `matchRoute` because it addresses the owner directory by
152
+ * tree path rather than by pathname, which needs the manifest tree itself.
153
+ * Omitting it disables the `'children'` interception shape and leaves the
154
+ * canonical route rendering, which is the fail-safe outcome.
155
+ *
156
+ * See design/07-routing.md §"Intercepting Routes"
157
+ */
158
+ matchInterceptedRoute?: import('./children-interception.js').InterceptedRouteMatcher;
145
159
  /**
146
160
  * Control Server-Timing header output.
147
161
  *
@@ -393,17 +407,30 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
393
407
  // DevSpanProcessor reads this for tree/summary output.
394
408
  await setSpanAttribute('http.response.status_code', result.status);
395
409
 
396
- // Vary: Accept — CDNs must cache HTML and RSC payload responses
397
- // separately for the same URL. Without this, a shared cache may
398
- // serve an RSC Flight payload to a browser expecting HTML (or
399
- // vice versa). See GHSA-wfc6-r584-vfw7, design/13-security.md.
410
+ // Vary on exactly the headers the `_rsc` cache key hashes.
400
411
  //
401
- // Vary: X-Timber-URL — intercepting route responses depend on
402
- // the source URL, so caches must store them separately.
403
- const varyTokens = ['Accept'];
404
- if (config.interceptionRewrites?.length) {
405
- varyTokens.push('X-Timber-URL');
406
- }
412
+ // Those two mechanisms answer the same question — which request
413
+ // headers change this response — so they are the same list, not
414
+ // two lists that happen to agree. A separate hand-written list
415
+ // here drifted from `RSC_KEY_HEADERS` the moment the key set
416
+ // grew, and the drift is invisible: `Vary` is the *fallback*
417
+ // layer, used only when a cache omits the query from its key,
418
+ // which is precisely when nobody is watching (TIM-1268).
419
+ //
420
+ // Why any of it: without `Vary: Accept` a shared cache may serve
421
+ // an RSC Flight payload to a browser expecting HTML, or the
422
+ // reverse (GHSA-wfc6-r584-vfw7, design/13-security.md). The
423
+ // `_rsc` param puts that distinction in the URL, so correctness
424
+ // no longer *depends* on `Vary` — which is opt-in configuration
425
+ // on Cloudflare and CloudFront. `Vary` covers the requests that
426
+ // arrive without the param: a stripped query, a hand-rolled
427
+ // client.
428
+ //
429
+ // It costs no hit rate. Document requests send no `X-Timber-*`
430
+ // header at all, so they collapse to a single cache key; payload
431
+ // requests are already fragmented by these same values via the
432
+ // URL.
433
+ const varyTokens = [...RSC_KEY_HEADERS];
407
434
  const existingVary = result.headers.get('Vary');
408
435
  const existingTokens = existingVary
409
436
  ? existingVary
@@ -419,6 +446,26 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
419
446
  );
420
447
  }
421
448
 
449
+ // A request may only claim an `_rsc` cache key that matches its
450
+ // own headers. The key is predictable by design, so without this
451
+ // a caller could render its own variant under another client's
452
+ // key and have a shared cache store it there (TIM-1268).
453
+ await enforceRscCacheKey(canonicalReq, result);
454
+
455
+ // Flight payloads must never be sniffable into a renderable
456
+ // type — applied at this single exit so every producer is
457
+ // covered, not just the success path (TIM-1268).
458
+ hardenRscPayloadResponse(result);
459
+
460
+ // A HEAD response carries the headers its GET would produce and
461
+ // no content (RFC 9110 §9.3.2). Applied at this single exit so
462
+ // every response shape is covered — page render, API route,
463
+ // metadata route, deny page, error page, proxy short-circuit —
464
+ // rather than per-renderer, where it was missing for page
465
+ // renders entirely (TIM-1324). The render still runs: the
466
+ // headers have to be the ones a GET would have sent.
467
+ result = stripHeadBody(result, method);
468
+
422
469
  // Append Server-Timing header based on configured mode.
423
470
  // Header mutability is guaranteed by the producer-side clone
424
471
  // in `outcomeToResponse` and the metadata-route / auto-sitemap
@@ -173,17 +173,17 @@ const registry = new Map<string, PrebuiltRegistration>();
173
173
  */
174
174
  function resolveKeyParams(store: {
175
175
  segmentParams?: Record<string, string | string[]>;
176
- slotParamsMap?: Map<string, Record<string, string | string[]>>;
176
+ slotParams?: Record<string, Record<string, string | string[]>>;
177
177
  }): Record<string, string | string[]> | null {
178
178
  const main = store.segmentParams ?? {};
179
- const map = store.slotParamsMap;
180
- if (!map || map.size === 0) return main;
179
+ const slots = store.slotParams;
180
+ if (!slots || Object.keys(slots).length === 0) return main;
181
181
  // Spread before canonicalizing: param records are framework-produced
182
182
  // Object.create(null) objects (prototype-pollution defense) — normalize
183
183
  // the records themselves, let nested values face the full allowlist.
184
184
  const mainCanonical = tryCanonicalize({ ...main });
185
185
  if (mainCanonical === null) return null;
186
- for (const slotParams of map.values()) {
186
+ for (const slotParams of Object.values(slots)) {
187
187
  const merged = tryCanonicalize({ ...main, ...slotParams });
188
188
  if (merged === null || merged !== mainCanonical) return null;
189
189
  }
@@ -113,6 +113,31 @@ export class DenySignal extends Error {
113
113
  readonly status: number;
114
114
  readonly data: JsonSerializable | undefined;
115
115
 
116
+ /**
117
+ * Segment key of the segment that owns the deny page matched for this
118
+ * signal — set by a framework catch site that matched an entry it may not
119
+ * render at its own position, and re-threw so the boundary at the owning
120
+ * segment renders it instead.
121
+ *
122
+ * Written only by the three in-tree catch sites (`PageDenyBoundary`,
123
+ * `TracedLayout`, `AccessGate`), never by user code. Two readers depend on
124
+ * it: `TimberErrorBoundary`, which declines any deny whose `ownerKey` is
125
+ * not its own `segmentKey`, and `buildRscPayloadResponse`, which keeps
126
+ * streaming instead of re-rendering when it is set.
127
+ *
128
+ * See design/04-authorization.md §"Where a Deny Page Renders", TIM-1356.
129
+ */
130
+ ownerKey?: string;
131
+
132
+ /**
133
+ * When true, the pipeline must respond with `rscErrorEnvelope` so the
134
+ * client hard-navigates instead of attempting to render a deny page
135
+ * from the RSC payload. Set by AccessGate when a skipped segment
136
+ * denies — rendering the deny page in-tree would appear inside the
137
+ * client's cached layout chrome (TIM-1074). See TIM-1363.
138
+ */
139
+ _hardNavigate?: boolean;
140
+
116
141
  constructor(status: number, data?: JsonSerializable) {
117
142
  super(`Access denied with status ${status}`);
118
143
  this.name = 'DenySignal';
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Publishing the request's params onto the RSC payload.
3
+ *
4
+ * Every tree the server sends the browser goes through here: the ordinary
5
+ * route payload (`route-element-builder.ts`), both deny renderers
6
+ * (`deny-renderer.ts`) and the error renderer. One helper rather than a wrap
7
+ * at each site, because these previously *were* separate sites — a response
8
+ * header, an inline script, and a second copy of each on the deny path — and
9
+ * the deny path shipping empty params was the bug that came of it (TIM-1285).
10
+ *
11
+ * Reads the request store rather than taking params as an argument, so a
12
+ * caller cannot pass a different record than the one the request rendered
13
+ * with. See design/41-global-params.md §"Transport".
14
+ */
15
+
16
+ import { toPlainRecord } from '../shared/param-value.js';
17
+ import type { RscPayloadRoot } from '../shared/payload-root.js';
18
+ import { getSegmentParamsForClient, getSlotParamsForClient } from './request-context.js';
19
+
20
+ /**
21
+ * Build the payload root: the tree, and the params it rendered with beside it.
22
+ *
23
+ * The params are a *sibling* of the tree, not a provider around it. A provider
24
+ * inside the payload is shadowed by the retained tree's own provider on a
25
+ * partial navigation, and its props are not readable at the instant the root
26
+ * row resolves — see `shared/payload-root.ts` for both, and TIM-1297. The
27
+ * client renders the one provider readers see, above the merge point.
28
+ *
29
+ * The records are flattened to plain objects on the way out. Every param
30
+ * record the framework builds is `Object.create(null)` (design/13-security.md
31
+ * #36b/#36c), and React Flight rejects a null prototype — "Classes or null
32
+ * prototypes are not supported". `ParamsProvider` restores the prototype on
33
+ * the other side, so what the app reads is unchanged; only the wire
34
+ * representation differs.
35
+ */
36
+ export function withPublishedParams(element: React.ReactElement): RscPayloadRoot {
37
+ return {
38
+ tree: element,
39
+ params: toPlainRecord(getSegmentParamsForClient()),
40
+ slotParams: toPlainRecord(getSlotParamsForClient() ?? null),
41
+ };
42
+ }
@@ -15,9 +15,14 @@
15
15
  */
16
16
 
17
17
  import { requestContextAls, type RequestContextStore } from './als-registry.js';
18
- import { _setGetSearchParamsFn } from '../search-params/define.js';
19
- import { _setGetSegmentParamsFn } from '../segment-params/define.js';
18
+ import { _setGetSearchParamsFn, _setGetSegmentParamsFn } from '../shared/als-slots.js';
20
19
  import { consumeSeededCookies } from './cookie-context.js';
20
+ import { appVisibleSearch } from '../shared/rsc-cache-key.js';
21
+ import {
22
+ mergeSlotParams,
23
+ resolveSegmentParams,
24
+ type SlotParamsRecord,
25
+ } from '../shared/slot-params.js';
21
26
  import { isDebug } from './debug.js';
22
27
 
23
28
  // Re-export the ALS for framework-internal consumers that need direct access.
@@ -111,17 +116,13 @@ export function getSegmentParams(segmentPath?: string): Record<string, string |
111
116
  );
112
117
  }
113
118
 
114
- // Check slot params map first — parallel slots may have different param
115
- // types than the main route (e.g. catch-all [..year] → string[] vs
116
- // dynamic [year] → string). If the requested segment path matches a
117
- // stored slot, return its params merged with the main route's.
118
- if (segmentPath && store.slotParamsMap?.has(segmentPath)) {
119
- const slotParams = store.slotParamsMap.get(segmentPath)!;
120
- // Merge: main params as base, slot-specific params override.
121
- // This ensures params from segments above the slot (that the slot
122
- // doesn't re-derive) are still available.
123
- return { ...store.segmentParams, ...slotParams };
124
- }
119
+ // Parallel slots may derive a param the main route never had, or the same
120
+ // name with a different type (catch-all [...year] → string[] vs dynamic
121
+ // [year] → string). `resolveSegmentParams` is the shared definition the
122
+ // client's useSegmentParams() also reads, so the two halves of one
123
+ // documented API cannot drift (TIM-1285).
124
+ const slotResolved = resolveSegmentParams(store.segmentParams, store.slotParams, segmentPath);
125
+ if (slotResolved !== store.segmentParams) return slotResolved;
125
126
 
126
127
  // Dev-mode validation: warn when the segment path expects dynamic
127
128
  // segments that don't exist on the actual matched segment. This catches
@@ -173,8 +174,82 @@ export function setSlotParams(
173
174
  ): void {
174
175
  const store = requestContextAls.getStore();
175
176
  if (!store) return; // non-throwing — optional diagnostic
176
- if (!store.slotParamsMap) store.slotParamsMap = new Map();
177
- store.slotParamsMap.set(segmentPath, params);
177
+ if (!store.slotParams) store.slotParams = Object.create(null) as SlotParamsRecord;
178
+ store.slotParams[segmentPath] = params;
179
+ }
180
+
181
+ /**
182
+ * Run `fn` with the segment params a parallel slot's own chain produced, so
183
+ * a no-arg `getSegmentParams()` inside that slot returns the slot's params
184
+ * rather than the main route's.
185
+ *
186
+ * ALS is the only channel available: the slot's page and layouts are plain
187
+ * components that receive no params prop and cannot know their own tree
188
+ * path, so they have no way to ask for the keyed overload. The slot resolver
189
+ * invokes each of them itself (page through `SafeSlotPage`, layouts and
190
+ * access functions through their wrappers), and this scopes those calls.
191
+ *
192
+ * The store is wrapped in a Proxy rather than cloned. Everything a slot
193
+ * renders can write to the *live* request store — `setDenyStatus` from an
194
+ * access gate, cookie writes, the flush flag — and a clone would silently
195
+ * strand those writes in a copy the pipeline never reads. Only the two
196
+ * params fields are shadowed; every other read and every write passes
197
+ * straight through to the real store.
198
+ *
199
+ * Returns `fn()`'s result unchanged, and no-ops outside a request context or
200
+ * before route matching has set the main params. See TIM-1283.
201
+ *
202
+ * @internal — framework use only
203
+ */
204
+ export function runWithSlotSegmentParams<T>(
205
+ slotSegmentPath: string | undefined,
206
+ slotParams: Record<string, string | string[]>,
207
+ fn: () => T
208
+ ): T {
209
+ const store = requestContextAls.getStore();
210
+ if (!store?.segmentParams) return fn();
211
+
212
+ const merged = mergeSlotParams(store.segmentParams, slotParams);
213
+ const matchedSegmentPath = slotSegmentPath ?? store.matchedSegmentPath;
214
+ const scoped = new Proxy(store, {
215
+ get(target, prop, receiver) {
216
+ if (prop === 'segmentParams') return merged;
217
+ if (prop === 'matchedSegmentPath') return matchedSegmentPath;
218
+ return Reflect.get(target, prop, receiver);
219
+ },
220
+ });
221
+ return requestContextAls.run(scoped, fn);
222
+ }
223
+
224
+ /**
225
+ * The main route's coerced params, or an empty record before route matching.
226
+ *
227
+ * Non-throwing, unlike `getSegmentParams()`: the deny payload path publishes
228
+ * params from wherever the pipeline happened to fail, which may be before
229
+ * matching completed.
230
+ *
231
+ * @internal — framework use only. See TIM-1285.
232
+ */
233
+ export function getSegmentParamsForClient(): Record<string, string | string[]> {
234
+ return requestContextAls.getStore()?.segmentParams ?? {};
235
+ }
236
+
237
+ /**
238
+ * The per-slot params to publish to the client, or `undefined` when the
239
+ * request rendered no slot with params of its own.
240
+ *
241
+ * The client cannot derive these: a slot matches the URL through its own
242
+ * sub-tree, and the browser only ever sees the main route's record. Reading
243
+ * the map here — rather than threading it back out of the element builder —
244
+ * keeps one producer, since `setSlotParams` already writes it during slot
245
+ * resolution and every serialization site runs after that completes.
246
+ *
247
+ * @internal — framework use only. See TIM-1285.
248
+ */
249
+ export function getSlotParamsForClient(): SlotParamsRecord | undefined {
250
+ const store = requestContextAls.getStore();
251
+ if (!store?.slotParams) return undefined;
252
+ return Object.keys(store.slotParams).length > 0 ? store.slotParams : undefined;
178
253
  }
179
254
 
180
255
  /**
@@ -247,7 +322,7 @@ export type ReadonlyHeaders = Pick<
247
322
  */
248
323
  export function runWithRequestContext<T>(req: Request, fn: () => T): T {
249
324
  const originalCopy = new Headers(req.headers);
250
- const parsedUrl = new URL(req.url);
325
+ const appVisible = appVisibleSearch(new URL(req.url));
251
326
  const seed = consumeSeededCookies(req);
252
327
  const store: RequestContextStore = {
253
328
  headers: freezeHeaders(req.headers),
@@ -257,8 +332,12 @@ export function runWithRequestContext<T>(req: Request, fn: () => T): T {
257
332
  // gated on `parsedCookies` being undefined.
258
333
  cookieHeader: seed ? '' : (req.headers.get('cookie') ?? ''),
259
334
  parsedCookies: seed,
260
- searchParams: parsedUrl.searchParams,
261
- searchString: parsedUrl.search,
335
+ // Not `parsedUrl.searchParams` / `parsedUrl.search`: this store is what
336
+ // `getSearchParams()` and `redirect({ preserveSearchParams })` read, and
337
+ // the RSC payload URL carries the framework's `_rsc` cache key that no
338
+ // other request has (TIM-1272).
339
+ searchParams: appVisible.params,
340
+ searchString: appVisible.search,
262
341
  cookieJar: new Map(),
263
342
  flushed: false,
264
343
  mutableContext: false,