void 1.1.0 → 1.1.12

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 (246) hide show
  1. package/dist/{account-cmd-BTcUzv9L.mjs → account-cmd-Cj6sCMTk.mjs} +4 -4
  2. package/dist/{application-analysis-AB_YYWgH.mjs → application-analysis-D7nNmNJb.mjs} +6 -6
  3. package/dist/{application-routing-L7V-TFhZ.mjs → application-routing-CZH66gXn.mjs} +1 -1
  4. package/dist/{auth-link-DUJuvRx5.mjs → auth-link-Dj7lAC_K.mjs} +4 -4
  5. package/dist/{auth-migrations-Cgs0k6lS.mjs → auth-migrations-BO27GDNr.mjs} +38 -2
  6. package/dist/{auth-router-CIxiMG7i.mjs → auth-router-CNsMOFCa.mjs} +5 -4
  7. package/dist/{better-auth-shared-B74NJIus.d.mts → better-auth-shared-Bv18bB-l.d.mts} +2 -0
  8. package/dist/{better-auth-shared-CMXlZG7W.mjs → better-auth-shared-D-6z0q0f.mjs} +28 -1
  9. package/dist/{build-cmd-BkIv25PA.mjs → build-cmd-ByhegwRC.mjs} +2 -2
  10. package/dist/{cache-Ctzfig-W.mjs → cache-CEFb5ban.mjs} +2 -2
  11. package/dist/{cancel-deploy-CD9o-SsC.mjs → cancel-deploy-CaARY26n.mjs} +2 -2
  12. package/dist/{cf-build-output-Bc8i3dzE.mjs → cf-build-output-ChEKWan2.mjs} +71 -7
  13. package/dist/cf-build-output-Dcmxa-Zm.mjs +1 -0
  14. package/dist/{cf-user-agent-ChjQp2MU.mjs → cf-command-values-b8OqDoo9.mjs} +5 -16
  15. package/dist/cf-user-agent-BkEHPDLA.mjs +16 -0
  16. package/dist/cli/cli.mjs +180 -57
  17. package/dist/cli/cloudflare-operation-process.mjs +46 -9
  18. package/dist/cli/env-schema-probe.mjs +3 -3
  19. package/dist/{client-DM9Kcf4e.mjs → client-BdzxubTS.mjs} +58 -13
  20. package/dist/client-DAnfyMe9.mjs +1 -0
  21. package/dist/{cloudflare-auth-CqFBDo52.mjs → cloudflare-auth-DSvBc1Gu.mjs} +1 -1
  22. package/dist/{cloudflare-cmd-BIAF_BIY.mjs → cloudflare-cmd-D_2-Q-_i.mjs} +4 -4
  23. package/dist/{cloudflare-config-DV60XFFK.mjs → cloudflare-config-rdFOys4X.mjs} +2 -2
  24. package/dist/{cloudflare-connect-WjwnVOJA.mjs → cloudflare-connect-BN-k2kD-.mjs} +2 -2
  25. package/dist/{cloudflare-operations-CrSUFRzJ.mjs → cloudflare-operations-BFLCpUCV.mjs} +1 -1
  26. package/dist/{cloudflare-operations-B42EZeJy.mjs → cloudflare-operations-D5PLrOqD.mjs} +18 -8
  27. package/dist/{cloudflare-process-CeDWJRhj.mjs → cloudflare-process-CZJ4viYl.mjs} +2 -2
  28. package/dist/collect-BWhkgtAn.mjs +1 -0
  29. package/dist/{collect-xjffdCdk.mjs → collect-Dew86qce.mjs} +4 -3
  30. package/dist/{config-D0GY5ItR.mjs → config-CyUJzi3q.mjs} +1 -1
  31. package/dist/{config-Bx_1SpnO.mjs → config-D26zcdKy.mjs} +2 -2
  32. package/dist/{config-BEm9vRvS.mjs → config-DC5llZaI.mjs} +2 -2
  33. package/dist/{config-QrJWu0IX.mjs → config-DYJV8aEH.mjs} +1 -1
  34. package/dist/{connect-CKtk-EZe.mjs → connect-C4_m2moF.mjs} +5 -5
  35. package/dist/{create-project-B-ewF_Af.mjs → create-project-CvuYDD-l.mjs} +1 -1
  36. package/dist/{create-project-yInGo72M.mjs → create-project-D8jQTwVQ.mjs} +2 -2
  37. package/dist/database-provider.d.mts +6 -0
  38. package/dist/{db-7I_gfdVq.mjs → db-BsiOAa0A.mjs} +306 -111
  39. package/dist/{db-types-Bb4WBWIs.mjs → db-types-NGxPwnlt.mjs} +1 -1
  40. package/dist/{delete-Cy-M1u-r.mjs → delete-CAma7nFi.mjs} +2 -2
  41. package/dist/{deploy-BYYlnsiy.mjs → deploy-D1gIPiAq.mjs} +148 -64
  42. package/dist/deploy-Dc0XsCQj.mjs +2 -0
  43. package/dist/{deploy-managed-static-Ca4TFdmx.mjs → deploy-managed-static-B9KVxY3X.mjs} +80 -34
  44. package/dist/{deploy-transport-DWlWBe6M.mjs → deploy-transport-B3mtEi_q.mjs} +2 -2
  45. package/dist/deploy.d.mts +22 -1
  46. package/dist/deploy.mjs +49 -8
  47. package/dist/discover-D4TPKo57.mjs +1 -0
  48. package/dist/{discover-D2PGT63u.mjs → discover-LaV0tbIu.mjs} +1 -1
  49. package/dist/{dispatch-DrTTk8Xg.mjs → dispatch-BAbbn3jg.mjs} +6 -6
  50. package/dist/{domain-CZGxPv9u.mjs → domain-BAdwm-QS.mjs} +3 -3
  51. package/dist/{drizzle-CF84FOVM.mjs → drizzle-BQfyvQKX.mjs} +13 -2
  52. package/dist/{email-DzyNVuoU.mjs → email-MwjA7kaL.mjs} +11 -12
  53. package/dist/{email-cloudflare-DfG6UEMm.mjs → email-cloudflare-etpKiITL.mjs} +7 -10
  54. package/dist/{entry-ehmBvs5w.mjs → entry-B_0IhV64.mjs} +1 -1
  55. package/dist/{env-Nx3yf50r.mjs → env-B163-G1s.mjs} +5 -5
  56. package/dist/{env-types-DS2_y4X8.mjs → env-types-GRchm5dw.mjs} +1 -1
  57. package/dist/{env-validation-BT7z-qpQ.mjs → env-validation-CuGfWRJd.mjs} +1 -1
  58. package/dist/{env-validation-DYxjz_Wo.mjs → env-validation-D_KyMdab.mjs} +2 -2
  59. package/dist/{fetch-BPCYVi3H.d.mts → fetch-CUX0tB78.d.mts} +16 -3
  60. package/dist/fetch-CtESUYWd.mjs +26 -0
  61. package/dist/{fetch-error-Dj3crt0e.mjs → fetch-error-Bw0n-IY-.mjs} +1 -1
  62. package/dist/{fetch-stream-PGgz4uGz.mjs → fetch-stream-BspOeTAI.mjs} +1 -1
  63. package/dist/{fetch-stream-obvZ7fvO.d.mts → fetch-stream-DfkAzZf-.d.mts} +1 -1
  64. package/dist/{gen-CufHEf42.mjs → gen-CYN3wiov.mjs} +26 -20
  65. package/dist/gen-Cf-RBVg4.mjs +1 -0
  66. package/dist/{generate-Dat0UTry.mjs → generate-B1m4Cm4n.mjs} +1 -1
  67. package/dist/{generate-ClI89brV.mjs → generate-DkEb9rL-.mjs} +1 -1
  68. package/dist/{github-cmd-FU8EjFyU.mjs → github-cmd-C8QsnJQs.mjs} +2 -2
  69. package/dist/{handler-_PqY82xe.d.mts → handler-D5K_yP6T.d.mts} +1 -1
  70. package/dist/{headers-Di1FsD3e.mjs → headers-Bi4bOAwp.mjs} +1 -1
  71. package/dist/{help-BT2hovNI.mjs → help-B2sFwn9b.mjs} +60 -15
  72. package/dist/help-w-xlx_kq.mjs +1 -0
  73. package/dist/{inbound-brj2-TM5.d.mts → inbound-Da7XsjH3.d.mts} +6 -12
  74. package/dist/index.d.mts +1 -1
  75. package/dist/index.mjs +139 -126
  76. package/dist/{info-l249eUdH.mjs → info-Bxunp14X.mjs} +4 -4
  77. package/dist/{init-D0A6M64Q.mjs → init-DGFQMnbk.mjs} +51 -28
  78. package/dist/{link-WMoJFf4i.mjs → link-CwrfpjIM.mjs} +3 -3
  79. package/dist/{list-CQ2EQEHL.mjs → list-hKoW5z-b.mjs} +3 -3
  80. package/dist/{live-DJONVlQK.d.mts → live-JheIDZKc.d.mts} +1 -1
  81. package/dist/{local-d1-BxvQYEFi.mjs → local-d1-CpaPbd_L.mjs} +5 -5
  82. package/dist/login-08mBwZfI.mjs +1 -0
  83. package/dist/{login-C2T1oVG-.mjs → login-f2eu2TQh.mjs} +3 -3
  84. package/dist/{logs-DnC1d7xB.mjs → logs-CEWqD-_B.mjs} +3 -3
  85. package/dist/{migrate-BDIprOYd.mjs → migrate-DYfdWBXt.mjs} +5 -5
  86. package/dist/migrate-Di-4EuoE.mjs +1 -0
  87. package/dist/{neon-n74ta1Pr.mjs → neon-DTZr7Bu7.mjs} +0 -1
  88. package/dist/nitro.mjs +3 -3
  89. package/dist/{node-cPadMgUO.mjs → node-uN8_zxJr.mjs} +15 -9
  90. package/dist/operator-cmd-Bv20yLu2.mjs +1 -0
  91. package/dist/{operator-cmd-DHieWtFp.mjs → operator-cmd-DCr_QGMH.mjs} +4 -4
  92. package/dist/{output-Ba6ZbrzY.mjs → output-CKguMgr7.mjs} +13 -1
  93. package/dist/pages/client.d.mts +2 -2
  94. package/dist/pages/client.mjs +18 -5
  95. package/dist/pages/index.d.mts +2 -2
  96. package/dist/pages/index.mjs +5 -5
  97. package/dist/pages/islands-plugin.d.mts +44 -6
  98. package/dist/pages/islands-plugin.mjs +99 -28
  99. package/dist/pages/protocol.d.mts +2 -2
  100. package/dist/pages/protocol.mjs +1 -1
  101. package/dist/pages/serialize.d.mts +2 -2
  102. package/dist/pages/serialize.mjs +1 -1
  103. package/dist/{platform-args-CaCL_1Ch.mjs → platform-args-B7ke06up.mjs} +1 -4
  104. package/dist/platform-args-B_LrqEZB.mjs +1 -0
  105. package/dist/{platform-auth-config-Z16-I8nT.mjs → platform-auth-config-qGvEuns3.mjs} +5 -5
  106. package/dist/{platform-auth-protection-BXwZiJSF.mjs → platform-auth-protection-CyLcD6ot.mjs} +3 -3
  107. package/dist/{platform-auth-recovery-CXjfqyOv.mjs → platform-auth-recovery-B2LKI8V2.mjs} +3 -3
  108. package/dist/{platform-cmd-PT4YwMLM.mjs → platform-cmd-B2ec5eFg.mjs} +1 -1
  109. package/dist/{platform-cmd-DaAOiWTl.mjs → platform-cmd-CX7phm7V.mjs} +6 -6
  110. package/dist/{platform-domain-CxpvUeo0.mjs → platform-domain-DDNK2y-4.mjs} +3 -3
  111. package/dist/{platform-lifecycle-DBiS0cJd.mjs → platform-lifecycle-3CR98Tg2.mjs} +399 -40
  112. package/dist/{platform-lifecycle-u9pMOvxC.mjs → platform-lifecycle-CWc5gr6c.mjs} +1 -1
  113. package/dist/{platform-management-DvBS83rC.mjs → platform-management-DAE6g2QU.mjs} +1 -1
  114. package/dist/{platform-management-DhEFdQAf.mjs → platform-management-o3LCCeE4.mjs} +40 -4
  115. package/dist/{platform-plans-config-BWn1S2Rv.mjs → platform-plans-config-CBMZxCep.mjs} +1 -1
  116. package/dist/{platform-recovery-BUGOB4RC.mjs → platform-recovery-Dmsg7lWA.mjs} +2 -2
  117. package/dist/{platform-setup-YvN9VQXV.mjs → platform-setup-hFbnWAVQ.mjs} +1 -1
  118. package/dist/{plugin-inference-DsARdQKE.mjs → plugin-inference-Bekzjuqw.mjs} +2 -2
  119. package/dist/{prepare-DEB5SeVJ.mjs → prepare-DepAGBcV.mjs} +9 -9
  120. package/dist/prepare-EVEbQ9n2.mjs +1 -0
  121. package/dist/{prepare-PQCgsny0.mjs → prepare-HKo7Rh5V.mjs} +2 -2
  122. package/dist/{project-cmd-DVatD8Ev.mjs → project-cmd-8ylYGx-O.mjs} +18 -18
  123. package/dist/{project-paths-DMvEeSau.mjs → project-paths-DGu_QZ_Q.mjs} +1 -1
  124. package/dist/{project-team-DJrWEAG1.mjs → project-team-Bvpl78we.mjs} +2 -2
  125. package/dist/{project-token-CBgLBuL6.mjs → project-token-QWHoJH2t.mjs} +2 -2
  126. package/dist/{project-tsconfig-bveqhlYA.mjs → project-tsconfig-Itv1f4WC.mjs} +1 -1
  127. package/dist/{project-zero-trust-92gLtZ25.mjs → project-zero-trust-8tJ-RFvu.mjs} +2 -2
  128. package/dist/{protocol-4H7V_3Os.d.mts → protocol-Ssc_LhHj.d.mts} +2 -2
  129. package/dist/{protocol-RNP0u7UY.mjs → protocol-bAUUkx70.mjs} +1 -1
  130. package/dist/{providers-BXuhmuub.mjs → providers-BUHwJlmM.mjs} +10 -1
  131. package/dist/provision-BgXFDv0d.mjs +1 -0
  132. package/dist/{provision-BnSSkiED.mjs → provision-DZKYCEJg.mjs} +66 -66
  133. package/dist/r2-conditions-B8xUgJRc.mjs +61 -0
  134. package/dist/{requests-7W1Pygt2.mjs → requests-Vk5Zyhcy.mjs} +2 -2
  135. package/dist/{rollback-BcASVnwP.mjs → rollback-CH4yMQys.mjs} +9 -8
  136. package/dist/{runner-CabsQ-iM.mjs → runner-3uGC-oLF.mjs} +9 -7
  137. package/dist/{runner-So9mYfcm.mjs → runner-WCdfeI0q.mjs} +1 -1
  138. package/dist/{runner-mysql-BhRaONkO.mjs → runner-mysql-BWmbk5IE.mjs} +1 -1
  139. package/dist/{runner-mysql-DWwE8jKi.mjs → runner-mysql-BcHnLUuM.mjs} +1 -1
  140. package/dist/{runner-pg-_Xncr3H5.mjs → runner-pg-Cgp-cr_p.mjs} +1 -1
  141. package/dist/{runner-pg-BRemq_GX.mjs → runner-pg-Cr3qrqi4.mjs} +1 -1
  142. package/dist/runtime/ai.d.mts +4 -0
  143. package/dist/runtime/ai.mjs +2 -37
  144. package/dist/runtime/better-auth-mysql.d.mts +1 -1
  145. package/dist/runtime/better-auth-mysql.mjs +2 -2
  146. package/dist/runtime/better-auth-pg.d.mts +1 -1
  147. package/dist/runtime/better-auth-pg.mjs +2 -2
  148. package/dist/runtime/better-auth.d.mts +1 -1
  149. package/dist/runtime/better-auth.mjs +2 -2
  150. package/dist/runtime/client-react.d.mts +2 -2
  151. package/dist/runtime/client-react.mjs +3 -3
  152. package/dist/runtime/client-solid.d.mts +2 -2
  153. package/dist/runtime/client-solid.mjs +3 -3
  154. package/dist/runtime/client-svelte.d.mts +2 -2
  155. package/dist/runtime/client-svelte.mjs +3 -3
  156. package/dist/runtime/client-vue.d.mts +2 -2
  157. package/dist/runtime/client-vue.mjs +3 -3
  158. package/dist/runtime/client.d.mts +2 -2
  159. package/dist/runtime/client.mjs +3 -3
  160. package/dist/runtime/email/testing.d.mts +1 -1
  161. package/dist/runtime/email.d.mts +2 -3
  162. package/dist/runtime/email.mjs +2 -3
  163. package/dist/runtime/fetch-server.d.mts +8 -0
  164. package/dist/runtime/fetch-server.mjs +30 -0
  165. package/dist/runtime/fetch-stream.d.mts +2 -2
  166. package/dist/runtime/fetch-stream.mjs +2 -2
  167. package/dist/runtime/fetch.d.mts +2 -2
  168. package/dist/runtime/fetch.mjs +3 -3
  169. package/dist/runtime/handler.d.mts +1 -1
  170. package/dist/runtime/live-client.d.mts +1 -1
  171. package/dist/runtime/live.d.mts +1 -1
  172. package/dist/runtime/migration-handler-mysql.mjs +4 -4
  173. package/dist/runtime/migration-handler-pg.mjs +9 -1
  174. package/dist/runtime/remote/binding-handler.mjs +25 -25
  175. package/dist/runtime/remote/index.d.mts +3 -0
  176. package/dist/runtime/remote/index.mjs +86 -23
  177. package/dist/runtime/routing.d.mts +2 -2
  178. package/dist/runtime/routing.mjs +1 -1
  179. package/dist/runtime/sse-client.d.mts +4 -0
  180. package/dist/runtime/validator.d.mts +1 -1
  181. package/dist/runtime/ws-server.d.mts +2 -2
  182. package/dist/runtime/ws.d.mts +1 -1
  183. package/dist/{scan-C0BMdmEd.mjs → scan-D2-FcLHs.mjs} +13 -5
  184. package/dist/{secret-bg73f1Ge.mjs → secret-wr6Sn4Xa.mjs} +4 -4
  185. package/dist/serialize-DtR8Vwa_.d.mts +18 -0
  186. package/dist/serialize-YHvlcG3Q.mjs +31 -0
  187. package/dist/{subcommand-prompt-Bm3ZlYgA.mjs → subcommand-prompt-CNZc4XUd.mjs} +1 -1
  188. package/dist/{types-BAp5AEBU.d.mts → types-7AIz0OZu.d.mts} +1 -1
  189. package/dist/{validate-CheZGRE7.mjs → validate-CnZPMq4q.mjs} +22 -17
  190. package/dist/validate-D7Wn8PUX.mjs +1 -0
  191. package/dist/{version-metadata-DIrqEHQo.mjs → version-metadata-B1Bm2wSq.mjs} +1 -1
  192. package/dist/{wrangler-BYs07Rxy.mjs → wrangler-C9XSzrju.mjs} +3 -3
  193. package/dist/wrangler-DAdxHEzh.mjs +1 -0
  194. package/dist/{wrapper-CwhpNWtH.mjs → wrapper-DGsYwNi6.mjs} +6 -4
  195. package/dist/{ws-aKVYB-fA.d.mts → ws-nnFnAyQb.d.mts} +6 -1
  196. package/docs/guide/auth.md +1 -1
  197. package/docs/guide/database/d1.md +2 -2
  198. package/docs/guide/database/mysql.md +1 -1
  199. package/docs/guide/deployment.md +2 -0
  200. package/docs/guide/edge/headers.md +10 -2
  201. package/docs/guide/edge/revalidation.md +2 -0
  202. package/docs/guide/email/receiving.md +1 -1
  203. package/docs/guide/email/sending.md +3 -3
  204. package/docs/guide/pages-routing/islands.md +2 -2
  205. package/docs/guide/pages-routing/markdown.md +3 -1
  206. package/docs/guide/platform/administration/connected-apps.md +18 -2
  207. package/docs/guide/platform/administration/email.md +7 -1
  208. package/docs/guide/platform/installation/ci.md +2 -0
  209. package/docs/guide/platform/installation/credentials.md +23 -5
  210. package/docs/guide/platform/installation/maintenance.md +32 -2
  211. package/docs/guide/platform/installation/setup.md +1 -1
  212. package/docs/guide/remote-dev.md +2 -0
  213. package/docs/guide/typed-fetch.md +1 -1
  214. package/docs/guide/websockets.md +2 -2
  215. package/docs/index.md +78 -22
  216. package/docs/integrations/cloudflare.md +1 -1
  217. package/docs/integrations/frameworks/tanstack-start.md +25 -0
  218. package/docs/reference/api/deploy.md +35 -3
  219. package/docs/reference/api/pages.md +7 -5
  220. package/docs/reference/api.md +2 -0
  221. package/docs/reference/cli/database.md +22 -5
  222. package/docs/reference/cli/deploy.md +12 -10
  223. package/docs/reference/cli/email.md +1 -1
  224. package/docs/reference/cli/generate.md +1 -1
  225. package/docs/reference/cli/platform-installation.md +4 -2
  226. package/docs/reference/cli/project.md +8 -4
  227. package/docs/reference/cli.md +2 -1
  228. package/docs/reference/config.md +12 -2
  229. package/package.json +8 -7
  230. package/dist/cf-build-output-BU3hqdHu.mjs +0 -1
  231. package/dist/client-B60PwCC4.mjs +0 -1
  232. package/dist/collect-Cae8A7Zr.mjs +0 -1
  233. package/dist/deploy-9lgfhrXS.mjs +0 -2
  234. package/dist/discover-ClzFSwns.mjs +0 -1
  235. package/dist/fetch-sAcwjzLO.mjs +0 -18
  236. package/dist/gen-sXyp5DFO.mjs +0 -1
  237. package/dist/help-i2YGGnTH.mjs +0 -1
  238. package/dist/login-XD844Xs-.mjs +0 -1
  239. package/dist/migrate-BRwU-blY.mjs +0 -1
  240. package/dist/operator-cmd-D6gnZsnK.mjs +0 -1
  241. package/dist/platform-args-B0HeTh0C.mjs +0 -1
  242. package/dist/prepare-CYT6tAzD.mjs +0 -1
  243. package/dist/r2-conditions-D1Wk8i7b.mjs +0 -30
  244. package/dist/serialize-BtQyaYoC.mjs +0 -20
  245. package/dist/serialize-CfSwWfF2.d.mts +0 -10
  246. package/dist/validate-BQFdf0Pi.mjs +0 -1
@@ -4,12 +4,12 @@ import { S as writePendingInstallationSecrets, a as latestPlatformWorkerCutoverG
4
4
  import { t as cfAccessHeaders } from "./cf-access-BM9G0lhO.mjs";
5
5
  import { t as ensurePlatformAccessToken } from "./cf-access-CWP4avfP.mjs";
6
6
  import { A as confirm, H as outro, K as select, L as log, U as password, X as text$1, tt as isCancel, z as multiselect } from "./dist-BVdsO7Py.mjs";
7
- import { f as import_picocolors, l as formatUrl, m as printSuccess, n as cliCommandName, p as note, r as createSpinner, u as getErrorMessage } from "./output-Ba6ZbrzY.mjs";
8
- import { l as resolveCloudflareOperationArgv } from "./cloudflare-process-CeDWJRhj.mjs";
9
- import { d as resolvePinnedApiBaseUrl, i as createDefaultRunWrangler } from "./provision-BnSSkiED.mjs";
10
- import { t as parsePlatformArgs } from "./platform-args-CaCL_1Ch.mjs";
11
- import { o as runCloudflareAuthCommand } from "./cloudflare-auth-CqFBDo52.mjs";
12
- import { a as platformManagementSetupPage, c as platformSetupLink, i as platformInstallCommandArguments, l as platformSetupPages, n as formatPlatformSetupPlan, o as platformPromptAnswer, r as openPlatformSetupPage, s as platformSetupFieldHelp, t as formatPlatformInstallCommand } from "./platform-setup-YvN9VQXV.mjs";
7
+ import { f as import_picocolors, l as formatUrl, m as printSuccess, n as cliCommandName, p as note, r as createSpinner, u as getErrorMessage } from "./output-CKguMgr7.mjs";
8
+ import { l as resolveCloudflareOperationArgv } from "./cloudflare-process-CZJ4viYl.mjs";
9
+ import { o as createDefaultRunWrangler, v as resolvePinnedApiBaseUrl } from "./provision-DZKYCEJg.mjs";
10
+ import { t as parsePlatformArgs } from "./platform-args-B7ke06up.mjs";
11
+ import { o as runCloudflareAuthCommand } from "./cloudflare-auth-DSvBc1Gu.mjs";
12
+ import { a as platformManagementSetupPage, c as platformSetupLink, i as platformInstallCommandArguments, l as platformSetupPages, n as formatPlatformSetupPlan, o as platformPromptAnswer, r as openPlatformSetupPage, s as platformSetupFieldHelp, t as formatPlatformInstallCommand } from "./platform-setup-hFbnWAVQ.mjs";
13
13
  import { copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
14
14
  import { fileURLToPath } from "node:url";
15
15
  import { isRecord } from "@void/deploy-core";
@@ -19,6 +19,7 @@ import { tmpdir } from "node:os";
19
19
  import { stripVTControlCharacters } from "node:util";
20
20
  import { cloudflareCommandDiagnostic, encodeCloudflareVersionMessage, parseCloudflareVersionMessage, readCloudflareTriggerConfig, readCloudflareVersionMigrationTag, stabilizeCloudflareVersionTriggers } from "@void/deploy-cloudflare";
21
21
  import { createServer, request } from "node:http";
22
+ import { setTimeout as setTimeout$1 } from "node:timers/promises";
22
23
  import { readFile } from "node:fs/promises";
23
24
  import { PLATFORM_ADMIN_ASSETS_DIRECTORY, platformDatabaseSchemaDigest, resolvePlatformRuntime } from "@void/platform/installer";
24
25
  import { request as request$1 } from "node:https";
@@ -45,12 +46,29 @@ var PlatformWorkerRoutesChangedError = class extends Error {
45
46
  this.name = "PlatformWorkerRoutesChangedError";
46
47
  }
47
48
  };
49
+ /**
50
+ * The runtime token cannot read the shared email zone. The operator can add
51
+ * the permission to the same token, so callers keep its saved value.
52
+ */
53
+ var PlatformRuntimeTokenEmailPermissionError = class extends Error {
54
+ /** Cloudflare answered HTTP 401 at least once: it did not accept the token. */
55
+ tokenNotValid;
56
+ constructor(message, tokenNotValid, options) {
57
+ super(message, options);
58
+ this.name = "PlatformRuntimeTokenEmailPermissionError";
59
+ this.tokenNotValid = tokenNotValid;
60
+ }
61
+ };
48
62
  async function verifyPlatformRuntimeTokenPermissions(client, input) {
49
63
  try {
50
64
  await client.listHyperdriveConfigs(input.accountId);
51
65
  } catch (error) {
52
66
  throw runtimeTokenPreflightError("Account → Hyperdrive → Write", error);
53
67
  }
68
+ if (input.emailZoneId) await verifyPlatformRuntimeTokenEmailPermissions(client, {
69
+ accountId: input.accountId,
70
+ zoneId: input.emailZoneId
71
+ });
54
72
  if (!input.zoneId) return;
55
73
  const probeUrl = `https://${input.applicationDomain}/.well-known/void/runtime-token-preflight-${randomUUID()}`;
56
74
  try {
@@ -67,6 +85,37 @@ async function verifyPlatformRuntimeTokenPermissions(client, input) {
67
85
  throw runtimeTokenPreflightError("Zone → SSL and Certificates → Edit", error);
68
86
  }
69
87
  }
88
+ /**
89
+ * Shared email setup uses the runtime token after the platform pauses traffic.
90
+ * Read-only requests find a missing Email Routing permission before that. A
91
+ * read cannot prove Edit access. Email Sending is not checked, because its
92
+ * answer depends on the account plan.
93
+ */
94
+ async function verifyPlatformRuntimeTokenEmailPermissions(client, input) {
95
+ const zone = `/zones/${encodeURIComponent(input.zoneId)}`;
96
+ const probes = [
97
+ ["Zone → Zone → Read", zone],
98
+ ["Zone → Zone Settings → Edit", `${zone}/email/routing`],
99
+ ["Zone → Email Routing Rules → Edit", `${zone}/email/routing/rules?per_page=5`],
100
+ ["Account → Email Routing Addresses → Edit", `/accounts/${encodeURIComponent(input.accountId)}/email/routing/addresses?per_page=5`]
101
+ ];
102
+ const missing = [];
103
+ let denial;
104
+ let tokenNotValid = false;
105
+ for (const [permission, path] of probes) try {
106
+ await client.request(path);
107
+ } catch (error) {
108
+ if (error instanceof PlatformCloudflareApiError && (error.status === 401 || error.status === 403)) {
109
+ missing.push(permission);
110
+ denial ??= error;
111
+ tokenNotValid ||= error.status === 401;
112
+ }
113
+ }
114
+ if (denial) {
115
+ const denied = `Cloudflare denied: ${missing.join(", ")} (HTTP ${denial.status}).`;
116
+ throw new PlatformRuntimeTokenEmailPermissionError(input.savedToken ? `platform: The runtime API token saved on this machine cannot use platform email. ${denied} Void checked this token because VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN is not set. If the platform uses a different runtime token, set VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN to that token, and Void checks that token instead. Otherwise, check that the zone permissions of the saved token include the email zone ${input.zoneId}. To add a missing permission, edit the token in the Cloudflare dashboard. The token value stays the same. Then run the command again.` : `platform: The runtime API token cannot use platform email. ${denied} Check that the token is valid and that its zone permissions include the email zone ${input.zoneId}. To add a missing permission, edit the token in the Cloudflare dashboard. The token value stays the same. Or set VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN to a valid token that has these permissions. Then run the command again.`, tokenNotValid, { cause: denial });
117
+ }
118
+ }
70
119
  function runtimeTokenPreflightError(permission, cause) {
71
120
  const status = cause instanceof PlatformCloudflareApiError ? cause.status : null;
72
121
  const message = status === 401 || status === 403 ? `Cloudflare denied the runtime-token check (HTTP ${status}). Check that the token is valid, scoped to this account, and includes ${permission}.` : status === 429 ? `Cloudflare rate-limited the runtime-token check for ${permission} (HTTP 429). Retry shortly; this does not mean the token is missing a permission.` : `Could not complete the runtime-token check for ${permission}${status === null ? "" : ` (Cloudflare HTTP ${status})`}. Retry the check; this failure does not establish that a permission is missing.`;
@@ -535,6 +584,22 @@ var PlatformCloudflareClient = class PlatformCloudflareClient {
535
584
  for (const binding of settings.bindings ?? []) if (binding.type === "plain_text" && typeof binding.name === "string" && typeof binding.text === "string") bindings[binding.name] = binding.text;
536
585
  return bindings;
537
586
  }
587
+ /**
588
+ * Where the last change to a Worker came from, for example `cf_cli`, `dash`
589
+ * (Cloudflare dashboard) or `api` (Workers API). Null when the Worker does
590
+ * not exist or Cloudflare does not report it.
591
+ */
592
+ async getWorkerLastDeployedFrom(accountId, workerName) {
593
+ let service;
594
+ try {
595
+ service = await this.request(`/accounts/${encodeURIComponent(accountId)}/workers/services/${encodeURIComponent(workerName)}`);
596
+ } catch (error) {
597
+ if (error instanceof PlatformCloudflareApiError && error.status === 404) return null;
598
+ throw error;
599
+ }
600
+ const source = service?.default_environment?.script?.last_deployed_from;
601
+ return typeof source === "string" && source !== "" ? source : null;
602
+ }
538
603
  async deleteKvValue(accountId, namespaceId, key) {
539
604
  try {
540
605
  await this.request(`/accounts/${encodeURIComponent(accountId)}/storage/kv/namespaces/${encodeURIComponent(namespaceId)}/values/${encodeURIComponent(key)}`, { method: "DELETE" });
@@ -3645,8 +3710,30 @@ function createPlatformHealthProbeToken(ownershipNonce) {
3645
3710
  //#endregion
3646
3711
  //#region src/cli/platform-installer-errors.ts
3647
3712
  const ANALYTICS_ENGINE_NOT_ENABLED = 10089;
3713
+ const UPLOAD_CONFLICT = "Aborting the upload operation because of conflicts";
3714
+ /** Why the Cloudflare CLI stopped an upload, and what to do. Null for other failures. */
3715
+ function uploadConflictMessage(result, operation) {
3716
+ const output = stripVTControlCharacters(`${result.stdout}\n${result.stderr}`);
3717
+ if (!output.includes(UPLOAD_CONFLICT)) return null;
3718
+ const lines = output.split(/\r?\n/).map((line) => line.replace(/^[\s▲│]+/, "").trim());
3719
+ const outsideChange = lines.find((line) => line.includes("last updated via the script API") || line.includes("set via the Cloudflare Dashboard"));
3720
+ if (outsideChange) return `platform: The Cloudflare CLI did not ${operation}: ${outsideChange.replace(/:$/, ".")} This Worker was changed outside Void. Run the same command in a terminal. Void then lists the changes and asks you before it replaces them.`;
3721
+ const secretNames = [...(lines.find((line) => / with (?:an )?existing remote secrets?\./.test(line))?.split(" conflict")[0] ?? "").matchAll(/`[^`]+`/g)].map(([name]) => name);
3722
+ if (secretNames.length === 1) return `platform: The Cloudflare CLI did not ${operation}: the Worker has a secret with the same name as a value that Void sets: ${secretNames[0]}. Delete that secret from the Worker in the Cloudflare dashboard, then run the command again.`;
3723
+ if (secretNames.length > 1) return `platform: The Cloudflare CLI did not ${operation}: the Worker has secrets with the same names as values that Void sets: ${new Intl.ListFormat("en").format(secretNames)}. Delete those secrets from the Worker in the Cloudflare dashboard, then run the command again.`;
3724
+ const workflow = lines.findIndex((line) => line.includes("already exist and belong to different workers"));
3725
+ if (workflow !== -1) {
3726
+ const owners = lines.slice(workflow + 1);
3727
+ const end = owners.findIndex((line) => !line.startsWith("- "));
3728
+ const workflows = owners.slice(0, end === -1 ? void 0 : end);
3729
+ return `platform: The Cloudflare CLI did not ${operation}: ${[lines[workflow], ...workflows].join(" ")}. ${workflows.length > 1 ? "Other Workers own these workflows. Delete each workflow, or rename it in the configuration of the Worker that owns it." : "Another Worker owns this workflow. Delete the workflow, or rename it in the configuration of that Worker."} Then run the command again.`;
3730
+ }
3731
+ return `platform: The Cloudflare CLI did not ${operation}. It stopped the upload because of a conflict that it could not confirm without a terminal. Fix the conflict, then run the command again.`;
3732
+ }
3648
3733
  function assertCleanPlatformWrangler(result, operation) {
3649
3734
  if (result.status !== 0 || result.signal || result.error) {
3735
+ const conflict = uploadConflictMessage(result, operation);
3736
+ if (conflict) throw new Error(conflict);
3650
3737
  const diagnostic = cloudflareCommandDiagnostic({
3651
3738
  ...result,
3652
3739
  stderr: result.stderr.trim() || result.errors?.map((error) => error.message).join("\n") || ""
@@ -3675,6 +3762,36 @@ async function readActivePlatformWorkerVersion(configPath, accountId, workerName
3675
3762
  if (active.length !== 1 || typeof active[0].version_id !== "string") return null;
3676
3763
  return active[0].version_id;
3677
3764
  }
3765
+ /**
3766
+ * The active version in a Cloudflare API answer for the deployments of a
3767
+ * platform Worker. deployPlatformWorker continues only when the latest
3768
+ * deployment sends all traffic to one version (deploymentRunsOnlyVersion).
3769
+ * `split` is each other answer, for example a gradual deployment.
3770
+ */
3771
+ function readActivePlatformWorkerDeployment(response) {
3772
+ const deployments = response && typeof response === "object" && !Array.isArray(response) ? response.deployments : null;
3773
+ if (!Array.isArray(deployments)) return { kind: "malformed" };
3774
+ if (deployments.length === 0) return { kind: "split" };
3775
+ const latest = deployments[0];
3776
+ const versions = latest && typeof latest === "object" ? latest.versions : null;
3777
+ if (!Array.isArray(versions) || versions.some((version) => !version || typeof version !== "object" || typeof version.version_id !== "string" || !Number.isFinite(Number(version.percentage)))) return { kind: "malformed" };
3778
+ const [only] = versions;
3779
+ return versions.length === 1 && only && Number(only.percentage) === 100 ? {
3780
+ kind: "active",
3781
+ versionId: only.version_id
3782
+ } : { kind: "split" };
3783
+ }
3784
+ /**
3785
+ * Whether a version of a platform Worker has Void's record of its triggers.
3786
+ * This is the rule of the upgrade: it refuses a version without the record,
3787
+ * for example a version deployed outside Void.
3788
+ */
3789
+ async function platformWorkerVersionHasTriggerRecord(readCloudflare, accountId, workerName, versionId) {
3790
+ const version = await readCloudflare(`/accounts/${encodeURIComponent(accountId)}/workers/scripts/${encodeURIComponent(workerName)}/versions/${encodeURIComponent(versionId)}`);
3791
+ const annotations = version && typeof version === "object" ? version.annotations : null;
3792
+ const message = annotations && typeof annotations === "object" ? annotations["workers/message"] : null;
3793
+ return parseCloudflareVersionMessage(typeof message === "string" ? message : null)?.schema === 2;
3794
+ }
3678
3795
  async function readPlatformWorkerDeployments(configPath, accountId, workerName, runner = runPlatformWrangler) {
3679
3796
  const result = await runner({
3680
3797
  type: "deployments.list",
@@ -3753,15 +3870,15 @@ function readPlatformWorkerOwnershipMarker(config) {
3753
3870
  if (typeof marker !== "string" || marker === "") throw new Error("platform: Platform Worker config is missing its ownership marker.");
3754
3871
  return marker;
3755
3872
  }
3756
- async function readActivePlatformWorkerSnapshot(configPath, accountId, workerName, expectedOwnershipMarker, runner = runPlatformWrangler) {
3873
+ async function readActivePlatformWorkerSnapshot(configPath, accountId, workerName, expectedOwnershipMarker, runner = runPlatformWrangler, unrecordedTriggerConfig) {
3757
3874
  const readActiveVersion = () => readActivePlatformWorkerVersion(configPath, accountId, workerName, runner);
3758
3875
  const versionId = await readActiveVersion();
3759
3876
  if (!versionId) throw new Error(`platform: Existing Worker ${workerName} has no single active production version.`);
3760
3877
  return await readPlatformWorkerVersionSnapshot(configPath, accountId, workerName, expectedOwnershipMarker, versionId, runner, async () => {
3761
3878
  if (await readActiveVersion() !== versionId) throw new Error(`platform: Worker ${workerName} changed concurrently while its active version was inspected.`);
3762
- });
3879
+ }, unrecordedTriggerConfig);
3763
3880
  }
3764
- async function readPlatformWorkerVersionSnapshot(configPath, accountId, workerName, expectedOwnershipMarker, versionId, runner, validateCurrentVersion) {
3881
+ async function readPlatformWorkerVersionSnapshot(configPath, accountId, workerName, expectedOwnershipMarker, versionId, runner, validateCurrentVersion, unrecordedTriggerConfig) {
3765
3882
  const result = await runner({
3766
3883
  type: "versions.view",
3767
3884
  versionId,
@@ -3779,6 +3896,11 @@ async function readPlatformWorkerVersionSnapshot(configPath, accountId, workerNa
3779
3896
  const annotations = value.annotations;
3780
3897
  const message = annotations && typeof annotations === "object" && typeof annotations["workers/message"] === "string" ? annotations["workers/message"] ?? null : null;
3781
3898
  const metadata = parseCloudflareVersionMessage(message);
3899
+ if (metadata?.schema !== 2 && unrecordedTriggerConfig) return {
3900
+ migrationTag: readCloudflareVersionMigrationTag(value),
3901
+ triggerConfig: unrecordedTriggerConfig,
3902
+ versionId
3903
+ };
3782
3904
  if (metadata?.schema !== 2) throw new Error(`platform: Active Worker ${workerName} predates safe trigger snapshots. Refusing to upgrade because its routes, cron, and queue consumers could not be restored after a failed cutover.`);
3783
3905
  const migrationTag = readCloudflareVersionMigrationTag(value);
3784
3906
  return {
@@ -4383,7 +4505,7 @@ async function deployPlatformWorker(config, secrets, options) {
4383
4505
  }
4384
4506
  }
4385
4507
  if (options.workerExisted) {
4386
- const previous = await readActivePlatformWorkerSnapshot(configPath, accountId, workerName, readPlatformWorkerOwnershipMarker(config), readRunner);
4508
+ const previous = await readActivePlatformWorkerSnapshot(configPath, accountId, workerName, readPlatformWorkerOwnershipMarker(config), readRunner, options.replaceOutsideChanges ? previousTriggers : void 0);
4387
4509
  previousVersionId = previous.versionId;
4388
4510
  const deployments = await readPlatformWorkerDeployments(configPath, accountId, workerName, readRunner);
4389
4511
  if (!deploymentRunsOnlyVersion(deployments[0], previousVersionId)) throw new Error(`platform: Worker ${workerName} changed concurrently while its deployment lineage was inspected.`);
@@ -4559,6 +4681,37 @@ async function deployPlatformWorker(config, secrets, options) {
4559
4681
  });
4560
4682
  }
4561
4683
  }
4684
+ /**
4685
+ * Upload a version of a platform Worker that was changed outside Void, and do
4686
+ * not deploy it. The Cloudflare CLI uses this terminal: it shows what the
4687
+ * upload replaces and asks the operator. After the operator agrees, later
4688
+ * uploads of this Worker work without a terminal again.
4689
+ */
4690
+ async function uploadPlatformWorkerForReview(config, options) {
4691
+ const directory = mkdtempSync(join(tmpdir(), "void-platform-review-"));
4692
+ const workerName = String(config.name);
4693
+ const accountId = String(config.account_id);
4694
+ const readRunner = platformWorkerApiReadRunner(accountId, workerName, options.readCloudflare, options.runner);
4695
+ try {
4696
+ const { wranglerConfig } = isolatePlatformWorkerCustomDomains(config);
4697
+ const configPath = join(directory, "wrangler.json");
4698
+ const writeConfig = (value) => writeFileSync(configPath, `${JSON.stringify(value, null, 2)}\n`, { mode: 384 });
4699
+ writeConfig(withoutPlatformWorkerTrafficAttachments(wranglerConfig));
4700
+ const active = await readActivePlatformWorkerSnapshot(configPath, accountId, workerName, readPlatformWorkerOwnershipMarker(config), readRunner, readTriggerConfigFromObject(wranglerConfig));
4701
+ writeConfig(withoutCompletedPlatformWorkerMigrations(withoutPlatformWorkerTrafficAttachments(wranglerConfig), active.migrationTag));
4702
+ return await options.runner({
4703
+ type: "versions.upload",
4704
+ configPath,
4705
+ message: "Void: replace changes made outside Void",
4706
+ interactive: true
4707
+ }, accountId, directory, true);
4708
+ } finally {
4709
+ rmSync(directory, {
4710
+ force: true,
4711
+ recursive: true
4712
+ });
4713
+ }
4714
+ }
4562
4715
  async function recoverFailedPlatformWorkerDeployment(input) {
4563
4716
  const failures = [];
4564
4717
  const attempt = async (label, operation) => {
@@ -4799,6 +4952,7 @@ async function uploadInstallationWorkers(input) {
4799
4952
  preservedRoutes,
4800
4953
  previousConfig: previousWorkerConfig,
4801
4954
  previousPublicEndpoints,
4955
+ ...dependencies.replaceOutsideChanges?.includes(action.name) ? { replaceOutsideChanges: true } : {},
4802
4956
  runner: parallelWorkerUploads ? runParallelPinnedPlatformWrangler : runPinnedPlatformWrangler,
4803
4957
  workerExisted: action.action !== "create"
4804
4958
  });
@@ -4942,6 +5096,12 @@ async function verifyPlatformDeploymentExecutionDrain(apiUrl, healthProbeToken,
4942
5096
  if (status?.protocolVersion !== 1 || status.installationId !== installationId || typeof status.admissionClosed !== "boolean" || !Number.isSafeInteger(status.pendingDeployments) || Number(status.pendingDeployments) < 0) throw new Error("platform: Deployment execution drain probe returned an invalid document.");
4943
5097
  if (!status.admissionClosed || status.pendingDeployments !== 0) throw new Error("platform: Durable deployment operations are still admitted or unfinished. Keep the current runtime and retry this command after they finish.");
4944
5098
  }
5099
+ const sharedEmailStepPermissions = /* @__PURE__ */ new Map([
5100
+ ["routing_enable", "Zone → Zone Settings → Edit"],
5101
+ ["subaddressing_ensure", "Zone → Zone Settings → Edit"],
5102
+ ["inbound_probe", "Zone → Zone Settings → Edit"],
5103
+ ["sending_onboard", "Account → Email Sending → Edit"]
5104
+ ]);
4945
5105
  async function bootstrapPlatformSharedEmail(apiUrl, healthProbeToken, fetcher = fetch) {
4946
5106
  const deadline = Date.now() + 3e5;
4947
5107
  let operationId = null;
@@ -5024,6 +5184,9 @@ async function bootstrapPlatformSharedEmail(apiUrl, healthProbeToken, fetcher =
5024
5184
  if (typeof status?.failureDetail === "string" && safeDetails.includes(status.failureDetail)) {
5025
5185
  details.push(`${status.failureDetail}.`);
5026
5186
  if (currentStep === "inbound_probe" && status.failureDetail === mxDetail) details.push(`Enable Email Routing for ${domain} in the Cloudflare dashboard, then resume this installation.`);
5187
+ } else if (failureCode === "blocked" && currentStep && sharedEmailStepPermissions.has(currentStep)) {
5188
+ const permission = sharedEmailStepPermissions.get(currentStep);
5189
+ details.push(`This step needs ${permission} on the runtime API token. If the token does not have it, edit the token in the Cloudflare dashboard and add it. The token value stays the same. Or set VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN to a token that has it. Then resume this installation.`);
5027
5190
  }
5028
5191
  const detail = details.length ? ` ${details.join(" ")}` : "";
5029
5192
  throw new Error(`platform: Shared email bootstrap did not reach inbound readiness at ${apiUrl} (HTTP ${response.status}).${detail} Traffic remains disabled.`);
@@ -5287,7 +5450,7 @@ async function verifyInstalledPlatformAccessProtection(input) {
5287
5450
  }
5288
5451
  const existingWorkers = input.plan.actions.filter((action) => action.kind === "worker" && action.action === "update").map((action) => action.name);
5289
5452
  if (existingWorkers.length) {
5290
- const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-BXwZiJSF.mjs");
5453
+ const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-CyLcD6ot.mjs");
5291
5454
  await verifyProtectionWorkerOrigins({
5292
5455
  request: input.client.request.bind(input.client),
5293
5456
  listWorkerDomains: input.client.listWorkerDomains.bind(input.client),
@@ -6447,6 +6610,7 @@ async function installPlatform(plan, secrets, existing, dependencies) {
6447
6610
  const runtime = resolvedRuntime.manifest;
6448
6611
  if (plan.deployment.appAccess && runtime.appAccessSetup !== 1) throw new Error("platform: This runtime does not support the installation’s app access setup.");
6449
6612
  const hasEmailGatewayArtifact = runtime.artifacts.emailGateway !== void 0;
6613
+ if (existing?.steps.some((step) => step.key === "private-previews-initialized:v1") && runtime.privatePreviews !== 1) throw new Error("platform: This installation has private previews. Use a runtime with private preview support.");
6450
6614
  if (runtime.emailProtocolVersion !== 1 && plan.deployment.capabilities.email) throw new Error("platform: This runtime cannot serve enabled platform email without email protocol version 1.");
6451
6615
  if (runtime.emailProtocolVersion !== 1 && existing?.resources.some((resource) => resource.key === "email-gateway-worker" && resource.state === "ready")) throw new Error("platform: This runtime cannot replace an installed email gateway Worker. Use a runtime with email protocol version 1.");
6452
6616
  const workerKeys = hasEmailGatewayArtifact ? [
@@ -6657,22 +6821,7 @@ async function installPlatform(plan, secrets, existing, dependencies) {
6657
6821
  const createsWorker = state.plan.actions.some((action) => action.kind === "worker" && action.action === "create" && (hasEmailGatewayArtifact || action.key !== "email-gateway-worker"));
6658
6822
  const recoveringCreatedWorker = interruptedCutover !== null && [...interruptedCutover.staged.values()].some((snapshot) => snapshot.previousVersionId === null);
6659
6823
  const requiresSandboxDrain = !preserveDisabled && targetSandboxDrainProtocol >= 1 && sandboxDrainState === "pending";
6660
- const requiresTrafficGuard = !previousPublicEndpoints || recoveringUnsafeTraffic || createsWorker || recoveringCreatedWorker || state.manifest.usageProtocolVersion !== targetUsageProtocolVersion || authenticationProtocolTransition || shouldBootstrapSharedEmail || requiresSandboxDrain || !!state.plan.deployment.appAccess && !state.manifest.steps.some((step) => step.key === "app-access-initialized:v1");
6661
- if (requiresTrafficGuard) {
6662
- await dependencies.client.putKvValue(state.plan.account.id, requireId(ids, "routing-kv"), PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE);
6663
- workerTrafficGuarded = true;
6664
- dependencies.onProgress?.("Application traffic paused for a safe platform cutover");
6665
- }
6666
- if (!preserveDisabled) {
6667
- const trafficGeneration = nextTrafficGeneration(state.manifest);
6668
- state.manifest = recordInstallationStep(state.manifest, {
6669
- completedAt: now(),
6670
- key: `traffic-enabled:${trafficGeneration}`,
6671
- resultHash: String(trafficGeneration)
6672
- }, now());
6673
- writeInstallationManifest(state.manifest);
6674
- await writeRemoteInstallationCheckpoint(dependencies.client, state.plan, state.manifest);
6675
- }
6824
+ const requiresTrafficGuard = !previousPublicEndpoints || recoveringUnsafeTraffic || createsWorker || recoveringCreatedWorker || state.manifest.usageProtocolVersion !== targetUsageProtocolVersion || runtime.privatePreviews === 1 && !state.manifest.steps.some((step) => step.key === "private-previews-initialized:v1") || authenticationProtocolTransition || shouldBootstrapSharedEmail || requiresSandboxDrain || !!state.plan.deployment.appAccess && !state.manifest.steps.some((step) => step.key === "app-access-initialized:v1");
6676
6825
  const configInput = {
6677
6826
  authenticationDatabaseUncached: true,
6678
6827
  proxyHealthBinding: true,
@@ -6696,23 +6845,43 @@ async function installPlatform(plan, secrets, existing, dependencies) {
6696
6845
  runtimeEntrypoints: entrypoints,
6697
6846
  ...runtime.assets ? { runtimeApiAssetsDirectory: join(runtimeDirectory, PLATFORM_ADMIN_ASSETS_DIRECTORY) } : {}
6698
6847
  };
6699
- const workerDeploymentSecrets = {
6700
- ...state.secrets,
6701
- workerSecretUpdates: state.workerSecretUpdateIntent?.updates ?? {}
6702
- };
6703
- const requiresStagedCommit = !preserveDisabled && requiresTrafficGuard;
6704
6848
  const enabledConfigs = createPlatformWorkerConfigs({
6705
6849
  ...configInput,
6850
+ privatePreviews: runtime.privatePreviews === 1,
6706
6851
  publicEndpoints: !preserveDisabled,
6707
6852
  trafficState: preserveDisabled ? "staging" : "enabled"
6708
6853
  });
6854
+ const outsideChangeConfigs = workerKeys.map((key) => enabledConfigs[key]).filter((config) => dependencies.replaceOutsideChanges?.includes(String(config.name)));
6855
+ if (outsideChangeConfigs.length > 0) await dependencies.uploadOutsideChanges?.(outsideChangeConfigs);
6856
+ if (requiresTrafficGuard) {
6857
+ await dependencies.client.putKvValue(state.plan.account.id, requireId(ids, "routing-kv"), PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE);
6858
+ workerTrafficGuarded = true;
6859
+ dependencies.onProgress?.("Application traffic paused for a safe platform cutover");
6860
+ }
6861
+ if (!preserveDisabled) {
6862
+ const trafficGeneration = nextTrafficGeneration(state.manifest);
6863
+ state.manifest = recordInstallationStep(state.manifest, {
6864
+ completedAt: now(),
6865
+ key: `traffic-enabled:${trafficGeneration}`,
6866
+ resultHash: String(trafficGeneration)
6867
+ }, now());
6868
+ writeInstallationManifest(state.manifest);
6869
+ await writeRemoteInstallationCheckpoint(dependencies.client, state.plan, state.manifest);
6870
+ }
6871
+ const workerDeploymentSecrets = {
6872
+ ...state.secrets,
6873
+ workerSecretUpdates: state.workerSecretUpdateIntent?.updates ?? {}
6874
+ };
6875
+ const requiresStagedCommit = !preserveDisabled && requiresTrafficGuard;
6709
6876
  const configs = requiresStagedCommit ? createPlatformWorkerConfigs({
6710
6877
  ...configInput,
6878
+ privatePreviews: runtime.privatePreviews === 1,
6711
6879
  publicEndpoints: true,
6712
6880
  trafficState: requiresSandboxDrain ? "sandbox-drain" : "staging"
6713
6881
  }) : enabledConfigs;
6714
6882
  const previousConfigs = createPlatformWorkerConfigs({
6715
6883
  ...configInput,
6884
+ privatePreviews: existing?.steps.some((step) => step.key === "private-previews-initialized:v1"),
6716
6885
  publicEndpoints: previousPublicEndpoints,
6717
6886
  trafficState: previousPublicEndpoints ? "enabled" : "staging"
6718
6887
  });
@@ -6943,6 +7112,11 @@ async function installPlatform(plan, secrets, existing, dependencies) {
6943
7112
  runtime,
6944
7113
  runtimeProvenance
6945
7114
  })).emailOperationId;
7115
+ if (runtime.privatePreviews === 1) state.manifest = recordInstallationStep(state.manifest, {
7116
+ key: "private-previews-initialized:v1",
7117
+ completedAt: now(),
7118
+ resultHash: hash("private-previews:v1")
7119
+ }, now());
6946
7120
  await checkpointOperation("complete");
6947
7121
  writeInstallationManifest(state.manifest);
6948
7122
  await writeRemoteInstallationCheckpoint(dependencies.client, state.plan, state.manifest);
@@ -7304,6 +7478,171 @@ async function replacePendingInstallationAuthentication(input) {
7304
7478
  };
7305
7479
  }
7306
7480
  //#endregion
7481
+ //#region src/cli/platform-installer-outside-changes.ts
7482
+ const OUTSIDE_SOURCES = {
7483
+ dash: "changed in the Cloudflare dashboard",
7484
+ api: "changed in the Cloudflare API",
7485
+ unrecorded: "has an active version without a Void deployment record"
7486
+ };
7487
+ const PLATFORM_WORKER_KEYS = [
7488
+ "api",
7489
+ "proxy",
7490
+ "emailGateway",
7491
+ "tail",
7492
+ "dispatch"
7493
+ ];
7494
+ const NO_WORKER_CHANGED = "No platform Worker changed. This command did not pause application traffic.";
7495
+ /** The wait before the second and the third read of a Worker. */
7496
+ const READ_RETRY_DELAYS_MS = [250, 500];
7497
+ /** Stop before the run changes a Worker, because Void cannot tell what the run replaces. */
7498
+ function unreadablePlatformWorker(workerName, error) {
7499
+ const status = error instanceof PlatformCloudflareApiError ? error.status : null;
7500
+ const answer = status === null ? `no HTTP response: ${error instanceof Error ? error.message : String(error)}` : `HTTP ${status}`;
7501
+ return new Error([
7502
+ `platform: Void cannot read the platform Worker ${workerName} (${answer}), so it cannot find changes made outside Void.`,
7503
+ NO_WORKER_CHANGED,
7504
+ status === 401 || status === 403 ? "Make sure that the Cloudflare API token has Account → Workers Scripts → Edit for this account. Then run the command again." : "Run the command again."
7505
+ ].join(" "), { cause: error });
7506
+ }
7507
+ /**
7508
+ * Read a Worker again after a rate limit, a Cloudflare server error or a
7509
+ * network failure. Each other failure, or a third failure, stops the run.
7510
+ */
7511
+ async function readPlatformWorker(workerName, read) {
7512
+ for (let attempt = 0;; attempt++) try {
7513
+ return await read();
7514
+ } catch (error) {
7515
+ const status = error instanceof PlatformCloudflareApiError ? error.status : null;
7516
+ const wait = READ_RETRY_DELAYS_MS[attempt];
7517
+ if (wait === void 0 || status !== null && status !== 429 && status < 500) throw unreadablePlatformWorker(workerName, error);
7518
+ await setTimeout$1(wait);
7519
+ }
7520
+ }
7521
+ /** The Cloudflare CLI asks only about these changes. The others need no upload for review. */
7522
+ function needsReviewUpload(change) {
7523
+ return change.source !== "unrecorded";
7524
+ }
7525
+ /**
7526
+ * The earlier version of each Worker that the installer makes active again
7527
+ * before it deploys. A run that stopped during a Worker cutover left Void's
7528
+ * version active, and the next run first restores the earlier one. Like the
7529
+ * installer, keep Void's version while the platform changes to configurable
7530
+ * sign-in and already requires sign-in. Every Worker that this check reads
7531
+ * exists, so the installation had Workers before.
7532
+ */
7533
+ async function restoredPlatformWorkerVersions(installation, runtime) {
7534
+ const cutover = interruptedWorkerCutover(installation.manifest);
7535
+ if (!cutover || installation.manifest.deployment.authentication.configurable !== true && runtime.manifest.authenticationProtocolVersion === 1 && (await installation.readAuthenticationState?.())?.sessionsRequired === true) return /* @__PURE__ */ new Map();
7536
+ return new Map([...cutover.staged.values()].flatMap((snapshot) => snapshot.previousVersionId === null ? [] : [[snapshot.workerName, snapshot.previousVersionId]]));
7537
+ }
7538
+ /** Find the existing platform Workers that a run uploads and that were changed outside Void. */
7539
+ async function findPlatformWorkerOutsideChanges(client, plan, runtime, installation) {
7540
+ const workers = PLATFORM_WORKER_KEYS.flatMap((key) => {
7541
+ if (key === "emailGateway" && runtime.manifest.artifacts.emailGateway === void 0) return [];
7542
+ const action = plan.actions.find((entry) => entry.key === platformWorkerResourceKey(key));
7543
+ return action?.kind === "worker" && action.action !== "create" ? [{
7544
+ key,
7545
+ name: action.name
7546
+ }] : [];
7547
+ });
7548
+ const restored = workers.length > 0 ? await restoredPlatformWorkerVersions(installation, runtime) : /* @__PURE__ */ new Map();
7549
+ return (await Promise.all(workers.map(async (worker) => {
7550
+ const readCloudflare = (path) => readPlatformWorker(worker.name, () => client.request(path));
7551
+ const source = await readPlatformWorker(worker.name, () => client.getWorkerLastDeployedFrom(plan.account.id, worker.name));
7552
+ const deployments = await readPlatformWorker(worker.name, () => client.request(`/accounts/${encodeURIComponent(plan.account.id)}/workers/scripts/${encodeURIComponent(worker.name)}/deployments`).catch((error) => {
7553
+ if (error instanceof PlatformCloudflareApiError && error.status === 404) return null;
7554
+ throw error;
7555
+ }));
7556
+ if (deployments === null) return source === "dash" || source === "api" ? {
7557
+ ...worker,
7558
+ source
7559
+ } : null;
7560
+ const active = readActivePlatformWorkerDeployment(deployments);
7561
+ if (active.kind === "malformed") throw new Error(`platform: Cloudflare returned malformed deployment data for the platform Worker ${worker.name}, so Void cannot find changes made outside Void. ${NO_WORKER_CHANGED} Run the command again.`);
7562
+ if (active.kind === "split") throw new Error(`platform: The platform Worker ${worker.name} has no single version that gets 100% of traffic, for example after a gradual deployment. This command deploys a new version only when one version gets all traffic. ${NO_WORKER_CHANGED} In the Cloudflare dashboard, deploy one version of ${worker.name} to 100% of traffic. Then run this command once in a terminal, so that you can approve the dashboard change.`);
7563
+ if (source === "dash" || source === "api") return {
7564
+ ...worker,
7565
+ source
7566
+ };
7567
+ const restoredVersion = restored.get(worker.name);
7568
+ return (await Promise.all([active.versionId, ...restoredVersion === void 0 ? [] : [restoredVersion]].map((versionId) => platformWorkerVersionHasTriggerRecord(readCloudflare, plan.account.id, worker.name, versionId)))).includes(false) ? {
7569
+ ...worker,
7570
+ source: "unrecorded"
7571
+ } : null;
7572
+ }))).filter((change) => change !== null);
7573
+ }
7574
+ function listPlatformWorkerOutsideChanges(changes) {
7575
+ return changes.map((change) => `${change.name}: ${OUTSIDE_SOURCES[change.source]}`).join("\n");
7576
+ }
7577
+ /**
7578
+ * The list of Workers after a heading. The heading must be true for each
7579
+ * source: an older Void release can have deployed the active version.
7580
+ */
7581
+ function formatPlatformWorkerOutsideChanges(changes) {
7582
+ return `These platform Workers need your approval before this command replaces their configuration:\n${listPlatformWorkerOutsideChanges(changes)}`;
7583
+ }
7584
+ /**
7585
+ * Do this before a run changes a Worker or pauses traffic. When platform
7586
+ * Workers were changed outside Void, stop, or ask the operator in a terminal.
7587
+ * Returns the Workers whose outside changes the operator agreed to replace.
7588
+ * The installer uploads them later with uploadPlatformWorkerOutsideChanges.
7589
+ */
7590
+ async function reviewPlatformWorkerOutsideChanges(input) {
7591
+ const changes = await findPlatformWorkerOutsideChanges(input.client, input.plan, input.runtime, input.installation);
7592
+ if (changes.length === 0) return [];
7593
+ if (!input.interactive) throw new Error([
7594
+ `platform: ${formatPlatformWorkerOutsideChanges(changes)}`,
7595
+ NO_WORKER_CHANGED,
7596
+ "This command replaces their configuration with the Void configuration. It can ask for your approval only in a terminal.",
7597
+ `Run this command once in a terminal to review them:\n${input.command}`
7598
+ ].join("\n"));
7599
+ note([
7600
+ listPlatformWorkerOutsideChanges(changes),
7601
+ "",
7602
+ "This command replaces the configuration of these Workers with the Void configuration.",
7603
+ "It removes values that Void does not set, for example an EMAIL_FROM that you added.",
7604
+ "It resets values that Void sets, for example AUTH_REDIRECT_URI.",
7605
+ ...changes.some(needsReviewUpload) ? [
7606
+ "First, it prepares the platform resources and the database.",
7607
+ "Then, before it pauses traffic or deploys a Worker, the Cloudflare CLI asks you again for each Worker changed in the Cloudflare dashboard or API. For a dashboard change, it shows the differences.",
7608
+ "It uploads a new version of each of these Workers and does not deploy it."
7609
+ ] : []
7610
+ ].join("\n"), "Approval needed");
7611
+ const answer = await confirm({
7612
+ message: "Replace the configuration of these Workers?",
7613
+ initialValue: false
7614
+ });
7615
+ if (isCancel(answer) || typeof answer === "symbol" || !answer) throw new Error(`platform: Cancelled. ${NO_WORKER_CHANGED}`);
7616
+ return changes;
7617
+ }
7618
+ /**
7619
+ * Upload a new version of each Worker that the operator agreed to replace, and
7620
+ * do not deploy it. The installer gives the configs after it creates the
7621
+ * resources that they use, and before it pauses traffic. The Cloudflare CLI
7622
+ * uses this terminal: it shows what the upload replaces and asks the operator.
7623
+ */
7624
+ async function uploadPlatformWorkerOutsideChanges(configs, input) {
7625
+ const { client } = input;
7626
+ const reviewed = configs.filter((config) => input.changes.some((change) => change.name === config.name && needsReviewUpload(change)));
7627
+ if (reviewed.length === 0) return;
7628
+ const runner = input.runner ?? ((operation, accountId, cwd, capture) => runPlatformWranglerAtApiBase(operation, accountId, cwd, capture, client.apiBaseUrl, false, input.operatorApiToken));
7629
+ input.progress?.pause();
7630
+ try {
7631
+ for (const config of reviewed) {
7632
+ const name = String(config.name);
7633
+ log.step(`Uploading a new version of ${name} without deploying it`);
7634
+ const uploaded = await uploadPlatformWorkerForReview(config, {
7635
+ readCloudflare: (path) => client.request(path),
7636
+ runner
7637
+ });
7638
+ const source = await client.getWorkerLastDeployedFrom(String(config.account_id), name);
7639
+ if (uploaded.status !== 0 || source === "dash" || source === "api") throw new Error(`platform: The Cloudflare CLI did not replace the changes to ${name}. Its output above shows why. No deployment changed. This command did not pause application traffic.`);
7640
+ }
7641
+ } finally {
7642
+ input.progress?.resume();
7643
+ }
7644
+ }
7645
+ //#endregion
7307
7646
  //#region src/cli/platform-saved-plans.ts
7308
7647
  function planId(args) {
7309
7648
  return createHash("sha256").update(JSON.stringify([args.account, args.name])).digest("hex");
@@ -7428,14 +7767,14 @@ function resolvePlatformInstallDatabaseUrl(checkpoint, manifest = null) {
7428
7767
  }
7429
7768
  async function runPlatformLifecycleCommand(commandArgs) {
7430
7769
  if (commandArgs.subcommand === "domain") {
7431
- const { runPlatformDomainCommand } = await import("./platform-domain-CxpvUeo0.mjs");
7770
+ const { runPlatformDomainCommand } = await import("./platform-domain-DDNK2y-4.mjs");
7432
7771
  await runPlatformDomainCommand(commandArgs);
7433
7772
  return;
7434
7773
  }
7435
7774
  if (commandArgs.subcommand === "discover") {
7436
7775
  const client = new PlatformCloudflareClient((await resolvePlatformCloudflareCredential()).token);
7437
7776
  const accountId = await selectAccount(await readAccounts(client), commandArgs.account);
7438
- const { recoverPlatformInstallations } = await import("./platform-recovery-BUGOB4RC.mjs");
7777
+ const { recoverPlatformInstallations } = await import("./platform-recovery-Dmsg7lWA.mjs");
7439
7778
  const recovered = await recoverPlatformInstallations(client, accountId, void 0, commandArgs.selector);
7440
7779
  if (recovered.length === 0) {
7441
7780
  log.info(`No recoverable Void platform installations were found in ${accountId}.`);
@@ -7446,7 +7785,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
7446
7785
  return;
7447
7786
  }
7448
7787
  if (commandArgs.subcommand !== "install") {
7449
- const { runInstalledPlatformCommand } = await import("./platform-management-DvBS83rC.mjs");
7788
+ const { runInstalledPlatformCommand } = await import("./platform-management-DAE6g2QU.mjs");
7450
7789
  await runInstalledPlatformCommand(commandArgs);
7451
7790
  return;
7452
7791
  }
@@ -7622,7 +7961,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
7622
7961
  progress?.stop("Read the saved installation.");
7623
7962
  progress = void 0;
7624
7963
  if (authoritative) {
7625
- const { selectAuthoritativePlatformManifest } = await import("./platform-management-DvBS83rC.mjs");
7964
+ const { selectAuthoritativePlatformManifest } = await import("./platform-management-DAE6g2QU.mjs");
7626
7965
  const selected = selectAuthoritativePlatformManifest(existing, authoritative);
7627
7966
  authoritativeProvisionIntents = true;
7628
7967
  if (!args.plan && JSON.stringify(selected) !== JSON.stringify(existing)) writeInstallationManifest(selected);
@@ -7831,8 +8170,10 @@ async function runPlatformLifecycleCommand(commandArgs) {
7831
8170
  break;
7832
8171
  } catch (error) {
7833
8172
  if (!isPlatformTokenAuthorizationError(error)) throw error;
8173
+ const details = /* @__PURE__ */ new Set();
8174
+ for (let cause = error, depth = 0; depth < 5 && cause instanceof Error; depth++, cause = cause.cause) details.add(cause.message.replaceAll(token, "[redacted]"));
7834
8175
  forgetRejectedManagementToken();
7835
- log.warn("Cloudflare rejected this token. Check its permissions and account/zone scope, then paste a replacement.");
8176
+ log.warn([...details, "Check the token permissions and account/zone scope, then paste a replacement."].join("\n"));
7836
8177
  }
7837
8178
  }
7838
8179
  } else if (managementAccess) await verifyPlatformManagementAccess(client, accountId, managementAccess);
@@ -7878,6 +8219,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
7878
8219
  accountId,
7879
8220
  applicationDomain,
7880
8221
  customDomains: plan.deployment.capabilities.customDomains,
8222
+ ...plan.deployment.capabilities.email && plan.deployment.emailSharedZoneId ? { emailZoneId: plan.deployment.emailSharedZoneId } : {},
7881
8223
  zoneId: plan.zone?.id ?? null
7882
8224
  });
7883
8225
  checkingRuntimePermissions = false;
@@ -7886,7 +8228,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
7886
8228
  plan = await verifyPlatformAiGatewayPlan(client, planInput, existing, plan, authoritativeProvisionIntents);
7887
8229
  }
7888
8230
  } catch (error) {
7889
- if (credentialSetup && token === values.cloudflareApiToken && isPlatformTokenAuthorizationError(error, checkingRuntimePermissions ? void 0 : "/ai-gateway/")) {
8231
+ if (credentialSetup && token === values.cloudflareApiToken && !(error instanceof PlatformRuntimeTokenEmailPermissionError) && isPlatformTokenAuthorizationError(error, checkingRuntimePermissions ? void 0 : "/ai-gateway/")) {
7890
8232
  delete values.cloudflareApiToken;
7891
8233
  writePendingInstallationSecrets(setupManifest, values);
7892
8234
  rejectedSavedRuntimeToken = true;
@@ -7981,6 +8323,14 @@ async function runPlatformLifecycleCommand(commandArgs) {
7981
8323
  title: "About these keys",
7982
8324
  url: "https://void.cloud/guide/platform/installation/credentials#signing-and-encryption-keys"
7983
8325
  }));
8326
+ const outsideChanges = await reviewPlatformWorkerOutsideChanges({
8327
+ client,
8328
+ plan,
8329
+ runtime,
8330
+ installation: { manifest: existing },
8331
+ interactive: process.stdin.isTTY === true && process.stdout.isTTY === true && !args.yes,
8332
+ command: `${cliCommandName()} platform install --resume --name ${existing.id}`
8333
+ });
7984
8334
  progress = startProgress("Installing the platform");
7985
8335
  if (credentialSetup) {
7986
8336
  saveValues({
@@ -7999,6 +8349,15 @@ async function runPlatformLifecycleCommand(commandArgs) {
7999
8349
  },
8000
8350
  client,
8001
8351
  operatorApiToken: managementApiToken || operatorCredential.token,
8352
+ ...outsideChanges.length > 0 ? {
8353
+ replaceOutsideChanges: outsideChanges.map((change) => change.name),
8354
+ uploadOutsideChanges: (configs) => uploadPlatformWorkerOutsideChanges(configs, {
8355
+ changes: outsideChanges,
8356
+ client,
8357
+ operatorApiToken: managementApiToken || operatorCredential.token,
8358
+ progress
8359
+ })
8360
+ } : {},
8002
8361
  runtime,
8003
8362
  healthCheckResumeCommand: `${cliCommandName()} platform install --resume --name ${existing.id}`,
8004
8363
  onProgress: (message) => progress?.message(message),
@@ -8040,7 +8399,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
8040
8399
  })).actions.filter((action) => action.kind === "worker"),
8041
8400
  revalidateBeforeWorkerDeploy: (manifest, action) => revalidatePlatformInstallAction(client, plan, manifest, action),
8042
8401
  verifyExistingOwnership: async (manifest, databaseCheckpointExists) => {
8043
- const { verifyPlatformInstallationOwnership } = await import("./platform-management-DvBS83rC.mjs");
8402
+ const { verifyPlatformInstallationOwnership } = await import("./platform-management-DAE6g2QU.mjs");
8044
8403
  const retainedReplacementKeys = new Set(plan.actions.filter((action) => {
8045
8404
  const previous = manifest.resources.find((resource) => resource.key === action.key);
8046
8405
  return action.action === "create" && previous && previous.name !== action.name;
@@ -8197,4 +8556,4 @@ async function promptSecret(message, masked = true, validate, placeholder) {
8197
8556
  return value;
8198
8557
  }
8199
8558
  //#endregion
8200
- export { matchesRecordedR2Fingerprint as A, activatePlatformAccessCredentials as B, platformTrafficAttachmentWorker as C, formatPlatformInstallPlan as D, dnsRecordConfigHash as E, platformDatabaseNameFromOwnerUrl as F, PlatformCloudflareClient as G, parsePlatformAccessSetupSpec as H, turnOffInstalledProjectZeroTrust as I, hyperdriveOriginMatches as J, hyperdriveOriginConfigHash as K, assertPlatformOperatorCredentialCanApplyPlan as L, r2BucketConfigHash as M, resourceMarkerProblem as N, hasProvisionIntentStep as O, revalidatePlatformInstallAction as P, resolvePlatformCloudflareCredential as R, recordResource as S, createPlatformInstallPlan as T, preparePlatformAccessSetup as U, checkpointPlatformAccessResources as V, PlatformCloudflareApiError as W, verifyPlatformRuntimeTokenPermissions as Y, readPlatformDatabase as _, authenticationSetupRequestHash as a, createPlatformInstallationSecrets as b, REMOTE_INSTALLATION_MANIFEST_KEY as c, acquirePlatformDatabaseLifecycleLockConnection as d, platformDatabaseClientUrl as f, formatZeroTrustApplications as g, assertProjectZeroTrustAllowsUninstall as h, verifyPlatformAiGatewayPlan as i, platformAdoptionIntentHash as j, legacyResourceConfigHash as k, installPlatform as l, readPlatformProjectZeroTrustState as m, resolvePlatformInstallDatabaseUrl as n, readLoginReplacementFile as o, readPlatformProjectSlugs as p, hyperdriveOriginFromConnectionString as q, runPlatformLifecycleCommand as r, replacePendingInstallationAuthentication as s, assertNoninteractivePlatformMutationAcknowledged as t, acquirePlatformDatabaseLifecycleLock as u, loadPlatformRuntime as v, recordPlatformWorkerTraffic as w, resolveBootstrapGitHubId as x, createPlatformHealthProbeToken as y, verifyPlatformCloudflareCredential as z };
8559
+ export { hyperdriveOriginMatches as $, dnsRecordConfigHash as A, turnOffInstalledProjectZeroTrust as B, createPlatformHealthProbeToken as C, platformTrafficAttachmentWorker as D, recordResource as E, platformAdoptionIntentHash as F, checkpointPlatformAccessResources as G, resolvePlatformCloudflareCredential as H, r2BucketConfigHash as I, PlatformCloudflareApiError as J, parsePlatformAccessSetupSpec as K, resourceMarkerProblem as L, hasProvisionIntentStep as M, legacyResourceConfigHash as N, recordPlatformWorkerTraffic as O, matchesRecordedR2Fingerprint as P, hyperdriveOriginFromConnectionString as Q, revalidatePlatformInstallAction as R, loadPlatformRuntime as S, resolveBootstrapGitHubId as T, verifyPlatformCloudflareCredential as U, assertPlatformOperatorCredentialCanApplyPlan as V, activatePlatformAccessCredentials as W, PlatformRuntimeTokenEmailPermissionError as X, PlatformCloudflareClient as Y, hyperdriveOriginConfigHash as Z, readPlatformProjectSlugs as _, findPlatformWorkerOutsideChanges as a, formatZeroTrustApplications as b, uploadPlatformWorkerOutsideChanges as c, replacePendingInstallationAuthentication as d, verifyPlatformRuntimeTokenEmailPermissions as et, REMOTE_INSTALLATION_MANIFEST_KEY as f, platformDatabaseClientUrl as g, acquirePlatformDatabaseLifecycleLockConnection as h, verifyPlatformAiGatewayPlan as i, formatPlatformInstallPlan as j, createPlatformInstallPlan as k, authenticationSetupRequestHash as l, acquirePlatformDatabaseLifecycleLock as m, resolvePlatformInstallDatabaseUrl as n, formatPlatformWorkerOutsideChanges as o, installPlatform as p, preparePlatformAccessSetup as q, runPlatformLifecycleCommand as r, reviewPlatformWorkerOutsideChanges as s, assertNoninteractivePlatformMutationAcknowledged as t, verifyPlatformRuntimeTokenPermissions as tt, readLoginReplacementFile as u, readPlatformProjectZeroTrustState as v, createPlatformInstallationSecrets as w, readPlatformDatabase as x, assertProjectZeroTrustAllowsUninstall as y, platformDatabaseNameFromOwnerUrl as z };