void 0.27.0 → 1.0.3

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 (337) hide show
  1. package/README.md +3 -1
  2. package/dist/{account-cmd-l-FM7Ioq.mjs → account-cmd-BTcUzv9L.mjs} +6 -6
  3. package/dist/{agents-B_pX_HmQ.mjs → agents-CuNtT0D_.mjs} +5 -2
  4. package/dist/{application-analysis-DKy02UY0.mjs → application-analysis-AB_YYWgH.mjs} +118 -135
  5. package/dist/{application-routing-DQyUh_5S.mjs → application-routing-L7V-TFhZ.mjs} +1 -2
  6. package/dist/atomic-write-Dq6R0BPN.mjs +18 -0
  7. package/dist/{auth-Dn2vw-SG.mjs → auth-B6iOCjKI.mjs} +23 -56
  8. package/dist/auth-Cbqi1iVX.mjs +1 -0
  9. package/dist/{auth-link-vz9Z2kmG.mjs → auth-link-DUJuvRx5.mjs} +11 -11
  10. package/dist/{auth-migrations-BwHgeEsD.mjs → auth-migrations-Cgs0k6lS.mjs} +28 -5
  11. package/dist/{auth-router-DvsCUVw4.mjs → auth-router-CIxiMG7i.mjs} +5 -5
  12. package/dist/base64-DVrOndmI.mjs +16 -0
  13. package/dist/{better-auth-shared-CPvWD3nG.d.mts → better-auth-shared-B74NJIus.d.mts} +8 -13
  14. package/dist/{better-auth-shared-DPpj8zxc.mjs → better-auth-shared-CMXlZG7W.mjs} +56 -68
  15. package/dist/{build-cmd-D6we0VjO.mjs → build-cmd-BkIv25PA.mjs} +6 -6
  16. package/dist/{cache-CZRdzKx1.mjs → cache-Ctzfig-W.mjs} +6 -6
  17. package/dist/{cancel-deploy-CQ3NnMvf.mjs → cancel-deploy-CD9o-SsC.mjs} +5 -5
  18. package/dist/{cf-access-TWNzXltp.mjs → cf-access-BM9G0lhO.mjs} +4 -3
  19. package/dist/{cf-access-BcIBSKqG.mjs → cf-access-CWP4avfP.mjs} +3 -7
  20. package/dist/cf-build-output-BU3hqdHu.mjs +1 -0
  21. package/dist/{cf-build-output-DjvB_872.mjs → cf-build-output-Bc8i3dzE.mjs} +2 -2
  22. package/dist/cf-user-agent-ChjQp2MU.mjs +33 -0
  23. package/dist/cli/cli.mjs +199 -312
  24. package/dist/cli/cloudflare-operation-process.mjs +41 -15
  25. package/dist/cli/env-schema-probe.d.mts +7 -44
  26. package/dist/cli/env-schema-probe.mjs +14 -80
  27. package/dist/client-B60PwCC4.mjs +1 -0
  28. package/dist/{client-DlDJuY0s.mjs → client-DM9Kcf4e.mjs} +161 -415
  29. package/dist/{cloudflare-auth-CuxfF6OA.mjs → cloudflare-auth-CqFBDo52.mjs} +12 -39
  30. package/dist/{cloudflare-cmd-lHqNlJGW.mjs → cloudflare-cmd-BIAF_BIY.mjs} +7 -6
  31. package/dist/{cloudflare-config-BmhBv3HV.mjs → cloudflare-config-DV60XFFK.mjs} +16 -28
  32. package/dist/{cloudflare-connect-2G3rL2rP.mjs → cloudflare-connect-WjwnVOJA.mjs} +4 -4
  33. package/dist/{cloudflare-operations-CwI1bChl.mjs → cloudflare-operations-B42EZeJy.mjs} +26 -34
  34. package/dist/cloudflare-operations-CrSUFRzJ.mjs +1 -0
  35. package/dist/{cloudflare-process-2-TfIEzB.mjs → cloudflare-process-CeDWJRhj.mjs} +12 -7
  36. package/dist/collect-Cae8A7Zr.mjs +1 -0
  37. package/dist/{collect-DiTn9yr6.mjs → collect-xjffdCdk.mjs} +1 -1
  38. package/dist/{config-CSa15FvD.d.mts → config-7qoq2p9v.d.mts} +2 -2
  39. package/dist/{config-CLYAosnQ.mjs → config-BEm9vRvS.mjs} +11 -5
  40. package/dist/{config-DiowPT80.mjs → config-Bx_1SpnO.mjs} +87 -177
  41. package/dist/{config-DPByhVck.mjs → config-D0GY5ItR.mjs} +1 -1
  42. package/dist/config-QrJWu0IX.mjs +1 -0
  43. package/dist/config-entry.d.mts +1 -1
  44. package/dist/{connect-BfPBHHm-.mjs → connect-CKtk-EZe.mjs} +9 -9
  45. package/dist/create-project-B-ewF_Af.mjs +1 -0
  46. package/dist/{create-project-BdXEFKal.mjs → create-project-yInGo72M.mjs} +8 -8
  47. package/dist/database-provider.mjs +1 -2
  48. package/dist/{db-Xs80hcaA.mjs → db-7I_gfdVq.mjs} +177 -268
  49. package/dist/db-types-Bb4WBWIs.mjs +49 -0
  50. package/dist/{delete-d2vuou3j.mjs → delete-Cy-M1u-r.mjs} +6 -6
  51. package/dist/deploy-9lgfhrXS.mjs +2 -0
  52. package/dist/deploy-BYYlnsiy.mjs +6164 -0
  53. package/dist/deploy-managed-static-Ca4TFdmx.mjs +1595 -0
  54. package/dist/deploy-transport-DWlWBe6M.mjs +180 -0
  55. package/dist/deploy.d.mts +10 -0
  56. package/dist/deploy.mjs +82 -0
  57. package/dist/dev-inbox-Rd6j_8vM.mjs +217 -0
  58. package/dist/discover-ClzFSwns.mjs +1 -0
  59. package/dist/{discover-CkCYv9T_.mjs → discover-D2PGT63u.mjs} +2 -2
  60. package/dist/dispatch-DrTTk8Xg.mjs +431 -0
  61. package/dist/{dist-D3m88sjf.mjs → dist-BVdsO7Py.mjs} +5 -6
  62. package/dist/dist-CfgIkieS.mjs +1 -0
  63. package/dist/{dist-BVqXeR_h.mjs → dist-ipQi0Q8y.mjs} +2 -3
  64. package/dist/{domain-BsDUBAvt.mjs → domain-CZGxPv9u.mjs} +8 -23
  65. package/dist/{dotenv-BfU6eqFt.mjs → dotenv-CNazY3-w.mjs} +4 -16
  66. package/dist/edge.mjs +1 -2
  67. package/dist/{email-d_Aux1vM.mjs → email-BcjSyAL0.mjs} +4 -20
  68. package/dist/{email-_lGAHOhp.mjs → email-DzyNVuoU.mjs} +100 -192
  69. package/dist/email-cloudflare-DfG6UEMm.mjs +1096 -0
  70. package/dist/email-protocol-D9nTvhCp.mjs +82 -0
  71. package/dist/{entry-CMAkqBmU.mjs → entry-ehmBvs5w.mjs} +2 -2
  72. package/dist/{env-DMA3cXZt.mjs → env-0jrMQJI_.mjs} +6 -14
  73. package/dist/{env-BxocywBB.mjs → env-BJjULvL0.mjs} +2 -2
  74. package/dist/{env-C74QepDE.mjs → env-Nx3yf50r.mjs} +9 -9
  75. package/dist/{env-public-DR7ZM6d-.d.mts → env-public-CCdykygU.d.mts} +6 -23
  76. package/dist/{env-raw-jZpP5n47.mjs → env-raw-D74P4ebM.mjs} +15 -21
  77. package/dist/{env-types-CwXgeMgL.mjs → env-types-DS2_y4X8.mjs} +2 -2
  78. package/dist/env-validation-BT7z-qpQ.mjs +1 -0
  79. package/dist/env-validation-DYxjz_Wo.mjs +488 -0
  80. package/dist/{gen-DtkQhvQg.mjs → gen-CufHEf42.mjs} +132 -254
  81. package/dist/gen-sXyp5DFO.mjs +1 -0
  82. package/dist/generate-ClI89brV.mjs +1 -0
  83. package/dist/{generate-GDbL7sUr.mjs → generate-Dat0UTry.mjs} +38 -4
  84. package/dist/generated-wrangler-config-DeWj5F9Y.mjs +18 -0
  85. package/dist/{github-cmd-DaDdBbSS.mjs → github-cmd-FU8EjFyU.mjs} +28 -72
  86. package/dist/{handler-BHAn2fZJ.mjs → handler-BZ1t7-Rv.mjs} +2 -2
  87. package/dist/{handler-CNAwjRcW.d.mts → handler-_PqY82xe.d.mts} +1 -1
  88. package/dist/{headers-DlfR78Nu.mjs → headers-Di1FsD3e.mjs} +26 -81
  89. package/dist/{help-0bTe_lID.mjs → help-BT2hovNI.mjs} +26 -14
  90. package/dist/help-i2YGGnTH.mjs +1 -0
  91. package/dist/{inbound-PfQDLXc5.mjs → inbound-BuTfm11U.mjs} +71 -222
  92. package/dist/{inbound-CH5Mksyy.d.mts → inbound-brj2-TM5.d.mts} +19 -58
  93. package/dist/index.d.mts +2 -18
  94. package/dist/index.mjs +714 -762
  95. package/dist/{info-PYWwkWyt.mjs → info-l249eUdH.mjs} +5 -5
  96. package/dist/{init-DaBGmaXC.mjs → init-D0A6M64Q.mjs} +229 -392
  97. package/dist/isr-config-fZaJJ8t7.mjs +165 -0
  98. package/dist/{link-C6fjafep.mjs → link-WMoJFf4i.mjs} +9 -9
  99. package/dist/{list-BTFBlqKl.mjs → list-CQ2EQEHL.mjs} +7 -18
  100. package/dist/{live-CgQuTpqD.mjs → live-BcHoTDFe.mjs} +19 -17
  101. package/dist/{live-Du8jXwOW.d.mts → live-DJONVlQK.d.mts} +1 -1
  102. package/dist/load-user-env-DD5qveNU.mjs +49 -0
  103. package/dist/{local-d1-ga5O_idV.mjs → local-d1-BxvQYEFi.mjs} +6 -6
  104. package/dist/{login-GKcNUmtI.mjs → login-C2T1oVG-.mjs} +12 -12
  105. package/dist/login-XD844Xs-.mjs +1 -0
  106. package/dist/{logs-BiMSULmc.mjs → logs-DnC1d7xB.mjs} +6 -6
  107. package/dist/{migrate-NLsjBbuM.mjs → migrate-BDIprOYd.mjs} +70 -22
  108. package/dist/migrate-BRwU-blY.mjs +1 -0
  109. package/dist/migration-handler-Cg0Y4EPu.mjs +470 -0
  110. package/dist/{migration-handler-DM4clYj5.d.mts → migration-handler-CwlEQUoo.d.mts} +17 -26
  111. package/dist/{mime-DxCznlJq.mjs → mime-srOklVVv.mjs} +92 -395
  112. package/dist/mysql-migration-sql-BIS5vbNk.mjs +241 -0
  113. package/dist/nitro.d.mts +30 -0
  114. package/dist/nitro.mjs +88 -0
  115. package/dist/{node-DJicPvPj.mjs → node-cPadMgUO.mjs} +9 -25
  116. package/dist/{operator-args-DOBhIaIg.mjs → operator-args-UnE8Y2eK.mjs} +27 -26
  117. package/dist/{operator-auth-BEZ_u0Cz.mjs → operator-auth-Cr2zCc-J.mjs} +2 -2
  118. package/dist/{operator-client-DbDv4vtE.mjs → operator-client-C-ROjk1I.mjs} +4 -4
  119. package/dist/operator-cmd-D6gnZsnK.mjs +1 -0
  120. package/dist/{operator-cmd-BT4hgavL.mjs → operator-cmd-DHieWtFp.mjs} +8 -8
  121. package/dist/{output-C50ag2r3.mjs → output-Ba6ZbrzY.mjs} +37 -6
  122. package/dist/{package-json-DXfiT1jV.mjs → package-json-BjYqR-So.mjs} +1 -1
  123. package/dist/pages/client.d.mts +1 -1
  124. package/dist/pages/client.mjs +91 -5
  125. package/dist/pages/head.mjs +1 -2
  126. package/dist/pages/index.d.mts +1 -2
  127. package/dist/pages/index.mjs +6 -6
  128. package/dist/pages/islands-plugin.mjs +5 -83
  129. package/dist/pages/prefetch.mjs +1 -2
  130. package/dist/pages/protocol.d.mts +2 -2
  131. package/dist/pages/protocol.mjs +1 -1
  132. package/dist/pages/serialize.mjs +1 -2
  133. package/dist/plan-CKX_jWnD.mjs +1 -0
  134. package/dist/platform-args-B0HeTh0C.mjs +1 -0
  135. package/dist/{platform-args-DUeXY9Om.mjs → platform-args-CaCL_1Ch.mjs} +43 -60
  136. package/dist/{platform-auth-config-CkSx3usH.mjs → platform-auth-config-Z16-I8nT.mjs} +11 -12
  137. package/dist/{platform-auth-protection-BJimB_p9.mjs → platform-auth-protection-BXwZiJSF.mjs} +37 -27
  138. package/dist/{platform-auth-recovery-BU6izFAU.mjs → platform-auth-recovery-CXjfqyOv.mjs} +9 -10
  139. package/dist/{platform-cmd-BbY1dWiM.mjs → platform-cmd-DaAOiWTl.mjs} +16 -16
  140. package/dist/platform-cmd-PT4YwMLM.mjs +1 -0
  141. package/dist/{platform-discovery-DIYz8V63.mjs → platform-discovery-CHhNs8Nn.mjs} +1 -1
  142. package/dist/{platform-domain-CHVS6cV0.mjs → platform-domain-CxpvUeo0.mjs} +6 -6
  143. package/dist/{platform-lifecycle-DzCwqhFq.mjs → platform-lifecycle-DBiS0cJd.mjs} +1693 -2120
  144. package/dist/platform-lifecycle-u9pMOvxC.mjs +1 -0
  145. package/dist/{platform-management-CuuVDhyt.mjs → platform-management-DhEFdQAf.mjs} +696 -130
  146. package/dist/platform-management-DvBS83rC.mjs +1 -0
  147. package/dist/{platform-plans-config-CN-heS4q.mjs → platform-plans-config-BWn1S2Rv.mjs} +16 -12
  148. package/dist/{platform-recovery-CskSJgLh.mjs → platform-recovery-BUGOB4RC.mjs} +6 -9
  149. package/dist/{platform-registry-Cjv2Qf0r.mjs → platform-registry-B9mWX9LO.mjs} +13 -18
  150. package/dist/{platform-setup-BBxRxmFC.mjs → platform-setup-YvN9VQXV.mjs} +21 -28
  151. package/dist/{plugin-inference-BlQbOL0P.mjs → plugin-inference-DsARdQKE.mjs} +18 -33
  152. package/dist/prepare-CYT6tAzD.mjs +1 -0
  153. package/dist/{prepare-Do96654b.mjs → prepare-DEB5SeVJ.mjs} +12 -13
  154. package/dist/{prepare-Dq9hTIbo.mjs → prepare-PQCgsny0.mjs} +4 -4
  155. package/dist/{prerender-render-Ct20jftc.mjs → prerender-render-Bfsumdkv.mjs} +8 -2
  156. package/dist/prerender-render.d.mts +2 -0
  157. package/dist/prerender-render.mjs +1 -2
  158. package/dist/{project-cmd-DaoRrn-8.mjs → project-cmd-DVatD8Ev.mjs} +20 -20
  159. package/dist/{project-paths-GgcMozYz.mjs → project-paths-DMvEeSau.mjs} +9 -14
  160. package/dist/{project-BAm2aB6Q.mjs → project-rqDnVsJN.mjs} +8 -4
  161. package/dist/project-slug-6cyz8E7k.mjs +1 -0
  162. package/dist/{project-team-Q_lCA7Io.mjs → project-team-DJrWEAG1.mjs} +7 -7
  163. package/dist/{project-token-BArgK9o1.mjs → project-token-CBgLBuL6.mjs} +6 -6
  164. package/dist/{project-tsconfig-CVJhNMxs.mjs → project-tsconfig-bveqhlYA.mjs} +3 -5
  165. package/dist/project-zdB3fs9G.mjs +1 -0
  166. package/dist/{project-zero-trust-KO9Hu2Pq.mjs → project-zero-trust-92gLtZ25.mjs} +6 -6
  167. package/dist/{protocol-BPZaNqBo.d.mts → protocol-4H7V_3Os.d.mts} +1 -1
  168. package/dist/{protocol-CfaUwNs8.mjs → protocol-RNP0u7UY.mjs} +9 -3
  169. package/dist/{provision-BfaLiWbj.mjs → provision-BnSSkiED.mjs} +119 -866
  170. package/dist/{requests-C7Oeoh5u.mjs → requests-7W1Pygt2.mjs} +5 -5
  171. package/dist/resolve-project-PnhzMtY6.mjs +1 -0
  172. package/dist/resolve-project-WpwkCB_c.mjs +48 -0
  173. package/dist/{rollback-DVAtrLAl.mjs → rollback-BcASVnwP.mjs} +8 -18
  174. package/dist/{route-types-CbtsIeFn.mjs → route-types-BZi26DVS.mjs} +9 -91
  175. package/dist/routing-assets-VkrKIbxE.mjs +139 -0
  176. package/dist/{runner-DMBKSrRk.mjs → runner-CabsQ-iM.mjs} +22 -34
  177. package/dist/runner-So9mYfcm.mjs +1 -0
  178. package/dist/runner-mysql-BhRaONkO.mjs +146 -0
  179. package/dist/runner-mysql-DWwE8jKi.mjs +1 -0
  180. package/dist/{runner-pg-DV8p_zjA.mjs → runner-pg-BRemq_GX.mjs} +3 -3
  181. package/dist/runner-pg-_Xncr3H5.mjs +1 -0
  182. package/dist/runtime/ai.mjs +23 -25
  183. package/dist/runtime/auth-client-react.mjs +1 -2
  184. package/dist/runtime/auth-client-solid.mjs +1 -2
  185. package/dist/runtime/auth-client-svelte.mjs +1 -2
  186. package/dist/runtime/auth-client-vue.mjs +1 -2
  187. package/dist/runtime/auth-client.mjs +1 -2
  188. package/dist/runtime/auth.mjs +1 -2
  189. package/dist/runtime/better-auth-mysql.d.mts +2 -5
  190. package/dist/runtime/better-auth-mysql.mjs +9 -31
  191. package/dist/runtime/better-auth-pg.d.mts +2 -5
  192. package/dist/runtime/better-auth-pg.mjs +6 -32
  193. package/dist/runtime/better-auth.d.mts +2 -4
  194. package/dist/runtime/better-auth.mjs +9 -19
  195. package/dist/runtime/db.mjs +6 -2
  196. package/dist/runtime/durable.d.mts +18 -1
  197. package/dist/runtime/durable.mjs +26 -2
  198. package/dist/runtime/email/testing.d.mts +1 -1
  199. package/dist/runtime/email/testing.mjs +9 -23
  200. package/dist/runtime/email-protocol.d.mts +12 -0
  201. package/dist/runtime/email-protocol.mjs +1 -70
  202. package/dist/runtime/email.d.mts +1 -1
  203. package/dist/runtime/email.mjs +79 -221
  204. package/dist/runtime/env-public.d.mts +1 -1
  205. package/dist/runtime/env-public.mjs +12 -38
  206. package/dist/runtime/env.d.mts +1 -12
  207. package/dist/runtime/env.mjs +1 -2
  208. package/dist/runtime/handler.d.mts +1 -1
  209. package/dist/runtime/handler.mjs +1 -1
  210. package/dist/runtime/isr.mjs +1 -1
  211. package/dist/runtime/kv.mjs +1 -1
  212. package/dist/runtime/limits.mjs +1 -2
  213. package/dist/runtime/live-client.d.mts +3 -2
  214. package/dist/runtime/live-server.d.mts +2 -1
  215. package/dist/runtime/live-server.mjs +1 -16
  216. package/dist/runtime/live.d.mts +1 -1
  217. package/dist/runtime/live.mjs +1 -2
  218. package/dist/runtime/log.d.mts +2 -1
  219. package/dist/runtime/migration-handler-mysql.d.mts +2 -2
  220. package/dist/runtime/migration-handler-mysql.mjs +39 -8
  221. package/dist/runtime/migration-handler-pg.d.mts +2 -2
  222. package/dist/runtime/migration-handler-pg.mjs +1 -1
  223. package/dist/runtime/migration-handler.d.mts +2 -2
  224. package/dist/runtime/migration-handler.mjs +1 -470
  225. package/dist/runtime/queues.mjs +1 -1
  226. package/dist/runtime/remote/binding-handler.mjs +62 -62
  227. package/dist/runtime/remote/index.mjs +16 -77
  228. package/dist/runtime/response.mjs +1 -2
  229. package/dist/runtime/route-url.mjs +1 -2
  230. package/dist/runtime/routing.d.mts +3 -5
  231. package/dist/runtime/routing.mjs +82 -218
  232. package/dist/runtime/sandbox-container.d.mts +2 -2
  233. package/dist/runtime/sandbox-container.mjs +1 -2
  234. package/dist/runtime/sandbox.d.mts +2 -2
  235. package/dist/runtime/sandbox.mjs +13 -6
  236. package/dist/runtime/seed.d.mts +2 -1
  237. package/dist/runtime/sse.mjs +1 -2
  238. package/dist/runtime/storage.mjs +1 -1
  239. package/dist/runtime/validator.d.mts +1 -1
  240. package/dist/runtime/validator.mjs +1 -2
  241. package/dist/runtime/ws-server.d.mts +4 -4
  242. package/dist/runtime/ws-server.mjs +6 -28
  243. package/dist/runtime/ws.d.mts +1 -1
  244. package/dist/{sandbox-container-Bo0eiFKz.d.mts → sandbox-container-ChQRum-j.d.mts} +3 -1
  245. package/dist/{sandbox-container-C6ItmVuN.mjs → sandbox-container-a9LRUtii.mjs} +13 -2
  246. package/dist/{sandbox-C5LFoJMf.d.mts → sandbox-q3waMc2T.d.mts} +1 -1
  247. package/dist/{scan-C3uDzz6J.mjs → scan-C0BMdmEd.mjs} +84 -7
  248. package/dist/{secret-BvtB7IjY.mjs → secret-bg73f1Ge.mjs} +63 -81
  249. package/dist/{serialize-BPvnNQuA.mjs → serialize-BtQyaYoC.mjs} +10 -4
  250. package/dist/{skills-BgVMvQdy.mjs → skills-C_yRTg0g.mjs} +3 -3
  251. package/dist/{subcommand-prompt-BSlnD1fI.mjs → subcommand-prompt-Bm3ZlYgA.mjs} +39 -44
  252. package/dist/sveltekit.d.mts +2 -1
  253. package/dist/sveltekit.mjs +1 -1
  254. package/dist/validate-BQFdf0Pi.mjs +1 -0
  255. package/dist/{validate-C9qJArv7.mjs → validate-CheZGRE7.mjs} +4 -8
  256. package/dist/version-metadata-DIrqEHQo.mjs +73 -0
  257. package/dist/{wrangler-D9KTuqnv.mjs → wrangler-BYs07Rxy.mjs} +119 -378
  258. package/dist/wrapper-CwhpNWtH.mjs +663 -0
  259. package/dist/{ws-CChrrAU-.d.mts → ws-aKVYB-fA.d.mts} +1 -1
  260. package/dist/yarn-pnp-DLbEFMT0.mjs +92 -0
  261. package/docs/guide/ai.md +8 -2
  262. package/docs/guide/auth.md +2 -0
  263. package/docs/guide/database/mysql.md +14 -3
  264. package/docs/guide/database/postgresql.md +2 -0
  265. package/docs/guide/database.md +3 -5
  266. package/docs/guide/durable-state.md +32 -4
  267. package/docs/guide/platform/administration/access.md +4 -0
  268. package/docs/guide/platform/administration/connected-apps.md +55 -0
  269. package/docs/guide/platform/installation/credentials.md +21 -3
  270. package/docs/guide/platform/installation/domains.md +1 -1
  271. package/docs/guide/platform/installation/maintenance.md +38 -1
  272. package/docs/guide/platform/installation/prerequisites.md +6 -2
  273. package/docs/guide/platform/installation/setup.md +23 -1
  274. package/docs/guide/platform/installation/uninstall.md +6 -1
  275. package/docs/guide/quickstart.md +2 -0
  276. package/docs/guide/sandboxes.md +3 -1
  277. package/docs/guide/self-hosted-platform.md +1 -1
  278. package/docs/integrations/cloudflare.md +2 -2
  279. package/docs/integrations/frameworks/analog.md +3 -11
  280. package/docs/integrations/frameworks/nuxt.md +7 -10
  281. package/docs/integrations/nodejs-bun-deno.md +2 -0
  282. package/docs/reference/api/deploy.md +23 -0
  283. package/docs/reference/api/pages.md +2 -0
  284. package/docs/reference/api.md +3 -1
  285. package/docs/reference/cli/database.md +9 -3
  286. package/docs/reference/cli/platform-installation.md +19 -7
  287. package/docs/reference/cli/setup.md +2 -0
  288. package/docs/reference/config.md +2 -0
  289. package/package.json +39 -36
  290. package/sandbox.Dockerfile +1 -1
  291. package/skills/void/SKILL.md +2 -1
  292. package/dist/auth-LMJcNESe.mjs +0 -2
  293. package/dist/cf-build-output-H9a97vME.mjs +0 -2
  294. package/dist/cf-user-agent-lKblH3zU.mjs +0 -17
  295. package/dist/client-tso2OfcG.mjs +0 -2
  296. package/dist/cloudflare-operations-BlYLlowZ.mjs +0 -2
  297. package/dist/collect-DLyFDiKW.mjs +0 -2
  298. package/dist/config-5r-YpMC-.mjs +0 -2
  299. package/dist/config-B_ggY-IO.mjs +0 -89
  300. package/dist/config-BtSFvXZx.mjs +0 -2
  301. package/dist/config-write-AHGesphx.mjs +0 -61
  302. package/dist/create-project-qFDC45zg.mjs +0 -2
  303. package/dist/deploy-Bqe1PYBw.mjs +0 -10458
  304. package/dist/deploy-VsWsVQkw.mjs +0 -2
  305. package/dist/dev-inbox-CK-UuPob.mjs +0 -297
  306. package/dist/discover-EDUf6JJw.mjs +0 -2
  307. package/dist/dist-Bx1z6Eva.mjs +0 -2
  308. package/dist/dist-_UUlL6bg.mjs +0 -2
  309. package/dist/env-validation-CrVNjsPm.mjs +0 -2
  310. package/dist/env-validation-Dxdx_5wo.mjs +0 -951
  311. package/dist/gen-dA9hW7AV.mjs +0 -2
  312. package/dist/head-client-DzmJGN4C.mjs +0 -90
  313. package/dist/help-DfQYVfGY.mjs +0 -2
  314. package/dist/login-mx_ydhmp.mjs +0 -2
  315. package/dist/migrate-BHp07yJE.mjs +0 -2
  316. package/dist/operator-cmd-CwBB-1yb.mjs +0 -2
  317. package/dist/pages/head-client.d.mts +0 -13
  318. package/dist/pages/head-client.mjs +0 -2
  319. package/dist/plan-CH2G51je.mjs +0 -2
  320. package/dist/platform-args-D4E1PjVw.mjs +0 -2
  321. package/dist/platform-cmd-BbmJiq5O.mjs +0 -2
  322. package/dist/platform-lifecycle-ByAlpkhV.mjs +0 -2
  323. package/dist/platform-management-CBOT4BSM.mjs +0 -2
  324. package/dist/prepare-DRUV-g3X.mjs +0 -2
  325. package/dist/project-DedqCp59.mjs +0 -2
  326. package/dist/project-slug-DofjTFd-.mjs +0 -2
  327. package/dist/provision-Wu9ZBk9L.mjs +0 -2
  328. package/dist/resolve-project-BIeYs9Cw.mjs +0 -2
  329. package/dist/resolve-project-CP8rZs_p.mjs +0 -28
  330. package/dist/runner-9wjsSZx-.mjs +0 -2
  331. package/dist/runner-mysql-CEzKtmFb.mjs +0 -54
  332. package/dist/runner-mysql-CkFqZ6CE.mjs +0 -2
  333. package/dist/runner-pg-BGYRFdRp.mjs +0 -2
  334. package/dist/runtime/env-helpers.d.mts +0 -2
  335. package/dist/runtime/env-helpers.mjs +0 -2
  336. package/dist/validate-BJr9LfXy.mjs +0 -2
  337. package/dist/yarn-pnp-CUX_iTPA.mjs +0 -188
@@ -0,0 +1,92 @@
1
+ import { a as join, n as dirname } from "./dist-ipQi0Q8y.mjs";
2
+ import { existsSync, readdirSync } from "node:fs";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+ //#region src/cli/yarn-pnp.ts
5
+ const drizzleKitBin = join(fileURLToPath(import.meta.resolve("drizzle-kit")), "..", "bin.cjs");
6
+ /** Read the PnP runtime files in `dir` only, or `undefined` when neither exists. */
7
+ function readPnpRuntimeAt(dir) {
8
+ const cjs = join(dir, ".pnp.cjs");
9
+ const loader = join(dir, ".pnp.loader.mjs");
10
+ const cjsExists = existsSync(cjs);
11
+ const loaderExists = existsSync(loader);
12
+ if (!cjsExists && !loaderExists) return;
13
+ return {
14
+ pnpCjs: cjsExists ? cjs : void 0,
15
+ pnpLoader: loaderExists ? loader : void 0
16
+ };
17
+ }
18
+ /**
19
+ * Whether `dir` has its own package-manager lockfile, i.e. it is an install
20
+ * root: workspace members share the root lockfile. `packageManager` is not a
21
+ * signal, because a Yarn workspace member may pin it and still resolve through
22
+ * the root's `.pnp.cjs`.
23
+ */
24
+ function hasLocalLockfile(dir) {
25
+ return existsSync(join(dir, "pnpm-lock.yaml")) || existsSync(join(dir, "package-lock.json")) || existsSync(join(dir, "yarn.lock")) || existsSync(join(dir, "bun.lock")) || existsSync(join(dir, "bun.lockb"));
26
+ }
27
+ /**
28
+ * Find Yarn Berry PnP runtime files at `start` or its nearest ancestor, since a
29
+ * monorepo keeps `.pnp.cjs` at the workspace root. A lockfile at `start` stops
30
+ * the walk: an outer PnP graph lacks the local install's dependencies.
31
+ */
32
+ function findYarnPnpRuntime(start) {
33
+ const local = readPnpRuntimeAt(start);
34
+ if (local !== void 0) return {
35
+ dir: start,
36
+ runtime: local
37
+ };
38
+ if (hasLocalLockfile(start)) return;
39
+ let dir = dirname(start);
40
+ if (dir === start) return;
41
+ while (true) {
42
+ const found = readPnpRuntimeAt(dir);
43
+ if (found !== void 0) return {
44
+ dir,
45
+ runtime: found
46
+ };
47
+ const parent = dirname(dir);
48
+ if (parent === dir) return;
49
+ dir = parent;
50
+ }
51
+ }
52
+ /**
53
+ * Like {@link findYarnPnpRuntime}, but only when Yarn has installed into that
54
+ * same directory. A committed `.pnp.cjs` alone does not prove an install: its
55
+ * ZIP archives may not be fetched yet.
56
+ */
57
+ function findInstalledYarnPnpRuntime(start) {
58
+ const found = findYarnPnpRuntime(start);
59
+ return found && isYarnPnpInstalled(found.dir) ? found.runtime : void 0;
60
+ }
61
+ /**
62
+ * Yarn writes `.yarn/install-state.gz` on every install; a zero-install
63
+ * checkout instead commits a populated `.yarn/cache`.
64
+ */
65
+ function isYarnPnpInstalled(dir) {
66
+ if (existsSync(join(dir, ".yarn", "install-state.gz"))) return true;
67
+ const cacheDir = join(dir, ".yarn", "cache");
68
+ if (!existsSync(cacheDir)) return false;
69
+ try {
70
+ return readdirSync(cacheDir).some((e) => e.endsWith(".zip"));
71
+ } catch {
72
+ return false;
73
+ }
74
+ }
75
+ /**
76
+ * Build a child env that loads the Yarn PnP runtime found at or above `root`,
77
+ * like `yarn node` does. Existing `NODE_OPTIONS` go after our flags so the PnP
78
+ * `--require` patches resolution first.
79
+ */
80
+ function buildDrizzleKitSpawnEnv(root) {
81
+ const env = { ...process.env };
82
+ const pnp = findYarnPnpRuntime(root)?.runtime;
83
+ if (!pnp) return env;
84
+ const flags = [];
85
+ if (pnp.pnpCjs) flags.push(`--require ${JSON.stringify(pnp.pnpCjs)}`);
86
+ if (pnp.pnpLoader) flags.push(`--experimental-loader ${pathToFileURL(pnp.pnpLoader).href}`);
87
+ const injected = flags.join(" ");
88
+ env.NODE_OPTIONS = process.env.NODE_OPTIONS ? `${injected} ${process.env.NODE_OPTIONS}` : injected;
89
+ return env;
90
+ }
91
+ //#endregion
92
+ export { hasLocalLockfile as i, drizzleKitBin as n, findInstalledYarnPnpRuntime as r, buildDrizzleKitSpawnEnv as t };
package/docs/guide/ai.md CHANGED
@@ -17,8 +17,14 @@ npm run dev
17
17
 
18
18
  When the app imports `void/ai`, Void enables a remote Workers AI binding during
19
19
  development and preview. Requests use your Cloudflare account and its allowance;
20
- Workers AI has no local simulator. Use your Cloudflare login or
21
- `CLOUDFLARE_API_TOKEN` in an automated environment.
20
+ Workers AI has no local simulator. Development and preview use the same
21
+ Cloudflare login as `void connect`; sign in with `void cloudflare login`. A
22
+ `CLOUDFLARE_API_TOKEN` takes precedence; use one in an automated environment.
23
+
24
+ If development stops with a Cloudflare authentication error, run
25
+ `void cloudflare login` in a terminal as a user who can access the deployment
26
+ account shown by `void cloudflare status`, or set `CLOUDFLARE_API_TOKEN`.
27
+ `wrangler login` does not affect development.
22
28
 
23
29
  For a team platform, use `void connect <platform-url>` and link your project.
24
30
  Development requests use that platform's account and usage limits.
@@ -127,6 +127,8 @@ Auth sessions use the same database as your app. Void creates `BETTER_AUTH_SECRE
127
127
 
128
128
  Local development needs no secret setup. To preview a production build locally, provide `BETTER_AUTH_SECRET`.
129
129
 
130
+ Responses to signed-in requests get `Cache-Control: no-store`, so neither the browser cache nor a shared cache keeps a user's data. A route keeps its own policy when it sets `no-store`, or `private` together with `no-cache`. To answer repeat requests with `304`, use `private, no-cache` with Hono's [`etag()`](https://hono.dev/docs/middleware/builtin/etag) middleware. If you set the `ETag` yourself, make it differ per user, so the `304` doesn't reuse another account's page. The browser cache keeps a copy of a `private, no-cache` page, so the Back button can show it again after the user signs out. Keep the default `no-store` for pages that must not stay in the browser cache.
131
+
130
132
  `POST`, `PUT`, `PATCH` and `DELETE` requests and WebSocket connections from another origin don't use the signed-in session unless that origin is in `trustedOrigins`. If a separate frontend calls your app, add its origin there (see [Customization](#customization)). If your routes use their own cookies, check the request `Origin` yourself, for example with Hono's [`csrf()`](https://hono.dev/docs/middleware/builtin/csrf) middleware.
131
133
 
132
134
  Deployed apps on Cloudflare limit auth requests per client IP with Better Auth's defaults, for example 3 sign-in attempts per 10 seconds. Each Worker instance keeps its own count. Change or turn off the limits with `rateLimit` in `auth.ts`. To share one count across instances, set `rateLimit: { storage: 'database' }`, then run `void db generate` for a direct Cloudflare deploy.
@@ -51,9 +51,20 @@ void deploy
51
51
 
52
52
  For direct Cloudflare deploys, export the production `DATABASE_URL` in the shell running `void deploy --platform cloudflare`. Void uses it to provision Hyperdrive and apply pending checked-in migrations before uploading the Worker; it is not written to the Worker config.
53
53
 
54
- ::: warning MySQL DDL is not transactional
55
- MySQL may implicitly commit schema changes. If a multi-statement migration fails partway through, earlier statements can remain applied even though Void does not record the migration as complete. Keep migrations small, review them before deploy, and make failed migrations safe to rerun after repairing the database.
56
- :::
54
+ Only one migration run changes a database at a time, whether it comes from `void db migrate`, `void db reset`, the reset that `void db seed` does before it loads data, `void deploy --platform cloudflare`, or a `void deploy` of any project that uses the database. Better Auth's table changes run inside the same run. Another run waits for it, up to about 20 seconds for a command that connects with `DATABASE_URL` and about 2 minutes for a `void deploy` to the Void platform, then stops with an error that asks you to try again.
55
+
56
+ ### Failed migrations {#failed-migrations}
57
+
58
+ Each migration file runs in a transaction, so a failed file that only changes data leaves the database unchanged. On a sharded Vitess keyspace, such as a sharded PlanetScale database, a commit that fails on one shard does not undo the shards that already committed. MySQL commits schema changes such as `CREATE TABLE` and `ALTER TABLE` immediately, so when a file with schema changes fails partway through, its earlier statements stay applied. The error names the file that failed.
59
+
60
+ To recover, undo the applied statements, fix the file, then run `void db migrate` or `void deploy` again:
61
+
62
+ ```sh
63
+ void db execute "DROP TABLE comments"
64
+ void db execute --remote "DROP TABLE comments" # deployed database
65
+ ```
66
+
67
+ MySQL rejects `IF NOT EXISTS` on `ADD COLUMN` and `CREATE INDEX`, so undoing a statement is usually simpler than making it safe to rerun. Small migrations leave less to undo.
57
68
 
58
69
  ## Database commands
59
70
 
@@ -40,6 +40,8 @@ For a Void platform, deploy prompts for the connection string if needed. You can
40
40
 
41
41
  Void provisions Hyperdrive without saving the connection string in project config. Both `postgres://` and `postgresql://` URLs are supported, including provider query strings such as `?sslmode=require`.
42
42
 
43
+ The Hyperdrive that Void creates connects with TLS in Cloudflare's default `require` mode. Hyperdrive does not use the `sslmode=verify-ca`, `sslmode=verify-full`, or `sslrootcert` settings from your connection string. To have Hyperdrive verify your database against a specific certificate authority on a direct Cloudflare deploy, [create the Hyperdrive in Cloudflare with that certificate](https://developers.cloudflare.com/hyperdrive/configuration/tls-ssl-certificates-for-hyperdrive/) and add its ID to [`cloudflare.hyperdrive`](../../integrations/cloudflare.md#databases-and-secrets).
44
+
43
45
  ## Schema Definition
44
46
 
45
47
  Import schema helpers from `void/schema-pg`:
@@ -47,6 +47,8 @@ Choose a database during `void init`, or set `database` in `void.config.ts`:
47
47
  | Managed by | Void | Bring your own database | Bring your own database |
48
48
  | Connection | Automatic D1 binding | Hyperdrive | Hyperdrive |
49
49
 
50
+ A Void platform keeps Hyperdrive query caching off for your database connection, so reads reflect completed writes. An existing connection is updated on the project's next deploy.
51
+
50
52
  ## Schema Definition
51
53
 
52
54
  Define your tables in `db/schema.ts` using column helpers from `void/schema-d1`, `void/schema-pg`, or `void/schema-mysql`.
@@ -232,10 +234,6 @@ const usersWithPosts = await db.query.users.findMany({
232
234
  });
233
235
  ```
234
236
 
235
- ::: warning ⚠️ Nuxt and Analog limitations
236
- In Nuxt and Analog, use the query builder (`db.select().from(table)`). The `db.query.*` relational API is not available in these frameworks.
237
- :::
238
-
239
237
  ## Seeding
240
238
 
241
239
  Use `void db seed` to reset your local database, re-apply migrations, and then run a seed file.
@@ -374,7 +372,7 @@ To keep an existing migration history:
374
372
 
375
373
  Review and commit the metadata, then run `void deploy` again. If no database has applied the SQL yet, you can instead replace it with migrations from `void db generate`.
376
374
 
377
- For D1 migrations containing triggers, add a `--> statement-breakpoint` line after each complete SQL statement, including the trigger's closing `END;`. Keep the trigger body together.
375
+ For D1 migrations containing triggers, and MySQL migrations containing triggers, procedures, functions or events, add a `--> statement-breakpoint` line after each complete SQL statement, including the trigger's closing `END;`. Keep the trigger body together.
378
376
 
379
377
  ## Scaffolding
380
378
 
@@ -6,7 +6,7 @@ outline: deep
6
6
 
7
7
  Use a Durable Object when requests need to share state under one name, such as a shopping cart, room, or rate limiter. Void gives you typed methods and stores the object's state between calls.
8
8
 
9
- Create a module in `durable-objects/` with `defineDurableState()`. Void provides a SQLite-backed Cloudflare Durable Object for it. This feature supports native Void apps deployed directly to Cloudflare.
9
+ Create a module in `durable-objects/` with `defineDurableState()`. Void provides a SQLite-backed Cloudflare Durable Object for it. This feature supports native Void apps on Void platforms and direct Cloudflare deployments.
10
10
 
11
11
  Commit `void.lock.json` when Void adds a resource. Keep its deployed migration entries in their original order.
12
12
 
@@ -117,7 +117,7 @@ export default Counter;
117
117
 
118
118
  State migrations update your saved values. Void manages Cloudflare’s separate class migrations in `void.lock.json`.
119
119
 
120
- Do not delete or reorder generated Durable Object migrations in `void.lock.json` after deployment. For a class addition, rename, or removal on an existing Worker, review the migration and run `void deploy --platform cloudflare --atomic`. If this Worker needs atomic publication on every deploy, set `deploy: { cloudflare: { mode: 'atomic' } }` in `void.config.ts`. Cloudflare applies class lifecycle changes in one deployment. The Worker receives traffic before Void checks readiness, and you cannot roll back across that migration boundary. Staged deploys keep pre-traffic readiness verification.
120
+ For direct Cloudflare deployments, do not delete or reorder generated Durable Object migrations in `void.lock.json` after deployment. For a class addition, rename, or removal on an existing Worker, review the migration and run `void deploy --platform cloudflare --atomic`. If this Worker needs atomic publication on every deploy, set `deploy: { cloudflare: { mode: 'atomic' } }` in `void.config.ts`. Cloudflare applies class lifecycle changes in one deployment. The Worker receives traffic before Void checks readiness, and you cannot roll back across that migration boundary. Staged deploys keep pre-traffic readiness verification.
121
121
 
122
122
  ## Rename a file while keeping its state
123
123
 
@@ -158,8 +158,36 @@ If you already moved the file, `void info` also shows resources recorded in `voi
158
158
 
159
159
  ## Deployment support
160
160
 
161
- Typed state works in local development and direct Cloudflare deploys of native Void apps. Deploy with `void deploy --platform cloudflare`.
161
+ Typed state works in local development, on Void platforms, and in direct Cloudflare deploys of native Void apps. Use `void deploy` for a Void platform or `void deploy --platform cloudflare` for your own Cloudflare account.
162
162
 
163
- Custom Durable Object modules are not supported on Void platforms, in meta-frameworks, or on Node.js, Bun, and Deno.
163
+ On a Void platform, each class keeps its storage across deployments and rollbacks. A rollback restores the class code and keeps the current stored data. Removing a definition makes the class inactive; adding it again with the same resource name restores access to its data. Deleting the project deletes its Durable Object storage.
164
+
165
+ A project supports up to 32 distinct custom classes, including removed classes whose storage is retained. Keep resource names and instance names stable to preserve data. Upgrade an older Void installation before deploying an app that uses custom Durable Objects.
166
+
167
+ Custom Durable Object modules are not supported in meta-frameworks or on Node.js, Bun, and Deno.
164
168
 
165
169
  This is separate from [typed WebSocket routes](./websockets.md), which also use SQLite-backed Durable Objects and work on both direct Cloudflare and hosted Void deployments.
170
+
171
+ ## Native Durable Object classes
172
+
173
+ Use `defineDurableObject` to keep a native Cloudflare class, including classes extending Cloudflare Agents. Void discovers its binding and exports the class without replacing its constructor, lifecycle, or RPC methods. Like Durable State, this supports Void platforms and direct Cloudflare deployments.
174
+
175
+ ```ts
176
+ // durable-objects/workspace.ts
177
+ import { DurableObject } from 'cloudflare:workers';
178
+ import { defineDurableObject } from 'void/durable';
179
+
180
+ class WorkspaceObject extends DurableObject {
181
+ async fetch() {
182
+ return new Response('Workspace');
183
+ }
184
+ }
185
+
186
+ export const Workspace = defineDurableObject({
187
+ name: 'workspace',
188
+ class: WorkspaceObject,
189
+ });
190
+ export default Workspace;
191
+ ```
192
+
193
+ Call `Workspace.get('project-id')` from a server handler to obtain its typed stub. Keep the resource name and instance name stable across deployments to retain storage.
@@ -158,3 +158,7 @@ Invitation history remains available after an involved account is removed. The s
158
158
  remains visible when that account's login no longer exists.
159
159
 
160
160
  `void platform signup open` allows anyone to sign up. Everyone who signs up can deploy apps on your application domain, so check how those apps [share cookies](/guide/platform/installation/domains#adding-a-domain) before opening signup. Use `void platform signup restrict` to require an allowlist match again. Disallowing an entry affects future signup; it does not suspend an existing account.
161
+
162
+ ## Connected apps
163
+
164
+ Register separate applications as OAuth clients through [Connected apps](./connected-apps.md). Users connect their identity and approve each publish on Void.
@@ -0,0 +1,55 @@
1
+ # Connected apps
2
+
3
+ A connected app is a separate application registered as an OAuth client on your Void installation. Users sign in on Void and decide whether to connect it. The application operator may be different from the platform administrator.
4
+
5
+ ## Register an application
6
+
7
+ Open **Admin → Connected apps**. Enter the app name, its operator, and each exact HTTPS callback URL on a separate line. Wildcards and callback query strings are not supported. Enable individual publish approvals if the app builds and deploys projects.
8
+
9
+ Save the returned client ID and secret on the app's server. Void shows the secret once. The client secret authenticates that application; it does not grant access to users' accounts. Register a new client if you need replacement credentials, then disable the old one.
10
+
11
+ **Disable and revoke access** invalidates the client's grants, pending sign-ins, and publish approvals. Registration and disablement appear in the operator audit.
12
+
13
+ Local development permits exact HTTP callbacks on localhost when the platform's development authentication bypass is explicitly enabled. Production clients require HTTPS.
14
+
15
+ ## Connect and disconnect
16
+
17
+ The app sends users to Void's authorization page, where Void displays its registered name, operator, callback origin, and requested permission. Sign-in permits reading the user's ID and username. It does not provide an account token or project management access.
18
+
19
+ Users can disconnect applications at `<platform API URL>/oauth/connections`. Grants also expire after an hour and become invalid when their platform login session is revoked or their account is suspended. Applications must request a new sign-in when access expires.
20
+
21
+ ## Approve a publish
22
+
23
+ The app builds first, then sends the user to Void with the prepared artifact. Void displays the project name, checkpoint label, resources, manifest, and artifact digest. The user must explicitly approve on Void.
24
+
25
+ Approval permits one deployment to that user's chosen project. Void creates a missing project during approval; existing projects require ownership. The app receives a credential valid for up to fifteen minutes, restricted to that artifact's asset uploads, deployment, and receipt. Retries use the same receipt.
26
+
27
+ Published code can use that project's existing secrets and resources. Review the app operator and deployment details before approving code for an existing project. Migrations and resource changes in the approved manifest take effect during deployment.
28
+
29
+ Disabling the app or disconnecting its grant stops authorization for subsequent actions and is checked again before a queued deployment publishes. Disconnecting does not remove an app that has already been published; manage that project through Void.
30
+
31
+ ## Build an OAuth client
32
+
33
+ Discover endpoints at `/.well-known/oauth-authorization-server` on the platform API origin. Use authorization code flow with `scope=profile`, a random `state`, and S256 PKCE. Authenticate token exchanges using HTTP Basic client authentication. Send access tokens as Bearer credentials to `/oauth/userinfo`; its response contains `sub` and `preferred_username`.
34
+
35
+ For publishing, package the built app with [`prepareDeployArtifact`](/reference/api/deploy). POST to `/oauth/deployment-requests` using the profile token:
36
+
37
+ ```ts
38
+ {
39
+ redirect_uri: registeredCallback,
40
+ state: publishState,
41
+ code_challenge: publishChallenge,
42
+ code_challenge_method: 'S256',
43
+ slug: projectSlug,
44
+ checkpoint: checkpointLabel,
45
+ artifact: prepared.artifact
46
+ }
47
+ ```
48
+
49
+ Redirect the browser to the returned `authorization_url`. Exchange its code with the publish verifier and the same registered callback. The response includes `project_id`, `approval_id`, and a `deploy:approve` access token. This publish flow is a Void extension; requesting that scope in an ordinary sign-in does not authorize deployment.
50
+
51
+ Use the token to request URLs from `POST /projects/:id/deploy/upload-urls`, upload the declared assets, and send the artifact to `POST /projects/:id/deploy`. Set `x-void-deploy-idempotency-key` to `approval_id`. Deployment uses Void's managed deployment protocol and requires the platform deployment Queue. The credential cannot read secrets, mint project tokens, delete projects, or deploy different bytes.
52
+
53
+ Revoke identity grants with `POST /oauth/revoke`, authenticated as the client. No refresh token or OpenID Connect ID token is issued.
54
+
55
+ If the API is protected by Cloudflare Access, the application operator must also configure a service identity permitted by that Access application's policy. Server OAuth endpoints and approved deployment requests still validate their own client, grant, and project authority; browser consent requires the user's company identity.
@@ -6,6 +6,18 @@ outline: deep
6
6
 
7
7
  Keep one password-manager entry for this platform. Paste the saved values into the installer when asked; most do not need shell environment variables.
8
8
 
9
+ | Credential | Created by | Why the platform needs it |
10
+ | -------------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------- |
11
+ | Management API token | You, in Cloudflare | Lets the CLI change DNS and Access for a domain installation or Access setup. |
12
+ | Runtime API token | You, in Cloudflare | Stored as a Worker secret so the platform can deploy apps after you close your terminal. |
13
+ | PostgreSQL URL | You, with your database provider | Stores platform users, projects, and deployments. |
14
+ | Login provider client ID and secret | You, or Void for Access login | Signs people in to the platform. |
15
+ | R2 Access Key ID and Secret Access Key | You, in Cloudflare | Lets the platform sign upload links so `void deploy` sends static files straight to R2. |
16
+ | Access setup and app-access tokens | You, in Cloudflare | Only with Cloudflare Access: create and manage Access applications. |
17
+ | JWT signing key | Void, on interactive installs | Signs platform login tokens. |
18
+ | Project encryption key | Void, on interactive installs | Encrypts app secrets stored by your platform. |
19
+ | Email signing key | Void, when email is enabled | Signs confirmation links and email requests. |
20
+
9
21
  ## Cloudflare API Tokens {#runtime-token-permissions}
10
22
 
11
23
  For a domain installation or Cloudflare Access setup, the installer guides you through creating separate management and runtime tokens using Cloudflare's [API token setup](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/). Its links preselect the permissions and suggest names based on your platform's display name, but Cloudflare's form cannot preselect a zone: for a domain installation, change the zone policy from **All Domains** to **Specified Domains** and select your zone. If Void will create the zone, keep **All Domains** on both tokens: the zone does not exist yet, and the runtime token needs it to purge cache. Save the tokens in your password manager and paste them into the masked CLI prompts.
@@ -39,6 +51,8 @@ Use the following permissions for the core platform. Cloudflare may label write
39
51
  | Account | Hyperdrive | Write | Write |
40
52
  | Account | Account Analytics | Read | Read |
41
53
  | Account | AI Gateway | Edit | Edit when installing with browser login |
54
+ | Account | Containers | — | Edit |
55
+ | Account | Cloudchamber | — | Edit |
42
56
  | Zone | Zone | Read | — |
43
57
  | Zone | DNS | Edit | — |
44
58
  | Zone | Workers Routes | Edit | — |
@@ -72,17 +86,21 @@ The installer deploys the email gateway, prepares the shared mail route, and ver
72
86
 
73
87
  ## R2 Upload Credentials
74
88
 
75
- In the **R2 token creation** form opened by the installer, select **Object Read & Write** and **Apply to all buckets in this account (including newly created buckets)**. Create an account token, or a user token if your role requires it. Save its **Access Key ID** and **Secret Access Key** in your password manager. These differ from the management and runtime API tokens. See [R2’s token instructions](https://developers.cloudflare.com/r2/api/tokens/).
89
+ `void deploy --platform void` uploads your app's static files straight to R2 instead of through the platform API. The API signs short-lived upload links for them with an R2 key pair.
90
+
91
+ The installer opens the **R2 token creation** form with a token name based on your platform's display name, **Object Read & Write**, and **Apply to all buckets in this account (including newly created buckets)** preselected. Review the settings and create an account token, or a user token if your role requires it. Save its **Access Key ID** and **Secret Access Key** in your password manager, then paste both into the installer. These differ from the management and runtime API tokens. See [R2’s token instructions](https://developers.cloudflare.com/r2/api/tokens/).
76
92
 
77
93
  ## Signing and Encryption Keys {#signing-and-encryption-keys}
78
94
 
79
- The **JWT signing key** signs platform login tokens. The **Project encryption key** encrypts app secrets stored by your platform. Generate a separate key for each by running this command twice:
95
+ The **JWT signing key** signs platform login tokens. The **Project encryption key** encrypts app secrets stored by your platform. An interactive install generates both and keeps them in this machine's encrypted recovery data. Lifecycle commands on this machine read them from there.
96
+
97
+ To keep your own copy, for example to repair the platform from CI or another machine, create both keys before installing and set `VOID_PLATFORM_JWT_SECRET` and `VOID_PLATFORM_PROJECT_SECRET_KEY`. Non-interactive installs must set both. Generate a separate key for each by running this command twice:
80
98
 
81
99
  ```sh
82
100
  openssl rand -base64 32
83
101
  ```
84
102
 
85
- Save each result in your password manager, then paste it into the corresponding installer prompt. The command generates 32 random bytes encoded as base64, suitable for either field. Keep the two original keys for recovery; do not regenerate them when resuming or upgrading.
103
+ Save each result in your password manager. The command generates 32 random bytes encoded as base64, suitable for either field. Keep the two original keys for recovery; do not regenerate them when resuming or upgrading.
86
104
 
87
105
  ::: details Generate the keys without printing them to your terminal
88
106
 
@@ -100,4 +100,4 @@ New platform resources use deterministic `void-<installation-name>-<role>` names
100
100
  | Proxied wildcard DNS records | 0 or 1 | Created only when an application domain is configured |
101
101
  | Zones | 0 or 1 | Created only when the requested application zone is absent |
102
102
 
103
- The API Worker uses four Durable Object classes for usage, cron scheduling, error monitoring, and concurrency. Worker bindings create the request and log datasets in Analytics Engine. The core installation doesn't create Container applications, a GitHub App, a dashboard Worker, or build Workers.
103
+ The API Worker uses four Durable Object classes for usage, cron scheduling, error monitoring, and concurrency. Worker bindings create the request and log datasets in Analytics Engine, which must be [enabled for the account](/guide/platform/installation/prerequisites#if-cloudflare-rejects-analytics-engine). The core installation doesn't create Container applications, a GitHub App, a dashboard Worker, or build Workers.
@@ -50,6 +50,43 @@ For completed provisioning whose administrator setup is still pending, run
50
50
  expired. Enter it at `/setup`, sign in, and confirm the displayed identity.
51
51
  An installation that already has an administrator does not reopen setup.
52
52
 
53
+ ### First administrator sign-in fails
54
+
55
+ If sign-in fails after you enter the setup code, the page shows the reason and an
56
+ error code. When a provider setting may be the cause, it also shows the callback
57
+ URL the provider must have.
58
+
59
+ | Error code | What to check |
60
+ | --------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
61
+ | `github_incorrect_client_credentials`, `github_failed`, `oidc_token_failed` | The client ID and client secret, and that the provider has the callback URL |
62
+ | `github_redirect_uri_mismatch` | The callback URL registered in the GitHub OAuth app |
63
+ | `oidc_discovery_failed` | The issuer URL, exactly, including any trailing slash |
64
+ | `github_unverified_user_email` | Verify the primary email of the GitHub account |
65
+ | `google_domain_not_allowed`, `oidc_group_not_allowed` | Sign in with an allowed account, or change the allowed domains or groups |
66
+ | `login_denied`, `github_bad_verification_code` | Start a new sign-in |
67
+
68
+ If the provider shows its own error page instead, register exactly the callback
69
+ URL printed with your setup code.
70
+
71
+ To change the login settings, run repair on the computer that installed the
72
+ platform:
73
+
74
+ ```sh
75
+ void platform repair <id>
76
+ void platform repair <id> --auth-config <path>
77
+ ```
78
+
79
+ Interactive repair asks whether to change the login settings, with the saved
80
+ values filled in; leave the client secret blank to keep it. `--auth-config`
81
+ takes a file in the [install format](/guide/platform/installation/setup#finish-login-configuration)
82
+ and is the way to change OIDC allowed groups. Login methods and Access protection
83
+ stay as installed. Repair prints a new setup code and the callback URL.
84
+
85
+ A GitHub-only installation signs in with the GitHub OAuth App from its
86
+ installation settings. To replace its client ID and secret, set
87
+ `VOID_PLATFORM_GITHUB_CLIENT_ID` and `VOID_PLATFORM_GITHUB_CLIENT_SECRET` when
88
+ you run `void platform repair <id>`.
89
+
53
90
  ### Repair missing resources
54
91
 
55
92
  Preview what needs repair, then apply it:
@@ -164,7 +201,7 @@ During a restore, keep platform and application traffic disabled before changing
164
201
 
165
202
  ### Where local state lives
166
203
 
167
- Installation records live in `~/.void/platforms/`. Credentials are stored separately in encrypted recovery files, with the encryption key in your operating system's keychain. Keep your original secrets in a password manager for recovery on another machine.
204
+ Installation records live in `~/.void/platforms/`. Credentials are stored separately in encrypted recovery files, with the encryption key in your operating system's keychain. Keep your original secrets in a password manager for recovery on another machine. Signing and encryption keys that Void generated exist only in these files; to keep your own copy, [supply them when installing](/guide/platform/installation/credentials#signing-and-encryption-keys).
168
205
 
169
206
  If the keychain isn't available, Void stops before writing secrets. Headless environments can supply `VOID_PLATFORM_RECOVERY_KEY`: a canonical base64-encoded 32-byte key from a secret manager. A temporary CI runner can use a new recovery-encryption key for each run only when every original credential remains available in protected CI secrets, including `VOID_PLATFORM_JWT_SECRET`, `VOID_PLATFORM_EMAIL_SIGNING_SECRET` for an email-enabled installation, and either the original `VOID_PLATFORM_PROJECT_SECRET_KEY` or the complete rotated keyring and active-version pair.
170
207
 
@@ -6,7 +6,7 @@ outline: deep
6
6
 
7
7
  To run a Void platform, you need:
8
8
 
9
- - A Cloudflare account with Workers for Platforms and R2 enabled.
9
+ - A Cloudflare account with Workers for Platforms, R2, and Analytics Engine enabled.
10
10
  - An empty hosted PostgreSQL database.
11
11
  - An account with your chosen login provider: GitHub, Google, OIDC, or Cloudflare Access.
12
12
  - A domain for your apps, or `workers.dev` for testing. You can [add a domain later](/guide/platform/installation/domains#adding-a-domain).
@@ -28,6 +28,10 @@ If that domain is already in this Cloudflare account, use its existing zone. Oth
28
28
 
29
29
  You can also let Void create the zone during installation. Setting it up now lets you scope the API tokens to that zone and finish installation without a DNS pause. The platform API uses `workers.dev` by default, so it needs no additional domain.
30
30
 
31
+ ### If Cloudflare rejects Analytics Engine
32
+
33
+ The platform stores request metrics and logs in Analytics Engine. If installation stops with "You need to enable Analytics Engine" (code 10089), add an Analytics Engine binding to a Worker that is not part of the platform under **Settings** > **Bindings**, and deploy it once from the dashboard. A new Hello World Worker works. Do not edit the platform's own Workers. Then run the printed `void platform install --resume` command.
34
+
31
35
  ## Install the CLI and Preview
32
36
 
33
37
  With Node.js 24.21.0 or later, install the CLI:
@@ -78,7 +82,7 @@ Use any PostgreSQL provider that accepts connections from your computer and Clou
78
82
  | [PlanetScale Postgres](https://planetscale.com/docs/postgres/connecting) | Choose **Postgres**, not Vitess/MySQL. Open **Connect**, create role credentials, and use the direct primary connection on port `5432`, not PgBouncer on `6432`. |
79
83
  | [Neon](https://neon.com/docs/get-started-with-neon/connect-neon) | Open **Connect**, select the database and owner role, and turn **connection pooling off**. |
80
84
 
81
- Once installation claims the database, continue using that same database for resume and maintenance commands. Uninstall never deletes external PostgreSQL.
85
+ Once installation claims the database, continue using that same database for resume and maintenance commands. If installation stops because it cannot use the database, for example because the database is not empty, set `VOID_PLATFORM_DATABASE_URL` to another database's URL before you resume. Uninstall never deletes external PostgreSQL.
82
86
 
83
87
  ### Use a provider CLI
84
88
 
@@ -153,6 +153,28 @@ providers, and existing company policies. Void creates dedicated applications
153
153
  and a scoped service token for protected installation checks. It preserves your
154
154
  company policies, including device and MFA requirements.
155
155
 
156
+ If no policy fits, choose **Allow my company’s email domain** in the policy list
157
+ and enter your domains. Void creates that Allow policy in your account and keeps
158
+ it there for reuse; you can add MFA or device rules to it in Cloudflare later.
159
+ For identity-provider groups or other rules, choose **Create in Cloudflare** and
160
+ follow the printed steps.
161
+
162
+ An Allow policy must name who may sign in: emails, email domains or lists,
163
+ identity-provider groups (Okta, Microsoft Entra ID, Google Workspace, GitHub
164
+ organizations, or SAML), authentication contexts, members of a Cloudflare
165
+ account, or Access groups built from them. Microsoft Entra ID groups and
166
+ authentication contexts count only when they come from an identity provider you
167
+ select. A login method also counts when it is one of the identity providers you select and uses
168
+ Cloudflare's connector for a company directory: Microsoft Entra ID, Okta,
169
+ OneLogin, PingOne, Centrify, Google Workspace, or the Cloudflare login with
170
+ **Restrict to account members** turned on. Policies that allow everyone, any
171
+ service token, or bypass Access are rejected, and so are policies that rely
172
+ only on One-time PIN, a public login such as GitHub, or a login added with the
173
+ generic **OpenID Connect** or **SAML** option, even one that fronts your
174
+ company directory. Void cannot tell who can sign in through a generic login;
175
+ add a Require rule such as **Emails ending in** your company domain to that
176
+ policy.
177
+
156
178
  The setup credential needs **Access: Apps and Policies Write** and
157
179
  **Access: Organizations, Identity Providers, and Groups Read** in the identity
158
180
  account. Creating protection also needs **Access: Service Tokens Write**.
@@ -212,7 +234,7 @@ This OAuth App handles sign-in.
212
234
 
213
235
  ## Finish installation
214
236
 
215
- The installer collects your runtime token, PostgreSQL URL, login-provider credentials, R2 credentials, and signing and encryption keys. It masks secret values and saves setup progress encrypted through your system keychain. Keep a password-manager copy for recovery on another machine.
237
+ The installer collects your runtime token, PostgreSQL URL, login-provider credentials, and R2 credentials, and generates the [signing and encryption keys](/guide/platform/installation/credentials#signing-and-encryption-keys). It masks secret values and saves setup progress encrypted through your system keychain. Keep a password-manager copy for recovery on another machine.
216
238
 
217
239
  Once installation finishes, open the printed admin dashboard link. For GitHub-only setup, sign in as the administrator selected during installation. For configurable login, use the one-time `/setup` code to confirm the administrator’s identity. Use the printed API URL to [connect and deploy an app](/guide/platform/installation/first-deployment).
218
240
 
@@ -33,7 +33,7 @@ void platform uninstall [id] --plan
33
33
  void platform uninstall [id]
34
34
  ```
35
35
 
36
- Uninstall blocks platform traffic, removes Queues that no remaining platform Worker uses, and lists the resources left for you to review. Use `--plan` to review deletions and retained resources before making changes. By default, Workers, the Queues they use, KV, R2, Hyperdrive, the dispatch namespace, and AI Gateway remain in your account. Adopted resources, external PostgreSQL, and zones are always retained. Email Routing settings are retained; `--purge-resources` removes only the rules that send mail to the platform. DNS records, routes, custom domains, and Cloudflare Access resources are retained unless you use `--purge-resources`.
36
+ Uninstall blocks platform traffic, removes Queues that no remaining platform Worker uses, and lists the resources left for you to review. Use `--plan` to review deletions and retained resources before making changes. By default, Workers, the Queues they use, KV, R2, Hyperdrive, the dispatch namespace, and AI Gateway remain in your account. Adopted resources, external PostgreSQL, and zones are always retained. To install a platform again, use a new empty PostgreSQL database. Email Routing settings are retained; `--purge-resources` removes only the rules that send mail to the platform. DNS records, routes, custom domains, and Cloudflare Access resources are retained unless you use `--purge-resources`.
37
37
 
38
38
  When uninstall finishes, the record of what was kept stays at `~/.void/platforms/<account-id>/<installation-id>.json`. Without `--purge-data`, the encrypted credentials file `<installation-id>.recovery.enc` next to it is kept too. Delete both once you have finished the manual cleanup below.
39
39
 
@@ -91,6 +91,11 @@ If installation configured Cloudflare Access, the uninstall plan lists its recor
91
91
 
92
92
  Uninstall does not remove the applications created for [project Zero Trust](/guide/platform/administration/zero-trust). While Zero Trust is enabled or still has Access applications, uninstall and `--plan` stop before any change and list those applications. Run `void platform zero-trust disable` first. Uninstall reads this from the installation database, so it also stops when the database cannot be reached.
93
93
 
94
+ If no platform user exists yet, for example because first administrator setup did
95
+ not finish, nobody can run `zero-trust disable`. Uninstall then turns off project
96
+ Zero Trust and deletes its applications itself. Run it on the computer that installed
97
+ the platform. If the uninstall asks you to, update an older platform runtime first.
98
+
94
99
  ::: details Why some resources require manual cleanup
95
100
 
96
101
  Resources that may have been shared or repurposed require manual review before deletion. Void verifies ownership, keeps those resources in place, and blocks platform traffic.
@@ -36,6 +36,8 @@ bunx void init
36
36
 
37
37
  Choose your UI framework, a starter, and a deployment target. Vite+ is the default build tool. D1 is a good first database: it runs locally without a separate database server. Choose Cloudflare to deploy to your own account, or skip deployment setup for now.
38
38
 
39
+ You do not need to install Vite+ globally. Setup preserves your existing package-manager versions and lockfiles.
40
+
39
41
  With pnpm, `pnpm create void my-app` also creates the project directory and configures native build permissions for you.
40
42
 
41
43
  ## Run locally
@@ -56,6 +56,8 @@ File operations live under `sandbox.files`: `readFile`, `writeFile`, `stat`, `ls
56
56
 
57
57
  To reach a server inside the container, await `sandbox.fetch(port, new Request(url))`. `sandbox.running()` checks whether the container is running; `sandbox.destroy()` stops it.
58
58
 
59
+ On native Cloudflare deployments, `sandbox.fetch()` also supports WebSocket upgrade requests. Return its response from your Worker handler to connect the client to the container. WebSocket upgrades are currently unavailable on managed Void deployments.
60
+
59
61
  `getSandbox()` options include `inactivityTimeoutMs` (default ten minutes, maximum six hours), `enableInternet` (default `false`), and string `labels`. Internet access and labels take effect on the next container start. `binding` selects a custom native binding; managed platforms use the configured binding.
60
62
 
61
63
  For code that runs on both deployment targets, use `getSandbox()`. Direct access through `c.env.SANDBOX` is available only on local and native Cloudflare deployments.
@@ -119,7 +121,7 @@ Custom images must include the helper matching Void's installed Sandbox SDK vers
119
121
 
120
122
  ```dockerfile
121
123
  FROM node:26.10.0-trixie-slim
122
- COPY --from=docker.io/cloudflare/sandbox:1.0.0 /usr/local/bin/sandbox-shim /usr/local/bin/sandbox-shim
124
+ COPY --from=docker.io/cloudflare/sandbox:1.0.1 /usr/local/bin/sandbox-shim /usr/local/bin/sandbox-shim
123
125
  WORKDIR /workspace
124
126
  CMD ["sleep", "infinity"]
125
127
  ```
@@ -24,7 +24,7 @@ Both targets use the same application APIs. A core platform adds shared access a
24
24
  | Workers AI and provider requests | Your account and gateway | Installation gateway and proxy |
25
25
  | Runtime logs | Live Cloudflare tail | Retained platform logs |
26
26
  | Application rollback | Worker versions | Retained platform deployments |
27
- | Typed Durable State | Supported | Unavailable |
27
+ | Typed Durable State and native Durable Objects | Supported | Supported |
28
28
  | Sandboxes | Requires Workers Paid and Docker | Requires Workers Paid on the platform account |
29
29
  | Custom application domains | Supported | Unavailable in the core installation |
30
30
  | Generated GitHub deployment workflow | Supported | Use your CI with a scoped developer token |
@@ -154,7 +154,7 @@ Void uses Access credentials for readiness checks without saving them. If checks
154
154
 
155
155
  ### Databases and secrets
156
156
 
157
- For PostgreSQL and MySQL, supply `DATABASE_URL` to the deploy process. Void uses it for Hyperdrive and migrations without writing it to config. MySQL schema changes can partially apply before an error.
157
+ For PostgreSQL and MySQL, supply `DATABASE_URL` to the deploy process. Void uses it for Hyperdrive and migrations without writing it to config. MySQL schema changes can partially apply before an error; see [failed MySQL migrations](../guide/database/mysql.md#failed-migrations).
158
158
 
159
159
  Creating Hyperdrive requires an API token with Hyperdrive edit permission. Alternatively, create it in Cloudflare and add its ID to `cloudflare.hyperdrive`; an existing binding works with browser login.
160
160
 
@@ -210,7 +210,7 @@ Custom domain commands update routes immediately. If a first deployment times ou
210
210
 
211
211
  Local D1, KV, and R2 bindings use local data. Your production resource IDs are used during deployment.
212
212
 
213
- Workers AI runs remotely after you connect to Cloudflare, so development calls consume your account's allowance.
213
+ Workers AI runs remotely after you connect to Cloudflare, so development calls consume your account's allowance. Remote bindings in development and preview use your `void cloudflare login` session, or `CLOUDFLARE_API_TOKEN` when it is set.
214
214
 
215
215
  ### AI on your Cloudflare account {#ai-self-host}
216
216