void 0.28.0 → 1.1.0

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 (212) hide show
  1. package/dist/{account-cmd-Ci00cncT.mjs → account-cmd-BTcUzv9L.mjs} +4 -4
  2. package/dist/{application-analysis-D72ZQfMZ.mjs → application-analysis-AB_YYWgH.mjs} +1 -1
  3. package/dist/{application-routing-Dy589Vgn.mjs → application-routing-L7V-TFhZ.mjs} +1 -1
  4. package/dist/auth-Cbqi1iVX.mjs +1 -0
  5. package/dist/{auth-link-DWr6Afao.mjs → auth-link-DUJuvRx5.mjs} +4 -4
  6. package/dist/{auth-router-DP14wVkZ.mjs → auth-router-CIxiMG7i.mjs} +3 -3
  7. package/dist/{build-cmd-Cr3FJxv0.mjs → build-cmd-BkIv25PA.mjs} +3 -3
  8. package/dist/{cache-D0Tt28cn.mjs → cache-Ctzfig-W.mjs} +3 -3
  9. package/dist/{cancel-deploy-CJKvk7AN.mjs → cancel-deploy-CD9o-SsC.mjs} +2 -2
  10. package/dist/cf-build-output-BU3hqdHu.mjs +1 -0
  11. package/dist/cli/cli.mjs +31 -31
  12. package/dist/cli/cloudflare-operation-process.mjs +2 -2
  13. package/dist/cli/env-schema-probe.d.mts +2 -1
  14. package/dist/cli/env-schema-probe.mjs +2 -2
  15. package/dist/client-B60PwCC4.mjs +1 -0
  16. package/dist/{cloudflare-cmd-CTrn-lXJ.mjs → cloudflare-cmd-BIAF_BIY.mjs} +2 -2
  17. package/dist/{cloudflare-connect-BosmCNlq.mjs → cloudflare-connect-WjwnVOJA.mjs} +1 -1
  18. package/dist/{cloudflare-operations-BKdSfNBN.mjs → cloudflare-operations-B42EZeJy.mjs} +3 -3
  19. package/dist/cloudflare-operations-CrSUFRzJ.mjs +1 -0
  20. package/dist/collect-Cae8A7Zr.mjs +1 -0
  21. package/dist/config-QrJWu0IX.mjs +1 -0
  22. package/dist/{connect-nukQSoEO.mjs → connect-CKtk-EZe.mjs} +5 -5
  23. package/dist/create-project-B-ewF_Af.mjs +1 -0
  24. package/dist/{create-project-D4APeBwX.mjs → create-project-yInGo72M.mjs} +3 -3
  25. package/dist/database-provider.mjs +1 -2
  26. package/dist/{db-27RztQLy.mjs → db-7I_gfdVq.mjs} +37 -38
  27. package/dist/db-types-Bb4WBWIs.mjs +49 -0
  28. package/dist/{delete-BbsZFZIw.mjs → delete-Cy-M1u-r.mjs} +3 -3
  29. package/dist/deploy-9lgfhrXS.mjs +2 -0
  30. package/dist/{deploy-B06EQq4t.mjs → deploy-BYYlnsiy.mjs} +176 -21
  31. package/dist/{deploy-managed-static-CGswbcay.mjs → deploy-managed-static-Ca4TFdmx.mjs} +24 -706
  32. package/dist/{deploy-transport-BiicfoQW.mjs → deploy-transport-DWlWBe6M.mjs} +1 -1
  33. package/dist/deploy.mjs +4 -4
  34. package/dist/discover-ClzFSwns.mjs +1 -0
  35. package/dist/dispatch-DrTTk8Xg.mjs +431 -0
  36. package/dist/{dist-D3m88sjf.mjs → dist-BVdsO7Py.mjs} +5 -6
  37. package/dist/dist-CfgIkieS.mjs +1 -0
  38. package/dist/{domain-Bfq9n03H.mjs → domain-CZGxPv9u.mjs} +4 -4
  39. package/dist/edge.mjs +1 -2
  40. package/dist/{email-DIwaQU4P.mjs → email-DzyNVuoU.mjs} +6 -6
  41. package/dist/{email-cloudflare-CH053RxK.mjs → email-cloudflare-DfG6UEMm.mjs} +1 -1
  42. package/dist/{env-BhdWMrNy.mjs → env-0jrMQJI_.mjs} +5 -2
  43. package/dist/{env-C6ipBLp3.mjs → env-Nx3yf50r.mjs} +4 -4
  44. package/dist/{env-raw-Cklzcde3.mjs → env-raw-D74P4ebM.mjs} +12 -1
  45. package/dist/env-validation-BT7z-qpQ.mjs +1 -0
  46. package/dist/{env-validation-cE0zcmzO.mjs → env-validation-DYxjz_Wo.mjs} +2 -0
  47. package/dist/{gen-CnN1Xidx.mjs → gen-CufHEf42.mjs} +2 -2
  48. package/dist/gen-sXyp5DFO.mjs +1 -0
  49. package/dist/generate-ClI89brV.mjs +1 -0
  50. package/dist/{github-cmd-BdkU4Nhe.mjs → github-cmd-FU8EjFyU.mjs} +3 -3
  51. package/dist/{help-Bug7pyK_.mjs → help-BT2hovNI.mjs} +9 -5
  52. package/dist/help-i2YGGnTH.mjs +1 -0
  53. package/dist/{inbound-DmkTQeWp.mjs → inbound-BuTfm11U.mjs} +1 -1
  54. package/dist/index.mjs +551 -303
  55. package/dist/{info-CujPwtMe.mjs → info-l249eUdH.mjs} +1 -1
  56. package/dist/{init-ZWOJvc-Z.mjs → init-D0A6M64Q.mjs} +60 -14
  57. package/dist/{isr-config-DPjXM8J2.mjs → isr-config-fZaJJ8t7.mjs} +1 -30
  58. package/dist/{link-UEc7bnF4.mjs → link-WMoJFf4i.mjs} +4 -4
  59. package/dist/{list-CuWeOnzk.mjs → list-CQ2EQEHL.mjs} +4 -4
  60. package/dist/{live-BxLX-JqJ.mjs → live-BcHoTDFe.mjs} +1 -1
  61. package/dist/{local-d1-BM3p74mm.mjs → local-d1-BxvQYEFi.mjs} +1 -1
  62. package/dist/{login-CZ2Cqa-D.mjs → login-C2T1oVG-.mjs} +3 -3
  63. package/dist/login-XD844Xs-.mjs +1 -0
  64. package/dist/{logs-TihRcLTk.mjs → logs-DnC1d7xB.mjs} +3 -3
  65. package/dist/{migrate-uFwojusJ.mjs → migrate-BDIprOYd.mjs} +2 -2
  66. package/dist/migrate-BRwU-blY.mjs +1 -0
  67. package/dist/mysql-migration-sql-BIS5vbNk.mjs +241 -0
  68. package/dist/nitro.d.mts +30 -0
  69. package/dist/nitro.mjs +88 -0
  70. package/dist/{node-DoKbo1SZ.mjs → node-cPadMgUO.mjs} +3 -3
  71. package/dist/operator-cmd-D6gnZsnK.mjs +1 -0
  72. package/dist/{operator-cmd-C5lCctnc.mjs → operator-cmd-DHieWtFp.mjs} +5 -5
  73. package/dist/{output-FNHKw5Ac.mjs → output-Ba6ZbrzY.mjs} +1 -1
  74. package/dist/pages/head.mjs +1 -2
  75. package/dist/pages/prefetch.mjs +1 -2
  76. package/dist/pages/serialize.mjs +1 -2
  77. package/dist/plan-CKX_jWnD.mjs +1 -0
  78. package/dist/platform-args-B0HeTh0C.mjs +1 -0
  79. package/dist/{platform-args-C6Mb_I3a.mjs → platform-args-CaCL_1Ch.mjs} +9 -2
  80. package/dist/{platform-auth-config-CJmNkFT2.mjs → platform-auth-config-Z16-I8nT.mjs} +6 -6
  81. package/dist/{platform-auth-protection-D5wvsI-Y.mjs → platform-auth-protection-BXwZiJSF.mjs} +4 -4
  82. package/dist/{platform-auth-recovery-D_0I3n-1.mjs → platform-auth-recovery-CXjfqyOv.mjs} +4 -4
  83. package/dist/{platform-cmd-DxxZO6e5.mjs → platform-cmd-DaAOiWTl.mjs} +7 -7
  84. package/dist/platform-cmd-PT4YwMLM.mjs +1 -0
  85. package/dist/{platform-domain-zLXnW1G_.mjs → platform-domain-CxpvUeo0.mjs} +4 -4
  86. package/dist/{platform-lifecycle-DOW-wLfx.mjs → platform-lifecycle-DBiS0cJd.mjs} +317 -99
  87. package/dist/platform-lifecycle-u9pMOvxC.mjs +1 -0
  88. package/dist/{platform-management-t7HKy4-U.mjs → platform-management-DhEFdQAf.mjs} +67 -9
  89. package/dist/platform-management-DvBS83rC.mjs +1 -0
  90. package/dist/{platform-plans-config-CNH6zbPX.mjs → platform-plans-config-BWn1S2Rv.mjs} +2 -2
  91. package/dist/{platform-recovery-DeucI7A9.mjs → platform-recovery-BUGOB4RC.mjs} +2 -2
  92. package/dist/{platform-setup-CTf6MMT9.mjs → platform-setup-YvN9VQXV.mjs} +3 -3
  93. package/dist/prepare-CYT6tAzD.mjs +1 -0
  94. package/dist/{prepare-CSH9dKTI.mjs → prepare-DEB5SeVJ.mjs} +3 -2
  95. package/dist/{prepare-C4zfwks4.mjs → prepare-PQCgsny0.mjs} +3 -3
  96. package/dist/prerender-render.mjs +1 -2
  97. package/dist/{project-cmd-Dq75AXzy.mjs → project-cmd-DVatD8Ev.mjs} +16 -16
  98. package/dist/project-slug-6cyz8E7k.mjs +1 -0
  99. package/dist/{project-team-B3_QcStG.mjs → project-team-DJrWEAG1.mjs} +3 -3
  100. package/dist/{project-token-CvsRvv2I.mjs → project-token-CBgLBuL6.mjs} +3 -3
  101. package/dist/project-zdB3fs9G.mjs +1 -0
  102. package/dist/{project-zero-trust-D1ICiwN_.mjs → project-zero-trust-92gLtZ25.mjs} +3 -3
  103. package/dist/{provision-DDh7ITVS.mjs → provision-BnSSkiED.mjs} +1 -1
  104. package/dist/{requests-3CL3BuZh.mjs → requests-7W1Pygt2.mjs} +2 -2
  105. package/dist/resolve-project-PnhzMtY6.mjs +1 -0
  106. package/dist/{resolve-project-C_Cu7E8a.mjs → resolve-project-WpwkCB_c.mjs} +1 -1
  107. package/dist/{rollback-Ce1d_0J9.mjs → rollback-BcASVnwP.mjs} +3 -3
  108. package/dist/{route-types-IrBuwJ7u.mjs → route-types-BZi26DVS.mjs} +2 -49
  109. package/dist/{runner-DcVDrzuR.mjs → runner-CabsQ-iM.mjs} +15 -6
  110. package/dist/runner-So9mYfcm.mjs +1 -0
  111. package/dist/runner-mysql-BhRaONkO.mjs +146 -0
  112. package/dist/runner-mysql-DWwE8jKi.mjs +1 -0
  113. package/dist/{runner-pg-CPd-CB_F.mjs → runner-pg-BRemq_GX.mjs} +2 -2
  114. package/dist/runner-pg-_Xncr3H5.mjs +1 -0
  115. package/dist/runtime/ai.mjs +15 -4
  116. package/dist/runtime/auth-client-react.mjs +1 -2
  117. package/dist/runtime/auth-client-solid.mjs +1 -2
  118. package/dist/runtime/auth-client-svelte.mjs +1 -2
  119. package/dist/runtime/auth-client-vue.mjs +1 -2
  120. package/dist/runtime/auth-client.mjs +1 -2
  121. package/dist/runtime/auth.mjs +1 -2
  122. package/dist/runtime/better-auth-mysql.mjs +4 -1
  123. package/dist/runtime/db.mjs +6 -2
  124. package/dist/runtime/durable.d.mts +2 -1
  125. package/dist/runtime/durable.mjs +1 -1
  126. package/dist/runtime/email/testing.mjs +1 -1
  127. package/dist/runtime/email-protocol.mjs +1 -2
  128. package/dist/runtime/email.mjs +1 -1
  129. package/dist/runtime/env-public.mjs +2 -2
  130. package/dist/runtime/env.mjs +1 -2
  131. package/dist/runtime/isr.mjs +1 -1
  132. package/dist/runtime/kv.mjs +1 -1
  133. package/dist/runtime/limits.mjs +1 -2
  134. package/dist/runtime/live-client.d.mts +2 -1
  135. package/dist/runtime/live-server.d.mts +2 -1
  136. package/dist/runtime/live-server.mjs +1 -1
  137. package/dist/runtime/live.mjs +1 -2
  138. package/dist/runtime/log.d.mts +2 -1
  139. package/dist/runtime/migration-handler-mysql.mjs +38 -8
  140. package/dist/runtime/migration-handler.mjs +1 -2
  141. package/dist/runtime/queues.mjs +1 -1
  142. package/dist/runtime/response.mjs +1 -2
  143. package/dist/runtime/route-url.mjs +1 -2
  144. package/dist/runtime/routing.d.mts +2 -1
  145. package/dist/runtime/sandbox-container.mjs +1 -2
  146. package/dist/runtime/sandbox.mjs +3 -3
  147. package/dist/runtime/seed.d.mts +2 -1
  148. package/dist/runtime/sse.mjs +1 -2
  149. package/dist/runtime/storage.mjs +1 -1
  150. package/dist/runtime/validator.mjs +1 -2
  151. package/dist/runtime/ws-server.d.mts +2 -1
  152. package/dist/runtime/ws-server.mjs +1 -1
  153. package/dist/{secret-B5J8bBsI.mjs → secret-bg73f1Ge.mjs} +5 -5
  154. package/dist/{skills-BJsan98C.mjs → skills-C_yRTg0g.mjs} +1 -1
  155. package/dist/{subcommand-prompt-gQ-NDA-u.mjs → subcommand-prompt-Bm3ZlYgA.mjs} +2 -2
  156. package/dist/sveltekit.d.mts +2 -1
  157. package/dist/validate-BQFdf0Pi.mjs +1 -0
  158. package/dist/wrapper-CwhpNWtH.mjs +663 -0
  159. package/docs/guide/ai.md +8 -2
  160. package/docs/guide/database/mysql.md +14 -3
  161. package/docs/guide/database.md +1 -5
  162. package/docs/guide/durable-state.md +9 -5
  163. package/docs/guide/platform/installation/credentials.md +18 -2
  164. package/docs/guide/platform/installation/domains.md +1 -1
  165. package/docs/guide/platform/installation/maintenance.md +38 -1
  166. package/docs/guide/platform/installation/prerequisites.md +6 -2
  167. package/docs/guide/platform/installation/setup.md +23 -1
  168. package/docs/guide/platform/installation/uninstall.md +6 -1
  169. package/docs/guide/sandboxes.md +1 -1
  170. package/docs/guide/self-hosted-platform.md +1 -1
  171. package/docs/integrations/cloudflare.md +2 -2
  172. package/docs/integrations/frameworks/analog.md +3 -11
  173. package/docs/integrations/frameworks/nuxt.md +7 -10
  174. package/docs/integrations/nodejs-bun-deno.md +2 -0
  175. package/docs/reference/api.md +1 -0
  176. package/docs/reference/cli/platform-installation.md +18 -6
  177. package/docs/reference/config.md +2 -0
  178. package/package.json +34 -28
  179. package/sandbox.Dockerfile +1 -1
  180. package/skills/void/SKILL.md +1 -1
  181. package/dist/auth-wn6F8dB8.mjs +0 -2
  182. package/dist/cf-build-output-2u583yJK.mjs +0 -2
  183. package/dist/client-C1BjRn3g.mjs +0 -2
  184. package/dist/cloudflare-operations-Ds-lX3Ts.mjs +0 -2
  185. package/dist/collect-NUlJMpLY.mjs +0 -2
  186. package/dist/config-CNnrSMYm.mjs +0 -2
  187. package/dist/create-project-DL7YXpjj.mjs +0 -2
  188. package/dist/deploy-Db2ALnQP.mjs +0 -3
  189. package/dist/discover-CTUiSsfG.mjs +0 -2
  190. package/dist/dist-Bx1z6Eva.mjs +0 -2
  191. package/dist/env-validation-CTn-HhG1.mjs +0 -2
  192. package/dist/gen-F8pSZnhc.mjs +0 -2
  193. package/dist/generate-Rii9klHB.mjs +0 -2
  194. package/dist/help-s9q7LTcu.mjs +0 -2
  195. package/dist/login-DhK7o1oJ.mjs +0 -2
  196. package/dist/migrate-BgT-hmu8.mjs +0 -2
  197. package/dist/operator-cmd-Cjk5DiRx.mjs +0 -2
  198. package/dist/plan-CH2G51je.mjs +0 -2
  199. package/dist/platform-args-Cm7x-fot.mjs +0 -2
  200. package/dist/platform-cmd-Cuj4oUVo.mjs +0 -2
  201. package/dist/platform-lifecycle-_gfnjUBr.mjs +0 -2
  202. package/dist/platform-management-CYrLvTGH.mjs +0 -2
  203. package/dist/prepare-dr9uxQSV.mjs +0 -2
  204. package/dist/project-DiiOBZPF.mjs +0 -2
  205. package/dist/project-slug-DofjTFd-.mjs +0 -2
  206. package/dist/resolve-project-B9Hr0D3n.mjs +0 -2
  207. package/dist/runner-B5huK2eC.mjs +0 -2
  208. package/dist/runner-mysql-CCtyI0p6.mjs +0 -55
  209. package/dist/runner-mysql-CaJq-hd6.mjs +0 -2
  210. package/dist/runner-pg-BJhFZZG4.mjs +0 -2
  211. package/dist/validate-C9xtFOYR.mjs +0 -2
  212. package/dist/{sandbox-container-DBKIqDEK.mjs → sandbox-container-a9LRUtii.mjs} +1 -1
@@ -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
 
@@ -234,10 +234,6 @@ const usersWithPosts = await db.query.users.findMany({
234
234
  });
235
235
  ```
236
236
 
237
- ::: warning ⚠️ Nuxt and Analog limitations
238
- In Nuxt and Analog, use the query builder (`db.select().from(table)`). The `db.query.*` relational API is not available in these frameworks.
239
- :::
240
-
241
237
  ## Seeding
242
238
 
243
239
  Use `void db seed` to reset your local database, re-apply migrations, and then run a seed file.
@@ -376,7 +372,7 @@ To keep an existing migration history:
376
372
 
377
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`.
378
374
 
379
- 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.
380
376
 
381
377
  ## Scaffolding
382
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,15 +158,19 @@ 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.
166
170
 
167
171
  ## Native Durable Object classes
168
172
 
169
- 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 direct Cloudflare deployments.
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.
170
174
 
171
175
  ```ts
172
176
  // durable-objects/workspace.ts
@@ -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.
@@ -74,17 +86,21 @@ The installer deploys the email gateway, prepares the shared mail route, and ver
74
86
 
75
87
  ## R2 Upload Credentials
76
88
 
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
+
77
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/).
78
92
 
79
93
  ## Signing and Encryption Keys {#signing-and-encryption-keys}
80
94
 
81
- 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:
82
98
 
83
99
  ```sh
84
100
  openssl rand -base64 32
85
101
  ```
86
102
 
87
- 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.
88
104
 
89
105
  ::: details Generate the keys without printing them to your terminal
90
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.
@@ -121,7 +121,7 @@ Custom images must include the helper matching Void's installed Sandbox SDK vers
121
121
 
122
122
  ```dockerfile
123
123
  FROM node:26.10.0-trixie-slim
124
- 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
125
125
  WORKDIR /workspace
126
126
  CMD ["sleep", "infinity"]
127
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
 
@@ -26,7 +26,6 @@ Void provides the local Cloudflare binding runtime. `nitro-cloudflare-dev` creat
26
26
  ### 3. Configure `vite.config.ts`
27
27
 
28
28
  ```ts
29
- import { resolve } from 'node:path';
30
29
  import analog from '@analogjs/platform';
31
30
  import { defineConfig } from 'vite';
32
31
  import { voidPlugin } from 'void';
@@ -41,12 +40,7 @@ export default defineConfig({
41
40
  nitro: {
42
41
  preset: 'cloudflare-module',
43
42
  cloudflareDev: { configPath: './.void-wrangler.jsonc' },
44
- modules: ['nitro-cloudflare-dev'],
45
- alias: {
46
- // Nitro has its own bundler that doesn't use Vite aliases.
47
- // Duplicate @schema here so Nitro can resolve it.
48
- '@schema': resolve(__dirname, 'db/schema.ts'),
49
- },
43
+ modules: ['nitro-cloudflare-dev', 'void/nitro'],
50
44
  },
51
45
  }),
52
46
  voidPlugin(),
@@ -54,6 +48,8 @@ export default defineConfig({
54
48
  });
55
49
  ```
56
50
 
51
+ The `void/nitro` module gives Analog API routes and page server loads your app's `void/db` and `@schema`.
52
+
57
53
  ### 4. Create `void.config.ts`
58
54
 
59
55
  Void generates the Cloudflare config used by Analog's development runtime:
@@ -98,10 +94,6 @@ export const load = async ({ event }: PageServerLoad) => {
98
94
  };
99
95
  ```
100
96
 
101
- ::: warning ⚠️ Analog limitation
102
- Use `db.select().from(table)` for database queries in Analog. The `db.query.*` relational API is not available.
103
- :::
104
-
105
97
  ### Other resources
106
98
 
107
99
  Use [KV](../../guide/kv.md), [object storage](../../guide/storage.md), and [AI](../../guide/ai.md) from server-side code with the same imports as a Void app. Add [cron jobs](../../guide/jobs.md) in `crons/` and [queue consumers](../../guide/queues.md) in `queues/`.
@@ -30,23 +30,24 @@ import { resolve } from 'node:path';
30
30
  import { voidPlugin } from 'void';
31
31
 
32
32
  export default defineNuxtConfig({
33
+ alias: {
34
+ '@schema': resolve(import.meta.dirname, 'db/schema.ts'),
35
+ },
33
36
  nitro: {
34
37
  preset: 'cloudflare-module',
35
- cloudflareDev: { configPath: './.void-wrangler.jsonc' },
38
+ modules: ['void/nitro'],
39
+ cloudflare: { dev: { configPath: './.void-wrangler.jsonc' } },
36
40
  // Required for Nuxt 4.6.0 on Windows.
37
41
  externals: {
38
42
  inline: [/[\\/]node_modules[\\/]nuxt[\\/]dist[\\/]/],
39
43
  },
40
- alias: {
41
- // Nitro has its own bundler that doesn't use Vite aliases.
42
- // Duplicate @schema here so Nitro can resolve it.
43
- '@schema': resolve(import.meta.dirname, 'db/schema.ts'),
44
- },
45
44
  },
46
45
  vite: { plugins: [voidPlugin()] },
47
46
  });
48
47
  ```
49
48
 
49
+ The `void/nitro` module gives Nuxt server routes your app's `void/db` and `@schema`. The top-level `alias` lets `nuxi typecheck` resolve `@schema`, because Nuxt also checks server routes with the app's types. `cloudflare.dev` gives the development server the bindings from Void's generated Cloudflare config; Nuxt runs it in development when `compatibilityDate` is `2025-07-15` or later.
50
+
50
51
  ### 4. Create `void.config.ts`
51
52
 
52
53
  Void generates the Cloudflare config used by Nuxt's development runtime:
@@ -88,10 +89,6 @@ export default defineEventHandler(async () => {
88
89
  });
89
90
  ```
90
91
 
91
- ::: warning ⚠️ Nuxt limitation
92
- Use `db.select().from(table)` for database queries in Nuxt. The `db.query.*` relational API is not available.
93
- :::
94
-
95
92
  ### Other resources
96
93
 
97
94
  Use [KV](../../guide/kv.md), [object storage](../../guide/storage.md), and [AI](../../guide/ai.md) from server-side code with the same imports as a Void app. Add [cron jobs](../../guide/jobs.md) in `crons/` and [queue consumers](../../guide/queues.md) in `queues/`.
@@ -80,6 +80,8 @@ dist/
80
80
 
81
81
  `vite preview` also uses `app.js` to serve your built app locally.
82
82
 
83
+ Installed packages that depend on `void` are bundled into `dist/ssr`. If one of their dependencies uses a native addon or reads files next to its own code, add that dependency, in the version the package uses, to your app's `dependencies`. The build then leaves it to Node.
84
+
83
85
  ## What Works
84
86
 
85
87
  These Void features work identically across all targets:
@@ -68,4 +68,5 @@ Import Void's app-facing APIs from these paths:
68
68
  | `void/queues` | `queues` proxy for sending messages to typed queues |
69
69
  | `void/sandbox` | `getSandbox`, `sandbox`, `SandboxLimitError`, `SandboxUnavailableError`, and the SDK 1.0 file, backup, and mount helpers. `getSandbox(id)` resolves a client. Commands, files, port requests, and process completion return promises; limits reject with `SandboxLimitError`, which extends `UsageLimit`. Container state lasts until inactivity (default ten minutes), a crash, or a restart. See [Sandboxes](../guide/sandboxes.md) for the API and deployment requirements. |
70
70
  | `void/env` | `defineEnv`, `env`, schema helpers (`string`, `number`, `boolean`, `url`, `email`, `oneOf`, `json`), and global Cloudflare env types |
71
+ | `void/nitro` | Nitro module for Nuxt and Analog. Add `'void/nitro'` to the Nitro `modules` so server routes get the app's `void/db` and `@schema` |
71
72
  | `void/sveltekit` | SvelteKit integration helpers: `withVoidTSConfig()` and `mergeVoidSvelteKitTsconfig()` |
@@ -58,11 +58,15 @@ authentication file. Upgrades preserve administrator settings.
58
58
 
59
59
  New resources use `void-<name>-<role>` names; choose an unused installation name. The installer opens setup pages for missing credentials and reuses values already supplied.
60
60
 
61
- During Access setup, choose existing company policies or **Create new** for manual
62
- setup instructions and an account dashboard link. After you save the policy and
63
- confirm completion, Void reloads the list so you can select it and continue in the
64
- same run. **Refresh list** reloads policies created in another window. Your
65
- identity-provider choice and still-available policy selections are retained.
61
+ During Access setup, choose existing company policies or **Create in Cloudflare**
62
+ for manual setup instructions and an account dashboard link. After you save the
63
+ policy and confirm completion, Void reloads the list so you can select it and
64
+ continue in the same run. When Void creates the Access applications, **Allow my
65
+ company’s email domain** creates an Allow policy for the domains you enter and
66
+ selects it. **Refresh list** reloads policies created in another window. Your
67
+ identity-provider choice and still-available policy selections are retained. If a
68
+ selected policy does not restrict sign-in to company identities, Void explains why
69
+ and asks again.
66
70
 
67
71
  Installation progress and partial credentials are saved encrypted locally. Rerun the installer to continue unfinished setup, or pass `--resume --name <id>`. Use lifecycle commands for completed installations.
68
72
 
@@ -98,7 +102,7 @@ Use these commands to recover, update, pause, or remove an installation:
98
102
  void platform discover [--account <id>] [--installation <id-or-name>]
99
103
  void platform upgrade [id] [--runtime <path>] [--dashboard-url <origin>] [--plan] [--yes]
100
104
  void platform rollback [id] --runtime <earlier-path> [--from-runtime <current-path>] [--plan] [--yes]
101
- void platform repair [id] [--runtime <path>] [--dashboard-url <origin>] [--plan] [--yes]
105
+ void platform repair [id] [--runtime <path>] [--dashboard-url <origin>] [--auth-config <path>] [--plan] [--yes]
102
106
  void platform disable [id] [--plan] [--yes]
103
107
  void platform enable [id] [--runtime <path>] [--plan] [--yes]
104
108
  void platform uninstall [id] [--plan] [--purge-data | --purge-resources] [--keep-zone] [--yes]
@@ -113,6 +117,12 @@ use `repair --dashboard-url <origin>` or `upgrade --dashboard-url <origin>`.
113
117
  Preview with `--plan` first. Existing Access protection must cover the configured
114
118
  dashboard origin before maintenance can proceed. See [Optional Dashboard](../../guide/platform/installation/domains.md#optional-dashboard).
115
119
 
120
+ While first administrator setup is pending, `repair --auth-config <path>` replaces
121
+ the login settings from a file in the install format and prints a new setup code.
122
+ Interactive repair offers the same change with the saved values filled in. Login
123
+ methods and Access protection stay as installed. Run it on the computer that
124
+ installed the platform. See [First administrator sign-in fails](../../guide/platform/installation/maintenance.md#first-administrator-sign-in-fails).
125
+
116
126
  After discovery on another machine, set `VOID_PLATFORM_DATABASE_URL`. See [Manage an installation from another machine](../../guide/platform/installation/maintenance.md#manage-an-installation-from-another-machine) for the secrets needed to recreate a missing Worker.
117
127
 
118
128
  | Command | Behavior |
@@ -137,6 +147,8 @@ An upgrade completes after the new Workers pass health checks. If rollout fails,
137
147
 
138
148
  `platform rollback` restores a compatible earlier runtime without reversing database migrations. Pass its files with `--runtime`; if the installed version is custom, also supply that version with `--from-runtime`. Void refuses incompatible targets.
139
149
 
150
+ If project Zero Trust is on and no platform user exists yet, uninstall turns it off and deletes its Access applications first. Run it on the computer that installed the platform.
151
+
140
152
  Uninstall verifies remote ownership before removing anything. Data resources are retained unless you pass `--purge-data`. Workers, the Queues they use, R2, AI Gateway, DNS records, routes, custom domains, adopted resources, external PostgreSQL, and zones are retained for manual review.
141
153
 
142
154
  `--purge-resources` includes `--purge-data` and also deletes every other resource the installation created, including Workers, Queues, R2, AI Gateway, the platform DNS record, routes, custom domains, and installer-created Access resources. It removes only the Email Routing rules that send mail to the platform email gateway, and keeps zones, adopted resources, external PostgreSQL, other Email Routing settings, and API tokens. A route, custom domain, DNS record, or Access resource that no longer matches the installation's record is kept and listed. It refuses before any change while projects remain or resource reads are denied. Use the Edit permissions listed by `--plan`; read checks cannot verify them, so a denied deletion can stop uninstall after changes have begun. Rerun the same command to continue after an interruption, or after a plain or `--purge-data` uninstall stopped.
@@ -297,6 +297,8 @@ Curated Cloudflare Workers configuration. `void init` pins `compatibility_date`
297
297
 
298
298
  `worker.vars` values must be strings. Root `.env` values override them during local development only. Production builds do not load `.env`, and reject any `worker.vars` name declared as a server key in `env.ts`. Use `void secret put` for production server values.
299
299
 
300
+ Managed deployments include `worker.vars` as plain-text bindings. A remote secret with the same name takes precedence. To use the configured variable instead, remove that remote secret and deploy again. Secret deletion changes the running Worker immediately, so plan this migration during a maintenance window.
301
+
300
302
  `worker.limits.cpu_ms` sets the CPU time limit per request, from 1 to 300000 ms. On a Void platform, deploy fails if the limit exceeds the account plan; lower it in `void.config.ts` before retrying. Rollback instead caps the old limit at the current plan ceiling. On direct deploys, [Cloudflare enforces the value](https://developers.cloudflare.com/workers/platform/limits/#cpu-time): Workers Free allows up to 10 ms and Workers Paid up to 300000 ms per request.
301
303
 
302
304
  ```json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "void",
3
- "version": "0.28.0",
3
+ "version": "1.1.0",
4
4
  "description": "Full-stack framework and deployment CLI for Cloudflare Workers, powered by Vite.",
5
5
  "homepage": "https://void.cloud",
6
6
  "bugs": {
@@ -90,6 +90,11 @@
90
90
  "./routes": {
91
91
  "types": "./dist/routes-stub.d.mts"
92
92
  },
93
+ "./nitro": {
94
+ "types": "./dist/nitro.d.mts",
95
+ "import": "./dist/nitro.mjs",
96
+ "require": "./dist/nitro.mjs"
97
+ },
93
98
  "./sveltekit": {
94
99
  "types": "./dist/sveltekit.d.mts",
95
100
  "import": "./dist/sveltekit.mjs",
@@ -334,26 +339,26 @@
334
339
  }
335
340
  },
336
341
  "dependencies": {
337
- "@cloudflare/build-output-utils": "^0.9.0",
338
- "@cloudflare/codemods": "^0.4.2",
339
- "@cloudflare/config": "^0.24.1",
340
- "@cloudflare/sandbox": "1.0.0",
341
- "@cloudflare/vite-plugin": "^1.63.1",
342
- "@cloudflare/workers-auth": "^0.13.1",
343
- "@cloudflare/workers-types": "^5.20261009.1",
344
- "@napi-rs/keyring": "^2.1.0",
345
- "@void/deploy-cloudflare": "0.28.0",
346
- "@void/deploy-core": "0.28.0",
347
- "@void/edge": "0.28.0",
348
- "@void/isr": "0.28.0",
349
- "@void/platform": "0.28.0",
342
+ "@cloudflare/build-output-utils": "^0.9.2",
343
+ "@cloudflare/codemods": "^0.5.0",
344
+ "@cloudflare/config": "^0.26.0",
345
+ "@cloudflare/sandbox": "^1.0.1",
346
+ "@cloudflare/vite-plugin": "^1.64.0",
347
+ "@cloudflare/workers-auth": "^0.14.0",
348
+ "@cloudflare/workers-types": "^5.20261014.1",
349
+ "@napi-rs/keyring": "^2.1.1",
350
+ "@void/deploy-cloudflare": "1.1.0",
351
+ "@void/deploy-core": "1.1.0",
352
+ "@void/edge": "1.1.0",
353
+ "@void/isr": "1.1.0",
354
+ "@void/platform": "1.1.0",
350
355
  "better-auth": "^1.7.7",
351
356
  "better-sqlite3": "^13.0.3",
352
357
  "blake3-jit": "^1.1.0",
353
- "cf": "^1.0.0-beta.14",
358
+ "cf": "^1.0.0-beta.17",
354
359
  "drizzle-arktype": "^0.1.3",
355
360
  "drizzle-kit": "^0.31.11",
356
- "drizzle-orm": "^0.45.3",
361
+ "drizzle-orm": "^0.45.4",
357
362
  "drizzle-valibot": "^0.4.2",
358
363
  "drizzle-zod": "^0.8.3",
359
364
  "email-validator": "^2.0.4",
@@ -361,23 +366,24 @@
361
366
  "ignore": "^7.0.12",
362
367
  "jiti": "^2.7.0",
363
368
  "jsonc-parser": "^3.3.1",
364
- "mime": "^4.1.0",
365
- "miniflare": "5.20261006.1-alpha",
369
+ "mime": "^4.1.1",
370
+ "miniflare": "5.20261012.0-beta",
366
371
  "minimatch": "^10.2.6",
367
- "mysql2": "^3.24.5",
372
+ "mysql2": "^3.24.6",
368
373
  "pg": "^8.23.1",
369
374
  "postal-mime": "^4.0.5",
370
375
  "proper-lockfile": "^4.1.2",
371
- "terminal-link": "^5.0.0"
376
+ "terminal-link": "^5.0.0",
377
+ "yaml": "^2.9.1"
372
378
  },
373
379
  "devDependencies": {
374
- "@electric-sql/pglite": "0.5.8",
380
+ "@electric-sql/pglite": "0.5.9",
375
381
  "@types/better-sqlite3": "^9.6.0",
376
- "@types/node": "^26.6.4",
382
+ "@types/node": "^26.6.5",
377
383
  "@types/pg": "^8.23.1",
378
384
  "@types/proper-lockfile": "^4.1.4",
379
- "@voidzero-dev/vite-plus-prompts": "1.1.0",
380
- "arktype": "^2.2.7",
385
+ "@voidzero-dev/vite-plus-prompts": "1.2.0",
386
+ "arktype": "^2.2.8",
381
387
  "ci-info": "^4.4.0",
382
388
  "estree-walker": "^3.0.3",
383
389
  "fast-wrap-ansi": "^0.2.2",
@@ -389,12 +395,12 @@
389
395
  "tinyglobby": "^0.2.17",
390
396
  "typescript": "7.0.2",
391
397
  "valibot": "^1.5.0",
392
- "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
393
- "vite-plus": "1.1.0",
394
- "zod": "^4.6.5"
398
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.2.0",
399
+ "vite-plus": "1.2.0",
400
+ "zod": "^4.6.7"
395
401
  },
396
402
  "peerDependencies": {
397
- "@void/md": "0.28.0",
403
+ "@void/md": "1.1.0",
398
404
  "arktype": ">=2.0.0",
399
405
  "valibot": ">=1.0.0-beta.7",
400
406
  "vite": "^8.0.0",