@timber-js/app 0.2.0-alpha.18 → 0.2.0-alpha.180

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 (1026) hide show
  1. package/LICENSE +8 -0
  2. package/agent-skill.md +344 -0
  3. package/dist/_chunks/actions-O_LsyCE4.js +317 -0
  4. package/dist/_chunks/actions-O_LsyCE4.js.map +1 -0
  5. package/dist/_chunks/build-output-helper-DF5uScqS.js +158 -0
  6. package/dist/_chunks/build-output-helper-DF5uScqS.js.map +1 -0
  7. package/dist/_chunks/cache-api-B-lhk9p4.js +1202 -0
  8. package/dist/_chunks/cache-api-B-lhk9p4.js.map +1 -0
  9. package/dist/_chunks/canonicalize-DQHyFClh.js +248 -0
  10. package/dist/_chunks/canonicalize-DQHyFClh.js.map +1 -0
  11. package/dist/_chunks/cli-schema-sync-D3naS3eH.js +688 -0
  12. package/dist/_chunks/cli-schema-sync-D3naS3eH.js.map +1 -0
  13. package/dist/_chunks/cloudflare-AHoWYTYr.js +1188 -0
  14. package/dist/_chunks/cloudflare-AHoWYTYr.js.map +1 -0
  15. package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
  16. package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
  17. package/dist/_chunks/define-COtkxMRT.js +191 -0
  18. package/dist/_chunks/define-COtkxMRT.js.map +1 -0
  19. package/dist/_chunks/define-c4au4I9R.js +82 -0
  20. package/dist/_chunks/define-c4au4I9R.js.map +1 -0
  21. package/dist/_chunks/dist-BA3u1z3W.js +423 -0
  22. package/dist/_chunks/dist-BA3u1z3W.js.map +1 -0
  23. package/dist/_chunks/fast-hash-D6hIVt1Y.js +36 -0
  24. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +1 -0
  25. package/dist/_chunks/format-CfwjgPz9.js +14 -0
  26. package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
  27. package/dist/_chunks/href-validation-CMc5JRls.js +141 -0
  28. package/dist/_chunks/href-validation-CMc5JRls.js.map +1 -0
  29. package/dist/_chunks/json-lossy-check-ClNvBM_3.js +63 -0
  30. package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +1 -0
  31. package/dist/_chunks/logger-AWfuX-KJ.js +1468 -0
  32. package/dist/_chunks/logger-AWfuX-KJ.js.map +1 -0
  33. package/dist/_chunks/navigation-root-bUDZLw74.js +124 -0
  34. package/dist/_chunks/navigation-root-bUDZLw74.js.map +1 -0
  35. package/dist/_chunks/plugin-context---kTF5v8.js +315 -0
  36. package/dist/_chunks/plugin-context---kTF5v8.js.map +1 -0
  37. package/dist/_chunks/registry-DbJPKoBp.js +20 -0
  38. package/dist/_chunks/registry-DbJPKoBp.js.map +1 -0
  39. package/dist/_chunks/resolve-schema-Dz3fcFUo.js +50 -0
  40. package/dist/_chunks/resolve-schema-Dz3fcFUo.js.map +1 -0
  41. package/dist/_chunks/router-ref-CtmF-aPv.js +28 -0
  42. package/dist/_chunks/router-ref-CtmF-aPv.js.map +1 -0
  43. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +119 -0
  44. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +1 -0
  45. package/dist/_chunks/segment-classify-Byy425ng.js +176 -0
  46. package/dist/_chunks/segment-classify-Byy425ng.js.map +1 -0
  47. package/dist/_chunks/segment-context-ZDnXDkbz.js +34 -0
  48. package/dist/_chunks/segment-context-ZDnXDkbz.js.map +1 -0
  49. package/dist/_chunks/sizeof-lXffQ1Vr.js +35 -0
  50. package/dist/_chunks/sizeof-lXffQ1Vr.js.map +1 -0
  51. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BOWsq18U.js} +1 -1
  52. package/dist/_chunks/ssr-data-BOWsq18U.js.map +1 -0
  53. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-DFvWd-EA.js} +71 -26
  54. package/dist/_chunks/use-query-states-DFvWd-EA.js.map +1 -0
  55. package/dist/_chunks/use-segment-params-D1CzlgBo.js +151 -0
  56. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -0
  57. package/dist/_chunks/walkers-BtTlKviE.js +1002 -0
  58. package/dist/_chunks/walkers-BtTlKviE.js.map +1 -0
  59. package/dist/adapters/build-output-helper.d.ts +29 -0
  60. package/dist/adapters/build-output-helper.d.ts.map +1 -0
  61. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  62. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  63. package/dist/adapters/cloudflare-dev.js +73 -0
  64. package/dist/adapters/cloudflare-dev.js.map +1 -0
  65. package/dist/adapters/cloudflare-kv-cache.d.ts +65 -0
  66. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  67. package/dist/adapters/cloudflare-kv-cache.js +124 -0
  68. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  69. package/dist/adapters/cloudflare.d.ts +189 -21
  70. package/dist/adapters/cloudflare.d.ts.map +1 -1
  71. package/dist/adapters/cloudflare.js +2 -188
  72. package/dist/adapters/compress-module.d.ts +5 -4
  73. package/dist/adapters/compress-module.d.ts.map +1 -1
  74. package/dist/adapters/nitro.d.ts +41 -3
  75. package/dist/adapters/nitro.d.ts.map +1 -1
  76. package/dist/adapters/nitro.js +224 -172
  77. package/dist/adapters/nitro.js.map +1 -1
  78. package/dist/adapters/shared.d.ts +6 -0
  79. package/dist/adapters/shared.d.ts.map +1 -0
  80. package/dist/adapters/types.d.ts +2 -6
  81. package/dist/adapters/types.d.ts.map +1 -1
  82. package/dist/cache/cache-api.d.ts +48 -0
  83. package/dist/cache/cache-api.d.ts.map +1 -0
  84. package/dist/cache/handler-store.d.ts +33 -0
  85. package/dist/cache/handler-store.d.ts.map +1 -0
  86. package/dist/cache/index.d.ts +31 -8
  87. package/dist/cache/index.d.ts.map +1 -1
  88. package/dist/cache/index.js +3 -326
  89. package/dist/cache/invalidation-epoch.d.ts +43 -0
  90. package/dist/cache/invalidation-epoch.d.ts.map +1 -0
  91. package/dist/cache/json-lossy-check.d.ts +11 -0
  92. package/dist/cache/json-lossy-check.d.ts.map +1 -0
  93. package/dist/cache/redis-handler.d.ts +140 -8
  94. package/dist/cache/redis-handler.d.ts.map +1 -1
  95. package/dist/cache/singleflight.d.ts +19 -2
  96. package/dist/cache/singleflight.d.ts.map +1 -1
  97. package/dist/cache/sizeof.d.ts +22 -0
  98. package/dist/cache/sizeof.d.ts.map +1 -0
  99. package/dist/cache/stable-stringify.d.ts +9 -0
  100. package/dist/cache/stable-stringify.d.ts.map +1 -1
  101. package/dist/cache/store.d.ts +53 -0
  102. package/dist/cache/store.d.ts.map +1 -0
  103. package/dist/cache/stores/cloudflare-kv.d.ts +38 -0
  104. package/dist/cache/stores/cloudflare-kv.d.ts.map +1 -0
  105. package/dist/cache/stores/cloudflare-kv.js +29 -0
  106. package/dist/cache/stores/cloudflare-kv.js.map +1 -0
  107. package/dist/cache/stores/memory.d.ts +42 -0
  108. package/dist/cache/stores/memory.d.ts.map +1 -0
  109. package/dist/cache/stores/memory.js +90 -0
  110. package/dist/cache/stores/memory.js.map +1 -0
  111. package/dist/cache/stores/redis.d.ts +69 -0
  112. package/dist/cache/stores/redis.d.ts.map +1 -0
  113. package/dist/cache/stores/redis.js +35 -0
  114. package/dist/cache/stores/redis.js.map +1 -0
  115. package/dist/cache/stores/vercel.d.ts +36 -0
  116. package/dist/cache/stores/vercel.d.ts.map +1 -0
  117. package/dist/cache/stores/vercel.js +33 -0
  118. package/dist/cache/stores/vercel.js.map +1 -0
  119. package/dist/cache/tag-aware-handler.d.ts +52 -0
  120. package/dist/cache/tag-aware-handler.d.ts.map +1 -0
  121. package/dist/cache/timber-cache.d.ts +20 -10
  122. package/dist/cache/timber-cache.d.ts.map +1 -1
  123. package/dist/cdn/cloudflare-purge.d.ts +23 -0
  124. package/dist/cdn/cloudflare-purge.d.ts.map +1 -0
  125. package/dist/cdn/fastly-purge.d.ts +25 -0
  126. package/dist/cdn/fastly-purge.d.ts.map +1 -0
  127. package/dist/cdn/headers.d.ts +97 -0
  128. package/dist/cdn/headers.d.ts.map +1 -0
  129. package/dist/cdn/index.d.ts +5 -0
  130. package/dist/cdn/index.d.ts.map +1 -0
  131. package/dist/cdn/purge-store.d.ts +23 -0
  132. package/dist/cdn/purge-store.d.ts.map +1 -0
  133. package/dist/cdn/workers-cache-purge.d.ts +16 -0
  134. package/dist/cdn/workers-cache-purge.d.ts.map +1 -0
  135. package/dist/cli-schema-sync.d.ts +59 -0
  136. package/dist/cli-schema-sync.d.ts.map +1 -0
  137. package/dist/cli.d.ts +35 -2
  138. package/dist/cli.d.ts.map +1 -1
  139. package/dist/cli.js +113 -34
  140. package/dist/cli.js.map +1 -1
  141. package/dist/client/browser-dev.d.ts +37 -1
  142. package/dist/client/browser-dev.d.ts.map +1 -1
  143. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  144. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  145. package/dist/client/browser-entry/hmr.d.ts +21 -0
  146. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  147. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  148. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  149. package/dist/client/browser-entry/index.d.ts +29 -0
  150. package/dist/client/browser-entry/index.d.ts.map +1 -0
  151. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  152. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  153. package/dist/client/browser-entry/router-init.d.ts +27 -0
  154. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  155. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  156. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  157. package/dist/client/browser-entry/scroll.d.ts +28 -0
  158. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  159. package/dist/client/error-boundary.d.ts +12 -5
  160. package/dist/client/error-boundary.d.ts.map +1 -1
  161. package/dist/client/error-boundary.js +47 -10
  162. package/dist/client/error-boundary.js.map +1 -1
  163. package/dist/client/error-reconstituter.d.ts +61 -0
  164. package/dist/client/error-reconstituter.d.ts.map +1 -0
  165. package/dist/client/form.d.ts +16 -27
  166. package/dist/client/form.d.ts.map +1 -1
  167. package/dist/client/history.d.ts +21 -6
  168. package/dist/client/history.d.ts.map +1 -1
  169. package/dist/client/index.d.ts +10 -24
  170. package/dist/client/index.d.ts.map +1 -1
  171. package/dist/client/index.js +185 -1134
  172. package/dist/client/index.js.map +1 -1
  173. package/dist/client/internal.d.ts +19 -0
  174. package/dist/client/internal.d.ts.map +1 -0
  175. package/dist/client/internal.js +887 -0
  176. package/dist/client/internal.js.map +1 -0
  177. package/dist/client/link.d.ts +69 -60
  178. package/dist/client/link.d.ts.map +1 -1
  179. package/dist/client/navigation-api.d.ts +121 -0
  180. package/dist/client/navigation-api.d.ts.map +1 -0
  181. package/dist/client/navigation-context.d.ts +3 -2
  182. package/dist/client/navigation-context.d.ts.map +1 -1
  183. package/dist/client/navigation-root.d.ts +119 -0
  184. package/dist/client/navigation-root.d.ts.map +1 -0
  185. package/dist/client/nuqs-adapter.d.ts +1 -1
  186. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  187. package/dist/client/router-ref.d.ts +1 -1
  188. package/dist/client/router.d.ts +99 -14
  189. package/dist/client/router.d.ts.map +1 -1
  190. package/dist/client/rsc-fetch.d.ts +48 -15
  191. package/dist/client/rsc-fetch.d.ts.map +1 -1
  192. package/dist/client/segment-cache.d.ts +26 -7
  193. package/dist/client/segment-cache.d.ts.map +1 -1
  194. package/dist/client/segment-outlet.d.ts +57 -0
  195. package/dist/client/segment-outlet.d.ts.map +1 -0
  196. package/dist/client/segment-update-context.d.ts +21 -0
  197. package/dist/client/segment-update-context.d.ts.map +1 -0
  198. package/dist/client/shallow-url.d.ts +10 -0
  199. package/dist/client/shallow-url.d.ts.map +1 -0
  200. package/dist/client/slot-context.d.ts +31 -0
  201. package/dist/client/slot-context.d.ts.map +1 -0
  202. package/dist/client/slot-outlet.d.ts +16 -0
  203. package/dist/client/slot-outlet.d.ts.map +1 -0
  204. package/dist/client/slot-provider.d.ts +25 -0
  205. package/dist/client/slot-provider.d.ts.map +1 -0
  206. package/dist/client/ssr-data.d.ts +13 -4
  207. package/dist/client/ssr-data.d.ts.map +1 -1
  208. package/dist/client/state.d.ts +1 -1
  209. package/dist/client/top-loader.d.ts +5 -5
  210. package/dist/client/top-loader.d.ts.map +1 -1
  211. package/dist/client/use-cookie.d.ts +12 -0
  212. package/dist/client/use-cookie.d.ts.map +1 -1
  213. package/dist/client/use-link-status.d.ts +5 -5
  214. package/dist/client/use-link-status.d.ts.map +1 -1
  215. package/dist/client/use-pathname.d.ts.map +1 -1
  216. package/dist/client/use-pending-navigation.d.ts +23 -0
  217. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  218. package/dist/client/use-query-states.d.ts +1 -1
  219. package/dist/client/use-query-states.d.ts.map +1 -1
  220. package/dist/client/use-router.d.ts +1 -1
  221. package/dist/client/use-router.d.ts.map +1 -1
  222. package/dist/client/use-search-params.d.ts +12 -5
  223. package/dist/client/use-search-params.d.ts.map +1 -1
  224. package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
  225. package/dist/client/use-segment-params.d.ts.map +1 -0
  226. package/dist/codec.d.ts +69 -0
  227. package/dist/codec.d.ts.map +1 -0
  228. package/dist/codec.js +76 -0
  229. package/dist/codec.js.map +1 -0
  230. package/dist/config-types.d.ts +284 -0
  231. package/dist/config-types.d.ts.map +1 -0
  232. package/dist/config-validation.d.ts +51 -0
  233. package/dist/config-validation.d.ts.map +1 -0
  234. package/dist/content/index.d.ts +1 -10
  235. package/dist/content/index.d.ts.map +1 -1
  236. package/dist/content/index.js +0 -2
  237. package/dist/cookies/define-cookie.d.ts +58 -25
  238. package/dist/cookies/define-cookie.d.ts.map +1 -1
  239. package/dist/cookies/index.d.ts +2 -1
  240. package/dist/cookies/index.d.ts.map +1 -1
  241. package/dist/cookies/index.js +257 -36
  242. package/dist/cookies/index.js.map +1 -1
  243. package/dist/cookies/json-cookie.d.ts +64 -0
  244. package/dist/cookies/json-cookie.d.ts.map +1 -0
  245. package/dist/cookies/validation.d.ts +34 -0
  246. package/dist/cookies/validation.d.ts.map +1 -0
  247. package/dist/dev-tools/404-page.d.ts +50 -0
  248. package/dist/dev-tools/404-page.d.ts.map +1 -0
  249. package/dist/dev-tools/browser-logs.d.ts +40 -0
  250. package/dist/dev-tools/browser-logs.d.ts.map +1 -0
  251. package/dist/dev-tools/dev-page-shell.d.ts +78 -0
  252. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -0
  253. package/dist/dev-tools/error-page.d.ts +32 -0
  254. package/dist/dev-tools/error-page.d.ts.map +1 -0
  255. package/dist/dev-tools/holding-server.d.ts +54 -0
  256. package/dist/dev-tools/holding-server.d.ts.map +1 -0
  257. package/dist/dev-tools/hydration-overlay.d.ts +11 -0
  258. package/dist/dev-tools/hydration-overlay.d.ts.map +1 -0
  259. package/dist/dev-tools/index.d.ts +31 -0
  260. package/dist/dev-tools/index.d.ts.map +1 -0
  261. package/dist/dev-tools/instrumentation.d.ts +59 -0
  262. package/dist/dev-tools/instrumentation.d.ts.map +1 -0
  263. package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
  264. package/dist/dev-tools/logger.d.ts.map +1 -0
  265. package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +17 -3
  266. package/dist/dev-tools/logs.d.ts.map +1 -0
  267. package/dist/dev-tools/overlay.d.ts +91 -0
  268. package/dist/dev-tools/overlay.d.ts.map +1 -0
  269. package/dist/dev-tools/stack-classifier.d.ts +34 -0
  270. package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
  271. package/dist/dev-tools/terminal.d.ts +28 -0
  272. package/dist/dev-tools/terminal.d.ts.map +1 -0
  273. package/dist/fonts/ast-walk.d.ts +68 -0
  274. package/dist/fonts/ast-walk.d.ts.map +1 -0
  275. package/dist/fonts/ast.d.ts +110 -6
  276. package/dist/fonts/ast.d.ts.map +1 -1
  277. package/dist/fonts/bundle.d.ts +50 -0
  278. package/dist/fonts/bundle.d.ts.map +1 -0
  279. package/dist/fonts/dev-middleware.d.ts +22 -0
  280. package/dist/fonts/dev-middleware.d.ts.map +1 -0
  281. package/dist/fonts/fallbacks.d.ts +0 -7
  282. package/dist/fonts/fallbacks.d.ts.map +1 -1
  283. package/dist/fonts/google.d.ts +4 -2
  284. package/dist/fonts/google.d.ts.map +1 -1
  285. package/dist/fonts/local.d.ts +4 -4
  286. package/dist/fonts/local.d.ts.map +1 -1
  287. package/dist/fonts/paths.d.ts +43 -0
  288. package/dist/fonts/paths.d.ts.map +1 -0
  289. package/dist/fonts/pipeline.d.ts +177 -0
  290. package/dist/fonts/pipeline.d.ts.map +1 -0
  291. package/dist/fonts/transform.d.ts +82 -0
  292. package/dist/fonts/transform.d.ts.map +1 -0
  293. package/dist/fonts/types.d.ts +47 -1
  294. package/dist/fonts/types.d.ts.map +1 -1
  295. package/dist/fonts/virtual-modules.d.ts +77 -0
  296. package/dist/fonts/virtual-modules.d.ts.map +1 -0
  297. package/dist/index.d.ts +46 -180
  298. package/dist/index.d.ts.map +1 -1
  299. package/dist/index.js +9243 -14093
  300. package/dist/index.js.map +1 -1
  301. package/dist/params/codec-registry.d.ts +26 -0
  302. package/dist/params/codec-registry.d.ts.map +1 -0
  303. package/dist/params/define-schema.d.ts +81 -0
  304. package/dist/params/define-schema.d.ts.map +1 -0
  305. package/dist/params/index.d.ts +5 -0
  306. package/dist/params/index.d.ts.map +1 -0
  307. package/dist/params/index.js +34 -0
  308. package/dist/params/index.js.map +1 -0
  309. package/dist/params/resolve-schema.d.ts +34 -0
  310. package/dist/params/resolve-schema.d.ts.map +1 -0
  311. package/dist/plugin-context.d.ts +217 -0
  312. package/dist/plugin-context.d.ts.map +1 -0
  313. package/dist/plugins/adapter-build.d.ts +21 -1
  314. package/dist/plugins/adapter-build.d.ts.map +1 -1
  315. package/dist/plugins/build-manifest.d.ts +7 -3
  316. package/dist/plugins/build-manifest.d.ts.map +1 -1
  317. package/dist/plugins/build-report.d.ts +43 -7
  318. package/dist/plugins/build-report.d.ts.map +1 -1
  319. package/dist/plugins/cache.d.ts +64 -0
  320. package/dist/plugins/cache.d.ts.map +1 -0
  321. package/dist/plugins/callsite-ast.d.ts +117 -0
  322. package/dist/plugins/callsite-ast.d.ts.map +1 -0
  323. package/dist/plugins/callsite-jsx.d.ts +35 -0
  324. package/dist/plugins/callsite-jsx.d.ts.map +1 -0
  325. package/dist/plugins/chunks.d.ts +11 -4
  326. package/dist/plugins/chunks.d.ts.map +1 -1
  327. package/dist/plugins/client-chunks.d.ts +40 -0
  328. package/dist/plugins/client-chunks.d.ts.map +1 -0
  329. package/dist/plugins/cloudflare-wasm.d.ts +21 -0
  330. package/dist/plugins/cloudflare-wasm.d.ts.map +1 -0
  331. package/dist/plugins/content.d.ts +1 -1
  332. package/dist/plugins/content.d.ts.map +1 -1
  333. package/dist/plugins/dev-server.d.ts +17 -1
  334. package/dist/plugins/dev-server.d.ts.map +1 -1
  335. package/dist/plugins/entries.d.ts +28 -4
  336. package/dist/plugins/entries.d.ts.map +1 -1
  337. package/dist/plugins/fonts.d.ts +16 -73
  338. package/dist/plugins/fonts.d.ts.map +1 -1
  339. package/dist/plugins/mdx.d.ts +1 -1
  340. package/dist/plugins/mdx.d.ts.map +1 -1
  341. package/dist/plugins/prebuilt-capture.d.ts +60 -0
  342. package/dist/plugins/prebuilt-capture.d.ts.map +1 -0
  343. package/dist/plugins/prebuilt-options-analysis.d.ts +40 -0
  344. package/dist/plugins/prebuilt-options-analysis.d.ts.map +1 -0
  345. package/dist/plugins/prebuilt.d.ts +82 -0
  346. package/dist/plugins/prebuilt.d.ts.map +1 -0
  347. package/dist/plugins/prerender-sugar.d.ts +42 -0
  348. package/dist/plugins/prerender-sugar.d.ts.map +1 -0
  349. package/dist/plugins/request-dep.d.ts +21 -0
  350. package/dist/plugins/request-dep.d.ts.map +1 -0
  351. package/dist/plugins/routing.d.ts +1 -1
  352. package/dist/plugins/routing.d.ts.map +1 -1
  353. package/dist/plugins/server-bundle.d.ts.map +1 -1
  354. package/dist/plugins/shims.d.ts +29 -5
  355. package/dist/plugins/shims.d.ts.map +1 -1
  356. package/dist/plugins/static-build.d.ts +5 -26
  357. package/dist/plugins/static-build.d.ts.map +1 -1
  358. package/dist/routing/codegen-shared.d.ts +67 -0
  359. package/dist/routing/codegen-shared.d.ts.map +1 -0
  360. package/dist/routing/codegen-types.d.ts +64 -0
  361. package/dist/routing/codegen-types.d.ts.map +1 -0
  362. package/dist/routing/codegen.d.ts +7 -2
  363. package/dist/routing/codegen.d.ts.map +1 -1
  364. package/dist/routing/convention-lint.d.ts +41 -0
  365. package/dist/routing/convention-lint.d.ts.map +1 -0
  366. package/dist/routing/export-detect.d.ts +56 -0
  367. package/dist/routing/export-detect.d.ts.map +1 -0
  368. package/dist/routing/file-cache.d.ts +8 -0
  369. package/dist/routing/file-cache.d.ts.map +1 -0
  370. package/dist/routing/index.d.ts +7 -1
  371. package/dist/routing/index.d.ts.map +1 -1
  372. package/dist/routing/index.js +4 -2
  373. package/dist/routing/interception.d.ts +0 -5
  374. package/dist/routing/interception.d.ts.map +1 -1
  375. package/dist/routing/link-codegen.d.ts +90 -0
  376. package/dist/routing/link-codegen.d.ts.map +1 -0
  377. package/dist/routing/manifest-codegen.d.ts +32 -0
  378. package/dist/routing/manifest-codegen.d.ts.map +1 -0
  379. package/dist/routing/scanner.d.ts +1 -10
  380. package/dist/routing/scanner.d.ts.map +1 -1
  381. package/dist/routing/schema-validation.d.ts +35 -0
  382. package/dist/routing/schema-validation.d.ts.map +1 -0
  383. package/dist/routing/segment-classify.d.ts +81 -0
  384. package/dist/routing/segment-classify.d.ts.map +1 -0
  385. package/dist/routing/segment-codegen.d.ts +38 -0
  386. package/dist/routing/segment-codegen.d.ts.map +1 -0
  387. package/dist/routing/types.d.ts +81 -25
  388. package/dist/routing/types.d.ts.map +1 -1
  389. package/dist/routing/walkers.d.ts +51 -0
  390. package/dist/routing/walkers.d.ts.map +1 -0
  391. package/dist/rsc-runtime/rsc.d.ts +1 -1
  392. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  393. package/dist/rsc-runtime/ssr.d.ts +12 -0
  394. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  395. package/dist/schema-bridge.d.ts +91 -0
  396. package/dist/schema-bridge.d.ts.map +1 -0
  397. package/dist/search-params/define.d.ts +188 -0
  398. package/dist/search-params/define.d.ts.map +1 -0
  399. package/dist/search-params/index.d.ts +4 -7
  400. package/dist/search-params/index.d.ts.map +1 -1
  401. package/dist/search-params/index.js +34 -441
  402. package/dist/search-params/index.js.map +1 -1
  403. package/dist/search-params/registry.d.ts +2 -2
  404. package/dist/search-params/registry.d.ts.map +1 -1
  405. package/dist/search-params/wrappers.d.ts +53 -0
  406. package/dist/search-params/wrappers.d.ts.map +1 -0
  407. package/dist/segment-params/define.d.ts +89 -0
  408. package/dist/segment-params/define.d.ts.map +1 -0
  409. package/dist/segment-params/index.d.ts +3 -0
  410. package/dist/segment-params/index.d.ts.map +1 -0
  411. package/dist/segment-params/index.js +2 -0
  412. package/dist/server/access-gate.d.ts +8 -3
  413. package/dist/server/access-gate.d.ts.map +1 -1
  414. package/dist/server/action-client.d.ts +42 -7
  415. package/dist/server/action-client.d.ts.map +1 -1
  416. package/dist/server/action-encryption.d.ts +76 -0
  417. package/dist/server/action-encryption.d.ts.map +1 -0
  418. package/dist/server/action-handler.d.ts +35 -1
  419. package/dist/server/action-handler.d.ts.map +1 -1
  420. package/dist/server/actions.d.ts +6 -30
  421. package/dist/server/actions.d.ts.map +1 -1
  422. package/dist/server/als-registry.d.ts +93 -11
  423. package/dist/server/als-registry.d.ts.map +1 -1
  424. package/dist/server/asset-headers.d.ts +8 -18
  425. package/dist/server/asset-headers.d.ts.map +1 -1
  426. package/dist/server/body-limits.d.ts.map +1 -1
  427. package/dist/server/build-manifest.d.ts +12 -29
  428. package/dist/server/build-manifest.d.ts.map +1 -1
  429. package/dist/server/canonicalize.d.ts +10 -0
  430. package/dist/server/canonicalize.d.ts.map +1 -1
  431. package/dist/server/coalesce-tick.d.ts +40 -0
  432. package/dist/server/coalesce-tick.d.ts.map +1 -0
  433. package/dist/server/cookie-context.d.ts +170 -0
  434. package/dist/server/cookie-context.d.ts.map +1 -0
  435. package/dist/server/cookie-parsing.d.ts +65 -0
  436. package/dist/server/cookie-parsing.d.ts.map +1 -0
  437. package/dist/server/csrf.d.ts +3 -2
  438. package/dist/server/csrf.d.ts.map +1 -1
  439. package/dist/server/default-logger.d.ts +22 -0
  440. package/dist/server/default-logger.d.ts.map +1 -0
  441. package/dist/server/deny-boundary.d.ts +117 -0
  442. package/dist/server/deny-boundary.d.ts.map +1 -0
  443. package/dist/server/deny-renderer.d.ts +2 -2
  444. package/dist/server/deny-renderer.d.ts.map +1 -1
  445. package/dist/server/dev-source-map.d.ts +22 -0
  446. package/dist/server/dev-source-map.d.ts.map +1 -0
  447. package/dist/server/early-hints-sender.d.ts.map +1 -1
  448. package/dist/server/early-hints.d.ts +13 -11
  449. package/dist/server/early-hints.d.ts.map +1 -1
  450. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  451. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  452. package/dist/server/fallback-error.d.ts +12 -7
  453. package/dist/server/fallback-error.d.ts.map +1 -1
  454. package/dist/server/flight-injection-state.d.ts +66 -0
  455. package/dist/server/flight-injection-state.d.ts.map +1 -0
  456. package/dist/server/flight-scripts.d.ts +42 -0
  457. package/dist/server/flight-scripts.d.ts.map +1 -0
  458. package/dist/server/form-data.d.ts +41 -0
  459. package/dist/server/form-data.d.ts.map +1 -1
  460. package/dist/server/html-injector-core.d.ts +242 -0
  461. package/dist/server/html-injector-core.d.ts.map +1 -0
  462. package/dist/server/html-injectors.d.ts +82 -41
  463. package/dist/server/html-injectors.d.ts.map +1 -1
  464. package/dist/server/index.d.ts +11 -47
  465. package/dist/server/index.d.ts.map +1 -1
  466. package/dist/server/index.js +182 -2906
  467. package/dist/server/index.js.map +1 -1
  468. package/dist/server/internal.d.ts +49 -0
  469. package/dist/server/internal.d.ts.map +1 -0
  470. package/dist/server/internal.js +3892 -0
  471. package/dist/server/internal.js.map +1 -0
  472. package/dist/server/logger.d.ts +39 -7
  473. package/dist/server/logger.d.ts.map +1 -1
  474. package/dist/server/metadata-routes.d.ts +60 -11
  475. package/dist/server/metadata-routes.d.ts.map +1 -1
  476. package/dist/server/metadata.d.ts +8 -0
  477. package/dist/server/metadata.d.ts.map +1 -1
  478. package/dist/server/middleware-runner.d.ts +19 -4
  479. package/dist/server/middleware-runner.d.ts.map +1 -1
  480. package/dist/server/node-stream-transforms.d.ts +119 -0
  481. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  482. package/dist/server/param-coercion.d.ts +54 -0
  483. package/dist/server/param-coercion.d.ts.map +1 -0
  484. package/dist/server/pipeline-helpers.d.ts +95 -0
  485. package/dist/server/pipeline-helpers.d.ts.map +1 -0
  486. package/dist/server/pipeline-interception.d.ts +1 -1
  487. package/dist/server/pipeline-interception.d.ts.map +1 -1
  488. package/dist/server/pipeline-metadata.d.ts +6 -0
  489. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  490. package/dist/server/pipeline-outcome.d.ts +49 -0
  491. package/dist/server/pipeline-outcome.d.ts.map +1 -0
  492. package/dist/server/pipeline-phases.d.ts +59 -0
  493. package/dist/server/pipeline-phases.d.ts.map +1 -0
  494. package/dist/server/pipeline.d.ts +140 -19
  495. package/dist/server/pipeline.d.ts.map +1 -1
  496. package/dist/server/port-resolution.d.ts +117 -0
  497. package/dist/server/port-resolution.d.ts.map +1 -0
  498. package/dist/server/prebuilt/cache-key.d.ts +62 -0
  499. package/dist/server/prebuilt/cache-key.d.ts.map +1 -0
  500. package/dist/server/prebuilt/capture-state.d.ts +57 -0
  501. package/dist/server/prebuilt/capture-state.d.ts.map +1 -0
  502. package/dist/server/prebuilt/key-discipline.d.ts +23 -0
  503. package/dist/server/prebuilt/key-discipline.d.ts.map +1 -0
  504. package/dist/server/prebuilt/manifest-tag-index.d.ts +27 -0
  505. package/dist/server/prebuilt/manifest-tag-index.d.ts.map +1 -0
  506. package/dist/server/prebuilt/overlay.d.ts +100 -0
  507. package/dist/server/prebuilt/overlay.d.ts.map +1 -0
  508. package/dist/server/prebuilt/payload-source.d.ts +78 -0
  509. package/dist/server/prebuilt/payload-source.d.ts.map +1 -0
  510. package/dist/server/prebuilt/slots.d.ts +99 -0
  511. package/dist/server/prebuilt/slots.d.ts.map +1 -0
  512. package/dist/server/prebuilt/synthetic-store.d.ts +66 -0
  513. package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -0
  514. package/dist/server/prebuilt-builder.d.ts +120 -0
  515. package/dist/server/prebuilt-builder.d.ts.map +1 -0
  516. package/dist/server/prebuilt-runtime.d.ts +111 -0
  517. package/dist/server/prebuilt-runtime.d.ts.map +1 -0
  518. package/dist/server/primitives.d.ts +88 -43
  519. package/dist/server/primitives.d.ts.map +1 -1
  520. package/dist/server/render-timeout.d.ts +51 -0
  521. package/dist/server/render-timeout.d.ts.map +1 -0
  522. package/dist/server/render-utils.d.ts +25 -0
  523. package/dist/server/render-utils.d.ts.map +1 -0
  524. package/dist/server/request-context.d.ts +62 -107
  525. package/dist/server/request-context.d.ts.map +1 -1
  526. package/dist/server/request-dep.d.ts +15 -0
  527. package/dist/server/request-dep.d.ts.map +1 -0
  528. package/dist/server/route-element-builder.d.ts +53 -25
  529. package/dist/server/route-element-builder.d.ts.map +1 -1
  530. package/dist/server/route-handler.d.ts.map +1 -1
  531. package/dist/server/route-matcher.d.ts +25 -36
  532. package/dist/server/route-matcher.d.ts.map +1 -1
  533. package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
  534. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
  535. package/dist/server/rsc-entry/api-handler.d.ts +12 -3
  536. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  537. package/dist/server/rsc-entry/deny-fallback.d.ts +29 -0
  538. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -0
  539. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  540. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  541. package/dist/server/rsc-entry/helpers.d.ts +69 -37
  542. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  543. package/dist/server/rsc-entry/index.d.ts +28 -6
  544. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  545. package/dist/server/rsc-entry/render-route.d.ts +51 -0
  546. package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
  547. package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
  548. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
  549. package/dist/server/rsc-entry/rsc-payload.d.ts +6 -6
  550. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  551. package/dist/server/rsc-entry/rsc-stream.d.ts +25 -1
  552. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  553. package/dist/server/rsc-entry/ssr-bridge.d.ts +5 -1
  554. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  555. package/dist/server/rsc-entry/ssr-renderer.d.ts +36 -4
  556. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  557. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +89 -0
  558. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
  559. package/dist/server/safe-load.d.ts +46 -0
  560. package/dist/server/safe-load.d.ts.map +1 -0
  561. package/dist/server/sensitive-fields.d.ts +74 -0
  562. package/dist/server/sensitive-fields.d.ts.map +1 -0
  563. package/dist/server/sitemap-generator.d.ts +129 -0
  564. package/dist/server/sitemap-generator.d.ts.map +1 -0
  565. package/dist/server/sitemap-handler.d.ts +22 -0
  566. package/dist/server/sitemap-handler.d.ts.map +1 -0
  567. package/dist/server/slot-resolver.d.ts +66 -5
  568. package/dist/server/slot-resolver.d.ts.map +1 -1
  569. package/dist/server/ssr-bridge-types.d.ts +121 -0
  570. package/dist/server/ssr-bridge-types.d.ts.map +1 -0
  571. package/dist/server/ssr-entry.d.ts +2 -43
  572. package/dist/server/ssr-entry.d.ts.map +1 -1
  573. package/dist/server/ssr-render.d.ts +64 -21
  574. package/dist/server/ssr-render.d.ts.map +1 -1
  575. package/dist/server/ssr-wrappers.d.ts +50 -0
  576. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  577. package/dist/server/state-tree-diff.d.ts +72 -9
  578. package/dist/server/state-tree-diff.d.ts.map +1 -1
  579. package/dist/server/status-code-resolver.d.ts +22 -11
  580. package/dist/server/status-code-resolver.d.ts.map +1 -1
  581. package/dist/server/stream-utils.d.ts +47 -0
  582. package/dist/server/stream-utils.d.ts.map +1 -0
  583. package/dist/server/tracing.d.ts +44 -9
  584. package/dist/server/tracing.d.ts.map +1 -1
  585. package/dist/server/tree-builder.d.ts +69 -30
  586. package/dist/server/tree-builder.d.ts.map +1 -1
  587. package/dist/server/tree-match.d.ts +49 -0
  588. package/dist/server/tree-match.d.ts.map +1 -0
  589. package/dist/server/types.d.ts +71 -6
  590. package/dist/server/types.d.ts.map +1 -1
  591. package/dist/server/utils/escape-html.d.ts +14 -0
  592. package/dist/server/utils/escape-html.d.ts.map +1 -0
  593. package/dist/server/utils/mdx-file.d.ts +15 -0
  594. package/dist/server/utils/mdx-file.d.ts.map +1 -0
  595. package/dist/server/version-skew.d.ts +61 -0
  596. package/dist/server/version-skew.d.ts.map +1 -0
  597. package/dist/server/workers-cache-bridge.d.ts +26 -0
  598. package/dist/server/workers-cache-bridge.d.ts.map +1 -0
  599. package/dist/shared/href-validation.d.ts +49 -0
  600. package/dist/shared/href-validation.d.ts.map +1 -0
  601. package/dist/shared/merge-search-params.d.ts +22 -0
  602. package/dist/shared/merge-search-params.d.ts.map +1 -0
  603. package/dist/shared/redirect-type.d.ts +17 -0
  604. package/dist/shared/redirect-type.d.ts.map +1 -0
  605. package/dist/shims/font-google.d.ts +1 -1
  606. package/dist/shims/font-google.d.ts.map +1 -1
  607. package/dist/shims/font-google.js +42 -0
  608. package/dist/shims/font-google.js.map +1 -0
  609. package/dist/shims/font-local.d.ts +26 -0
  610. package/dist/shims/font-local.d.ts.map +1 -0
  611. package/dist/shims/font-local.js +20 -0
  612. package/dist/shims/font-local.js.map +1 -0
  613. package/dist/shims/headers.d.ts +53 -1
  614. package/dist/shims/headers.d.ts.map +1 -1
  615. package/dist/shims/image.d.ts +120 -120
  616. package/dist/shims/image.d.ts.map +1 -1
  617. package/dist/shims/navigation-client.d.ts +35 -11
  618. package/dist/shims/navigation-client.d.ts.map +1 -1
  619. package/dist/shims/navigation.d.ts +11 -5
  620. package/dist/shims/navigation.d.ts.map +1 -1
  621. package/dist/utils/state-machine.d.ts +80 -0
  622. package/dist/utils/state-machine.d.ts.map +1 -0
  623. package/docs/api/30-api-server.mdx +233 -0
  624. package/docs/api/31-api-client.mdx +161 -0
  625. package/docs/api/32-api-cache.mdx +311 -0
  626. package/docs/api/33-api-search-params.mdx +154 -0
  627. package/docs/api/34-api-config.mdx +325 -0
  628. package/docs/api/35-api-typescript.mdx +170 -0
  629. package/docs/api/36-cli.mdx +143 -0
  630. package/docs/learn/00-introduction.mdx +109 -0
  631. package/docs/learn/01-quick-start.mdx +94 -0
  632. package/docs/learn/02-pages-and-layouts.mdx +147 -0
  633. package/docs/learn/03-fetching-data.mdx +211 -0
  634. package/docs/learn/03b-access-control.mdx +130 -0
  635. package/docs/learn/04-loading-states.mdx +67 -0
  636. package/docs/learn/04b-the-flush-point.mdx +115 -0
  637. package/docs/learn/05-typed-params.mdx +275 -0
  638. package/docs/learn/06-forms-and-actions.mdx +146 -0
  639. package/docs/learn/07-typed-routes.mdx +127 -0
  640. package/docs/learn/08-streaming.mdx +146 -0
  641. package/docs/learn/09-caching.mdx +252 -0
  642. package/docs/learn/10-middleware.mdx +157 -0
  643. package/docs/learn/11-error-handling.mdx +156 -0
  644. package/docs/learn/12-client-navigation.mdx +176 -0
  645. package/docs/learn/13-configuration.mdx +162 -0
  646. package/docs/learn/14-deploying.mdx +264 -0
  647. package/docs/more/01-advanced-routing.mdx +173 -0
  648. package/docs/more/02-advanced-forms.mdx +137 -0
  649. package/docs/more/03-coming-from-nextjs.mdx +186 -0
  650. package/docs/more/04-metadata-and-fonts.mdx +193 -0
  651. package/docs/more/04b-mdx.mdx +209 -0
  652. package/docs/more/05-content-collections.mdx +90 -0
  653. package/docs/more/06-instrumentation.mdx +214 -0
  654. package/docs/more/07-security.mdx +129 -0
  655. package/docs/more/08-developer-experience.mdx +134 -0
  656. package/docs/more/40-why-timber.mdx +50 -0
  657. package/docs/more/41-timber-vs-nextjs.mdx +81 -0
  658. package/docs/more/42-timber-vs-others.mdx +68 -0
  659. package/docs/more/50-ai-agent-instructions.mdx +169 -0
  660. package/llms.txt +55 -0
  661. package/package.json +105 -26
  662. package/src/adapters/build-output-helper.ts +199 -0
  663. package/src/adapters/cloudflare-dev.ts +177 -0
  664. package/src/adapters/cloudflare-kv-cache.ts +204 -0
  665. package/src/adapters/cloudflare.ts +620 -129
  666. package/src/adapters/compress-module.ts +27 -92
  667. package/src/adapters/nitro.ts +266 -122
  668. package/src/adapters/raw-imports.d.ts +5 -0
  669. package/src/adapters/shared.ts +68 -0
  670. package/src/adapters/types.ts +2 -7
  671. package/src/adapters/wrangler.d.ts +7 -0
  672. package/src/cache/cache-api.ts +107 -0
  673. package/src/cache/handler-store.ts +76 -0
  674. package/src/cache/index.ts +114 -21
  675. package/src/cache/invalidation-epoch.ts +93 -0
  676. package/src/cache/json-lossy-check.ts +75 -0
  677. package/src/cache/redis-handler.ts +197 -19
  678. package/src/cache/singleflight.ts +64 -6
  679. package/src/cache/sizeof.ts +33 -0
  680. package/src/cache/stable-stringify.ts +65 -2
  681. package/src/cache/store.ts +71 -0
  682. package/src/cache/stores/cloudflare-kv.ts +52 -0
  683. package/src/cache/stores/memory.ts +125 -0
  684. package/src/cache/stores/redis.ts +97 -0
  685. package/src/cache/stores/vercel.ts +59 -0
  686. package/src/cache/tag-aware-handler.ts +237 -0
  687. package/src/cache/timber-cache.ts +161 -36
  688. package/src/cdn/cloudflare-purge.ts +50 -0
  689. package/src/cdn/fastly-purge.ts +63 -0
  690. package/src/cdn/headers.ts +153 -0
  691. package/src/cdn/index.ts +17 -0
  692. package/src/cdn/purge-store.ts +34 -0
  693. package/src/cdn/workers-cache-purge.ts +30 -0
  694. package/src/cli-schema-sync.ts +401 -0
  695. package/src/cli.ts +167 -34
  696. package/src/client/browser-dev.ts +156 -1
  697. package/src/client/browser-entry/action-dispatch.ts +124 -0
  698. package/src/client/browser-entry/hmr.ts +70 -0
  699. package/src/client/browser-entry/hydrate.ts +187 -0
  700. package/src/client/browser-entry/index.ts +113 -0
  701. package/src/client/browser-entry/post-hydration.ts +110 -0
  702. package/src/client/browser-entry/router-init.ts +286 -0
  703. package/src/client/browser-entry/rsc-stream.ts +157 -0
  704. package/src/client/browser-entry/scroll.ts +50 -0
  705. package/src/client/error-boundary.tsx +127 -22
  706. package/src/client/error-reconstituter.tsx +79 -0
  707. package/src/client/form.tsx +31 -32
  708. package/src/client/history.ts +21 -6
  709. package/src/client/index.ts +67 -45
  710. package/src/client/internal.ts +58 -0
  711. package/src/client/link.tsx +349 -150
  712. package/src/client/navigation-api.ts +345 -0
  713. package/src/client/navigation-context.ts +15 -7
  714. package/src/client/navigation-root.tsx +355 -0
  715. package/src/client/nuqs-adapter.tsx +16 -3
  716. package/src/client/router-ref.ts +1 -1
  717. package/src/client/router.ts +565 -212
  718. package/src/client/rsc-fetch.ts +215 -34
  719. package/src/client/segment-cache.ts +91 -17
  720. package/src/client/segment-outlet.tsx +141 -0
  721. package/src/client/segment-update-context.ts +42 -0
  722. package/src/client/shallow-url.ts +22 -0
  723. package/src/client/slot-context.ts +50 -0
  724. package/src/client/slot-outlet.tsx +22 -0
  725. package/src/client/slot-provider.tsx +32 -0
  726. package/src/client/ssr-data.ts +13 -5
  727. package/src/client/state.ts +2 -2
  728. package/src/client/top-loader.tsx +11 -9
  729. package/src/client/use-cookie.ts +60 -15
  730. package/src/client/use-link-status.ts +7 -7
  731. package/src/client/use-pathname.ts +1 -0
  732. package/src/client/use-pending-navigation.ts +40 -0
  733. package/src/client/use-query-states.ts +108 -10
  734. package/src/client/use-router.ts +4 -1
  735. package/src/client/use-search-params.ts +31 -44
  736. package/src/client/{use-params.ts → use-segment-params.ts} +9 -6
  737. package/src/codec.ts +149 -0
  738. package/src/config-types.ts +282 -0
  739. package/src/config-validation.ts +330 -0
  740. package/src/content/index.ts +5 -13
  741. package/src/cookies/define-cookie.ts +217 -53
  742. package/src/cookies/index.ts +12 -1
  743. package/src/cookies/json-cookie.ts +105 -0
  744. package/src/cookies/validation.ts +192 -0
  745. package/src/dev-tools/404-page.ts +286 -0
  746. package/src/dev-tools/browser-logs.ts +55 -0
  747. package/src/dev-tools/dev-page-shell.ts +260 -0
  748. package/src/dev-tools/error-page.ts +331 -0
  749. package/src/dev-tools/holding-server.ts +187 -0
  750. package/src/dev-tools/hydration-overlay.ts +158 -0
  751. package/src/dev-tools/index.ts +83 -0
  752. package/src/dev-tools/instrumentation.ts +213 -0
  753. package/src/{server/dev-logger.ts → dev-tools/logger.ts} +33 -51
  754. package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +122 -26
  755. package/src/dev-tools/overlay.ts +469 -0
  756. package/src/dev-tools/stack-classifier.ts +75 -0
  757. package/src/dev-tools/terminal.ts +182 -0
  758. package/src/fonts/ast-walk.ts +235 -0
  759. package/src/fonts/ast.ts +477 -126
  760. package/src/fonts/bundle.ts +138 -0
  761. package/src/fonts/dev-middleware.ts +85 -0
  762. package/src/fonts/fallbacks.ts +0 -23
  763. package/src/fonts/google.ts +100 -18
  764. package/src/fonts/local.ts +9 -8
  765. package/src/fonts/paths.ts +58 -0
  766. package/src/fonts/pipeline.ts +348 -0
  767. package/src/fonts/transform.ts +311 -0
  768. package/src/fonts/types.ts +52 -1
  769. package/src/fonts/virtual-modules.ts +179 -0
  770. package/src/index.ts +446 -352
  771. package/src/params/codec-registry.ts +34 -0
  772. package/src/params/define-schema.ts +115 -0
  773. package/src/params/index.ts +17 -0
  774. package/src/params/resolve-schema.ts +84 -0
  775. package/src/plugin-context.ts +432 -0
  776. package/src/plugins/adapter-build.ts +220 -7
  777. package/src/plugins/build-manifest.ts +177 -23
  778. package/src/plugins/build-report.ts +253 -35
  779. package/src/plugins/cache.ts +243 -0
  780. package/src/plugins/callsite-ast.ts +472 -0
  781. package/src/plugins/callsite-jsx.ts +243 -0
  782. package/src/plugins/chunks.ts +74 -5
  783. package/src/plugins/client-chunks.ts +185 -0
  784. package/src/plugins/cloudflare-wasm.ts +141 -0
  785. package/src/plugins/content.ts +1 -1
  786. package/src/plugins/dev-server.ts +284 -94
  787. package/src/plugins/entries.ts +134 -16
  788. package/src/plugins/fonts.ts +225 -660
  789. package/src/plugins/mdx.ts +47 -10
  790. package/src/plugins/prebuilt-capture.ts +217 -0
  791. package/src/plugins/prebuilt-options-analysis.ts +175 -0
  792. package/src/plugins/prebuilt.ts +655 -0
  793. package/src/plugins/prerender-sugar.ts +328 -0
  794. package/src/plugins/request-dep.ts +458 -0
  795. package/src/plugins/routing.ts +237 -241
  796. package/src/plugins/server-bundle.ts +89 -12
  797. package/src/plugins/shims.ts +241 -64
  798. package/src/plugins/static-build.ts +15 -90
  799. package/src/routing/codegen-shared.ts +115 -0
  800. package/src/routing/codegen-types.ts +65 -0
  801. package/src/routing/codegen.ts +372 -178
  802. package/src/routing/convention-lint.ts +394 -0
  803. package/src/routing/export-detect.ts +304 -0
  804. package/src/routing/file-cache.ts +23 -0
  805. package/src/routing/index.ts +10 -1
  806. package/src/routing/interception.ts +3 -22
  807. package/src/routing/link-codegen.ts +313 -0
  808. package/src/routing/manifest-codegen.ts +287 -0
  809. package/src/routing/scanner.ts +338 -189
  810. package/src/routing/schema-validation.ts +155 -0
  811. package/src/routing/segment-classify.ts +223 -0
  812. package/src/routing/segment-codegen.ts +98 -0
  813. package/src/routing/types.ts +82 -25
  814. package/src/routing/walkers.ts +90 -0
  815. package/src/rsc-runtime/rsc.ts +9 -0
  816. package/src/rsc-runtime/ssr.ts +50 -0
  817. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  818. package/src/schema-bridge.ts +253 -0
  819. package/src/search-params/define.ts +576 -0
  820. package/src/search-params/index.ts +14 -20
  821. package/src/search-params/registry.ts +2 -2
  822. package/src/search-params/wrappers.ts +101 -0
  823. package/src/segment-params/define.ts +249 -0
  824. package/src/segment-params/index.ts +9 -0
  825. package/src/server/access-gate.tsx +111 -34
  826. package/src/server/action-client.ts +120 -29
  827. package/src/server/action-encryption.ts +144 -0
  828. package/src/server/action-handler.ts +123 -33
  829. package/src/server/actions.ts +48 -54
  830. package/src/server/als-registry.ts +137 -20
  831. package/src/server/asset-headers.ts +15 -37
  832. package/src/server/body-limits.ts +10 -2
  833. package/src/server/build-manifest.ts +19 -56
  834. package/src/server/canonicalize.ts +6 -3
  835. package/src/server/coalesce-tick.ts +75 -0
  836. package/src/server/compress.ts +34 -7
  837. package/src/server/cookie-context.ts +484 -0
  838. package/src/server/cookie-parsing.ts +163 -0
  839. package/src/server/csrf.ts +39 -6
  840. package/src/server/default-logger.ts +99 -0
  841. package/src/server/deny-boundary.ts +314 -0
  842. package/src/server/deny-renderer.ts +85 -77
  843. package/src/server/dev-source-map.ts +31 -0
  844. package/src/server/early-hints-sender.ts +3 -2
  845. package/src/server/early-hints.ts +37 -27
  846. package/src/server/error-boundary-wrapper.ts +61 -22
  847. package/src/server/fallback-error.ts +79 -102
  848. package/src/server/flight-injection-state.ts +113 -0
  849. package/src/server/flight-scripts.ts +62 -0
  850. package/src/server/form-data.ts +124 -12
  851. package/src/server/html-injector-core.ts +495 -0
  852. package/src/server/html-injectors.ts +271 -254
  853. package/src/server/index.ts +31 -185
  854. package/src/server/internal.ts +181 -0
  855. package/src/server/logger.ts +72 -36
  856. package/src/server/metadata-routes.ts +205 -24
  857. package/src/server/metadata.ts +21 -0
  858. package/src/server/middleware-runner.ts +31 -4
  859. package/src/server/node-stream-transforms.ts +336 -0
  860. package/src/server/param-coercion.ts +207 -0
  861. package/src/server/pipeline-helpers.ts +204 -0
  862. package/src/server/pipeline-interception.ts +45 -18
  863. package/src/server/pipeline-metadata.ts +14 -0
  864. package/src/server/pipeline-outcome.ts +197 -0
  865. package/src/server/pipeline-phases.ts +545 -0
  866. package/src/server/pipeline.ts +274 -382
  867. package/src/server/port-resolution.ts +215 -0
  868. package/src/server/prebuilt/cache-key.ts +298 -0
  869. package/src/server/prebuilt/capture-state.ts +89 -0
  870. package/src/server/prebuilt/key-discipline.ts +53 -0
  871. package/src/server/prebuilt/manifest-tag-index.ts +46 -0
  872. package/src/server/prebuilt/overlay.ts +256 -0
  873. package/src/server/prebuilt/payload-source.ts +201 -0
  874. package/src/server/prebuilt/slots.ts +190 -0
  875. package/src/server/prebuilt/synthetic-store.ts +121 -0
  876. package/src/server/prebuilt-builder.ts +809 -0
  877. package/src/server/prebuilt-runtime.ts +815 -0
  878. package/src/server/primitives.ts +160 -83
  879. package/src/server/render-timeout.ts +108 -0
  880. package/src/server/render-utils.ts +31 -0
  881. package/src/server/request-context.ts +170 -337
  882. package/src/server/request-dep.ts +37 -0
  883. package/src/server/route-element-builder.ts +699 -295
  884. package/src/server/route-handler.ts +31 -4
  885. package/src/server/route-matcher.ts +158 -277
  886. package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
  887. package/src/server/rsc-entry/api-handler.ts +69 -32
  888. package/src/server/rsc-entry/deny-fallback.ts +92 -0
  889. package/src/server/rsc-entry/error-renderer.ts +306 -89
  890. package/src/server/rsc-entry/helpers.ts +210 -85
  891. package/src/server/rsc-entry/index.ts +332 -332
  892. package/src/server/rsc-entry/render-route.ts +300 -0
  893. package/src/server/rsc-entry/revalidate-renderer.ts +349 -0
  894. package/src/server/rsc-entry/rsc-payload.ts +102 -42
  895. package/src/server/rsc-entry/rsc-stream.ts +93 -13
  896. package/src/server/rsc-entry/ssr-bridge.ts +18 -5
  897. package/src/server/rsc-entry/ssr-renderer.ts +275 -43
  898. package/src/server/rsc-entry/wrap-action-dispatch.ts +186 -0
  899. package/src/server/safe-load.ts +60 -0
  900. package/src/server/sensitive-fields.ts +230 -0
  901. package/src/server/server-only-guard-noop.js +3 -0
  902. package/src/server/sitemap-generator.ts +345 -0
  903. package/src/server/sitemap-handler.ts +157 -0
  904. package/src/server/slot-resolver.ts +574 -250
  905. package/src/server/ssr-bridge-types.ts +124 -0
  906. package/src/server/ssr-entry.ts +206 -86
  907. package/src/server/ssr-render.ts +345 -86
  908. package/src/server/ssr-wrappers.tsx +141 -0
  909. package/src/server/state-tree-diff.ts +177 -30
  910. package/src/server/status-code-resolver.ts +115 -130
  911. package/src/server/stream-utils.ts +288 -0
  912. package/src/server/tracing.ts +126 -14
  913. package/src/server/tree-builder.ts +214 -90
  914. package/src/server/tree-match.ts +262 -0
  915. package/src/server/types.ts +78 -9
  916. package/src/server/utils/escape-html.ts +20 -0
  917. package/src/server/utils/mdx-file.ts +22 -0
  918. package/src/server/version-skew.ts +104 -0
  919. package/src/server/workers-cache-bridge.ts +33 -0
  920. package/src/shared/href-validation.ts +159 -0
  921. package/src/shared/merge-search-params.ts +55 -0
  922. package/src/shared/redirect-type.ts +17 -0
  923. package/src/shims/font-google.ts +1 -1
  924. package/src/shims/font-local.ts +34 -0
  925. package/src/shims/headers.ts +122 -1
  926. package/src/shims/navigation-client.ts +51 -29
  927. package/src/shims/navigation.ts +14 -7
  928. package/src/utils/state-machine.ts +111 -0
  929. package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
  930. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  931. package/dist/_chunks/debug-B3Gypr3D.js +0 -108
  932. package/dist/_chunks/debug-B3Gypr3D.js.map +0 -1
  933. package/dist/_chunks/format-RyoGQL74.js +0 -164
  934. package/dist/_chunks/format-RyoGQL74.js.map +0 -1
  935. package/dist/_chunks/interception-BOoWmLUA.js +0 -676
  936. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  937. package/dist/_chunks/metadata-routes-Cjmvi3rQ.js +0 -153
  938. package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
  939. package/dist/_chunks/request-context-BQUC8PHn.js +0 -330
  940. package/dist/_chunks/request-context-BQUC8PHn.js.map +0 -1
  941. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  942. package/dist/_chunks/tracing-CemImE6h.js +0 -187
  943. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  944. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  945. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  946. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  947. package/dist/adapters/cloudflare.js.map +0 -1
  948. package/dist/cache/index.js.map +0 -1
  949. package/dist/cache/register-cached-function.d.ts +0 -17
  950. package/dist/cache/register-cached-function.d.ts.map +0 -1
  951. package/dist/client/browser-entry.d.ts +0 -21
  952. package/dist/client/browser-entry.d.ts.map +0 -1
  953. package/dist/client/head.d.ts +0 -16
  954. package/dist/client/head.d.ts.map +0 -1
  955. package/dist/client/link-status-provider.d.ts +0 -11
  956. package/dist/client/link-status-provider.d.ts.map +0 -1
  957. package/dist/client/segment-merger.d.ts +0 -119
  958. package/dist/client/segment-merger.d.ts.map +0 -1
  959. package/dist/client/stale-reload.d.ts +0 -44
  960. package/dist/client/stale-reload.d.ts.map +0 -1
  961. package/dist/client/transition-root.d.ts +0 -74
  962. package/dist/client/transition-root.d.ts.map +0 -1
  963. package/dist/client/use-navigation-pending.d.ts +0 -26
  964. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  965. package/dist/client/use-params.d.ts.map +0 -1
  966. package/dist/plugins/cache-transform.d.ts +0 -36
  967. package/dist/plugins/cache-transform.d.ts.map +0 -1
  968. package/dist/plugins/dev-error-overlay.d.ts +0 -60
  969. package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
  970. package/dist/plugins/dev-logs.d.ts.map +0 -1
  971. package/dist/plugins/dynamic-transform.d.ts +0 -72
  972. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  973. package/dist/plugins/server-action-exports.d.ts +0 -26
  974. package/dist/plugins/server-action-exports.d.ts.map +0 -1
  975. package/dist/routing/status-file-lint.d.ts +0 -33
  976. package/dist/routing/status-file-lint.d.ts.map +0 -1
  977. package/dist/search-params/analyze.d.ts +0 -54
  978. package/dist/search-params/analyze.d.ts.map +0 -1
  979. package/dist/search-params/builtin-codecs.d.ts +0 -105
  980. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  981. package/dist/search-params/codecs.d.ts +0 -53
  982. package/dist/search-params/codecs.d.ts.map +0 -1
  983. package/dist/search-params/create.d.ts +0 -106
  984. package/dist/search-params/create.d.ts.map +0 -1
  985. package/dist/server/client-module-map.d.ts +0 -47
  986. package/dist/server/client-module-map.d.ts.map +0 -1
  987. package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
  988. package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
  989. package/dist/server/dev-logger.d.ts.map +0 -1
  990. package/dist/server/dev-span-processor.d.ts +0 -29
  991. package/dist/server/dev-span-processor.d.ts.map +0 -1
  992. package/dist/server/dev-warnings.d.ts +0 -129
  993. package/dist/server/dev-warnings.d.ts.map +0 -1
  994. package/dist/server/flush.d.ts +0 -74
  995. package/dist/server/flush.d.ts.map +0 -1
  996. package/dist/server/manifest-status-resolver.d.ts +0 -58
  997. package/dist/server/manifest-status-resolver.d.ts.map +0 -1
  998. package/dist/server/prerender.d.ts +0 -77
  999. package/dist/server/prerender.d.ts.map +0 -1
  1000. package/dist/utils/directive-parser.d.ts +0 -70
  1001. package/dist/utils/directive-parser.d.ts.map +0 -1
  1002. package/src/cache/register-cached-function.ts +0 -103
  1003. package/src/client/browser-entry.ts +0 -678
  1004. package/src/client/head.ts +0 -61
  1005. package/src/client/link-status-provider.tsx +0 -30
  1006. package/src/client/segment-merger.ts +0 -339
  1007. package/src/client/stale-reload.ts +0 -87
  1008. package/src/client/transition-root.tsx +0 -166
  1009. package/src/client/use-navigation-pending.ts +0 -38
  1010. package/src/plugins/cache-transform.ts +0 -199
  1011. package/src/plugins/dev-error-overlay.ts +0 -230
  1012. package/src/plugins/dynamic-transform.ts +0 -161
  1013. package/src/plugins/server-action-exports.ts +0 -220
  1014. package/src/routing/status-file-lint.ts +0 -112
  1015. package/src/search-params/analyze.ts +0 -192
  1016. package/src/search-params/builtin-codecs.ts +0 -228
  1017. package/src/search-params/codecs.ts +0 -153
  1018. package/src/search-params/create.ts +0 -321
  1019. package/src/server/client-module-map.ts +0 -58
  1020. package/src/server/dev-fetch-instrumentation.ts +0 -96
  1021. package/src/server/dev-span-processor.ts +0 -78
  1022. package/src/server/dev-warnings.ts +0 -283
  1023. package/src/server/flush.ts +0 -182
  1024. package/src/server/manifest-status-resolver.ts +0 -215
  1025. package/src/server/prerender.ts +0 -139
  1026. package/src/utils/directive-parser.ts +0 -529
@@ -8,7 +8,7 @@
8
8
  * 1. Direct call: action(input) → Promise<ActionResult>
9
9
  * 2. React useActionState: (prevState, formData) => Promise<ActionResult>
10
10
  *
11
- * See design/08-forms-and-actions.md §"Middleware for Server Actions"
11
+ * See design/08-forms-and-actions.md §"Middleware and Server Actions"
12
12
  */
13
13
 
14
14
  // ─── ActionError ─────────────────────────────────────────────────────────
@@ -131,6 +131,13 @@ interface ActionClientConfig<TCtx> {
131
131
  middleware?: ActionMiddleware<TCtx> | ActionMiddleware<Record<string, unknown>>[];
132
132
  /** Max file size in bytes. Files exceeding this are rejected with validation errors. */
133
133
  fileSizeLimit?: number;
134
+ /**
135
+ * Override the sensitive-field deny-list for this action client.
136
+ * See `SensitiveFieldsOption` in `./sensitive-fields.ts`. Per-action config
137
+ * takes precedence over the global `forms.stripSensitiveFields` option in
138
+ * `timber.config.ts`. See design/08-forms-and-actions.md and TIM-816.
139
+ */
140
+ stripSensitiveFields?: SensitiveFieldsOption;
134
141
  }
135
142
 
136
143
  /** Intermediate builder returned by createActionClient(). */
@@ -138,22 +145,53 @@ export interface ActionBuilder<TCtx> {
138
145
  /** Declare the input schema. Validation errors are returned typed. */
139
146
  schema<TInput>(schema: ActionSchema<TInput>): ActionBuilderWithSchema<TCtx, TInput>;
140
147
  /** Define the action body without input validation. */
141
- action<TData>(fn: (ctx: ActionContext<TCtx, undefined>) => Promise<TData>): ActionFn<TData>;
148
+ action<TData>(
149
+ fn: (ctx: ActionContext<TCtx, undefined>) => Promise<TData>
150
+ ): ActionFn<TData, undefined>;
142
151
  }
143
152
 
144
153
  /** Builder after .schema() has been called. */
145
154
  export interface ActionBuilderWithSchema<TCtx, TInput> {
146
155
  /** Define the action body with validated input. */
147
- action<TData>(fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>): ActionFn<TData>;
156
+ action<TData>(fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>): ActionFn<TData, TInput>;
148
157
  }
149
158
 
150
159
  /**
151
- * The final action function. Callable two ways:
160
+ * The final action function. Callable three ways:
152
161
  * - Direct: action(input) → Promise<ActionResult<TData>>
153
162
  * - React useActionState: action(prevState, formData) → Promise<ActionResult<TData>>
163
+ * - React <form action={fn}>: action(formData) → void (return value ignored by React)
164
+ *
165
+ * The third overload exists purely for type compatibility with React's
166
+ * `<form action>` prop, which expects `(formData: FormData) => void`.
167
+ * At runtime the function still returns Promise<ActionResult>, but React
168
+ * discards it. This lets validated actions be passed directly to forms
169
+ * without casts.
170
+ */
171
+ /**
172
+ * Map schema output keys to `string | undefined` for form-facing APIs.
173
+ * HTML form values are always strings, and fields can be absent.
174
+ * Gives autocomplete for field names without lying about value types.
154
175
  */
155
- export type ActionFn<TData> = {
156
- (input?: unknown): Promise<ActionResult<TData>>;
176
+ export type InputHint<T> =
177
+ T extends Record<string, unknown> ? { [K in keyof T]: string | undefined } : T;
178
+
179
+ /**
180
+ * ActionFn — the callable returned by `createActionClient().action()`.
181
+ *
182
+ * Generic order: `<TData, TInput>` — TData first for backward compatibility.
183
+ * Previously ActionFn had a single `<TData>` generic, so existing code like
184
+ * `ActionFn<MyResult>` must still work with TData in the first position.
185
+ * See TIM-797.
186
+ */
187
+ export type ActionFn<TData = unknown, TInput = unknown> = {
188
+ /** <form action={fn}> compatibility — React discards the return value. */
189
+ (formData: FormData): void;
190
+ /** Direct call: action(input) — optional when TInput is undefined/unknown (no-schema actions). */
191
+ (
192
+ ...args: undefined extends TInput ? [input?: TInput] : [input: TInput]
193
+ ): Promise<ActionResult<TData>>;
194
+ /** React useActionState: action(prevState, formData) */
157
195
  (prevState: ActionResult<TData> | null, formData: FormData): Promise<ActionResult<TData>>;
158
196
  };
159
197
 
@@ -183,8 +221,15 @@ async function runActionMiddleware<TCtx>(
183
221
 
184
222
  // Re-export parseFormData for use throughout the framework
185
223
  import { parseFormData } from './form-data.js';
186
- import { formatSize } from '#/utils/format.js';
224
+ import { formatSize } from '../utils/format.js';
187
225
  import { isDebug, isDevMode } from './debug.js';
226
+ import { RedirectSignal, DenySignal } from './primitives.js';
227
+ import {
228
+ stripSensitiveFields,
229
+ resolveSensitivePredicate,
230
+ getGlobalSensitiveFieldsConfig,
231
+ type SensitiveFieldsOption,
232
+ } from './sensitive-fields.js';
188
233
 
189
234
  /**
190
235
  * Extract validation errors from a schema error.
@@ -286,7 +331,7 @@ export function createActionClient<TCtx = Record<string, never>>(
286
331
  function buildAction<TInput, TData>(
287
332
  schema: ActionSchema<TInput> | undefined,
288
333
  fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>
289
- ): ActionFn<TData> {
334
+ ): ActionFn<TData, TInput> {
290
335
  async function actionHandler(...args: unknown[]): Promise<ActionResult<TData>> {
291
336
  try {
292
337
  // Run middleware
@@ -308,6 +353,25 @@ export function createActionClient<TCtx = Record<string, never>>(
308
353
  rawInput = args[0];
309
354
  }
310
355
 
356
+ // Resolve the sensitive-field stripping predicate once per invocation.
357
+ // Precedence: per-action (config.stripSensitiveFields) > global
358
+ // (forms.stripSensitiveFields from timber.config.ts) > built-in deny-list.
359
+ // See TIM-816.
360
+ const sensitivePredicate = resolveSensitivePredicate(
361
+ config.stripSensitiveFields,
362
+ getGlobalSensitiveFieldsConfig()
363
+ );
364
+
365
+ // Capture a "safe-to-echo" snapshot of the raw input once. Files are
366
+ // stripped (can't serialize, shouldn't echo back) and sensitive fields
367
+ // (passwords, tokens, CVV, etc.) are removed before they would land
368
+ // in the RSC payload → client form `defaultValue` → DOM.
369
+ const buildSubmittedValues = (): Record<string, unknown> | undefined => {
370
+ const withoutFiles = stripFiles(rawInput);
371
+ if (withoutFiles === undefined) return undefined;
372
+ return stripSensitiveFields(withoutFiles, sensitivePredicate);
373
+ };
374
+
311
375
  // Validate file sizes before schema validation.
312
376
  if (config.fileSizeLimit !== undefined && rawInput && typeof rawInput === 'object') {
313
377
  const fileSizeErrors = validateFileSizes(
@@ -315,14 +379,12 @@ export function createActionClient<TCtx = Record<string, never>>(
315
379
  config.fileSizeLimit
316
380
  );
317
381
  if (fileSizeErrors) {
318
- const submittedValues = stripFiles(rawInput);
319
- return { validationErrors: fileSizeErrors, submittedValues };
382
+ return { validationErrors: fileSizeErrors, submittedValues: buildSubmittedValues() };
320
383
  }
321
384
  }
322
385
 
323
386
  // Capture submitted values for repopulation on validation failure.
324
- // Exclude File objects (can't serialize, shouldn't echo back).
325
- const submittedValues = schema ? stripFiles(rawInput) : undefined;
387
+ const submittedValues = schema ? buildSubmittedValues() : undefined;
326
388
 
327
389
  // Validate with schema if provided
328
390
  let input: TInput;
@@ -366,22 +428,33 @@ export function createActionClient<TCtx = Record<string, never>>(
366
428
  const data = await fn({ ctx, input });
367
429
  return { data };
368
430
  } catch (error) {
431
+ // Re-throw redirect/deny signals — these are control flow, not errors.
432
+ // They must propagate to executeAction() which converts them to proper
433
+ // HTTP responses (302 redirect, 4xx deny). Catching them here would
434
+ // wrap them as INTERNAL_ERROR and break redirect()/redirectExternal()/deny().
435
+ if (error instanceof RedirectSignal || error instanceof DenySignal) {
436
+ throw error;
437
+ }
369
438
  return handleActionError(error);
370
439
  }
371
440
  }
372
441
 
373
- return actionHandler as ActionFn<TData>;
442
+ return actionHandler as ActionFn<TData, TInput>;
374
443
  }
375
444
 
376
445
  return {
377
446
  schema<TInput>(schema: ActionSchema<TInput>) {
378
447
  return {
379
- action<TData>(fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>): ActionFn<TData> {
448
+ action<TData>(
449
+ fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>
450
+ ): ActionFn<TData, TInput> {
380
451
  return buildAction(schema, fn);
381
452
  },
382
453
  };
383
454
  },
384
- action<TData>(fn: (ctx: ActionContext<TCtx, undefined>) => Promise<TData>): ActionFn<TData> {
455
+ action<TData>(
456
+ fn: (ctx: ActionContext<TCtx, undefined>) => Promise<TData>
457
+ ): ActionFn<TData, undefined> {
385
458
  return buildAction(undefined, fn as (ctx: ActionContext<TCtx, unknown>) => Promise<TData>);
386
459
  },
387
460
  };
@@ -410,7 +483,7 @@ export function createActionClient<TCtx = Record<string, never>>(
410
483
  export function validated<TInput, TData>(
411
484
  schema: ActionSchema<TInput>,
412
485
  handler: (input: TInput) => Promise<TData>
413
- ): ActionFn<TData> {
486
+ ): ActionFn<TData, TInput> {
414
487
  return createActionClient()
415
488
  .schema(schema)
416
489
  .action(async ({ input }) => handler(input));
@@ -437,26 +510,38 @@ function logValidationFailure(errors: ValidationErrors): void {
437
510
  * Returns validation errors keyed by field name, or null if all files are ok.
438
511
  */
439
512
  function validateFileSizes(input: Record<string, unknown>, limit: number): ValidationErrors | null {
440
- const errors: ValidationErrors = {};
441
513
  const limitKb = Math.round(limit / 1024);
442
514
  const limitLabel =
443
515
  limit >= 1024 * 1024 ? `${Math.round(limit / (1024 * 1024))}MB` : `${limitKb}KB`;
444
516
 
445
- for (const [key, value] of Object.entries(input)) {
446
- if (value instanceof File && value.size > limit) {
447
- errors[key] = [
448
- `File "${value.name}" (${formatSize(value.size)}) exceeds the ${limitLabel} limit`,
449
- ];
450
- } else if (Array.isArray(value)) {
451
- const oversized = value.filter((item) => item instanceof File && item.size > limit);
452
- if (oversized.length > 0) {
453
- errors[key] = oversized.map(
454
- (f: File) => `File "${f.name}" (${formatSize(f.size)}) exceeds the ${limitLabel} limit`
455
- );
517
+ const errors: ValidationErrors = {};
518
+
519
+ function walk(obj: Record<string, unknown>, prefix: string): void {
520
+ for (const [key, value] of Object.entries(obj)) {
521
+ const path = prefix ? `${prefix}.${key}` : key;
522
+ if (value instanceof File && value.size > limit) {
523
+ errors[path] = [
524
+ `File "${value.name}" (${formatSize(value.size)}) exceeds the ${limitLabel} limit`,
525
+ ];
526
+ } else if (Array.isArray(value)) {
527
+ for (let i = 0; i < value.length; i++) {
528
+ const item = value[i];
529
+ const itemPath = `${path}[${i}]`;
530
+ if (item instanceof File && item.size > limit) {
531
+ (errors[itemPath] ??= []).push(
532
+ `File "${item.name}" (${formatSize(item.size)}) exceeds the ${limitLabel} limit`
533
+ );
534
+ } else if (typeof item === 'object' && item !== null && !(item instanceof File)) {
535
+ walk(item as Record<string, unknown>, itemPath);
536
+ }
537
+ }
538
+ } else if (typeof value === 'object' && value !== null && !(value instanceof File)) {
539
+ walk(value as Record<string, unknown>, path);
456
540
  }
457
541
  }
458
542
  }
459
543
 
544
+ walk(input, '');
460
545
  return Object.keys(errors).length > 0 ? errors : null;
461
546
  }
462
547
 
@@ -472,7 +557,13 @@ function stripFiles(value: unknown): Record<string, unknown> | undefined {
472
557
  for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
473
558
  if (v instanceof File) continue;
474
559
  if (Array.isArray(v)) {
475
- result[k] = v.filter((item) => !(item instanceof File));
560
+ result[k] = v
561
+ .filter((item) => !(item instanceof File))
562
+ .map((item) =>
563
+ typeof item === 'object' && item !== null && !(item instanceof File)
564
+ ? (stripFiles(item) ?? {})
565
+ : item
566
+ );
476
567
  } else if (typeof v === 'object' && v !== null && !(v instanceof File)) {
477
568
  result[k] = stripFiles(v) ?? {};
478
569
  } else {
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Server action bound args encryption utilities.
3
+ *
4
+ * Provides key management for the RSC plugin's built-in bound args encryption.
5
+ * The RSC plugin (@vitejs/plugin-rsc) handles the actual encrypt/decrypt via
6
+ * AES-256-GCM — this module handles:
7
+ *
8
+ * 1. Key sourcing: auto-generated at build time (embedded in bundle), overridable
9
+ * via env var for cross-build key sharing (rolling/blue-green deployments)
10
+ * 2. Build-time key expression generation for the RSC plugin's `defineEncryptionKey`
11
+ *
12
+ * Encryption is always on in production. In dev mode, it's on by default
13
+ * (matching the RSC plugin's behavior) but can be disabled for debugging.
14
+ *
15
+ * ## Known Security Considerations
16
+ *
17
+ * 1. **defineEncryptionKey is a raw JS expression.** The RSC plugin inlines it
18
+ * verbatim into generated code. We only emit the hardcoded string
19
+ * `process.env.TIMBER_ACTIONS_ENCRYPTION_KEY` — never user-controlled input.
20
+ * If this function is ever extended to accept configurable env var names,
21
+ * the expression MUST be validated against a safe pattern.
22
+ *
23
+ * 2. **Key material lives in GC-visible JS strings.** `atob()` decodes the key
24
+ * into a regular JavaScript string on the V8 heap. JavaScript has no
25
+ * `SecureString` or memory-zeroing primitive — this is an inherent platform
26
+ * limitation. Acceptable for web server use; would need review for FIPS.
27
+ *
28
+ * 3. **TIMBER_ACTIONS_ENCRYPTION_KEY must be set at both build time and runtime.**
29
+ * At build time, we validate the key format and emit a runtime expression.
30
+ * If the env var is present at build time but missing at runtime, the server
31
+ * will crash on first action invocation with an opaque `atob(undefined)` error.
32
+ * If the env var is present at runtime but was absent at build time, the RSC
33
+ * plugin will have generated its own key and the env var is silently ignored.
34
+ *
35
+ * See design/08-forms-and-actions.md §"Security"
36
+ * See design/13-security.md
37
+ */
38
+
39
+ // ─── Types ────────────────────────────────────────────────────────────────
40
+
41
+ /** User-facing configuration for action bound args encryption. */
42
+ export interface ActionEncryptionConfig {
43
+ /**
44
+ * Disable encryption in dev mode for easier debugging.
45
+ * Has no effect in production — encryption is always enabled.
46
+ * Default: false (encryption is on in dev too).
47
+ */
48
+ disableInDev?: boolean;
49
+ }
50
+
51
+ // ─── Key Resolution ───────────────────────────────────────────────────────
52
+
53
+ /**
54
+ * Regex for safe `defineEncryptionKey` expressions.
55
+ *
56
+ * The RSC plugin inlines this expression verbatim into generated JavaScript.
57
+ * We restrict it to `process.env.<UPPER_SNAKE_CASE>` to prevent code injection.
58
+ * See "Known Security Considerations" at the top of this file.
59
+ */
60
+ const SAFE_KEY_EXPR = /^process\.env\.[A-Z_][A-Z0-9_]*$/;
61
+
62
+ /**
63
+ * Build the `defineEncryptionKey` expression for the RSC plugin.
64
+ *
65
+ * The RSC plugin accepts a JavaScript expression string that will be
66
+ * inlined into the encryption runtime module. At runtime, this expression
67
+ * must evaluate to the base64-encoded encryption key.
68
+ *
69
+ * Priority:
70
+ * 1. `TIMBER_ACTIONS_ENCRYPTION_KEY` env var (for cross-build key sharing
71
+ * in rolling/blue-green deployments)
72
+ * 2. Auto-generated at build time (RSC plugin default — embedded in bundle,
73
+ * consistent across all instances of the same build)
74
+ *
75
+ * For env var keys, we generate a runtime expression that reads the env var.
76
+ * For auto-generated keys, we return undefined and let the RSC plugin handle it.
77
+ */
78
+ export function resolveEncryptionKeyExpression(): string | undefined {
79
+ // Check for env var override — used for cross-build key sharing where
80
+ // multiple builds must agree on the same encryption key.
81
+ const envKey = process.env.TIMBER_ACTIONS_ENCRYPTION_KEY;
82
+ if (envKey) {
83
+ // Validate the key format (must be base64-encoded 32-byte key)
84
+ validateKeyFormat(envKey);
85
+
86
+ // Return a runtime expression that reads the env var at startup.
87
+ // This ensures the key is read at runtime, not embedded in the build.
88
+ const expr = 'process.env.TIMBER_ACTIONS_ENCRYPTION_KEY';
89
+
90
+ // Defense-in-depth: validate the expression matches our safe pattern.
91
+ // This is redundant today (hardcoded string), but protects against
92
+ // future refactors that might make the expression configurable.
93
+ if (!SAFE_KEY_EXPR.test(expr)) {
94
+ throw new Error(`Unsafe encryption key expression: ${expr}`);
95
+ }
96
+
97
+ return expr;
98
+ }
99
+
100
+ // No override — let the RSC plugin auto-generate a per-build key
101
+ return undefined;
102
+ }
103
+
104
+ /**
105
+ * Determine whether action encryption should be enabled.
106
+ *
107
+ * Encryption is always enabled in production. In dev mode, it's enabled
108
+ * by default but can be disabled via config for debugging.
109
+ */
110
+ export function shouldEnableEncryption(isDev: boolean, config?: ActionEncryptionConfig): boolean {
111
+ if (!isDev) return true; // Always on in production
112
+ if (config?.disableInDev) return false; // Opt-out in dev
113
+ return true; // On by default in dev too
114
+ }
115
+
116
+ // ─── Key Validation ───────────────────────────────────────────────────────
117
+
118
+ /**
119
+ * Validate that a key string is a valid base64-encoded 256-bit key.
120
+ * Throws a descriptive error if the key is malformed.
121
+ */
122
+ export function validateKeyFormat(key: string): void {
123
+ // Decode base64 and check length (32 bytes = 256 bits)
124
+ try {
125
+ const decoded = atob(key);
126
+ const bytes = decoded.length;
127
+ if (bytes !== 32) {
128
+ throw new Error(
129
+ `TIMBER_ACTIONS_ENCRYPTION_KEY must be a base64-encoded 256-bit (32-byte) key. ` +
130
+ `Got ${bytes} bytes. Generate one with: ` +
131
+ `node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"`
132
+ );
133
+ }
134
+ } catch (error) {
135
+ if (error instanceof Error && error.message.includes('TIMBER_ACTIONS_ENCRYPTION_KEY')) {
136
+ throw error;
137
+ }
138
+ throw new Error(
139
+ `TIMBER_ACTIONS_ENCRYPTION_KEY is not valid base64. ` +
140
+ `Generate a key with: ` +
141
+ `node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"`
142
+ );
143
+ }
144
+ }
@@ -18,19 +18,24 @@ import {
18
18
  decodeReply,
19
19
  decodeAction,
20
20
  renderToReadableStream,
21
- } from '#/rsc-runtime/rsc.js';
21
+ } from '../rsc-runtime/rsc.js';
22
22
 
23
23
  import { validateCsrf, type CsrfConfig } from './csrf.js';
24
24
  import { executeAction, type RevalidateRenderer } from './actions.js';
25
- import {
26
- runWithRequestContext,
27
- setMutableCookieContext,
28
- getSetCookieHeaders,
29
- } from './request-context.js';
25
+ import { runWithRequestContext, setMutableCookieContext } from './request-context.js';
26
+ import { getSetCookieHeaders, getCookiesForSsr } from './cookie-context.js';
30
27
  import { handleActionError } from './action-client.js';
31
28
  import { enforceBodyLimits, enforceFieldLimit, type BodyLimitsConfig } from './body-limits.js';
32
29
  import { parseFormData } from './form-data.js';
30
+ import {
31
+ stripSensitiveFields,
32
+ resolveSensitivePredicate,
33
+ getGlobalSensitiveFieldsConfig,
34
+ type SensitiveFieldsOption,
35
+ } from './sensitive-fields.js';
33
36
  import type { FormFlashData } from './form-flash.js';
37
+ import { checkVersionSkew, applyReloadHeaders } from './version-skew.js';
38
+ import { logActionError } from './logger.js';
34
39
 
35
40
  // ─── Types ────────────────────────────────────────────────────────────────
36
41
 
@@ -42,6 +47,12 @@ export interface ActionDispatchConfig {
42
47
  revalidateRenderer?: RevalidateRenderer;
43
48
  /** Body size limits (from timber.config.ts). */
44
49
  bodyLimits?: BodyLimitsConfig;
50
+ /**
51
+ * Override the sensitive-field deny-list for the no-JS form POST path.
52
+ * Defaults to the global `forms.stripSensitiveFields` from `timber.config.ts`.
53
+ * See `SensitiveFieldsOption` in `./sensitive-fields.ts` and TIM-816.
54
+ */
55
+ sensitiveFields?: SensitiveFieldsOption;
45
56
  }
46
57
 
47
58
  // ─── Constants ────────────────────────────────────────────────────────────
@@ -57,6 +68,12 @@ const RSC_CONTENT_TYPE = 'text/x-component';
57
68
  * - With JS: POST with `x-rsc-action` header (client callServer dispatch)
58
69
  * - Without JS: POST with form data containing `$ACTION_REF` or `$ACTION_KEY`
59
70
  * (React's progressive enhancement hidden fields)
71
+ *
72
+ * **Important:** This function returns true for ANY POST with a form
73
+ * Content-Type, including non-action POSTs to route.ts API handlers.
74
+ * The caller (wrap-action-dispatch.ts) MUST check the matched route type
75
+ * before entering the action path — route.ts matches skip action detection
76
+ * entirely so their body is not pre-parsed. See TIM-870.
60
77
  */
61
78
  export function isActionRequest(req: Request): boolean {
62
79
  if (req.method !== 'POST') return false;
@@ -75,9 +92,30 @@ export function isActionRequest(req: Request): boolean {
75
92
 
76
93
  // ─── Handler ──────────────────────────────────────────────────────────────
77
94
 
78
- /** Signal from handleFormAction to re-render the page with flash data instead of redirecting. */
95
+ /**
96
+ * Signal from handleFormAction to re-render the page with flash data instead of redirecting.
97
+ *
98
+ * Carries two cookie-related snapshots taken before the action's ALS scope
99
+ * exits, so the rerender pipeline (which establishes its own fresh cookie
100
+ * jar from the original request) doesn't lose the action's mutations:
101
+ *
102
+ * - `setCookieHeaders`: serialized Set-Cookie headers to append to the
103
+ * final HTML response. Without this, cookies set inside the action are
104
+ * silently dropped from the response. See TIM-836 (LOCAL-740).
105
+ *
106
+ * - `cookies`: the post-action read-your-own-writes view of the cookie
107
+ * jar, as the same `Map<string, string>` shape used by the request
108
+ * context's `parsedCookies`. The rerender dispatcher seeds this map
109
+ * directly into the rerender request context via `seedRequestCookies`,
110
+ * bypassing any string round-trip through a `Cookie:` header. The
111
+ * direct-Map seed eliminates the value-smuggling primitive that the
112
+ * previous `cookieHeader: string` shape carried — see
113
+ * ONGOING_SECURITY.md H-3 (TIM-868) and TIM-837.
114
+ */
79
115
  export interface FormRerender {
80
116
  rerender: FormFlashData;
117
+ setCookieHeaders: string[];
118
+ cookies: Map<string, string>;
81
119
  }
82
120
 
83
121
  /**
@@ -90,7 +128,28 @@ export async function handleActionRequest(
90
128
  req: Request,
91
129
  config: ActionDispatchConfig
92
130
  ): Promise<Response | FormRerender | null> {
131
+ // Version skew detection — reject actions from stale clients (TIM-446).
132
+ // On mismatch, return a structured RSC error response that the client
133
+ // handles by showing a brief "App updated" message and reloading.
134
+ const skewCheck = checkVersionSkew(req);
135
+ if (!skewCheck.ok) {
136
+ const reloadHeaders = new Headers({
137
+ 'Content-Type': RSC_CONTENT_TYPE,
138
+ });
139
+ applyReloadHeaders(reloadHeaders);
140
+ // Return the reload signal as an RSC stream so createFromFetch can
141
+ // decode it. The client checks X-Timber-Reload before processing.
142
+ const rscStream = renderToReadableStream({ _versionSkew: true });
143
+ return new Response(rscStream, { status: 200, headers: reloadHeaders });
144
+ }
145
+
93
146
  // CSRF validation — reject cross-origin mutation requests.
147
+ //
148
+ // Defense-in-depth: the pipeline boundary in rsc-entry/index.ts already
149
+ // validates Origin on every unsafe-method request before dispatch reaches
150
+ // here, so this call is a no-op on the happy path. It is intentionally
151
+ // retained so that handleActionRequest remains safe to call from any
152
+ // future entry point that bypasses the wrapper. See LOCAL-773.
94
153
  const csrfResult = validateCsrf(req, config.csrf);
95
154
  if (!csrfResult.ok) {
96
155
  return new Response(null, { status: csrfResult.status });
@@ -106,7 +165,7 @@ export async function handleActionRequest(
106
165
  return new Response(null, { status: limitsResult.status });
107
166
  }
108
167
 
109
- // Run inside request context so headers(), cookies() work in actions.
168
+ // Run inside request context so getHeaders(), getCookies() work in actions.
110
169
  // Actions are a mutable context — they can set cookies (design/29-cookies.md).
111
170
  return runWithRequestContext(req, async () => {
112
171
  setMutableCookieContext(true);
@@ -121,11 +180,27 @@ export async function handleActionRequest(
121
180
  result = await handleFormAction(req, config);
122
181
  }
123
182
 
124
- // Apply cookie jar to action responses
183
+ // Apply cookie jar to action responses.
184
+ //
185
+ // For Response results we append Set-Cookie directly. For FormRerender
186
+ // signals we snapshot the headers here, before this ALS scope exits, so
187
+ // the caller can apply them to the rerender pipeline's response (which
188
+ // runs in its own request-context scope with a fresh cookie jar).
189
+ // See LOCAL-740 — without this snapshot, cookies set inside a no-JS
190
+ // form action that returns validation errors are silently dropped.
125
191
  if (result instanceof Response) {
126
192
  for (const value of getSetCookieHeaders()) {
127
193
  result.headers.append('Set-Cookie', value);
128
194
  }
195
+ } else if (result && 'rerender' in result) {
196
+ result.setCookieHeaders = getSetCookieHeaders();
197
+ // Snapshot the post-action RYW cookie state as a Map so the rerender
198
+ // dispatcher can seed it directly into the rerender request context
199
+ // via `seedRequestCookies`, with no string round-trip. See TIM-837
200
+ // and ONGOING_SECURITY.md H-3 (TIM-868). `getCookiesForSsr` already
201
+ // returns a defensive copy, so the rerender scope cannot mutate the
202
+ // snapshot through this reference.
203
+ result.cookies = getCookiesForSsr();
129
204
  }
130
205
  return result;
131
206
  });
@@ -177,7 +252,7 @@ async function handleRscAction(
177
252
  });
178
253
  } catch (error) {
179
254
  // Log full error server-side for debugging
180
- console.error('[timber] server action error:', error);
255
+ logActionError({ method: req.method, path: new URL(req.url).pathname, error });
181
256
 
182
257
  // Return structured error response — ActionError gets its code/data,
183
258
  // unexpected errors get sanitized { code: 'INTERNAL_ERROR' }
@@ -224,10 +299,9 @@ async function handleRscAction(
224
299
  _tree: result.revalidation.element,
225
300
  };
226
301
  headers['X-Timber-Revalidation'] = '1';
227
- // Forward head elements as JSON so the client can update <head>.
228
- if (result.revalidation.headElements.length > 0) {
229
- headers['X-Timber-Head'] = JSON.stringify(result.revalidation.headElements);
230
- }
302
+ // Metadata (<title>/<meta>/<link>) now rides the revalidation element
303
+ // tree as React elements — React 19 Float manages them in document.head
304
+ // during client rendering. No X-Timber-Head header needed. See TIM-1151.
231
305
  } else {
232
306
  payload = result.actionResult;
233
307
  }
@@ -264,26 +338,25 @@ async function handleFormAction(
264
338
  return new Response(null, { status: fieldResult.status });
265
339
  }
266
340
 
267
- // Check if this is actually a React server action form.
268
- // If there's no $ACTION_REF_* or $ACTION_KEY, it's a regular form POST
269
- // that should be handled by the route's route handler, not here.
270
- // React uses `$ACTION_REF_` + identifierPrefix — since we don't set one,
271
- // the suffix is empty. Check for any key starting with $ACTION_REF_ or $ACTION_ID_.
272
- const allKeys = [...formData.keys()];
273
- const hasActionField = allKeys.some(
274
- (k) => k.startsWith('$ACTION_REF_') || k.startsWith('$ACTION_ID_')
275
- );
276
- if (!hasActionField && !formData.has('$ACTION_KEY')) {
277
- return null;
278
- }
279
-
280
341
  // Capture submitted values for re-render on validation failure.
281
- // Parse before decodeAction consumes the FormData.
282
- const submittedValues = parseFormData(formData);
342
+ // Parse before decodeAction consumes the FormData, then strip sensitive
343
+ // fields (passwords, tokens, CVV, etc.) so they are never rendered back
344
+ // into the HTML as `defaultValue` attributes. See TIM-816.
345
+ const sensitivePredicate = resolveSensitivePredicate(
346
+ config.sensitiveFields,
347
+ getGlobalSensitiveFieldsConfig()
348
+ );
349
+ const submittedValues = stripSensitiveFields(parseFormData(formData), sensitivePredicate);
283
350
 
284
351
  // decodeAction resolves the action function from the form data's hidden fields.
285
- // It returns a bound function with the form data already applied.
286
- const actionFn = (await decodeAction(formData)) as (...args: unknown[]) => Promise<unknown>;
352
+ // Returns null when no $ACTION_REF_/$ACTION_ID_ fields are present — meaning
353
+ // this is a regular form POST, not a React server action.
354
+ const actionFn = (await decodeAction(formData)) as
355
+ | ((...args: unknown[]) => Promise<unknown>)
356
+ | null;
357
+ if (!actionFn) {
358
+ return null;
359
+ }
287
360
 
288
361
  // Execute the action — no additional args needed (form data is already bound).
289
362
  // Errors are caught to prevent stack traces from leaking in the response.
@@ -293,7 +366,7 @@ async function handleFormAction(
293
366
  renderer: config.revalidateRenderer,
294
367
  });
295
368
  } catch (error) {
296
- console.error('[timber] server action error:', error);
369
+ logActionError({ method: req.method, path: new URL(req.url).pathname, error });
297
370
 
298
371
  // Return the error as flash data for re-render.
299
372
  // handleActionError produces { serverError } for ActionErrors
@@ -304,6 +377,9 @@ async function handleFormAction(
304
377
  ...errorResult,
305
378
  submittedValues,
306
379
  },
380
+ // Filled in by handleActionRequest before the ALS scope exits.
381
+ setCookieHeaders: [],
382
+ cookies: new Map(),
307
383
  };
308
384
  }
309
385
 
@@ -321,5 +397,19 @@ async function handleFormAction(
321
397
  // This handles both success ({ data }) and validation failure
322
398
  // ({ validationErrors, submittedValues }) — the form is the single source of truth.
323
399
  const actionResult = result.actionResult as FormFlashData;
324
- return { rerender: actionResult };
400
+
401
+ // Defense-in-depth: strip sensitive fields from `actionResult.submittedValues`
402
+ // even if the action already built it. `createActionClient` strips internally,
403
+ // but raw `'use server'` functions that manually return `{ submittedValues }`
404
+ // are not covered by the inner strip. See TIM-816.
405
+ if (actionResult && actionResult.submittedValues) {
406
+ actionResult.submittedValues = stripSensitiveFields(
407
+ actionResult.submittedValues,
408
+ sensitivePredicate
409
+ );
410
+ }
411
+
412
+ // setCookieHeaders + cookies are filled in by handleActionRequest before
413
+ // the ALS scope exits.
414
+ return { rerender: actionResult, setCookieHeaders: [], cookies: new Map() };
325
415
  }