void 0.21.8 → 0.22.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 (132) hide show
  1. package/dist/{account-cmd-CQ2wi4Th.mjs → account-cmd-CjyxcGkM.mjs} +4 -4
  2. package/dist/{auth-link-B_lceSHK.mjs → auth-link-BLO4ptzo.mjs} +4 -4
  3. package/dist/{auth-router-cZq0HuWe.mjs → auth-router-ZUg9MF_U.mjs} +5 -5
  4. package/dist/{build-cmd-Dpt0jd-x.mjs → build-cmd-BxR5FROK.mjs} +3 -3
  5. package/dist/{cache-7_UeZdTk.mjs → cache-D0sWhgKI.mjs} +3 -3
  6. package/dist/{cancel-deploy-D23R1RXT.mjs → cancel-deploy-D4NUqFbi.mjs} +3 -3
  7. package/dist/{cf-build-output-CGT03qCD.mjs → cf-build-output-BJ6yGEIS.mjs} +139 -62
  8. package/dist/cli/cf-compat.mjs +164 -42
  9. package/dist/cli/cli.mjs +73 -44
  10. package/dist/cli/env-schema-probe.d.mts +1 -1
  11. package/dist/{client-QTl6ko_D.mjs → client-BTZ3XkrB.mjs} +25 -0
  12. package/dist/client-Czz8o5jP.mjs +2 -0
  13. package/dist/{cloudflare-auth-C4_GPZr0.mjs → cloudflare-auth-DQkqoMYa.mjs} +1 -6
  14. package/dist/{cloudflare-cmd-bSmZ1d5L.mjs → cloudflare-cmd-BKlfGHAy.mjs} +6 -7
  15. package/dist/{cloudflare-connect-jAwacxxP.mjs → cloudflare-connect-Ctmrw579.mjs} +3 -3
  16. package/dist/{cloudflare-operations-sMZXpk_S.mjs → cloudflare-operations-B9tzgjmf.mjs} +10 -39
  17. package/dist/{cloudflare-operations-BipGMJ5O.mjs → cloudflare-operations-BT6OWFBk.mjs} +1 -1
  18. package/dist/{config-CafTW6Cz.mjs → config-Br_JZD6u.mjs} +2 -7
  19. package/dist/{config-s7Xj7tPb.mjs → config-CyQ-wVd7.mjs} +1 -1
  20. package/dist/{config-CF69HgXc.d.mts → config-VavjpDnp.d.mts} +1 -2
  21. package/dist/config-entry.d.mts +1 -1
  22. package/dist/{config-write-BSduPMY8.mjs → config-write-B1f88wJA.mjs} +1 -1
  23. package/dist/{connect-BY38i-9E.mjs → connect-Dg-WkW-C.mjs} +5 -5
  24. package/dist/{create-project-BniEV0OW.mjs → create-project-DdoqwFLF.mjs} +1 -1
  25. package/dist/{create-project-DBfFSZKY.mjs → create-project-l9J7pbtm.mjs} +8 -4
  26. package/dist/{db-BIo37Y7H.mjs → db-gp2sCXyN.mjs} +14 -14
  27. package/dist/{delete-D6dZ9B6B.mjs → delete-TTedbH6B.mjs} +3 -3
  28. package/dist/{deploy-BM_LoBXC.mjs → deploy-B19L2Bra.mjs} +1 -1
  29. package/dist/{deploy-C0JaQSWS.mjs → deploy-CH-o2CaZ.mjs} +47 -36
  30. package/dist/{dist-BR1quN_w.mjs → dist-AoCzRTJE.mjs} +226 -60
  31. package/dist/{dist-C5fND3R0.mjs → dist-BuDuKZJv.mjs} +1 -1
  32. package/dist/{dist-Dn6nn2IU.mjs → dist-CTBk70IR.mjs} +42 -42
  33. package/dist/{domain-Dmhvb2oU.mjs → domain-JRF59P_r.mjs} +4 -4
  34. package/dist/{email-dMnE_Lat.mjs → email-Bo6G9LOZ.mjs} +6 -6
  35. package/dist/{env-Csi-tMbT.mjs → env-BYOrWQnv.mjs} +4 -4
  36. package/dist/{env-public-D_6u46fX.d.mts → env-public-BxU_0yTL.d.mts} +2 -1
  37. package/dist/gen-CNJ62MM7.mjs +2 -0
  38. package/dist/{gen-Dz3X1Qab.mjs → gen-sCtlCOdA.mjs} +3 -3
  39. package/dist/{github-cmd-BED3_9JD.mjs → github-cmd-0-7PexDq.mjs} +5 -7
  40. package/dist/{handler-BXJTXd02.d.mts → handler-HEcZsaij.d.mts} +2 -1
  41. package/dist/{headers-BOg_velo.mjs → headers-DWi2IXWx.mjs} +1 -1
  42. package/dist/help-CmZzxUba.mjs +2 -0
  43. package/dist/{help-DC7gdz7L.mjs → help-GKtwl07I.mjs} +124 -4
  44. package/dist/index.d.mts +1 -1
  45. package/dist/index.mjs +53 -24
  46. package/dist/{init-CJSnEcuj.mjs → init-FZx3Elvz.mjs} +13 -13
  47. package/dist/{link-CsHOinF7.mjs → link-BrQfb_CU.mjs} +4 -4
  48. package/dist/{list-CDb-4bZ1.mjs → list-D44jmIAM.mjs} +4 -4
  49. package/dist/{live-CKiJilLr.d.mts → live-CKJlvlNp.d.mts} +1 -1
  50. package/dist/{local-d1-CC8sKFGu.mjs → local-d1-Bg9OzEEO.mjs} +1 -1
  51. package/dist/{login-DZldyb8c.mjs → login-CAsAsQ-_.mjs} +4 -4
  52. package/dist/login-CGcRKEoi.mjs +2 -0
  53. package/dist/{logs-BdfiOezj.mjs → logs-BjKvFnVM.mjs} +4 -4
  54. package/dist/{migrate-B8KuoYsO.mjs → migrate-BPITvDJN.mjs} +4 -4
  55. package/dist/migrate-CYfbKkXh.mjs +2 -0
  56. package/dist/{node-BM43oz4G.mjs → node-Dt7z256D.mjs} +1 -1
  57. package/dist/{operator-cmd-B9dbG3Od.mjs → operator-cmd-BK5CCiT9.mjs} +4 -4
  58. package/dist/output-Dm_A4Tbv.mjs +81 -0
  59. package/dist/pages/client.d.mts +1 -1
  60. package/dist/pages/index.d.mts +1 -1
  61. package/dist/pages/index.mjs +2 -2
  62. package/dist/pages/islands-plugin.d.mts +16 -6
  63. package/dist/pages/islands-plugin.mjs +1 -1
  64. package/dist/pages/protocol.d.mts +2 -2
  65. package/dist/{output-CCH48AMM.mjs → picocolors-BTps1_gs.mjs} +2 -76
  66. package/dist/{platform-auth-config-Bex45lQt.mjs → platform-auth-config-BlN8xTdD.mjs} +3 -3
  67. package/dist/{platform-auth-protection-Dma02l6-.mjs → platform-auth-protection-7d5aV2Jg.mjs} +3 -3
  68. package/dist/{platform-auth-recovery-COOhMCvx.mjs → platform-auth-recovery-Dxij8ZbR.mjs} +3 -3
  69. package/dist/{platform-cmd-BtxZrT6w.mjs → platform-cmd-B3hwKrFK.mjs} +5 -5
  70. package/dist/{platform-cmd-CjNB09OF.mjs → platform-cmd-E0FuL212.mjs} +1 -1
  71. package/dist/{platform-domain-DppaTARe.mjs → platform-domain-D6Xcy9ZX.mjs} +36 -9
  72. package/dist/{platform-lifecycle-CYll-oKE.mjs → platform-lifecycle-DMh_qrry.mjs} +1 -1
  73. package/dist/{platform-lifecycle-BpDlxT3t.mjs → platform-lifecycle-k0E0xoxx.mjs} +769 -59
  74. package/dist/{platform-management-BKYenDlE.mjs → platform-management-Brz_BDiT.mjs} +72 -10
  75. package/dist/{platform-management-BS5r6Ao8.mjs → platform-management-DOtss0BN.mjs} +1 -1
  76. package/dist/{platform-recovery-dJ5Me-I0.mjs → platform-recovery-BvtcXON5.mjs} +2 -2
  77. package/dist/prepare-Bm3iq-u4.mjs +2 -0
  78. package/dist/{prepare-DyZ-Yok5.mjs → prepare-C-6YZyyg.mjs} +3 -3
  79. package/dist/{prepare-C3kt3Rst.mjs → prepare-CRhJbVrG.mjs} +1 -1
  80. package/dist/{project-cmd-B44I8J_W.mjs → project-cmd-BZLCqOqw.mjs} +29 -15
  81. package/dist/{project-team-BkbYIsXN.mjs → project-team-BvgM0WoX.mjs} +3 -3
  82. package/dist/{project-token-C8xEEQnB.mjs → project-token-l5DqK6Az.mjs} +3 -3
  83. package/dist/project-zero-trust-v6Mvpp8y.mjs +63 -0
  84. package/dist/{protocol-ZH3jP4a7.d.mts → protocol-BBa6cstI.d.mts} +1 -1
  85. package/dist/{provision-BhreDAOS.mjs → provision-C4IGqkBf.mjs} +24 -19
  86. package/dist/{provision-DNtrtaVD.mjs → provision-Fr9pRqce.mjs} +1 -1
  87. package/dist/{requests-DFyhBMaf.mjs → requests-DN-BbNiM.mjs} +3 -3
  88. package/dist/{rollback-DHHxXZiS.mjs → rollback-D7rzSaZM.mjs} +4 -4
  89. package/dist/runtime/env-public.d.mts +1 -1
  90. package/dist/runtime/handler.d.mts +1 -1
  91. package/dist/runtime/live-client.d.mts +1 -1
  92. package/dist/runtime/live.d.mts +1 -1
  93. package/dist/runtime/sandbox-container.d.mts +3 -0
  94. package/dist/runtime/sandbox-container.mjs +2 -0
  95. package/dist/runtime/sandbox.d.mts +4 -32
  96. package/dist/runtime/sandbox.mjs +118 -72
  97. package/dist/runtime/validator.d.mts +1 -1
  98. package/dist/runtime/ws-server.d.mts +1 -1
  99. package/dist/runtime/ws.d.mts +1 -1
  100. package/dist/sandbox-container-4fdqLnyb.mjs +279 -0
  101. package/dist/sandbox-container-DdNEBfCc.d.mts +72 -0
  102. package/dist/sandbox-qpNBT8a3.d.mts +49 -0
  103. package/dist/{secret-DN9sSNiV.mjs → secret-BOtOl_cb.mjs} +4 -4
  104. package/dist/{skills-O6FUaizK.mjs → skills-D1II1Juz.mjs} +1 -1
  105. package/dist/{subcommand-prompt-BuGYkAkC.mjs → subcommand-prompt-CY1C4fvl.mjs} +2 -2
  106. package/dist/{wrangler-BymcxrRa.mjs → wrangler-DQF1vKyf.mjs} +37 -27
  107. package/dist/{ws-BwcqizuH.d.mts → ws-BoY7vQML.d.mts} +1 -1
  108. package/package.json +40 -32
  109. package/sandbox.Dockerfile +4 -0
  110. package/schema.json +10 -22
  111. package/skills/void/SKILL.md +2 -0
  112. package/skills/void/docs/guide/deployment.md +1 -1
  113. package/skills/void/docs/guide/edge/revalidation.md +1 -1
  114. package/skills/void/docs/guide/edge/static-assets.md +1 -0
  115. package/skills/void/docs/guide/platform/administration/zero-trust.md +318 -0
  116. package/skills/void/docs/guide/platform/development/local.md +2 -2
  117. package/skills/void/docs/guide/platform/installation/domains.md +1 -1
  118. package/skills/void/docs/guide/platform/installation/first-deployment.md +4 -0
  119. package/skills/void/docs/guide/platform/installation/prerequisites.md +1 -1
  120. package/skills/void/docs/guide/platform/installation/uninstall.md +17 -2
  121. package/skills/void/docs/guide/platform-administration.md +1 -0
  122. package/skills/void/docs/guide/sandboxes.md +70 -41
  123. package/skills/void/docs/integrations/cloudflare.md +1 -1
  124. package/skills/void/docs/reference/api.md +35 -35
  125. package/skills/void/docs/reference/cli.md +68 -6
  126. package/skills/void/docs/reference/config.md +16 -16
  127. package/dist/client-4cDVv7BO.mjs +0 -2
  128. package/dist/gen-Vnv2f65C.mjs +0 -2
  129. package/dist/help-DQMfeKMz.mjs +0 -2
  130. package/dist/login-t6rndSRW.mjs +0 -2
  131. package/dist/migrate-TsHGBnDA.mjs +0 -2
  132. package/dist/prepare-BZXkjdNe.mjs +0 -2
@@ -1,7 +1,7 @@
1
- import { i as createSpinner } from "./output-CCH48AMM.mjs";
2
1
  import { a as listInstallationManifests, d as readInstallationRecoverySecrets, h as resolveInstallationManifest, m as removePlatformConnectionForInstallation, p as removeInstallationRecoverySecrets, t as acquirePlatformLifecycleLock, v as writeInstallationManifest } from "./platform-registry-QBa4DK32.mjs";
3
- import { E as confirm, I as select, N as note, P as outro, W as isCancel, j as log } from "./dist-Dn6nn2IU.mjs";
4
- import { A as hyperdriveOriginFromConnectionString, C as assertPlatformOperatorCredentialCanApplyPlan, M as verifyPlatformRuntimeTokenPermissions, O as PlatformCloudflareClient, S as platformDatabaseNameFromOwnerUrl, _ as createPlatformInstallPlan, a as REMOTE_INSTALLATION_MANIFEST_KEY, b as platformProvisionIntentHash, d as loadPlatformRuntime, g as trackedPlatformWorkerTraffic, j as hyperdriveOriginMatches, k as hyperdriveOriginConfigHash, l as createPlatformInstallationSecrets, m as resolveBootstrapGitHubId, n as resolvePlatformInstallDatabaseUrl, o as acquirePlatformDatabaseLifecycleLock, t as assertNoninteractivePlatformMutationAcknowledged, u as installPlatform, v as formatPlatformInstallPlan, w as resolvePlatformCloudflareCredential, x as revalidatePlatformInstallAction, y as platformAdoptionIntentHash } from "./platform-lifecycle-BpDlxT3t.mjs";
2
+ import { E as confirm, I as select, N as note, P as outro, W as isCancel, j as log } from "./dist-CTBk70IR.mjs";
3
+ import { i as createSpinner } from "./output-Dm_A4Tbv.mjs";
4
+ import { A as PlatformCloudflareClient, C as revalidatePlatformInstallAction, E as resolvePlatformCloudflareCredential, M as hyperdriveOriginFromConnectionString, N as hyperdriveOriginMatches, P as verifyPlatformRuntimeTokenPermissions, S as platformProvisionIntentHash, T as assertPlatformOperatorCredentialCanApplyPlan, a as REMOTE_INSTALLATION_MANIFEST_KEY, b as formatPlatformInstallPlan, d as loadPlatformRuntime, g as assertProjectZeroTrustAllowsUninstall, h as resolveBootstrapGitHubId, j as hyperdriveOriginConfigHash, l as createPlatformInstallationSecrets, n as resolvePlatformInstallDatabaseUrl, o as acquirePlatformDatabaseLifecycleLock, p as readPlatformProjectZeroTrustState, t as assertNoninteractivePlatformMutationAcknowledged, u as installPlatform, v as trackedPlatformWorkerTraffic, w as platformDatabaseNameFromOwnerUrl, x as platformAdoptionIntentHash, y as createPlatformInstallPlan } from "./platform-lifecycle-k0E0xoxx.mjs";
5
5
  import { createHash } from "node:crypto";
6
6
  import { PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE, PLATFORM_R2_OWNERSHIP_MARKER_KEY, createPlatformResourceOwnershipMarker, parsePlatformInstallationManifest, parsePlatformResourceOwnershipMarker, recordInstallationResource, recordInstallationStep, setInstallationDesiredState, transitionInstallation } from "@void/platform";
7
7
  //#region src/cli/platform-management.ts
@@ -26,6 +26,14 @@ function selectAuthoritativePlatformManifest(local, authoritative) {
26
26
  async function runInstalledPlatformCommand(args) {
27
27
  if (args.subcommand !== "upgrade" && args.subcommand !== "rollback" && args.subcommand !== "repair" && args.subcommand !== "disable" && args.subcommand !== "enable" && args.subcommand !== "uninstall") throw new Error(`platform: Unsupported lifecycle command ${args.subcommand}.`);
28
28
  assertNoninteractivePlatformMutationAcknowledged(args, process.stdin.isTTY === true);
29
+ const timingStart = performance.now();
30
+ let timingPrevious = timingStart;
31
+ const markPhase = (phase) => {
32
+ if (process.env.VOID_PLATFORM_TIMINGS !== "1") return;
33
+ const current = performance.now();
34
+ process.stderr.write(`[platform timing] phase ${phase} ${(current - timingPrevious).toFixed(0)} ms, total ${(current - timingStart).toFixed(0)} ms\n`);
35
+ timingPrevious = current;
36
+ };
29
37
  const manifest = await resolveInstalledPlatformManifest(args.selector);
30
38
  const operatorCredential = await resolvePlatformCloudflareCredential();
31
39
  const operatorClient = new PlatformCloudflareClient(operatorCredential.token);
@@ -50,7 +58,11 @@ async function runInstalledPlatformCommand(args) {
50
58
  if (args.subcommand === "uninstall") {
51
59
  await uninstallPlatform(client, manifest, args, {
52
60
  checkpoint: databaseLock?.checkpoint,
53
- databaseUrl
61
+ databaseUrl,
62
+ readProjectZeroTrust: databaseLock ? databaseLock.readProjectZeroTrust : () => readPlatformProjectZeroTrustState(databaseUrl, manifest.id, manifest.ownershipNonce),
63
+ lockProjectZeroTrust: databaseLock?.lockProjectZeroTrust,
64
+ fenceProjectZeroTrust: databaseLock?.fenceProjectZeroTrust,
65
+ liftProjectZeroTrustFence: databaseLock?.liftProjectZeroTrustFence
54
66
  });
55
67
  return;
56
68
  }
@@ -77,6 +89,7 @@ async function runInstalledPlatformCommand(args) {
77
89
  includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0,
78
90
  enableSandbox: runtime.manifest.safetyProtocols.sandboxDrain >= 3
79
91
  });
92
+ markPhase("plan");
80
93
  note(formatPlatformInstallPlan(plan), args.subcommand === "upgrade" ? "Upgrade plan" : args.subcommand === "rollback" ? "Rollback plan" : args.subcommand === "enable" ? "Enable plan" : "Repair plan");
81
94
  note([
82
95
  `Version: ${runtime.manifest.platformVersion}`,
@@ -99,6 +112,7 @@ async function runInstalledPlatformCommand(args) {
99
112
  allowUninitializedRoutingCheckpoint: args.subcommand === "repair" && databaseCheckpointExists,
100
113
  databaseUrl
101
114
  });
115
+ markPhase("ownership");
102
116
  const installation = args.subcommand === "enable" ? setInstallationDesiredState(manifest, "enabled", (/* @__PURE__ */ new Date()).toISOString()) : manifest;
103
117
  if (installation !== manifest) writeInstallationManifest(installation);
104
118
  const bootstrapGitHubLogin = process.env.VOID_PLATFORM_ADMIN_GITHUB_LOGIN || recovery?.bootstrapGitHubLogin || "";
@@ -130,10 +144,12 @@ async function runInstalledPlatformCommand(args) {
130
144
  customDomains: plan.deployment.capabilities.customDomains,
131
145
  zoneId: plan.zone?.id ?? null
132
146
  });
147
+ markPhase("runtime token");
133
148
  if (!databaseLock?.readAuthenticationState) throw new Error("platform: The database lifecycle lock cannot read authoritative authentication settings.");
134
149
  const result = await installPlatform(plan, secrets, installation, {
135
150
  acquireDatabaseLifecycleLock: async () => Object.assign(async () => {}, {
136
151
  checkpoint: databaseLock?.checkpoint,
152
+ liftProjectZeroTrustFence: databaseLock?.liftProjectZeroTrustFence,
137
153
  prepareDatabase: databaseLock?.prepareDatabase,
138
154
  prepareSandboxDrain: databaseLock?.prepareSandboxDrain,
139
155
  readAuthenticationState: databaseLock?.readAuthenticationState,
@@ -142,7 +158,10 @@ async function runInstalledPlatformCommand(args) {
142
158
  }),
143
159
  client,
144
160
  databaseRollbackSource: rollbackSourceRuntime ?? void 0,
145
- onProgress: (message) => progress?.message(message),
161
+ onProgress: (message) => {
162
+ markPhase(message);
163
+ progress?.message(message);
164
+ },
146
165
  runtime,
147
166
  replanWorkers: async (recoveryManifest) => (await createPlatformInstallPlan(client, planInput, recoveryManifest, {
148
167
  authoritativeProvisionIntents: true,
@@ -150,9 +169,13 @@ async function runInstalledPlatformCommand(args) {
150
169
  includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0,
151
170
  enableSandbox: runtime.manifest.safetyProtocols.sandboxDrain >= 3
152
171
  })).actions.filter((action) => action.kind === "worker"),
153
- revalidateBeforeWorkerDeploy: (manifest, action) => revalidatePlatformInstallAction(client, plan, manifest, action, { repairMissing: args.subcommand === "repair" })
172
+ revalidateBeforeWorkerDeploy: (manifest, action) => revalidatePlatformInstallAction(client, plan, manifest, action, {
173
+ repairMissing: args.subcommand === "repair",
174
+ stableWorkerUpdate: args.subcommand === "upgrade"
175
+ })
154
176
  });
155
177
  progress.message("Finalizing platform changes");
178
+ markPhase("installer complete");
156
179
  reportResult = () => {
157
180
  progress?.stop(result.waitingForDns || result.waitingForSandboxDrain ? "Platform operation paused; progress is saved." : `Platform ${args.subcommand} complete.`);
158
181
  progress = void 0;
@@ -186,6 +209,7 @@ async function runInstalledPlatformCommand(args) {
186
209
  const databaseUrl = resolvePlatformInstallDatabaseUrl(recovery, current);
187
210
  if (!databaseUrl) throw new Error("platform: DATABASE_URL is required to safely serialize lifecycle changes across hosts.");
188
211
  const releaseDatabase = await acquirePlatformDatabaseLifecycleLock(databaseUrl, current.id, current.ownershipNonce);
212
+ markPhase("database lock");
189
213
  try {
190
214
  const authoritative = releaseDatabase.authoritativeManifest;
191
215
  const databaseCheckpointExists = authoritative !== null && authoritative !== void 0;
@@ -197,6 +221,7 @@ async function runInstalledPlatformCommand(args) {
197
221
  await releaseDatabase();
198
222
  }
199
223
  reportResult?.();
224
+ markPhase("complete");
200
225
  } catch (error) {
201
226
  progress?.error(`Platform ${args.subcommand} failed.`);
202
227
  progress = void 0;
@@ -298,8 +323,9 @@ async function uninstallPlatform(client, initialManifest, args, dependencies = {
298
323
  const interactive = dependencies.interactive ?? process.stdin.isTTY;
299
324
  const confirmAction = dependencies.confirm ?? promptForConfirmation;
300
325
  if (createdZone && args.deleteZone === true) throw new Error(`platform: Refusing to delete Cloudflare zone ${JSON.stringify(createdZone.name)} automatically. A zone can contain unrelated DNS, settings, and products that the installer cannot exhaustively prove ownership of. Uninstall with --keep-zone, inspect the retained zone in Cloudflare, and delete it manually if appropriate.`);
326
+ await assertProjectZeroTrustAllowsUninstall(dependencies.readProjectZeroTrust);
301
327
  const dataMessage = retainData ? "Retain installer-owned Workers, storage, dispatch, AI logs, and Hyperdrive by default." : args.purgeData ? "Delete safely identifiable installer-owned data (--purge-data); retain Workers, R2, AI Gateway, and external PostgreSQL for manual cleanup." : "Retain installer-owned data; external PostgreSQL is never deleted.";
302
- note(`Disable all platform traffic through installation-owned routing storage.\nRetain DNS records, routes, and custom domains for explicit dashboard cleanup.\nDelete installer-owned Queues.\n${dataMessage}\n${createdZone ? `Keep zone ${createdZone.name} for explicit manual cleanup.` : "Never delete the adopted application zone."}${(manifest.authenticationResources ?? []).length ? "\nRetain Access resources for deliberate cleanup:\n" + manifest.authenticationResources.map((resource) => ` ${resource.ownership} ${resource.kind}: ${resource.name} (${resource.id}, account ${resource.accountId})`).join("\n") : ""}`, "Uninstall plan");
328
+ note(`Disable all platform traffic through installation-owned routing storage.\nRetain DNS records, routes, and custom domains for explicit dashboard cleanup.\nDelete installer-owned Queues unless a retained Worker still uses them.\n${dataMessage}\n${createdZone ? `Keep zone ${createdZone.name} for explicit manual cleanup.` : "Never delete the adopted application zone."}${(manifest.authenticationResources ?? []).length ? "\nRetain Access resources for deliberate cleanup:\n" + manifest.authenticationResources.map((resource) => ` ${resource.ownership} ${resource.kind}: ${resource.name} (${resource.id}, account ${resource.accountId})`).join("\n") : ""}`, "Uninstall plan");
303
329
  if (args.plan) {
304
330
  outro("No Cloudflare or local installation state was changed.");
305
331
  return;
@@ -328,12 +354,34 @@ async function uninstallPlatform(client, initialManifest, args, dependencies = {
328
354
  await verifyPlatformInstallationOwnership(client, manifest, { databaseUrl: dependencies.databaseUrl });
329
355
  missingResources = /* @__PURE__ */ new Set();
330
356
  }
331
- let next = transitionInstallation(manifest, "uninstalling", (/* @__PURE__ */ new Date()).toISOString());
332
- writeInstallationManifest(next);
357
+ const { fenceProjectZeroTrust, liftProjectZeroTrustFence, lockProjectZeroTrust } = dependencies;
358
+ if (!lockProjectZeroTrust || !fenceProjectZeroTrust || !liftProjectZeroTrustFence) throw new Error("platform: Refusing to uninstall because no platform database connection is available to hold off project Zero Trust changes.");
359
+ const releaseProjectZeroTrust = await lockProjectZeroTrust();
360
+ let fenced = false;
361
+ let disablingTraffic = false;
362
+ const stopProjectZeroTrustHold = async () => {
363
+ if (fenced && !disablingTraffic) await liftProjectZeroTrustFence().catch((error) => {
364
+ log.warn(`Could not reopen project Zero Trust changes after the uninstall stopped: ${error instanceof Error ? error.message : String(error)}\nRun \`void platform uninstall\` again, or \`void platform repair\` to keep the platform.`);
365
+ });
366
+ await releaseProjectZeroTrust();
367
+ };
368
+ let next = manifest;
369
+ try {
370
+ await assertProjectZeroTrustAllowsUninstall(dependencies.readProjectZeroTrust);
371
+ fenced = true;
372
+ await fenceProjectZeroTrust();
373
+ next = transitionInstallation(manifest, "uninstalling", (/* @__PURE__ */ new Date()).toISOString());
374
+ writeInstallationManifest(next);
375
+ } catch (error) {
376
+ await stopProjectZeroTrustHold();
377
+ throw error;
378
+ }
333
379
  try {
334
380
  await writeRemoteManifestIfPresent(client, next);
335
381
  const routing = next.resources.find((resource) => resource.key === "routing-kv" && resource.state === "ready");
382
+ disablingTraffic = true;
336
383
  if (routing) await client.putKvValue(next.account.id, routing.id, PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE);
384
+ await releaseProjectZeroTrust();
337
385
  for (const key of missingResources) {
338
386
  const resource = requireResource(next, key);
339
387
  next = updateResourceState(next, key, resource.ownership === "created" ? "deleted" : "retained");
@@ -366,6 +414,7 @@ async function uninstallPlatform(client, initialManifest, args, dependencies = {
366
414
  zone: 8
367
415
  };
368
416
  const resources = [...next.resources].sort((left, right) => resourceDeletionPriority(left, deletionPriority) - resourceDeletionPriority(right, deletionPriority));
417
+ const queuesInUse = hasRoutingCheckpoint && resources.some((resource) => resource.kind === "queue" && shouldDeleteResource(resource, retainData)) && await hasLiveInstallationWorker(client, next);
369
418
  for (const resource of resources) {
370
419
  if (resource.state !== "ready") continue;
371
420
  if (!hasRoutingCheckpoint && resource.kind !== "zone") {
@@ -378,7 +427,7 @@ async function uninstallPlatform(client, initialManifest, args, dependencies = {
378
427
  await writeLifecycleCheckpoint(client, next);
379
428
  continue;
380
429
  }
381
- if (resource.kind === "dns-record" && !zone) {
430
+ if (resource.kind === "dns-record" && !zone || resource.kind === "queue" && queuesInUse) {
382
431
  next = updateResourceState(next, resource.key, "retained");
383
432
  await writeLifecycleCheckpoint(client, next);
384
433
  continue;
@@ -403,6 +452,7 @@ async function uninstallPlatform(client, initialManifest, args, dependencies = {
403
452
  removePlatformConnectionForInstallation(next.id);
404
453
  log.success(retainData ? `${next.deployment.displayName} was uninstalled; data resources were retained and recorded in ${next.id}.` : `${next.deployment.displayName} was uninstalled.`);
405
454
  } catch (error) {
455
+ await stopProjectZeroTrustHold().catch(() => {});
406
456
  next = transitionInstallation(next, "failed", (/* @__PURE__ */ new Date()).toISOString());
407
457
  writeInstallationManifest(next);
408
458
  await writeRemoteManifestIfPresent(client, next).catch(() => {});
@@ -488,6 +538,18 @@ function shouldDeleteResource(resource, retainData) {
488
538
  if (resource.kind === "worker-route" || resource.kind === "worker-custom-domain") return false;
489
539
  return !(retainData && DATA_RESOURCE_KINDS.has(resource.kind));
490
540
  }
541
+ async function hasLiveInstallationWorker(client, manifest) {
542
+ const names = manifest.deployment.resources;
543
+ const installationWorkers = /* @__PURE__ */ new Set([
544
+ names.apiWorker,
545
+ names.proxyWorker,
546
+ names.emailGatewayWorker,
547
+ names.tailWorker,
548
+ names.dispatchWorker,
549
+ ...manifest.resources.filter((resource) => resource.kind === "worker").map((resource) => resource.name)
550
+ ]);
551
+ return (await client.listWorkerNames(manifest.account.id)).some((name) => installationWorkers.has(name));
552
+ }
491
553
  function resourceDeletionPriority(resource, priorities) {
492
554
  return resource.key === "routing-kv" ? 100 : priorities[resource.kind] ?? 99;
493
555
  }
@@ -1,2 +1,2 @@
1
- import { c as selectAuthoritativePlatformManifest, s as runInstalledPlatformCommand, u as verifyPlatformInstallationOwnership } from "./platform-management-BKYenDlE.mjs";
1
+ import { c as selectAuthoritativePlatformManifest, s as runInstalledPlatformCommand, u as verifyPlatformInstallationOwnership } from "./platform-management-Brz_BDiT.mjs";
2
2
  export { runInstalledPlatformCommand, selectAuthoritativePlatformManifest, verifyPlatformInstallationOwnership };
@@ -1,7 +1,7 @@
1
1
  import { t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
2
2
  import { a as listInstallationManifests, g as savePlatformConnection, t as acquirePlatformLifecycleLock, v as writeInstallationManifest } from "./platform-registry-QBa4DK32.mjs";
3
- import { _ as createPlatformInstallPlan, a as REMOTE_INSTALLATION_MANIFEST_KEY } from "./platform-lifecycle-BpDlxT3t.mjs";
4
- import { i as recoverDurablyMarkedProvisionIntents, r as isPlatformManifestMonotonicExtension, u as verifyPlatformInstallationOwnership } from "./platform-management-BKYenDlE.mjs";
3
+ import { a as REMOTE_INSTALLATION_MANIFEST_KEY, y as createPlatformInstallPlan } from "./platform-lifecycle-k0E0xoxx.mjs";
4
+ import { i as recoverDurablyMarkedProvisionIntents, r as isPlatformManifestMonotonicExtension, u as verifyPlatformInstallationOwnership } from "./platform-management-Brz_BDiT.mjs";
5
5
  import { parsePlatformInstallationManifest, setInstallationEndpoints } from "@void/platform";
6
6
  //#region src/cli/platform-recovery.ts
7
7
  async function recoverPlatformInstallations(client, accountId, verifyEndpoint = verifyInstallationEndpoint, selector = "") {
@@ -0,0 +1,2 @@
1
+ import { t as prepareProject } from "./prepare-CRhJbVrG.mjs";
2
+ export { prepareProject };
@@ -1,6 +1,6 @@
1
- import { r as cliTitle } from "./output-CCH48AMM.mjs";
2
- import { N as note, O as intro, P as outro, j as log } from "./dist-Dn6nn2IU.mjs";
3
- import { t as prepareProject } from "./prepare-C3kt3Rst.mjs";
1
+ import { N as note, O as intro, P as outro, j as log } from "./dist-CTBk70IR.mjs";
2
+ import { r as cliTitle } from "./output-Dm_A4Tbv.mjs";
3
+ import { t as prepareProject } from "./prepare-CRhJbVrG.mjs";
4
4
  //#region src/cli/prepare.ts
5
5
  async function runPrepareCommand(root, _args) {
6
6
  console.log();
@@ -1,7 +1,7 @@
1
1
  import { a as join } from "./dist-BVqXeR_h.mjs";
2
2
  import { i as resolveProjectPaths } from "./project-paths-GgcMozYz.mjs";
3
3
  import { n as loadVoidAuthConfig, t as findVoidAuthConfig } from "./config-DPByhVck.mjs";
4
- import { m as readConfig, u as getDatabaseDialect } from "./config-CafTW6Cz.mjs";
4
+ import { m as readConfig, u as getDatabaseDialect } from "./config-Br_JZD6u.mjs";
5
5
  import { n as ensureProjectTsconfig, r as writeFileIfChanged } from "./project-tsconfig-B8GeM0RM.mjs";
6
6
  import { r as scanRoutes } from "./scan-ClYmX3sa.mjs";
7
7
  import { i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference-BMfKRSqE.mjs";
@@ -1,8 +1,8 @@
1
- import { a as dim, c as import_picocolors, r as cliTitle, u as tablePrefix } from "./output-CCH48AMM.mjs";
2
1
  import { c as getToken, s as getSiteDomain } from "./auth-DLNN0D3Z.mjs";
3
2
  import { i as readDeploymentPlatform } from "./project-C0Fqu05O.mjs";
4
- import { O as intro, P as outro, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
3
+ import { O as intro, P as outro, j as log } from "./dist-CTBk70IR.mjs";
4
+ import { n as PlatformClient } from "./client-BTZ3XkrB.mjs";
5
+ import { a as dim, c as import_picocolors, d as tablePrefix, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
6
6
  //#region src/cli/projects.ts
7
7
  async function runProjectsCommand(root) {
8
8
  console.log();
@@ -39,63 +39,77 @@ async function runProjectsCommand(root) {
39
39
  async function runProjectCommand(root, args) {
40
40
  const cloudflare = readDeploymentPlatform(root) === "cloudflare";
41
41
  if (args.subcommand === "status") {
42
- const { runListCommand } = await import("./list-CDb-4bZ1.mjs");
42
+ const { runListCommand } = await import("./list-D44jmIAM.mjs");
43
43
  return runListCommand(root, args.name || void 0);
44
44
  }
45
45
  if (args.subcommand === "link") {
46
46
  if (cloudflare) throw new Error("project: Direct Cloudflare apps are identified by cloudflare.name in void.config.ts and do not need linking.");
47
- const { runLink } = await import("./link-CsHOinF7.mjs");
47
+ const { runLink } = await import("./link-BrQfb_CU.mjs");
48
48
  return runLink(root, args.name || void 0);
49
49
  }
50
50
  if (args.subcommand === "list") {
51
51
  if (cloudflare) {
52
- const { runListCommand } = await import("./list-CDb-4bZ1.mjs");
52
+ const { runListCommand } = await import("./list-D44jmIAM.mjs");
53
53
  return runListCommand(root);
54
54
  }
55
55
  return runProjectsCommand(root);
56
56
  }
57
57
  if (args.subcommand === "token") {
58
58
  if (cloudflare) throw new Error("project: CI deploy credentials are available only for Void platform projects.");
59
- const { runProjectTokenCommand } = await import("./project-token-C8xEEQnB.mjs");
59
+ const { runProjectTokenCommand } = await import("./project-token-l5DqK6Az.mjs");
60
60
  return runProjectTokenCommand(root, args);
61
61
  }
62
62
  if (args.subcommand === "team") {
63
63
  if (args.action === "") {
64
- const { printHelpPage } = await import("./help-DQMfeKMz.mjs");
64
+ const { printHelpPage } = await import("./help-CmZzxUba.mjs");
65
65
  printHelpPage(["project", "team"]);
66
66
  return;
67
67
  }
68
68
  const accountInvitationAction = args.action === "pending" || args.action === "accept" || args.action === "decline";
69
69
  if (cloudflare && !accountInvitationAction) throw new Error("project: Teams are available only for projects hosted on a Void platform, not direct Cloudflare deployments.");
70
- const { runProjectTeamCommand } = await import("./project-team-BkbYIsXN.mjs");
70
+ const { runProjectTeamCommand } = await import("./project-team-BvgM0WoX.mjs");
71
71
  return runProjectTeamCommand(root, args);
72
72
  }
73
+ if (args.subcommand === "zero-trust") {
74
+ if (cloudflare) throw new Error("project: Zero Trust overrides are available only for projects hosted on a Void platform.");
75
+ if (args.action === "") {
76
+ const { printHelpPage } = await import("./help-CmZzxUba.mjs");
77
+ printHelpPage(["project", "zero-trust"]);
78
+ return;
79
+ }
80
+ const action = args.action;
81
+ const { runProjectZeroTrustCommand } = await import("./project-zero-trust-v6Mvpp8y.mjs");
82
+ return runProjectZeroTrustCommand(root, {
83
+ ...args,
84
+ action
85
+ });
86
+ }
73
87
  if (args.subcommand === "logs") {
74
- const { runLogsCommand } = await import("./logs-BdfiOezj.mjs");
88
+ const { runLogsCommand } = await import("./logs-BjKvFnVM.mjs");
75
89
  return runLogsCommand(root, args.filter, args.range, args.deployment || void 0, args.level || void 0);
76
90
  }
77
91
  if (args.subcommand === "requests") {
78
92
  if (cloudflare) throw new Error("project: Historical request analytics require the Void platform. Use `void project logs` for a live Cloudflare tail.");
79
- const { runRequestsCommand } = await import("./requests-DFyhBMaf.mjs");
93
+ const { runRequestsCommand } = await import("./requests-DN-BbNiM.mjs");
80
94
  return runRequestsCommand(root, args.range, args.status || void 0);
81
95
  }
82
96
  if (args.subcommand === "rollback") {
83
- const { runRollbackCommand } = await import("./rollback-DHHxXZiS.mjs");
97
+ const { runRollbackCommand } = await import("./rollback-D7rzSaZM.mjs");
84
98
  return runRollbackCommand(root, args.deployId || void 0);
85
99
  }
86
100
  if (args.subcommand === "cancel") {
87
101
  if (cloudflare) throw new Error("project: Direct Cloudflare deploys activate only after readiness succeeds, so there is no remote build to cancel.");
88
- const { runCancelDeployCommand } = await import("./cancel-deploy-D23R1RXT.mjs");
102
+ const { runCancelDeployCommand } = await import("./cancel-deploy-D4NUqFbi.mjs");
89
103
  return runCancelDeployCommand(root, args.deployId || void 0);
90
104
  }
91
105
  if (args.subcommand === "delete") {
92
106
  if (cloudflare) throw new Error("project: Refusing to delete Cloudflare resources through this command. Direct deployments are additive and existing resources may be shared.");
93
- const { runDeleteCommand } = await import("./delete-D6dZ9B6B.mjs");
107
+ const { runDeleteCommand } = await import("./delete-TTedbH6B.mjs");
94
108
  return runDeleteCommand(root, args.name || void 0, { force: args.force });
95
109
  }
96
110
  if (args.subcommand === "purge-cache") {
97
111
  if (cloudflare) throw new Error("project: Direct Cloudflare ISR cache purge is not available yet; redeploy or purge the configured KV namespace explicitly.");
98
- const { runPurgeCacheCommand } = await import("./cache-7_UeZdTk.mjs");
112
+ const { runPurgeCacheCommand } = await import("./cache-D0sWhgKI.mjs");
99
113
  return runPurgeCacheCommand(root, args.projectSlug || void 0);
100
114
  }
101
115
  }
@@ -1,8 +1,8 @@
1
- import { r as cliTitle } from "./output-CCH48AMM.mjs";
2
1
  import { c as getToken, i as getAccountCredential } from "./auth-DLNN0D3Z.mjs";
3
2
  import { o as readProjectConfig } from "./project-C0Fqu05O.mjs";
4
- import { N as note, O as intro, P as outro, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient, o as parsePlatformErrorBody, s as platformErrorMessage, t as PlatformApiError } from "./client-QTl6ko_D.mjs";
3
+ import { N as note, O as intro, P as outro, j as log } from "./dist-CTBk70IR.mjs";
4
+ import { n as PlatformClient, o as parsePlatformErrorBody, s as platformErrorMessage, t as PlatformApiError } from "./client-BTZ3XkrB.mjs";
5
+ import { r as cliTitle } from "./output-Dm_A4Tbv.mjs";
6
6
  import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-BG5ORGID.mjs";
7
7
  //#region src/cli/project-team.ts
8
8
  function clean(value) {
@@ -1,8 +1,8 @@
1
- import { a as dim, r as cliTitle, u as tablePrefix } from "./output-CCH48AMM.mjs";
2
1
  import { c as getToken } from "./auth-DLNN0D3Z.mjs";
3
2
  import { o as readProjectConfig } from "./project-C0Fqu05O.mjs";
4
- import { O as intro, P as outro, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
3
+ import { O as intro, P as outro, j as log } from "./dist-CTBk70IR.mjs";
4
+ import { n as PlatformClient } from "./client-BTZ3XkrB.mjs";
5
+ import { a as dim, d as tablePrefix, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
6
6
  import { r as resolveProjectBySlug } from "./resolve-project-BG5ORGID.mjs";
7
7
  //#region src/cli/project-token.ts
8
8
  async function resolveTarget(root, args) {
@@ -0,0 +1,63 @@
1
+ import { c as getToken } from "./auth-DLNN0D3Z.mjs";
2
+ import { o as readProjectConfig } from "./project-C0Fqu05O.mjs";
3
+ import { N as note, O as intro, P as outro, j as log } from "./dist-CTBk70IR.mjs";
4
+ import { n as PlatformClient } from "./client-BTZ3XkrB.mjs";
5
+ import { l as sanitizeTerminalText, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
6
+ import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-BG5ORGID.mjs";
7
+ //#region src/cli/project-zero-trust.ts
8
+ async function resolveTarget(root, args) {
9
+ const token = getToken(root);
10
+ if (!token) throw new Error("project: Not logged in. Run `void account login` first.");
11
+ const client = new PlatformClient(token, { root });
12
+ const requestedSlug = getRequestedProjectSlug({ projectSlug: args.projectSlug });
13
+ if (requestedSlug) {
14
+ const project = resolveProjectBySlug(await client.listProjects(), requestedSlug);
15
+ if (!project) throw new Error(`project: No project found with slug '${requestedSlug}'.`);
16
+ return {
17
+ client,
18
+ projectId: project.projectId,
19
+ slug: project.slug
20
+ };
21
+ }
22
+ const linked = readProjectConfig(root);
23
+ if (!linked) throw new Error("project: No linked project. Pass --project <name> or set VOID_PROJECT.");
24
+ return {
25
+ client,
26
+ projectId: linked.projectId,
27
+ slug: linked.slug
28
+ };
29
+ }
30
+ function statusLines(result) {
31
+ const project = result.project;
32
+ const platformStatus = sanitizeTerminalText(result.platformStatus);
33
+ const unavailableMessage = result.platformStatus === "invalid_configuration" ? "The platform Zero Trust configuration is invalid. Ask a platform administrator to review it." : result.platformStatus === "configuring" ? "The platform is still applying Zero Trust configuration. A platform administrator can resume it with `void platform zero-trust reconcile`." : result.platformStatus === "disabling" ? "The platform is disabling project Zero Trust. A platform administrator can resume it with `void platform zero-trust reconcile`." : result.platformStatus === "error" ? "The platform Zero Trust configuration needs administrator attention. A platform administrator can inspect its status and reconcile it." : result.platformStatus === "ready" ? "The platform administrator has disabled project Zero Trust." : "The platform administrator has not configured project Zero Trust.";
34
+ return [
35
+ `Available: ${result.available ? "yes" : "no"}`,
36
+ `Platform: ${platformStatus}`,
37
+ ...result.platformStatus === "not_configured" || result.platformStatus === "invalid_configuration" ? [] : [`Default for new projects: ${result.protectNewProjects ? "protected" : "public"}`],
38
+ `Desired: ${project ? project.desired_protected ? "protected" : "public" : "not initialized"}`,
39
+ `Effective: ${project ? project.effective_protected ? "protected" : "public" : "not initialized"}`,
40
+ `State: ${project?.state ?? "not initialized"}`,
41
+ ...project?.last_error ? [`Last error: ${sanitizeTerminalText(project.last_error)}`] : [],
42
+ ...!result.available ? [unavailableMessage] : []
43
+ ].join("\n");
44
+ }
45
+ async function runProjectZeroTrustCommand(root, args) {
46
+ console.log();
47
+ intro(cliTitle(`project zero-trust ${args.action}`));
48
+ const { client, projectId, slug } = await resolveTarget(root, args);
49
+ if (args.action === "status") {
50
+ note(statusLines(await client.getProjectZeroTrust(projectId)), slug);
51
+ outro(`${slug} Zero Trust status`);
52
+ return;
53
+ }
54
+ const result = args.action === "reconcile" ? await client.reconcileProjectZeroTrust(projectId) : await client.setProjectZeroTrust(projectId, args.action === "protect");
55
+ if (result.project.last_error) log.warn(sanitizeTerminalText(result.project.last_error));
56
+ if (result.project.state === "reconciling") {
57
+ outro(`${slug} Zero Trust update is still in progress. Run \`void project zero-trust reconcile\` to continue, or wait for scheduled maintenance.`);
58
+ return;
59
+ }
60
+ outro(args.action === "protect" ? `${slug} is protected by Zero Trust.` : args.action === "public" ? `${slug} is public.` : `${slug} Zero Trust reconciled (${result.project.state}).`);
61
+ }
62
+ //#endregion
63
+ export { runProjectZeroTrustCommand };
@@ -1,5 +1,5 @@
1
1
  import { n as HeadDescriptor, t as HeadConfig } from "./head-Do8P4puT.mjs";
2
- import { n as CloudBindings, r as CloudContext } from "./handler-BXJTXd02.mjs";
2
+ import { n as CloudBindings, r as CloudContext } from "./handler-HEcZsaij.mjs";
3
3
  import { a as PageRenderMode, t as DevCssAsset } from "./types-BAp5AEBU.mjs";
4
4
  //#region src/pages/protocol.d.ts
5
5
  /** Escape characters that are unsafe inside inline <script> tags to prevent XSS. */
@@ -1,5 +1,5 @@
1
1
  import { a as join, n as dirname, o as normalize, t as basename, u as resolve$2 } from "./dist-BVqXeR_h.mjs";
2
- import { R as persistCloudflareConfig, _ as readProvisionedBindingEntry, k as writeProvisionedWranglerConfig, s as assertNoDuplicateMembers } from "./wrangler-BymcxrRa.mjs";
2
+ import { V as persistCloudflareConfig, _ as readProvisionedBindingEntry, k as writeProvisionedWranglerConfig, s as assertNoDuplicateMembers } from "./wrangler-DQF1vKyf.mjs";
3
3
  import { i as voidWarn, r as voidLog } from "./log-ChfPKsVd.mjs";
4
4
  import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
5
5
  import { o as resolveWranglerArgv } from "./preset-UHj9ARyP.mjs";
@@ -418,8 +418,8 @@ let activeProvisionQuarantineHook;
418
418
  function isQuarantineError(error) {
419
419
  return error instanceof WranglerQuarantineError || error?.quarantine === true;
420
420
  }
421
- /** The (at most one) currently-registered {runner, owning-lock} pair. */
422
- let activeRegistration;
421
+ /** Concurrent registrations are allowed only for two immutable Worker uploads. */
422
+ const activeRegistrations = /* @__PURE__ */ new Map();
423
423
  let coordinatorListenersInstalled = false;
424
424
  let activeTeardown;
425
425
  let reRaisedOnce = false;
@@ -437,21 +437,25 @@ function removeCoordinatorListeners() {
437
437
  process.removeListener("SIGINT", onCoordinatorSigint);
438
438
  process.removeListener("SIGTERM", onCoordinatorSigterm);
439
439
  }
440
- function registerRunner(registrant) {
441
- if (activeRegistration !== void 0) throw new Error("provision: internal invariant violated — a second wrangler child tried to register while one is already active in this process");
442
- activeRegistration = {
440
+ function canRegisterRunner(parallelWorkerUpload) {
441
+ return activeRegistrations.size === 0 || parallelWorkerUpload && activeProvisionQuarantineHook === void 0 && activeRegistrations.size < 2 && [...activeRegistrations.values()].every((entry) => entry.parallelWorkerUpload);
442
+ }
443
+ function registerRunner(registrant, parallelWorkerUpload) {
444
+ if (!canRegisterRunner(parallelWorkerUpload)) throw new Error("provision: internal invariant violated — a Cloudflare child tried to register outside its concurrency limit");
445
+ activeRegistrations.set(registrant, {
443
446
  registrant,
444
- lockQuarantine: activeProvisionQuarantineHook
445
- };
447
+ lockQuarantine: activeProvisionQuarantineHook,
448
+ parallelWorkerUpload
449
+ });
446
450
  installCoordinatorListeners();
447
451
  }
448
452
  function deregisterRunner(registrant) {
449
- if (activeRegistration?.registrant === registrant) activeRegistration = void 0;
450
- if (activeRegistration === void 0 && activeTeardown === void 0 && retentionWatchdog === void 0) removeCoordinatorListeners();
453
+ activeRegistrations.delete(registrant);
454
+ if (activeRegistrations.size === 0 && activeTeardown === void 0 && retentionWatchdog === void 0) removeCoordinatorListeners();
451
455
  }
452
456
  function coordinatorHandleSignal(signal) {
453
457
  if (activeTeardown !== void 0) return;
454
- if (retentionWatchdog !== void 0 && activeRegistration === void 0) {
458
+ if (retentionWatchdog !== void 0 && activeRegistrations.size === 0) {
455
459
  process.stderr.write(`provision: ignoring ${signal} — a provision lock is retained while an unconfirmed wrangler child may live and its quarantine metadata is not yet durable. The process exits once the child is confirmed dead or the metadata persists.\n`);
456
460
  return;
457
461
  }
@@ -462,15 +466,15 @@ function coordinatorHandleSignal(signal) {
462
466
  persistFailed: false,
463
467
  finished: false,
464
468
  deadlineTimer: void 0,
465
- expirePendingPair: void 0
469
+ expirePendingPairs: []
466
470
  };
467
471
  activeTeardown = teardown;
468
- const snapshot = activeRegistration !== void 0 ? [activeRegistration] : [];
472
+ const snapshot = [...activeRegistrations.values()];
469
473
  teardown.pending = snapshot.length;
470
474
  if (snapshot.length > 0) {
471
475
  const deadlineMs = Math.max(...snapshot.map((r) => r.registrant.teardownDeadlineMs));
472
476
  teardown.deadlineTimer = setTimeout(() => {
473
- teardown.expirePendingPair?.(`the coordinator-wide ${deadlineMs}ms teardown deadline expired before the process group's termination was confirmed`);
477
+ for (const expire of teardown.expirePendingPairs) expire(`the coordinator-wide ${deadlineMs}ms teardown deadline expired before the process group's termination was confirmed`);
474
478
  }, deadlineMs);
475
479
  }
476
480
  for (const registration of snapshot) coordinatorTearDownRegistrant(teardown, registration);
@@ -507,7 +511,7 @@ function coordinatorTearDownRegistrant(teardown, registration) {
507
511
  registrant.quarantine(detail);
508
512
  complete();
509
513
  };
510
- teardown.expirePendingPair = quarantinePair;
514
+ teardown.expirePendingPairs.push(quarantinePair);
511
515
  const outcome = registrant.signalGroup(teardown.signal);
512
516
  if (typeof outcome === "object") {
513
517
  quarantinePair(`the process group could not be signalled: ${outcome.error.message}`);
@@ -560,7 +564,7 @@ function armRetentionWatchdog(lock, info) {
560
564
  const resolveWatchdog = () => {
561
565
  if (retentionWatchdog !== void 0) clearTimeout(retentionWatchdog.timer);
562
566
  retentionWatchdog = void 0;
563
- if (activeRegistration === void 0 && activeTeardown === void 0) removeCoordinatorListeners();
567
+ if (activeRegistrations.size === 0 && activeTeardown === void 0) removeCoordinatorListeners();
564
568
  };
565
569
  const tick = () => {
566
570
  if (info.pid !== void 0) {
@@ -616,12 +620,13 @@ function createDefaultRunWrangler(root, options) {
616
620
  const isWindows = process.platform === "win32";
617
621
  const teardownDeadlineMs = options?.signalTeardownDeadlineMs ?? confirmGraceMs + SIGNAL_TEARDOWN_DEADLINE_MARGIN_MS;
618
622
  return (args, opts) => new Promise((resolvePromise, rejectPromise) => {
623
+ const parallelWorkerUpload = options?.parallelWorkerUpload === true && args[0] === "versions" && args[1] === "upload";
619
624
  if (activeTeardown !== void 0) {
620
625
  rejectPromise(/* @__PURE__ */ new Error(`provision: refusing to spawn wrangler — a fatal ${activeTeardown.signal} is being handled and this process is terminating; no new wrangler work may start.`));
621
626
  return;
622
627
  }
623
- if (activeRegistration !== void 0) {
624
- rejectPromise(/* @__PURE__ */ new Error("provision: refusing to spawn wrangler — another wrangler child is already active in this process (wrangler calls must run sequentially; provisions run at most one per process)."));
628
+ if (!canRegisterRunner(parallelWorkerUpload)) {
629
+ rejectPromise(/* @__PURE__ */ new Error("provision: refusing to spawn wrangler — another wrangler child is already active in this process (only two immutable Worker uploads may overlap; all other Cloudflare commands and provisions remain sequential)."));
625
630
  return;
626
631
  }
627
632
  const child = spawn(command, [...prefix, ...args], {
@@ -842,7 +847,7 @@ function createDefaultRunWrangler(root, options) {
842
847
  confirmThenSettle(makeResult, `the child's exit (status ${String(code)}; surviving process-group members were SIGKILLed)`);
843
848
  nudgeConfirmPolls();
844
849
  });
845
- registerRunner(registrant);
850
+ registerRunner(registrant, parallelWorkerUpload);
846
851
  options?.onSpawnedChild?.(child);
847
852
  });
848
853
  }
@@ -1,3 +1,3 @@
1
1
  import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
2
- import { _ as resolvePinnedApiBaseUrl, a as checkCloudflareProvisionDrift, c as enableD1ReadReplicationViaApi, d as isQueueConfirmedAbsent, f as isRealD1Id, g as provisionEnv, h as provisionCloudflareResources, i as assertValidResourceName, l as isAlreadyGoneKillError, m as normalizeRunWranglerResult, n as acquireProvisionLock, o as createDefaultRunWrangler, p as isRealKvId, r as assertNoTransportRedirectInProjectDotenv, s as deleteEnvVarCaseAware, t as WranglerQuarantineError, u as isQuarantineError, v as resolveProperLockfileKey } from "./provision-BhreDAOS.mjs";
2
+ import { _ as resolvePinnedApiBaseUrl, a as checkCloudflareProvisionDrift, c as enableD1ReadReplicationViaApi, d as isQueueConfirmedAbsent, f as isRealD1Id, g as provisionEnv, h as provisionCloudflareResources, i as assertValidResourceName, l as isAlreadyGoneKillError, m as normalizeRunWranglerResult, n as acquireProvisionLock, o as createDefaultRunWrangler, p as isRealKvId, r as assertNoTransportRedirectInProjectDotenv, s as deleteEnvVarCaseAware, t as WranglerQuarantineError, u as isQuarantineError, v as resolveProperLockfileKey } from "./provision-C4IGqkBf.mjs";
3
3
  export { WranglerQuarantineError, acquireProvisionLock, assertNoTransportRedirectInProjectDotenv, assertValidResourceName, checkCloudflareProvisionDrift, createDefaultRunWrangler, deleteEnvVarCaseAware, enableD1ReadReplicationViaApi, isAlreadyGoneKillError, isQuarantineError, isQueueConfirmedAbsent, isRealD1Id, isRealKvId, normalizeRunWranglerResult, provisionCloudflareResources, provisionEnv, resolvePinnedApiBaseUrl, resolveProperLockfileKey, scanWranglerDotenvKeys };
@@ -1,8 +1,8 @@
1
- import { a as dim, c as import_picocolors, r as cliTitle } from "./output-CCH48AMM.mjs";
2
1
  import { c as getToken } from "./auth-DLNN0D3Z.mjs";
3
2
  import { o as readProjectConfig } from "./project-C0Fqu05O.mjs";
4
- import { O as intro, P as outro, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
3
+ import { O as intro, P as outro, j as log } from "./dist-CTBk70IR.mjs";
4
+ import { n as PlatformClient } from "./client-BTZ3XkrB.mjs";
5
+ import { a as dim, c as import_picocolors, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
6
6
  //#region src/cli/requests.ts
7
7
  async function runRequestsCommand(root, range, status) {
8
8
  console.log();
@@ -1,8 +1,8 @@
1
- import { a as dim, c as import_picocolors, i as createSpinner, o as ensureUtc, r as cliTitle } from "./output-CCH48AMM.mjs";
2
1
  import { c as getToken } from "./auth-DLNN0D3Z.mjs";
3
2
  import { i as readDeploymentPlatform, o as readProjectConfig } from "./project-C0Fqu05O.mjs";
4
- import { E as confirm, I as select, O as intro, P as outro, T as cancel, W as isCancel, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
3
+ import { E as confirm, I as select, O as intro, P as outro, T as cancel, W as isCancel, j as log } from "./dist-CTBk70IR.mjs";
4
+ import { n as PlatformClient } from "./client-BTZ3XkrB.mjs";
5
+ import { a as dim, c as import_picocolors, i as createSpinner, o as ensureUtc, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
6
6
  //#region src/cli/rollback.ts
7
7
  async function runRollbackCommand(root, deployId) {
8
8
  console.log();
@@ -83,7 +83,7 @@ async function runRollbackCommand(root, deployId) {
83
83
  outro(dim("Traffic is now serving the rolled-back deployment."));
84
84
  }
85
85
  async function runCloudflareRollback(root, deployId) {
86
- const { activateCloudflareExistingVersion, readCloudflareWorkerStatus, resolveCloudflareOperationContext } = await import("./cloudflare-operations-BipGMJ5O.mjs");
86
+ const { activateCloudflareExistingVersion, readCloudflareWorkerStatus, resolveCloudflareOperationContext } = await import("./cloudflare-operations-BT6OWFBk.mjs");
87
87
  const context = resolveCloudflareOperationContext(root);
88
88
  const status = await readCloudflareWorkerStatus(context);
89
89
  const deployedVersionIds = new Set(status.deployedVersionIds);
@@ -1,4 +1,4 @@
1
1
  /// <reference types="@cloudflare/workers-types" />
2
2
  import { a as number, c as url, i as json, n as boolean, o as oneOf, r as email, s as string, t as EnvSchema } from "../env-helpers-CyKtOBpj.mjs";
3
- import { a as _getSchemaDefaults, c as defineEnv, i as _getRegisteredSchema, l as env, n as EnvValidationReport, o as _hasRegisteredSchema, r as ValidatedEnv, s as _validateEnvOnce, t as EnvValidationError, u as validateAllEnv } from "../env-public-D_6u46fX.mjs";
3
+ import { a as _getSchemaDefaults, c as defineEnv, i as _getRegisteredSchema, l as env, n as EnvValidationReport, o as _hasRegisteredSchema, r as ValidatedEnv, s as _validateEnvOnce, t as EnvValidationError, u as validateAllEnv } from "../env-public-BxU_0yTL.mjs";
4
4
  export { type EnvSchema, EnvValidationError, EnvValidationReport, ValidatedEnv, _getRegisteredSchema, _getSchemaDefaults, _hasRegisteredSchema, _validateEnvOnce, boolean, defineEnv, email, env, json, number, oneOf, string, url, validateAllEnv };
@@ -1,3 +1,3 @@
1
1
  /// <reference types="@cloudflare/workers-types" />
2
- import { C as defer, E as ValidatorSlots, S as InferProps, T as HandlerInput, _ as defineQueue, a as CloudEnv, b as Deferred, c as QueueRetryOptions, d as TypedQueueHandler, f as VoidAssetRewriteError, g as defineMiddleware, h as defineHead, i as CloudContextVariables, l as RenderAssetTags, m as defineHandler, n as CloudBindings, o as QueueBatch, p as basicAuth, r as CloudContext, s as QueueMessage, t as BasicAuthOptions, u as TypedHandler, v as defineRender, w as ValidationError, y as defineScheduled } from "../handler-BXJTXd02.mjs";
2
+ import { C as defer, E as ValidatorSlots, S as InferProps, T as HandlerInput, _ as defineQueue, a as CloudEnv, b as Deferred, c as QueueRetryOptions, d as TypedQueueHandler, f as VoidAssetRewriteError, g as defineMiddleware, h as defineHead, i as CloudContextVariables, l as RenderAssetTags, m as defineHandler, n as CloudBindings, o as QueueBatch, p as basicAuth, r as CloudContext, s as QueueMessage, t as BasicAuthOptions, u as TypedHandler, v as defineRender, w as ValidationError, y as defineScheduled } from "../handler-HEcZsaij.mjs";
3
3
  export { BasicAuthOptions, CloudBindings, CloudContext, CloudContextVariables, CloudEnv, type Deferred, type HandlerInput, type InferProps, QueueBatch, QueueMessage, QueueRetryOptions, RenderAssetTags, TypedHandler, TypedQueueHandler, ValidationError, type ValidatorSlots, VoidAssetRewriteError, basicAuth, defer, defineHandler, defineHead, defineMiddleware, defineQueue, defineRender, defineScheduled };