void 0.20.2 → 0.20.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{auth-cmd-gniL2fNt.mjs → auth-cmd-CzwquNiP.mjs} +3 -3
- package/dist/{auth-link-NZdjCmSc.mjs → auth-link-ElDTgF7j.mjs} +3 -3
- package/dist/{build-cmd-sI18tX_O.mjs → build-cmd-BpJe6boP.mjs} +1 -1
- package/dist/{cache-IHn5MwBC.mjs → cache-D98YTqeE.mjs} +1 -1
- package/dist/{cancel-deploy-C5qTOdLi.mjs → cancel-deploy-CPbEQLMG.mjs} +1 -1
- package/dist/cli/cli.mjs +27 -26
- package/dist/{client-dHfSJvAN.mjs → client-BQBrZoCX.mjs} +143 -78
- package/dist/{connect-Bfk31O_8.mjs → connect-WCQZ_u3m.mjs} +3 -3
- package/dist/{create-project-Bk9Z0-Jg.mjs → create-project-D0oXA090.mjs} +2 -3
- package/dist/{db-BkRoptAt.mjs → db-DJ-9qs3S.mjs} +2 -2
- package/dist/{delete-DouASY9P.mjs → delete-BZ4-WaGm.mjs} +1 -1
- package/dist/{deploy-DTaWUS1S.mjs → deploy-BAhhcg5q.mjs} +17 -10
- package/dist/{domain-1RhhOVrC.mjs → domain-BxAyhxXN.mjs} +1 -1
- package/dist/{email-C-lGh51B.mjs → email-Bj7Cvdwp.mjs} +2 -2
- package/dist/{env-DJHsPE7Z.mjs → env-DP_EErve.mjs} +1 -1
- package/dist/{github-cmd-PW7ZnWTp.mjs → github-cmd-C-z_xRrQ.mjs} +13 -19
- package/dist/index.mjs +4 -4
- package/dist/{init-BWZ7q5Z4.mjs → init-BGktCXgA.mjs} +4 -4
- package/dist/{link-Rmvu2Wl_.mjs → link-D2kbqhWb.mjs} +2 -2
- package/dist/{list-DEE2S6mY.mjs → list-CvkK_G7k.mjs} +1 -1
- package/dist/{login-Uvferzmm.mjs → login-WIjNc77c.mjs} +2 -2
- package/dist/{logs-27FenuiC.mjs → logs-dLUFCapG.mjs} +1 -1
- package/dist/{operator-cmd-CjOTmAYE.mjs → operator-cmd-CKJ7xIRs.mjs} +2 -2
- package/dist/{platform-auth-config-DrbQXXiW.mjs → platform-auth-config-CdVWRRJr.mjs} +2 -2
- package/dist/{platform-auth-protection-Bhtvp0B_.mjs → platform-auth-protection-Drl0qhrn.mjs} +2 -2
- package/dist/{platform-auth-recovery-CeOKGVeJ.mjs → platform-auth-recovery-CmKEWpDo.mjs} +2 -2
- package/dist/{platform-cmd-BFhieCdV.mjs → platform-cmd-5q_k56xS.mjs} +3 -3
- package/dist/{platform-domain-C74PULqV.mjs → platform-domain-4GiDlcqx.mjs} +2 -2
- package/dist/{platform-lifecycle-BwAIgz-t.mjs → platform-lifecycle-R9xAxvtG.mjs} +61 -25
- package/dist/{platform-management-COogu_Se.mjs → platform-management-BfWsXHEW.mjs} +5 -3
- package/dist/{platform-recovery-ewqLefp1.mjs → platform-recovery-CbK-I1FB.mjs} +2 -2
- package/dist/{project-cmd-DmZK9Hxf.mjs → project-cmd-CTdmnzvc.mjs} +12 -12
- package/dist/{project-team-D8jOJMUJ.mjs → project-team-CGxsQe3_.mjs} +4 -2
- package/dist/{project-token-DA34bf-C.mjs → project-token-Cirx7uwZ.mjs} +1 -1
- package/dist/{requests-CUExwGQQ.mjs → requests-4Nq59hOr.mjs} +1 -1
- package/dist/{rollback-CDNGU1gr.mjs → rollback-Dr7u0Ljx.mjs} +1 -1
- package/dist/runtime/remote/index.mjs +49 -8
- package/dist/runtime/sandbox.d.mts +4 -56
- package/dist/runtime/sandbox.mjs +81 -220
- package/dist/{secret-Bzzi2e9E.mjs → secret-AcPi-FoA.mjs} +1 -1
- package/package.json +7 -7
- package/skills/void/SKILL.md +2 -2
- package/skills/void/docs/guide/deployment.md +14 -14
- package/skills/void/docs/guide/email.md +12 -10
- package/skills/void/docs/guide/platform/administration/access.md +163 -0
- package/skills/void/docs/guide/platform/administration/email.md +121 -0
- package/skills/void/docs/guide/platform/administration/operations.md +97 -0
- package/skills/void/docs/guide/platform/administration/projects.md +54 -0
- package/skills/void/docs/guide/platform/development/local.md +119 -0
- package/skills/void/docs/guide/platform/development/runtime.md +124 -0
- package/skills/void/docs/guide/platform/development/schema-ci.md +95 -0
- package/skills/void/docs/guide/platform/installation/ci.md +55 -0
- package/skills/void/docs/guide/platform/installation/credentials.md +80 -0
- package/skills/void/docs/guide/platform/installation/domains.md +68 -0
- package/skills/void/docs/guide/platform/installation/first-deployment.md +82 -0
- package/skills/void/docs/guide/platform/installation/maintenance.md +137 -0
- package/skills/void/docs/guide/platform/installation/prerequisites.md +86 -0
- package/skills/void/docs/guide/platform/installation/setup.md +169 -0
- package/skills/void/docs/guide/platform/installation/uninstall.md +54 -0
- package/skills/void/docs/guide/platform-administration.md +6 -414
- package/skills/void/docs/guide/platform-development.md +5 -316
- package/skills/void/docs/guide/project-collaboration.md +1 -1
- package/skills/void/docs/guide/sandboxes.md +9 -24
- package/skills/void/docs/guide/self-hosted-platform.md +11 -694
- package/skills/void/docs/reference/api.md +34 -34
- package/skills/void/docs/reference/cli.md +28 -11
- package/skills/void/docs/reference/config.md +1 -1
- package/skills/void/docs/reference/resource-inference.md +10 -10
|
@@ -1501,7 +1501,7 @@ async function verifyInstalledPlatformAccessProtection(input) {
|
|
|
1501
1501
|
}
|
|
1502
1502
|
const existingWorkers = input.plan.actions.filter((action) => action.kind === "worker" && action.action === "update").map((action) => action.name);
|
|
1503
1503
|
if (existingWorkers.length) {
|
|
1504
|
-
const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-
|
|
1504
|
+
const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-Drl0qhrn.mjs");
|
|
1505
1505
|
await verifyProtectionWorkerOrigins({
|
|
1506
1506
|
request: input.client.request.bind(input.client),
|
|
1507
1507
|
listWorkerDomains: input.client.listWorkerDomains.bind(input.client),
|
|
@@ -1599,6 +1599,7 @@ async function createPlatformInstallPlan(client, input, existing, options) {
|
|
|
1599
1599
|
const enableEmail = options?.includeEmailGateway !== false && !!emailSharedZoneId && !!normalizedEmailSenderDomain;
|
|
1600
1600
|
const capabilities = {
|
|
1601
1601
|
...existing?.deployment.capabilities,
|
|
1602
|
+
...options?.enableSandbox ? { sandbox: true } : {},
|
|
1602
1603
|
...input.authentication ? {
|
|
1603
1604
|
githubOAuth: input.authentication.providers.includes("github"),
|
|
1604
1605
|
googleOAuth: input.authentication.providers.includes("google")
|
|
@@ -1629,13 +1630,20 @@ async function createPlatformInstallPlan(client, input, existing, options) {
|
|
|
1629
1630
|
});
|
|
1630
1631
|
const { emailSharedZoneId: configuredEmailZone, emailSenderDomain: configuredSenderDomain, ...deploymentWithoutEmailZone } = deployment;
|
|
1631
1632
|
const { emailSharedZoneId: recordedEmailZone, emailSenderDomain: recordedSenderDomain, ...existingWithoutEmailZone } = existing?.deployment ?? deployment;
|
|
1632
|
-
const
|
|
1633
|
+
const existingWithSandbox = existing && options?.enableSandbox ? {
|
|
1633
1634
|
...existingWithoutEmailZone,
|
|
1634
1635
|
capabilities: {
|
|
1635
1636
|
...existingWithoutEmailZone.capabilities,
|
|
1636
|
-
|
|
1637
|
+
sandbox: true
|
|
1637
1638
|
}
|
|
1638
1639
|
} : existingWithoutEmailZone;
|
|
1640
|
+
const comparableExistingWithoutEmailZone = existing && deployment.capabilities.email && !existing.deployment.capabilities.email ? {
|
|
1641
|
+
...existingWithSandbox,
|
|
1642
|
+
capabilities: {
|
|
1643
|
+
...existingWithSandbox.capabilities,
|
|
1644
|
+
email: true
|
|
1645
|
+
}
|
|
1646
|
+
} : existingWithSandbox;
|
|
1639
1647
|
if (existing && (JSON.stringify(comparableExistingWithoutEmailZone) !== JSON.stringify(deploymentWithoutEmailZone) || recordedEmailZone !== void 0 && recordedEmailZone !== configuredEmailZone || recordedSenderDomain !== void 0 && recordedSenderDomain !== configuredSenderDomain)) throw new Error(`platform: --resume inputs do not match installation ${existing.id}. Use its recorded configuration.`);
|
|
1640
1648
|
const names = deployment.resources;
|
|
1641
1649
|
const wildcardHostname = `*.${deployment.application.baseDomain}`;
|
|
@@ -1793,7 +1801,8 @@ async function revalidatePlatformInstallAction(client, original, manifest, actio
|
|
|
1793
1801
|
zoneName: deployment.application.zoneName
|
|
1794
1802
|
}, manifest, {
|
|
1795
1803
|
...options,
|
|
1796
|
-
includeEmailGateway: original.actions.some((entry) => entry.key === "email-gateway-worker")
|
|
1804
|
+
includeEmailGateway: original.actions.some((entry) => entry.key === "email-gateway-worker"),
|
|
1805
|
+
enableSandbox: original.deployment.capabilities.sandbox
|
|
1797
1806
|
})).actions.find((entry) => entry.key === action.key);
|
|
1798
1807
|
if (!current || current.kind !== action.kind || current.name !== action.name || current.action !== action.action) throw new Error(`platform: Cloudflare changed after the installation plan was approved for ${action.kind} ${JSON.stringify(action.name)}. Review a new plan before retrying.`);
|
|
1799
1808
|
if (action.kind === "worker" && action.action === "update") {
|
|
@@ -2771,7 +2780,8 @@ async function installPlatform(plan, secrets, existing, dependencies) {
|
|
|
2771
2780
|
const targetSandboxDrainProtocol = runtime.safetyProtocols?.sandboxDrain ?? 0;
|
|
2772
2781
|
const prepareSandboxDrain = dependencies.prepareSandboxDrain ?? releaseDatabaseLock.prepareSandboxDrain;
|
|
2773
2782
|
if (targetSandboxDrainProtocol >= 1 && !prepareSandboxDrain) throw new Error("platform: The PostgreSQL lifecycle lock cannot establish the sandbox-drain safety checkpoint.");
|
|
2774
|
-
const sandboxDrainPreparation = targetSandboxDrainProtocol >= 1 ? await prepareSandboxDrain(targetSandboxDrainProtocol >= 2 ? 2 : 0) : null;
|
|
2783
|
+
const sandboxDrainPreparation = targetSandboxDrainProtocol >= 1 ? await prepareSandboxDrain(targetSandboxDrainProtocol >= 3 ? 3 : targetSandboxDrainProtocol >= 2 ? 2 : 0) : null;
|
|
2784
|
+
if (sandboxDrainPreparation && sandboxDrainPreparation.admissionProtocol < targetSandboxDrainProtocol) throw new Error("platform: The database did not arm the Sandbox admission protocol required by this runtime.");
|
|
2775
2785
|
const sandboxDrainRoutingKvId = requireId(Object.fromEntries(manifest.resources.map((resource) => [resource.key, resource.id])), "routing-kv");
|
|
2776
2786
|
const writeSandboxDrainMirror = async (preparation) => {
|
|
2777
2787
|
await dependencies.client.putKvValue(plan.account.id, sandboxDrainRoutingKvId, PLATFORM_SANDBOX_DRAIN_KEY, preparation.mirrorValue);
|
|
@@ -3836,14 +3846,14 @@ async function preparePlatformSandboxDrainConnection(client, requiredAdmissionPr
|
|
|
3836
3846
|
AND table_name = 'sandbox_drain_checkpoints'
|
|
3837
3847
|
AND column_name = 'admission_protocol'
|
|
3838
3848
|
) AS "present"`)).rows[0]?.present === true;
|
|
3839
|
-
if (requiredAdmissionProtocol
|
|
3849
|
+
if (requiredAdmissionProtocol >= 2 && !hasAdmissionColumn) throw new Error("platform: The runtime database does not include the sandbox deployment admission barrier.");
|
|
3840
3850
|
const readCheckpoint = () => client.query(`SELECT ${hasAdmissionColumn ? "\"admission_protocol\"" : "0 AS \"admission_protocol\""}, "generation", "state", "phase", "cursor", "started_at", "updated_at", "completed_at"
|
|
3841
3851
|
FROM "sandbox_drain_checkpoints"
|
|
3842
3852
|
WHERE "singleton" = true`);
|
|
3843
3853
|
const classify = (row) => {
|
|
3844
3854
|
if (!row) return null;
|
|
3845
3855
|
const cursor = row.cursor;
|
|
3846
|
-
if (!row.generation || row.admission_protocol !== 0 && row.admission_protocol !== 2 || !row.started_at || !row.updated_at || row.state !== "draining" && row.state !== "complete" || row.phase !== "deployments" && row.phase !== "resources" || !cursor || cursor.pass !== "1" && cursor.pass !== "2" || row.state === "complete" && (!row.completed_at || row.phase !== "resources" || cursor.pass !== "2") || row.state === "draining" && row.completed_at !== null) throw new Error("platform: The authoritative sandbox-drain database checkpoint is invalid. Traffic remains disabled.");
|
|
3856
|
+
if (!row.generation || row.admission_protocol !== 0 && row.admission_protocol !== 2 && row.admission_protocol !== 3 || !row.started_at || !row.updated_at || row.state !== "draining" && row.state !== "complete" || row.phase !== "deployments" && row.phase !== "resources" || !cursor || cursor.pass !== "1" && cursor.pass !== "2" || row.state === "complete" && (!row.completed_at || row.phase !== "resources" || cursor.pass !== "2") || row.state === "draining" && row.completed_at !== null) throw new Error("platform: The authoritative sandbox-drain database checkpoint is invalid. Traffic remains disabled.");
|
|
3847
3857
|
return {
|
|
3848
3858
|
admissionProtocol: row.admission_protocol,
|
|
3849
3859
|
generation: row.generation,
|
|
@@ -3860,7 +3870,23 @@ async function preparePlatformSandboxDrainConnection(client, requiredAdmissionPr
|
|
|
3860
3870
|
};
|
|
3861
3871
|
const existingState = classify((await readCheckpoint()).rows[0]);
|
|
3862
3872
|
if (existingState && (requiredAdmissionProtocol === 0 || existingState.admissionProtocol >= requiredAdmissionProtocol)) return existingState;
|
|
3863
|
-
if (requiredAdmissionProtocol
|
|
3873
|
+
if (requiredAdmissionProtocol >= 2) {
|
|
3874
|
+
if (existingState && existingState.admissionProtocol >= 2) {
|
|
3875
|
+
await client.query("BEGIN");
|
|
3876
|
+
try {
|
|
3877
|
+
await client.query("LOCK TABLE \"deployments\" IN SHARE MODE");
|
|
3878
|
+
await client.query(`UPDATE "sandbox_drain_checkpoints"
|
|
3879
|
+
SET "admission_protocol" = GREATEST("admission_protocol", $1), "updated_at" = now()
|
|
3880
|
+
WHERE "singleton" = true`, [requiredAdmissionProtocol]);
|
|
3881
|
+
const advanced = classify((await readCheckpoint()).rows[0]);
|
|
3882
|
+
if (!advanced || advanced.admissionProtocol < requiredAdmissionProtocol) throw new Error("platform: The Sandbox controller admission barrier could not be armed.");
|
|
3883
|
+
await client.query("COMMIT");
|
|
3884
|
+
return advanced;
|
|
3885
|
+
} catch (error) {
|
|
3886
|
+
await client.query("ROLLBACK").catch(() => void 0);
|
|
3887
|
+
throw error;
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3864
3890
|
const generation = randomUUID();
|
|
3865
3891
|
await client.query("BEGIN");
|
|
3866
3892
|
try {
|
|
@@ -3893,8 +3919,10 @@ async function preparePlatformSandboxDrainConnection(client, requiredAdmissionPr
|
|
|
3893
3919
|
WHERE "singleton" = true
|
|
3894
3920
|
AND "admission_protocol" = 2
|
|
3895
3921
|
AND "generation" = $1`, [generation]);
|
|
3922
|
+
if (requiredAdmissionProtocol >= 3) await client.query(`UPDATE "sandbox_drain_checkpoints" SET "admission_protocol" = $1
|
|
3923
|
+
WHERE "singleton" = true`, [requiredAdmissionProtocol]);
|
|
3896
3924
|
const armed = classify((await readCheckpoint()).rows[0]);
|
|
3897
|
-
if (!armed || armed.admissionProtocol
|
|
3925
|
+
if (!armed || armed.admissionProtocol < requiredAdmissionProtocol) throw new Error("platform: The sandbox deployment admission barrier could not be armed.");
|
|
3898
3926
|
await client.query("COMMIT");
|
|
3899
3927
|
return armed;
|
|
3900
3928
|
} catch (error) {
|
|
@@ -3937,12 +3965,17 @@ async function readRequiredPlatformSafetyProtocols(client) {
|
|
|
3937
3965
|
AND table_name = 'sandbox_drain_checkpoints'
|
|
3938
3966
|
AND column_name = 'admission_protocol'
|
|
3939
3967
|
) AS "present"`)).rows[0]?.present === true) {
|
|
3940
|
-
|
|
3968
|
+
const admission = await client.query(`SELECT EXISTS(
|
|
3941
3969
|
SELECT 1
|
|
3942
3970
|
FROM "sandbox_drain_checkpoints"
|
|
3943
3971
|
WHERE "singleton" = true
|
|
3944
3972
|
AND "admission_protocol" >= 2
|
|
3945
|
-
) AS "required"
|
|
3973
|
+
) AS "required", (SELECT "admission_protocol" FROM "sandbox_drain_checkpoints"
|
|
3974
|
+
WHERE "singleton" = true) AS "protocol"`);
|
|
3975
|
+
if (admission.rows[0]?.required === true) {
|
|
3976
|
+
if (admission.rows[0].protocol != null && admission.rows[0].protocol > 3) throw new Error("platform: The database requires a newer Sandbox controller protocol.");
|
|
3977
|
+
return { sandboxDrain: admission.rows[0].protocol === 3 ? 3 : 2 };
|
|
3978
|
+
}
|
|
3946
3979
|
}
|
|
3947
3980
|
return { sandboxDrain: (await client.query(`SELECT EXISTS(
|
|
3948
3981
|
SELECT 1
|
|
@@ -4817,7 +4850,7 @@ var PlatformAccessBlockedError = class extends Error {
|
|
|
4817
4850
|
"Void’s own authentication stays enabled. Keep account-wide Default-Deny on.",
|
|
4818
4851
|
"",
|
|
4819
4852
|
"For platforms that must remain Access-protected:",
|
|
4820
|
-
"https://void.cloud/guide/
|
|
4853
|
+
"https://void.cloud/guide/platform/installation/maintenance#cloudflare-access"
|
|
4821
4854
|
].join("\n"));
|
|
4822
4855
|
}
|
|
4823
4856
|
};
|
|
@@ -5199,9 +5232,9 @@ function platformSetupLink(page, hyperlinks = supportsSetupLinks()) {
|
|
|
5199
5232
|
return hyperlinks ? "\x1B]8;;" + page.url + "\x1B\\" + page.title + "\x1B]8;;\x1B\\" : page.title + ": " + page.url;
|
|
5200
5233
|
}
|
|
5201
5234
|
function platformSetupFieldHelp(key) {
|
|
5202
|
-
const docs = (section, title) => platformSetupLink({
|
|
5235
|
+
const docs = (page, section, title) => platformSetupLink({
|
|
5203
5236
|
title,
|
|
5204
|
-
url:
|
|
5237
|
+
url: `https://void.cloud/guide/platform/installation/${page}#${section}`
|
|
5205
5238
|
});
|
|
5206
5239
|
switch (key) {
|
|
5207
5240
|
case "databaseUrl": return {
|
|
@@ -5209,10 +5242,10 @@ function platformSetupFieldHelp(key) {
|
|
|
5209
5242
|
description: "Stores platform users, projects, and deployments; use an empty hosted database, e.g. " + platformSetupLink({
|
|
5210
5243
|
title: "Neon",
|
|
5211
5244
|
url: "https://neon.com/"
|
|
5212
|
-
}) + ". " + docs("platform-database", "Database setup")
|
|
5245
|
+
}) + ". " + docs("prerequisites", "platform-database", "Database setup")
|
|
5213
5246
|
};
|
|
5214
|
-
case "jwtSecret": return { description: "Signs platform login tokens. Run openssl rand -base64 32; save the key in your password manager. " + docs("signing-and-encryption-keys", "Key setup") };
|
|
5215
|
-
case "projectSecretKey": return { description: "Encrypts app secrets. Run openssl rand -base64 32 separately; save this key for recovery. " + docs("signing-and-encryption-keys", "Key setup") };
|
|
5247
|
+
case "jwtSecret": return { description: "Signs platform login tokens. Run openssl rand -base64 32; save the key in your password manager. " + docs("credentials", "signing-and-encryption-keys", "Key setup") };
|
|
5248
|
+
case "projectSecretKey": return { description: "Encrypts app secrets. Run openssl rand -base64 32 separately; save this key for recovery. " + docs("credentials", "signing-and-encryption-keys", "Key setup") };
|
|
5216
5249
|
default: return;
|
|
5217
5250
|
}
|
|
5218
5251
|
}
|
|
@@ -5407,14 +5440,14 @@ function resolvePlatformInstallDatabaseUrl(checkpoint, manifest = null) {
|
|
|
5407
5440
|
}
|
|
5408
5441
|
async function runPlatformLifecycleCommand(args) {
|
|
5409
5442
|
if (args.subcommand === "domain") {
|
|
5410
|
-
const { runPlatformDomainCommand } = await import("./platform-domain-
|
|
5443
|
+
const { runPlatformDomainCommand } = await import("./platform-domain-4GiDlcqx.mjs");
|
|
5411
5444
|
await runPlatformDomainCommand(args);
|
|
5412
5445
|
return;
|
|
5413
5446
|
}
|
|
5414
5447
|
if (args.subcommand === "discover") {
|
|
5415
5448
|
const client = new PlatformCloudflareClient((await resolvePlatformCloudflareCredential()).token);
|
|
5416
5449
|
const accountId = await selectAccount(await readAccounts(client), args.account);
|
|
5417
|
-
const { recoverPlatformInstallations } = await import("./platform-recovery-
|
|
5450
|
+
const { recoverPlatformInstallations } = await import("./platform-recovery-CbK-I1FB.mjs");
|
|
5418
5451
|
const recovered = await recoverPlatformInstallations(client, accountId, void 0, args.selector);
|
|
5419
5452
|
if (recovered.length === 0) {
|
|
5420
5453
|
log.info(`No recoverable Void platform installations were found in ${accountId}.`);
|
|
@@ -5424,7 +5457,7 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5424
5457
|
return;
|
|
5425
5458
|
}
|
|
5426
5459
|
if (args.subcommand !== "install") {
|
|
5427
|
-
const { runInstalledPlatformCommand } = await import("./platform-management-
|
|
5460
|
+
const { runInstalledPlatformCommand } = await import("./platform-management-BfWsXHEW.mjs");
|
|
5428
5461
|
await runInstalledPlatformCommand(args);
|
|
5429
5462
|
return;
|
|
5430
5463
|
}
|
|
@@ -5574,7 +5607,7 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5574
5607
|
progress?.stop("Read the saved installation.");
|
|
5575
5608
|
progress = void 0;
|
|
5576
5609
|
if (authoritative) {
|
|
5577
|
-
const { selectAuthoritativePlatformManifest } = await import("./platform-management-
|
|
5610
|
+
const { selectAuthoritativePlatformManifest } = await import("./platform-management-BfWsXHEW.mjs");
|
|
5578
5611
|
const selected = selectAuthoritativePlatformManifest(existing, authoritative);
|
|
5579
5612
|
authoritativeProvisionIntents = true;
|
|
5580
5613
|
if (!args.plan && JSON.stringify(selected) !== JSON.stringify(existing)) writeInstallationManifest(selected);
|
|
@@ -5599,7 +5632,8 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5599
5632
|
let plan = await createPlatformInstallPlan(client, planInput, existing, {
|
|
5600
5633
|
authoritativeProvisionIntents,
|
|
5601
5634
|
allowUnverifiedAiGateway: true,
|
|
5602
|
-
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0
|
|
5635
|
+
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0,
|
|
5636
|
+
enableSandbox: runtime.manifest.safetyProtocols.sandboxDrain >= 3
|
|
5603
5637
|
});
|
|
5604
5638
|
note(formatPlatformInstallPlan(plan), args.plan ? "Read-only installation plan" : "Installation plan");
|
|
5605
5639
|
note(formatPlatformRuntime(runtime), "Platform runtime");
|
|
@@ -5780,11 +5814,12 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5780
5814
|
replanWorkers: async (manifest) => (await createPlatformInstallPlan(client, planInput, manifest, {
|
|
5781
5815
|
authoritativeProvisionIntents: true,
|
|
5782
5816
|
repairMissing: true,
|
|
5783
|
-
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0
|
|
5817
|
+
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0,
|
|
5818
|
+
enableSandbox: runtime.manifest.safetyProtocols.sandboxDrain >= 3
|
|
5784
5819
|
})).actions.filter((action) => action.kind === "worker"),
|
|
5785
5820
|
revalidateBeforeWorkerDeploy: (manifest, action) => revalidatePlatformInstallAction(client, plan, manifest, action),
|
|
5786
5821
|
verifyExistingOwnership: async (manifest, databaseCheckpointExists) => {
|
|
5787
|
-
const { verifyPlatformInstallationOwnership } = await import("./platform-management-
|
|
5822
|
+
const { verifyPlatformInstallationOwnership } = await import("./platform-management-BfWsXHEW.mjs");
|
|
5788
5823
|
const retainedReplacementKeys = new Set(plan.actions.filter((action) => {
|
|
5789
5824
|
const previous = manifest.resources.find((resource) => resource.key === action.key);
|
|
5790
5825
|
return action.action === "create" && previous && previous.name !== action.name;
|
|
@@ -5849,7 +5884,8 @@ async function verifyPlatformAiGatewayPlan(client, input, existing, preview, aut
|
|
|
5849
5884
|
try {
|
|
5850
5885
|
verified = await createPlatformInstallPlan(client, input, existing, {
|
|
5851
5886
|
authoritativeProvisionIntents,
|
|
5852
|
-
includeEmailGateway: preview.actions.some((entry) => entry.key === "email-gateway-worker")
|
|
5887
|
+
includeEmailGateway: preview.actions.some((entry) => entry.key === "email-gateway-worker"),
|
|
5888
|
+
enableSandbox: preview.deployment.capabilities.sandbox
|
|
5853
5889
|
});
|
|
5854
5890
|
} catch (error) {
|
|
5855
5891
|
if (error instanceof PlatformCloudflareApiError && (error.status === 401 || error.status === 403) && error.requestPath?.includes("/ai-gateway/")) throw new Error("platform: The runtime token could not verify AI Gateway access. Include Account → AI Gateway → Edit for this account, then retry. No platform resources were created.", { cause: error });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as outro, D as log, I as isCancel, J as listInstallationManifests, M as select, W as acquirePlatformLifecycleLock, et as readInstallationRecoverySecrets, i as createSpinner, it as resolveInstallationManifest, k as note, nt as removeInstallationRecoverySecrets, rt as removePlatformConnectionForInstallation, st as writeInstallationManifest, w as confirm } from "./output-B0cfNSx5.mjs";
|
|
2
|
-
import { C as PlatformCloudflareClient, D as verifyPlatformRuntimeTokenPermissions, E as hyperdriveOriginMatches, T as hyperdriveOriginFromConnectionString, _ as revalidatePlatformInstallAction, a as createPlatformInstallationSecrets, assertNoninteractivePlatformMutationAcknowledged, f as trackedPlatformWorkerTraffic, g as platformProvisionIntentHash, h as platformAdoptionIntentHash, m as formatPlatformInstallPlan, n as acquirePlatformDatabaseLifecycleLock, o as installPlatform, p as createPlatformInstallPlan, resolvePlatformInstallDatabaseUrl, s as loadPlatformRuntime, t as REMOTE_INSTALLATION_MANIFEST_KEY, u as resolveBootstrapGitHubId, v as assertPlatformOperatorCredentialCanApplyPlan, w as hyperdriveOriginConfigHash, y as resolvePlatformCloudflareCredential } from "./platform-lifecycle-
|
|
2
|
+
import { C as PlatformCloudflareClient, D as verifyPlatformRuntimeTokenPermissions, E as hyperdriveOriginMatches, T as hyperdriveOriginFromConnectionString, _ as revalidatePlatformInstallAction, a as createPlatformInstallationSecrets, assertNoninteractivePlatformMutationAcknowledged, f as trackedPlatformWorkerTraffic, g as platformProvisionIntentHash, h as platformAdoptionIntentHash, m as formatPlatformInstallPlan, n as acquirePlatformDatabaseLifecycleLock, o as installPlatform, p as createPlatformInstallPlan, resolvePlatformInstallDatabaseUrl, s as loadPlatformRuntime, t as REMOTE_INSTALLATION_MANIFEST_KEY, u as resolveBootstrapGitHubId, v as assertPlatformOperatorCredentialCanApplyPlan, w as hyperdriveOriginConfigHash, y as resolvePlatformCloudflareCredential } from "./platform-lifecycle-R9xAxvtG.mjs";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE, PLATFORM_R2_OWNERSHIP_MARKER_KEY, createPlatformResourceOwnershipMarker, parsePlatformInstallationManifest, parsePlatformResourceOwnershipMarker, recordInstallationResource, recordInstallationStep, setInstallationDesiredState, transitionInstallation } from "@void/platform";
|
|
5
5
|
//#region src/cli/platform-management.ts
|
|
@@ -72,7 +72,8 @@ async function runInstalledPlatformCommand(args) {
|
|
|
72
72
|
authoritativeProvisionIntents: databaseCheckpointExists,
|
|
73
73
|
repairMissing: args.subcommand === "repair",
|
|
74
74
|
allowUnverifiedAiGateway: args.plan,
|
|
75
|
-
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0
|
|
75
|
+
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0,
|
|
76
|
+
enableSandbox: runtime.manifest.safetyProtocols.sandboxDrain >= 3
|
|
76
77
|
});
|
|
77
78
|
note(formatPlatformInstallPlan(plan), args.subcommand === "upgrade" ? "Upgrade plan" : args.subcommand === "rollback" ? "Rollback plan" : args.subcommand === "enable" ? "Enable plan" : "Repair plan");
|
|
78
79
|
note([
|
|
@@ -144,7 +145,8 @@ async function runInstalledPlatformCommand(args) {
|
|
|
144
145
|
replanWorkers: async (recoveryManifest) => (await createPlatformInstallPlan(client, planInput, recoveryManifest, {
|
|
145
146
|
authoritativeProvisionIntents: true,
|
|
146
147
|
repairMissing: true,
|
|
147
|
-
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0
|
|
148
|
+
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0,
|
|
149
|
+
enableSandbox: runtime.manifest.safetyProtocols.sandboxDrain >= 3
|
|
148
150
|
})).actions.filter((action) => action.kind === "worker"),
|
|
149
151
|
revalidateBeforeWorkerDeploy: (manifest, action) => revalidatePlatformInstallAction(client, plan, manifest, action, { repairMissing: args.subcommand === "repair" })
|
|
150
152
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { J as listInstallationManifests, W as acquirePlatformLifecycleLock, at as savePlatformConnection, st as writeInstallationManifest } from "./output-B0cfNSx5.mjs";
|
|
2
2
|
import { t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
|
|
3
|
-
import { p as createPlatformInstallPlan, t as REMOTE_INSTALLATION_MANIFEST_KEY } from "./platform-lifecycle-
|
|
4
|
-
import { isPlatformManifestMonotonicExtension, recoverDurablyMarkedProvisionIntents, verifyPlatformInstallationOwnership } from "./platform-management-
|
|
3
|
+
import { p as createPlatformInstallPlan, t as REMOTE_INSTALLATION_MANIFEST_KEY } from "./platform-lifecycle-R9xAxvtG.mjs";
|
|
4
|
+
import { isPlatformManifestMonotonicExtension, recoverDurablyMarkedProvisionIntents, verifyPlatformInstallationOwnership } from "./platform-management-BfWsXHEW.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 = "") {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as outro, D as log, E as intro, a as dim, c as import_picocolors, r as cliTitle, u as tablePrefix } from "./output-B0cfNSx5.mjs";
|
|
2
2
|
import { c as getSiteDomain, l as getToken, x as readDeploymentPlatform } from "./auth-DPl6kck4.mjs";
|
|
3
|
-
import { n as PlatformClient } from "./client-
|
|
3
|
+
import { n as PlatformClient } from "./client-BQBrZoCX.mjs";
|
|
4
4
|
//#region src/cli/projects.ts
|
|
5
5
|
async function runProjectsCommand(root) {
|
|
6
6
|
console.log();
|
|
@@ -37,24 +37,24 @@ async function runProjectsCommand(root) {
|
|
|
37
37
|
async function runProjectCommand(root, args) {
|
|
38
38
|
const cloudflare = readDeploymentPlatform(root) === "cloudflare";
|
|
39
39
|
if (args.subcommand === "status") {
|
|
40
|
-
const { runListCommand } = await import("./list-
|
|
40
|
+
const { runListCommand } = await import("./list-CvkK_G7k.mjs");
|
|
41
41
|
return runListCommand(root, args.name || void 0);
|
|
42
42
|
}
|
|
43
43
|
if (args.subcommand === "link") {
|
|
44
44
|
if (cloudflare) throw new Error("project: Direct Cloudflare apps are identified by the name in wrangler.jsonc and do not need linking.");
|
|
45
|
-
const { runLink } = await import("./link-
|
|
45
|
+
const { runLink } = await import("./link-D2kbqhWb.mjs");
|
|
46
46
|
return runLink(root, args.name || void 0);
|
|
47
47
|
}
|
|
48
48
|
if (args.subcommand === "list") {
|
|
49
49
|
if (cloudflare) {
|
|
50
|
-
const { runListCommand } = await import("./list-
|
|
50
|
+
const { runListCommand } = await import("./list-CvkK_G7k.mjs");
|
|
51
51
|
return runListCommand(root);
|
|
52
52
|
}
|
|
53
53
|
return runProjectsCommand(root);
|
|
54
54
|
}
|
|
55
55
|
if (args.subcommand === "token") {
|
|
56
56
|
if (cloudflare) throw new Error("project: CI deploy credentials are available only for Void platform projects.");
|
|
57
|
-
const { runProjectTokenCommand } = await import("./project-token-
|
|
57
|
+
const { runProjectTokenCommand } = await import("./project-token-Cirx7uwZ.mjs");
|
|
58
58
|
return runProjectTokenCommand(root, args);
|
|
59
59
|
}
|
|
60
60
|
if (args.subcommand === "team") {
|
|
@@ -65,35 +65,35 @@ async function runProjectCommand(root, args) {
|
|
|
65
65
|
}
|
|
66
66
|
const accountInvitationAction = args.action === "pending" || args.action === "accept" || args.action === "decline";
|
|
67
67
|
if (cloudflare && !accountInvitationAction) throw new Error("project: Teams are available only for projects hosted on a Void platform, not direct Cloudflare deployments.");
|
|
68
|
-
const { runProjectTeamCommand } = await import("./project-team-
|
|
68
|
+
const { runProjectTeamCommand } = await import("./project-team-CGxsQe3_.mjs");
|
|
69
69
|
return runProjectTeamCommand(root, args);
|
|
70
70
|
}
|
|
71
71
|
if (args.subcommand === "logs") {
|
|
72
|
-
const { runLogsCommand } = await import("./logs-
|
|
72
|
+
const { runLogsCommand } = await import("./logs-dLUFCapG.mjs");
|
|
73
73
|
return runLogsCommand(root, args.filter, args.range, args.deployment || void 0, args.level || void 0);
|
|
74
74
|
}
|
|
75
75
|
if (args.subcommand === "requests") {
|
|
76
76
|
if (cloudflare) throw new Error("project: Historical request analytics require the Void platform. Use `void project logs` for a live Cloudflare tail.");
|
|
77
|
-
const { runRequestsCommand } = await import("./requests-
|
|
77
|
+
const { runRequestsCommand } = await import("./requests-4Nq59hOr.mjs");
|
|
78
78
|
return runRequestsCommand(root, args.range, args.status || void 0);
|
|
79
79
|
}
|
|
80
80
|
if (args.subcommand === "rollback") {
|
|
81
|
-
const { runRollbackCommand } = await import("./rollback-
|
|
81
|
+
const { runRollbackCommand } = await import("./rollback-Dr7u0Ljx.mjs");
|
|
82
82
|
return runRollbackCommand(root, args.deployId || void 0);
|
|
83
83
|
}
|
|
84
84
|
if (args.subcommand === "cancel") {
|
|
85
85
|
if (cloudflare) throw new Error("project: Direct Cloudflare deploys activate only after readiness succeeds, so there is no remote build to cancel.");
|
|
86
|
-
const { runCancelDeployCommand } = await import("./cancel-deploy-
|
|
86
|
+
const { runCancelDeployCommand } = await import("./cancel-deploy-CPbEQLMG.mjs");
|
|
87
87
|
return runCancelDeployCommand(root, args.deployId || void 0);
|
|
88
88
|
}
|
|
89
89
|
if (args.subcommand === "delete") {
|
|
90
90
|
if (cloudflare) throw new Error("project: Refusing to delete Cloudflare resources through this command. Direct deployments are additive and existing resources may be shared.");
|
|
91
|
-
const { runDeleteCommand } = await import("./delete-
|
|
91
|
+
const { runDeleteCommand } = await import("./delete-BZ4-WaGm.mjs");
|
|
92
92
|
return runDeleteCommand(root, args.name || void 0, { force: args.force });
|
|
93
93
|
}
|
|
94
94
|
if (args.subcommand === "purge-cache") {
|
|
95
95
|
if (cloudflare) throw new Error("project: Direct Cloudflare ISR cache purge is not available yet; redeploy or purge the configured KV namespace explicitly.");
|
|
96
|
-
const { runPurgeCacheCommand } = await import("./cache-
|
|
96
|
+
const { runPurgeCacheCommand } = await import("./cache-D98YTqeE.mjs");
|
|
97
97
|
return runPurgeCacheCommand(root, args.projectSlug || void 0);
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as outro, D as log, E as intro, k as note, r as cliTitle } from "./output-B0cfNSx5.mjs";
|
|
2
2
|
import { S as readProjectConfig, a as getAccountCredential, l as getToken } from "./auth-DPl6kck4.mjs";
|
|
3
|
-
import { n as PlatformClient, t as PlatformApiError } from "./client-
|
|
3
|
+
import { n as PlatformClient, o as parsePlatformErrorBody, s as platformErrorMessage, t as PlatformApiError } from "./client-BQBrZoCX.mjs";
|
|
4
4
|
import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project--Vxawf7z.mjs";
|
|
5
5
|
//#region src/cli/project-team.ts
|
|
6
6
|
function clean(value) {
|
|
@@ -42,13 +42,15 @@ async function resolveProjectId(root, client, projectSlug) {
|
|
|
42
42
|
}
|
|
43
43
|
function invitationResponseError(error, apiUrl) {
|
|
44
44
|
if (!(error instanceof PlatformApiError)) return error;
|
|
45
|
+
if (platformErrorMessage(parsePlatformErrorBody(error.body))) return error;
|
|
45
46
|
let message;
|
|
46
47
|
if (error.code === "project invitation not found") message = `Invitation not found on ${apiUrl}. Check VOID_API_URL if set, connect to the platform in your invitation with \`void connect <url>\`, then run \`void project team pending\` to check the invitation ID. If it is missing, ask a project administrator for a new invitation.`;
|
|
47
48
|
else if (error.code === "forbidden") message = `Your account cannot respond to this invitation on ${apiUrl}. Sign in with the account whose registered email received the invitation. To switch accounts, set VOID_API_URL to ${apiUrl}, unset VOID_TOKEN if present, then run \`void auth logout\` and \`void auth login\`. Run \`void project team pending\` to see that account's invitations.`;
|
|
48
49
|
else if (error.code === "project invitation has expired") message = "This invitation has expired. Ask a project administrator to invite you again, then run `void project team pending`.";
|
|
49
50
|
else if (error.code === "project invitation is no longer pending") message = "This invitation has already been answered or revoked. Run `void project team pending` to see invitations awaiting your response, or ask a project administrator to check your access.";
|
|
50
51
|
else return error;
|
|
51
|
-
|
|
52
|
+
error.message = message;
|
|
53
|
+
return error;
|
|
52
54
|
}
|
|
53
55
|
async function runProjectTeamCommand(root, args) {
|
|
54
56
|
console.log();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as outro, D as log, E as intro, a as dim, r as cliTitle, u as tablePrefix } from "./output-B0cfNSx5.mjs";
|
|
2
2
|
import { S as readProjectConfig, l as getToken } from "./auth-DPl6kck4.mjs";
|
|
3
|
-
import { n as PlatformClient } from "./client-
|
|
3
|
+
import { n as PlatformClient } from "./client-BQBrZoCX.mjs";
|
|
4
4
|
import { r as resolveProjectBySlug } from "./resolve-project--Vxawf7z.mjs";
|
|
5
5
|
//#region src/cli/project-token.ts
|
|
6
6
|
async function resolveTarget(root, args) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as outro, D as log, E as intro, a as dim, c as import_picocolors, r as cliTitle } from "./output-B0cfNSx5.mjs";
|
|
2
2
|
import { S as readProjectConfig, l as getToken } from "./auth-DPl6kck4.mjs";
|
|
3
|
-
import { n as PlatformClient } from "./client-
|
|
3
|
+
import { n as PlatformClient } from "./client-BQBrZoCX.mjs";
|
|
4
4
|
//#region src/cli/requests.ts
|
|
5
5
|
async function runRequestsCommand(root, range, status) {
|
|
6
6
|
console.log();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as outro, C as cancel, D as log, E as intro, I as isCancel, M as select, a as dim, c as import_picocolors, i as createSpinner, o as ensureUtc, r as cliTitle, w as confirm } from "./output-B0cfNSx5.mjs";
|
|
2
2
|
import { S as readProjectConfig, l as getToken, x as readDeploymentPlatform } from "./auth-DPl6kck4.mjs";
|
|
3
|
-
import { n as PlatformClient } from "./client-
|
|
3
|
+
import { n as PlatformClient } from "./client-BQBrZoCX.mjs";
|
|
4
4
|
//#region src/cli/rollback.ts
|
|
5
5
|
async function runRollbackCommand(root, deployId) {
|
|
6
6
|
console.log();
|
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
import { t as cfAccessHeaders } from "../../cf-access-DRsQRe6k.mjs";
|
|
2
2
|
import { n as serializeR2Conditional } from "../../r2-conditions-D1Wk8i7b.mjs";
|
|
3
3
|
//#region src/runtime/remote/client.ts
|
|
4
|
+
function readableMessage(value) {
|
|
5
|
+
if (typeof value !== "string") return;
|
|
6
|
+
const text = value.replace(/(?:\u001b\]|\u009d)[\s\S]*?(?:\u0007|\u001b\\|\u009c|$)/g, "").replace(/(?:\u001b\[|\u009b)[0-?]*[ -/]*[@-~]/g, "").replace(/[\u0000-\u001f\u007f-\u009f]/g, " ").trim();
|
|
7
|
+
if (!text || /^[{[]/.test(text) || /<\/?[a-z!][^>]*>/i.test(text)) return;
|
|
8
|
+
return text.length > 500 ? `${text.slice(0, 500)}…` : text;
|
|
9
|
+
}
|
|
10
|
+
function isGenericPermissionMessage(message) {
|
|
11
|
+
return /^(?:(?:HTTP\s*)?(?:401|403)\s*[:-]?\s*)?(?:forbidden|unauthorized|access denied|permission denied|invalid or expired token)[.!]?$/i.test(message);
|
|
12
|
+
}
|
|
13
|
+
async function proxyError(response) {
|
|
14
|
+
const reader = response.body?.getReader();
|
|
15
|
+
const decoder = new TextDecoder();
|
|
16
|
+
let text = "";
|
|
17
|
+
let remaining = 16384;
|
|
18
|
+
try {
|
|
19
|
+
while (reader && remaining > 0) {
|
|
20
|
+
const { done, value } = await reader.read();
|
|
21
|
+
if (done) break;
|
|
22
|
+
text += decoder.decode(value.subarray(0, remaining), { stream: true });
|
|
23
|
+
remaining -= value.byteLength;
|
|
24
|
+
}
|
|
25
|
+
text += decoder.decode();
|
|
26
|
+
} catch {} finally {
|
|
27
|
+
await reader?.cancel().catch(() => {});
|
|
28
|
+
reader?.releaseLock();
|
|
29
|
+
}
|
|
30
|
+
let message;
|
|
31
|
+
let error;
|
|
32
|
+
try {
|
|
33
|
+
const body = JSON.parse(text);
|
|
34
|
+
if (body && typeof body === "object" && !Array.isArray(body)) {
|
|
35
|
+
const payload = body;
|
|
36
|
+
message = readableMessage(payload.message);
|
|
37
|
+
error = readableMessage(payload.error);
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
if (!response.headers.get("content-type")?.includes("text/html")) error = readableMessage(text);
|
|
41
|
+
}
|
|
42
|
+
if (message && isGenericPermissionMessage(message)) message = void 0;
|
|
43
|
+
if (!message && error && !isGenericPermissionMessage(error)) message = error;
|
|
44
|
+
if (!message) {
|
|
45
|
+
if (response.status === 401) message = "Remote access could not be authenticated. Sign in to the connected platform again, or restart the build to obtain a fresh prerender token.";
|
|
46
|
+
else if (response.status === 403) message = "Remote access could not be authorized. Check the selected platform and project, then ask a project admin or owner to confirm your access. If your access is correct, retry shortly.";
|
|
47
|
+
else message = error ?? "The remote service returned an unreadable error. Retry the request.";
|
|
48
|
+
}
|
|
49
|
+
return /* @__PURE__ */ new Error(`remote: Proxy request failed with ${response.status}: ${message}`);
|
|
50
|
+
}
|
|
4
51
|
/**
|
|
5
52
|
* HTTP client for the remote bindings proxy (proxy.void.cloud).
|
|
6
53
|
*
|
|
@@ -37,10 +84,7 @@ var ProxyClient = class {
|
|
|
37
84
|
}),
|
|
38
85
|
redirect: "manual"
|
|
39
86
|
});
|
|
40
|
-
if (!res.ok)
|
|
41
|
-
const text = await res.text().catch(() => res.statusText);
|
|
42
|
-
throw new Error(`remote: Proxy request failed with ${res.status}: '${text}'.`);
|
|
43
|
-
}
|
|
87
|
+
if (!res.ok) throw await proxyError(res);
|
|
44
88
|
return res;
|
|
45
89
|
}
|
|
46
90
|
/**
|
|
@@ -66,10 +110,7 @@ var ProxyClient = class {
|
|
|
66
110
|
body,
|
|
67
111
|
redirect: "manual"
|
|
68
112
|
});
|
|
69
|
-
if (!res.ok)
|
|
70
|
-
const text = await res.text().catch(() => res.statusText);
|
|
71
|
-
throw new Error(`remote: Proxy request failed with ${res.status}: '${text}'.`);
|
|
72
|
-
}
|
|
113
|
+
if (!res.ok) throw await proxyError(res);
|
|
73
114
|
return res;
|
|
74
115
|
}
|
|
75
116
|
};
|
|
@@ -3,80 +3,28 @@ import { Sandbox, SandboxOptions } from "@cloudflare/sandbox";
|
|
|
3
3
|
//#region src/runtime/sandbox.d.ts
|
|
4
4
|
export declare const DEFAULT_SANDBOX_ID = "default";
|
|
5
5
|
export declare const DEFAULT_SANDBOX_BINDING = "SANDBOX";
|
|
6
|
-
export declare const
|
|
7
|
-
export declare const SANDBOX_GATE_BINDING = "__VOID_PROXY";
|
|
8
|
-
export declare const HEARTBEAT_MS: number;
|
|
6
|
+
export declare const SANDBOX_SERVICE_BINDING = "__VOID_SANDBOX";
|
|
9
7
|
export type VoidSandboxOptions = SandboxOptions & {
|
|
10
8
|
binding?: string;
|
|
11
9
|
};
|
|
12
|
-
export type SandboxUsageEvent = Readonly<{
|
|
13
|
-
requests: 0;
|
|
14
|
-
responseBytes: 0;
|
|
15
|
-
userId?: string;
|
|
16
|
-
projectId?: string;
|
|
17
|
-
slug?: string;
|
|
18
|
-
sandboxRuntimeSeconds: number;
|
|
19
|
-
sandboxInstanceId: string;
|
|
20
|
-
}>;
|
|
21
|
-
/**
|
|
22
|
-
* Thrown by `getSandbox()` when the platform gate denies a new acquire because
|
|
23
|
-
* the user has hit a concurrency or runtime budget cap. Surface this to the
|
|
24
|
-
* caller so they can render a friendly error; do not retry transparently.
|
|
25
|
-
*/
|
|
26
10
|
export declare class SandboxLimitError extends Error {
|
|
27
11
|
override readonly name = "SandboxLimitError";
|
|
28
12
|
readonly reason: "concurrency" | "runtime_budget";
|
|
29
13
|
constructor(reason: "concurrency" | "runtime_budget", message?: string);
|
|
30
14
|
}
|
|
31
|
-
/** Managed platform Sandbox is unavailable or its activation gate cannot be verified. */
|
|
32
15
|
export declare class SandboxUnavailableError extends Error {
|
|
33
16
|
override readonly name = "SandboxUnavailableError";
|
|
34
17
|
constructor(message?: string);
|
|
35
18
|
}
|
|
36
19
|
export declare function __setSandboxBindingName(bindingName: string): void;
|
|
37
20
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* the usage queue, and notifies the gate when the container stops.
|
|
41
|
-
*
|
|
42
|
-
* Generated code from `void inference` wires user `Sandbox` subclasses to
|
|
43
|
-
* extend this class on platform deploys so per-tenant accounting works
|
|
44
|
-
* without user opt-in. On local dev (no usage-queue / gate bindings), all
|
|
45
|
-
* overrides degrade to no-ops and the sandbox behaves like the upstream
|
|
46
|
-
* `Sandbox` class.
|
|
21
|
+
* Retained for generated native/local Worker entries. Managed deployments host
|
|
22
|
+
* the platform-owned Sandbox class in a separate Worker and never use this DO.
|
|
47
23
|
*/
|
|
48
24
|
export declare class VoidPlatformSandbox<Env = unknown> extends Sandbox<Env> {
|
|
49
25
|
override onStart(): Promise<void>;
|
|
50
|
-
override alarm(alarmProps?: AlarmInvocationInfo): Promise<void>;
|
|
51
|
-
override onStop(): Promise<void>;
|
|
52
|
-
override onActivityExpired(): Promise<void>;
|
|
53
|
-
private flushFinal;
|
|
54
26
|
}
|
|
55
|
-
/**
|
|
56
|
-
* Resolve the platform-provided sandbox stub for the given id, optionally
|
|
57
|
-
* coordinating with the platform gate to enforce per-user concurrency and
|
|
58
|
-
* runtime budgets.
|
|
59
|
-
*
|
|
60
|
-
* When the gate binding (`__VOID_PROXY` by default) is present AND the
|
|
61
|
-
* platform's `__PROJECT_ID` + `__VOID_PROXY_TOKEN` identity vars are
|
|
62
|
-
* available, we POST to `https://gate/sandbox/acquire` with the HMAC-signed
|
|
63
|
-
* body the shared proxy auth middleware expects. A `409` response means the
|
|
64
|
-
* user has exceeded a budget — we throw `SandboxLimitError` so the caller
|
|
65
|
-
* can render a clear message. Any other non-OK status (or a thrown transport
|
|
66
|
-
* error from the service binding) fails closed before returning a usable
|
|
67
|
-
* managed stub.
|
|
68
|
-
*
|
|
69
|
-
* When all reserved platform identity bindings are absent, this is a native
|
|
70
|
-
* Cloudflare or local deployment and returns the upstream stub directly.
|
|
71
|
-
*
|
|
72
|
-
* The stub is constructed BEFORE calling the gate so we can pass its opaque,
|
|
73
|
-
* namespace-specific Durable Object id (`stub.id.toString()`) as `sandboxId`.
|
|
74
|
-
* The same id is available as `ctx.id.toString()` inside lifecycle hooks, so
|
|
75
|
-
* acquire, heartbeat, and release use one globally unique instance identity
|
|
76
|
-
* even when separate projects or deployments both request the name `default`.
|
|
77
|
-
* Constructing the stub does NOT start a container — that only happens on
|
|
78
|
-
* the first method call against the stub.
|
|
79
|
-
*/
|
|
27
|
+
/** Resolve an isolated Sandbox on the current deployment. Starts on first use. */
|
|
80
28
|
export declare function getSandbox<T extends Sandbox = Sandbox>(id?: string, options?: VoidSandboxOptions): Promise<T>;
|
|
81
29
|
export declare const sandbox: {
|
|
82
30
|
get: typeof getSandbox;
|