void 0.23.0 → 0.24.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.
- package/AGENTS_TEMPLATE.md +1 -1
- package/dist/{account-cmd-C84Ee8cO.mjs → account-cmd-vJhh5lrb.mjs} +5 -5
- package/dist/{auth-CSkdO2Bb.mjs → auth-CQkSDS50.mjs} +22 -49
- package/dist/auth-DX3JURcX.mjs +2 -0
- package/dist/{auth-link-CioEg6uY.mjs → auth-link-D75t9wO2.mjs} +5 -5
- package/dist/{auth-router-BsR981d4.mjs → auth-router-ClfhL1J7.mjs} +7 -7
- package/dist/{build-cmd-LzvNJORH.mjs → build-cmd-zMi1iFnS.mjs} +6 -6
- package/dist/{cache-C4MvnrMH.mjs → cache-ZtQmyxVV.mjs} +5 -5
- package/dist/{cancel-deploy-abUxpP2n.mjs → cancel-deploy-Box0kkEV.mjs} +5 -5
- package/dist/{cf-access-P0iZnu0q.mjs → cf-access-BGe5sWXF.mjs} +4 -48
- package/dist/{cf-access-DRsQRe6k.mjs → cf-access-TWNzXltp.mjs} +3 -11
- package/dist/cli/cli.mjs +47 -44
- package/dist/cli/cloudflare-operation-process.mjs +14 -5
- package/dist/cli/env-schema-probe.mjs +3 -3
- package/dist/client-B9UBI03V.mjs +2 -0
- package/dist/{client-RV8NVeB8.mjs → client-DKAsFA4X.mjs} +33 -15
- package/dist/{cloudflare-cmd-BcrVyTmJ.mjs → cloudflare-cmd-CmY8dGkd.mjs} +1 -1
- package/dist/{cloudflare-connect-B8uPZ4nx.mjs → cloudflare-connect-IiR3ZieC.mjs} +1 -1
- package/dist/{cloudflare-operations-AiWashgg.mjs → cloudflare-operations-BCdXSsmo.mjs} +1 -1
- package/dist/{cloudflare-operations-fxHb-byx.mjs → cloudflare-operations-DzH-A966.mjs} +1 -1
- package/dist/{connect-Bd4kJd9U.mjs → connect-B-usTnlF.mjs} +9 -9
- package/dist/{create-project-bMf6ffLZ.mjs → create-project-CYOOAYcn.mjs} +12 -12
- package/dist/{create-project-Boczwj5r.mjs → create-project-FWbf5Olo.mjs} +1 -1
- package/dist/{db-8uG64XLl.mjs → db-Ck2eZ2iB.mjs} +15 -15
- package/dist/{delete-NvbiyeJf.mjs → delete-sK56qtzZ.mjs} +5 -5
- package/dist/{deploy-DzAIwqNU.mjs → deploy-gCVaiJbS.mjs} +86 -44
- package/dist/{deploy-bjXdFCtn.mjs → deploy-irP5q0-x.mjs} +1 -1
- package/dist/{domain-y5Tvydvo.mjs → domain-DFfQE8jg.mjs} +6 -6
- package/dist/{email-B3umsW75.mjs → email-CdnhUHvJ.mjs} +7 -7
- package/dist/{env-BS6qYHDb.mjs → env-DmGdHi5i.mjs} +8 -8
- package/dist/{env-types-C2_bIk_b.mjs → env-types-D5kds_OZ.mjs} +1 -1
- package/dist/{env-validation-BPn7vk-V.mjs → env-validation-C_8tPdhs.mjs} +2 -2
- package/dist/{env-validation-DbTg7-ar.mjs → env-validation-zZOCcQVZ.mjs} +1 -1
- package/dist/{gen-B580--vC.mjs → gen-CshAkukR.mjs} +2 -2
- package/dist/gen-DvQTWzDU.mjs +2 -0
- package/dist/{github-cmd-v45BdfKX.mjs → github-cmd-DftuEvIt.mjs} +13 -13
- package/dist/{headers-DWi2IXWx.mjs → headers-2rKda9Y6.mjs} +1 -1
- package/dist/{help-daGKjXGk.mjs → help-Dotbf6iz.mjs} +8 -4
- package/dist/help-mabuIV98.mjs +2 -0
- package/dist/{inbound-aVHEUhKo.mjs → inbound-fRkqcXaC.mjs} +1 -1
- package/dist/index.mjs +16 -20
- package/dist/{init-Bvy7zrBo.mjs → init-BTQEZZGJ.mjs} +25 -22
- package/dist/{link-CDqqCjFl.mjs → link-B46sYH0K.mjs} +6 -6
- package/dist/{list-CZj0dzKY.mjs → list-BnPrIsU_.mjs} +6 -6
- package/dist/log-vqY3pqwI.mjs +29 -0
- package/dist/{login-UZKFM_u7.mjs → login-BuiMyUrx.mjs} +8 -8
- package/dist/login-DIy9Sb-U.mjs +2 -0
- package/dist/{logs-CUZ6t9t3.mjs → logs-CZG9d-ic.mjs} +10 -11
- package/dist/migrate-BCiJ8w0f.mjs +2 -0
- package/dist/{migrate-DHul7PRV.mjs → migrate-q4_njtaW.mjs} +2 -2
- package/dist/{operator-args-CLgKGlwU.mjs → operator-args-B3BTmSoi.mjs} +12 -5
- package/dist/{operator-auth-8KnOVXVd.mjs → operator-auth-7erYc6Lt.mjs} +2 -2
- package/dist/{operator-client-DUwumHpQ.mjs → operator-client-CpHjTd0t.mjs} +3 -3
- package/dist/{operator-cmd-DBA6dl0m.mjs → operator-cmd-DGqPJUD3.mjs} +6 -6
- package/dist/{output-Dm_A4Tbv.mjs → output-CbM85T4k.mjs} +18 -10
- package/dist/pages/index.mjs +1 -1
- package/dist/{platform-args-BJdRtlLq.mjs → platform-args-3k8X9-H_.mjs} +11 -3
- package/dist/platform-args-DdnM6WIf.mjs +2 -0
- package/dist/{platform-auth-config-B56E9YP1.mjs → platform-auth-config-DDrxUy4m.mjs} +6 -6
- package/dist/{platform-auth-protection-BDWO_aER.mjs → platform-auth-protection-BLadnnct.mjs} +8 -8
- package/dist/{platform-auth-recovery-1gg4CSRe.mjs → platform-auth-recovery-CmCzX2Fl.mjs} +6 -6
- package/dist/{platform-cmd-DMcQStSc.mjs → platform-cmd-DMDEc9uS.mjs} +10 -10
- package/dist/{platform-cmd-Bt-1w6pY.mjs → platform-cmd-pMTRhvYs.mjs} +1 -1
- package/dist/{platform-domain-BNkcz0OB.mjs → platform-domain-Di6EYrQl.mjs} +5 -5
- package/dist/{platform-lifecycle-9OyBALhH.mjs → platform-lifecycle-BBoNzojY.mjs} +1264 -407
- package/dist/{platform-lifecycle-BE6C_jxh.mjs → platform-lifecycle-BFdSi9Qt.mjs} +1 -1
- package/dist/{platform-management-CjwLVQwN.mjs → platform-management-CWOQOWXm.mjs} +5 -5
- package/dist/{platform-management-CnyTdcWX.mjs → platform-management-DG47jys8.mjs} +1 -1
- package/dist/{platform-plans-config-BNGKGr4P.mjs → platform-plans-config-Vl9BP3H4.mjs} +3 -3
- package/dist/{platform-recovery-D6KSpuFm.mjs → platform-recovery-BJnQJEtQ.mjs} +4 -4
- package/dist/{platform-registry-QBa4DK32.mjs → platform-registry-DkPPXfp_.mjs} +2 -2
- package/dist/{prepare-B5Mkic5u.mjs → prepare-CBLT3CHH.mjs} +3 -3
- package/dist/prepare-CnjcTV2s.mjs +2 -0
- package/dist/{prepare-DOsL0CC9.mjs → prepare-DnaKBi--.mjs} +1 -1
- package/dist/{project-C0Fqu05O.mjs → project-DKG5Ra8p.mjs} +15 -82
- package/dist/project-DsblYifa.mjs +2 -0
- package/dist/{project-cmd-CNzrqvBv.mjs → project-cmd-DxnXstAq.mjs} +19 -19
- package/dist/{project-team-DQOWPfQT.mjs → project-team-BmHcaALJ.mjs} +5 -5
- package/dist/{project-token-CTDYU0Cc.mjs → project-token-GionZlBI.mjs} +5 -5
- package/dist/{project-zero-trust-BNAkW-_0.mjs → project-zero-trust-JLCjVQA7.mjs} +5 -5
- package/dist/prompts-2TGE6oXx.mjs +2 -0
- package/dist/prompts-BNUoTiaf.mjs +2044 -0
- package/dist/{provision-C4ORE7G7.mjs → provision-CVku1JFU.mjs} +1 -1
- package/dist/{provision-CJFgTZY8.mjs → provision-CaoxO_U7.mjs} +1 -1
- package/dist/{requests-MhxYnau8.mjs → requests-BOjIVAeF.mjs} +5 -5
- package/dist/{rollback-CJ6iSDoU.mjs → rollback-CwR3pLj3.mjs} +6 -6
- package/dist/runtime/ai.mjs +3 -5
- package/dist/runtime/email/testing.mjs +1 -1
- package/dist/runtime/email.mjs +1 -1
- package/dist/runtime/remote/index.mjs +2 -2
- package/dist/{secret-Dli5fP0B.mjs → secret-ByWJWBUG.mjs} +7 -7
- package/dist/{skills-D1II1Juz.mjs → skills-C1PlclPt.mjs} +1 -1
- package/dist/{subcommand-prompt-CY1C4fvl.mjs → subcommand-prompt-klFCfcor.mjs} +40 -32
- package/package.json +8 -9
- package/skills/void/SKILL.md +6 -1
- package/skills/void/docs/guide/deployment.md +22 -0
- package/skills/void/docs/guide/edge/headers.md +1 -1
- package/skills/void/docs/guide/email/domains.md +5 -1
- package/skills/void/docs/guide/email/sending.md +1 -1
- package/skills/void/docs/guide/platform/administration/zero-trust.md +27 -9
- package/skills/void/docs/guide/platform/installation/ci.md +1 -1
- package/skills/void/docs/guide/platform/installation/credentials.md +10 -3
- package/skills/void/docs/guide/platform/installation/domains.md +8 -3
- package/skills/void/docs/guide/platform/installation/first-deployment.md +2 -2
- package/skills/void/docs/guide/platform/installation/maintenance.md +12 -0
- package/skills/void/docs/guide/platform/installation/prerequisites.md +8 -7
- package/skills/void/docs/guide/platform/installation/setup.md +80 -10
- package/skills/void/docs/guide/remote-dev.md +1 -1
- package/skills/void/docs/reference/cli/auth.md +4 -3
- package/skills/void/docs/reference/cli/database.md +1 -1
- package/skills/void/docs/reference/cli/deploy.md +20 -0
- package/skills/void/docs/reference/cli/platform-installation.md +42 -27
- package/skills/void/docs/reference/cli/platform-zero-trust.md +14 -0
- package/skills/void/docs/reference/config.md +1 -1
- package/dist/auth-CCjt0hcq.mjs +0 -2
- package/dist/client-Cu7jWiF1.mjs +0 -2
- package/dist/dist-BuDuKZJv.mjs +0 -2
- package/dist/dist-CTBk70IR.mjs +0 -1310
- package/dist/gen-BVaUUumi.mjs +0 -2
- package/dist/help-DofyZuY7.mjs +0 -2
- package/dist/log-ChfPKsVd.mjs +0 -26
- package/dist/login-DYt_An22.mjs +0 -2
- package/dist/migrate-8_2u55MD.mjs +0 -2
- package/dist/platform-args-D3RXyR6h.mjs +0 -2
- package/dist/prepare-cgvDMtSb.mjs +0 -2
- package/dist/project-BuUwfj6f.mjs +0 -2
|
@@ -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-
|
|
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-CaoxO_U7.mjs";
|
|
3
3
|
export { WranglerQuarantineError, acquireProvisionLock, assertNoTransportRedirectInProjectDotenv, assertValidResourceName, checkCloudflareProvisionDrift, createDefaultRunWrangler, deleteEnvVarCaseAware, enableD1ReadReplicationViaApi, isAlreadyGoneKillError, isQuarantineError, isQueueConfirmedAbsent, isRealD1Id, isRealKvId, normalizeRunWranglerResult, provisionCloudflareResources, provisionEnv, resolvePinnedApiBaseUrl, resolveProperLockfileKey, scanWranglerDotenvKeys };
|
|
@@ -1,7 +1,7 @@
|
|
|
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
2
|
import { i as persistCloudflareConfig } from "./cloudflare-config-Bktvwtpf.mjs";
|
|
3
3
|
import { A as writeProvisionedWranglerConfig, s as assertNoDuplicateMembers, v as readProvisionedBindingEntry } from "./wrangler-7K-bW_DL.mjs";
|
|
4
|
-
import { i as voidWarn, r as voidLog } from "./log-
|
|
4
|
+
import { i as voidWarn, r as voidLog } from "./log-vqY3pqwI.mjs";
|
|
5
5
|
import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
|
|
6
6
|
import { c as resolveCloudflareOperationArgv, n as decodeCloudflareOperationResult, r as encodeCloudflareOperation } from "./cloudflare-process-B-wekeR6.mjs";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { n as PlatformClient } from "./client-
|
|
5
|
-
import { a as dim, c as import_picocolors, r as cliTitle } from "./output-
|
|
1
|
+
import { r as readProjectConfig } from "./project-DKG5Ra8p.mjs";
|
|
2
|
+
import { c as getToken } from "./auth-CQkSDS50.mjs";
|
|
3
|
+
import { H as outro, L as log, N as intro } from "./prompts-BNUoTiaf.mjs";
|
|
4
|
+
import { n as PlatformClient } from "./client-DKAsFA4X.mjs";
|
|
5
|
+
import { a as dim, c as import_picocolors, r as cliTitle } from "./output-CbM85T4k.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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { n as PlatformClient } from "./client-
|
|
5
|
-
import { a as dim, c as import_picocolors, i as createSpinner, o as ensureUtc, r as cliTitle } from "./output-
|
|
1
|
+
import { n as readDeploymentPlatform, r as readProjectConfig } from "./project-DKG5Ra8p.mjs";
|
|
2
|
+
import { c as getToken } from "./auth-CQkSDS50.mjs";
|
|
3
|
+
import { A as confirm, H as outro, K as select, L as log, N as intro, O as cancel, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
|
|
4
|
+
import { n as PlatformClient } from "./client-DKAsFA4X.mjs";
|
|
5
|
+
import { a as dim, c as import_picocolors, i as createSpinner, o as ensureUtc, r as cliTitle } from "./output-CbM85T4k.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-
|
|
86
|
+
const { activateCloudflareExistingVersion, readCloudflareWorkerStatus, resolveCloudflareOperationContext } = await import("./cloudflare-operations-BCdXSsmo.mjs");
|
|
87
87
|
const context = resolveCloudflareOperationContext(root);
|
|
88
88
|
const status = await readCloudflareWorkerStatus(context);
|
|
89
89
|
const deployedVersionIds = new Set(status.deployedVersionIds);
|
package/dist/runtime/ai.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as cfAccessHeaders } from "../cf-access-
|
|
1
|
+
import { t as cfAccessHeaders } from "../cf-access-TWNzXltp.mjs";
|
|
2
2
|
import { a as getRawRuntimeEnv } from "../env-raw-Cx8ElDdj.mjs";
|
|
3
3
|
import { a as readUsageLimit, i as limitOperation, r as limitFromResponse, t as UsageLimit } from "../limits-Cjuk2VPm.mjs";
|
|
4
4
|
//#region src/runtime/ai-types.ts
|
|
@@ -27,8 +27,6 @@ const PROVIDER_KEY_MAP = {
|
|
|
27
27
|
};
|
|
28
28
|
//#endregion
|
|
29
29
|
//#region src/runtime/ai.ts
|
|
30
|
-
const PROXY_URL = "https://proxy.void.cloud/ai";
|
|
31
|
-
const STAGING_PROXY_URL = "https://proxy.staging.void.cloud/ai";
|
|
32
30
|
const VOID_FILE_MARKER = "__voidFile";
|
|
33
31
|
const PROVIDER_AUTH_DEFAULTS = {
|
|
34
32
|
"google-ai-studio": {
|
|
@@ -239,8 +237,8 @@ function resolveProviderKey(provider, runtimeEnv, options) {
|
|
|
239
237
|
}
|
|
240
238
|
function getProxyUrl(runtimeEnv) {
|
|
241
239
|
const custom = runtimeEnv.__VOID_PROXY_URL;
|
|
242
|
-
if (typeof custom === "string" && custom.length > 0) return custom + "/ai";
|
|
243
|
-
|
|
240
|
+
if (typeof custom === "string" && custom.length > 0) return custom.replace(/\/+$/, "") + "/ai";
|
|
241
|
+
throw new Error("ai: No connected platform proxy is available. Run `void connect <url>` first.");
|
|
244
242
|
}
|
|
245
243
|
function providerAuthDefaults(provider) {
|
|
246
244
|
return PROVIDER_AUTH_DEFAULTS[provider] ?? {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as normalizeEmail, r as buildMime } from "../../mime-D5Nmdzf7.mjs";
|
|
2
2
|
import { n as compileEmailPattern, t as compareEmailRoutes } from "../../email--tEtMoj_.mjs";
|
|
3
3
|
import { y as registerEmailSink } from "../../dev-inbox-P0u4tM8Y.mjs";
|
|
4
|
-
import { i as createMessageProxy, n as MAX_INBOUND_HEADERS, t as MAX_INBOUND_BYTES } from "../../inbound-
|
|
4
|
+
import { i as createMessageProxy, n as MAX_INBOUND_HEADERS, t as MAX_INBOUND_BYTES } from "../../inbound-fRkqcXaC.mjs";
|
|
5
5
|
//#region src/runtime/email/testing.ts
|
|
6
6
|
/**
|
|
7
7
|
* Test harnesses for void/email.
|
package/dist/runtime/email.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as normalizeEmail, n as MimeError, r as buildMime } from "../mime-D5Nmdzf7.mjs";
|
|
2
2
|
import { a as DEV_INBOX_ENV_VAR, b as serializeCapturedMessage, c as DEV_INBOX_TOKEN_ENV_VAR, d as captureMessage, h as hasActiveSink, i as DEV_INBOX_CAPTURE_URL, p as dispatchToSinks } from "../dev-inbox-P0u4tM8Y.mjs";
|
|
3
3
|
import { a as getRawRuntimeEnv } from "../env-raw-Cx8ElDdj.mjs";
|
|
4
|
-
import { a as defineEmail, c as parseEmail, i as createMessageProxy, l as replyEmail, o as enactEmailActions, r as ParseEmailError, s as isForwardableEmailMessage } from "../inbound-
|
|
4
|
+
import { a as defineEmail, c as parseEmail, i as createMessageProxy, l as replyEmail, o as enactEmailActions, r as ParseEmailError, s as isForwardableEmailMessage } from "../inbound-fRkqcXaC.mjs";
|
|
5
5
|
//#region src/runtime/email.ts
|
|
6
6
|
const VALID_SLUG = /^[a-z0-9](?:[a-z0-9-]{0,54}[a-z0-9])?$/;
|
|
7
7
|
function makeError(code, message, cause) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as cfAccessHeaders } from "../../cf-access-
|
|
1
|
+
import { t as cfAccessHeaders } from "../../cf-access-TWNzXltp.mjs";
|
|
2
2
|
import { n as serializeR2Conditional } from "../../r2-conditions-D1Wk8i7b.mjs";
|
|
3
3
|
//#region src/runtime/remote/client.ts
|
|
4
4
|
function readableMessage(value) {
|
|
@@ -49,7 +49,7 @@ async function proxyError(response) {
|
|
|
49
49
|
return /* @__PURE__ */ new Error(`remote: Proxy request failed with ${response.status}: ${message}`);
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
|
-
* HTTP client for the remote bindings proxy
|
|
52
|
+
* HTTP client for the connected platform's remote bindings proxy.
|
|
53
53
|
*
|
|
54
54
|
* Used by ProxyD1Database, ProxyKVNamespace, and ProxyR2Bucket to forward
|
|
55
55
|
* binding operations to the platform proxy during local development.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { _ as validateSecretValues } from "./env-validation-
|
|
4
|
-
import {
|
|
5
|
-
import { n as PlatformClient } from "./client-
|
|
6
|
-
import { r as cliTitle } from "./output-
|
|
1
|
+
import { n as readDeploymentPlatform, r as readProjectConfig } from "./project-DKG5Ra8p.mjs";
|
|
2
|
+
import { c as getToken } from "./auth-CQkSDS50.mjs";
|
|
3
|
+
import { _ as validateSecretValues } from "./env-validation-C_8tPdhs.mjs";
|
|
4
|
+
import { A as confirm, B as note, H as outro, L as log, N as intro, O as cancel, U as password, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
|
|
5
|
+
import { n as PlatformClient } from "./client-DKAsFA4X.mjs";
|
|
6
|
+
import { r as cliTitle } from "./output-CbM85T4k.mjs";
|
|
7
7
|
import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-BG5ORGID.mjs";
|
|
8
8
|
import { readFileSync } from "node:fs";
|
|
9
9
|
//#region src/cli/secret.ts
|
|
@@ -78,7 +78,7 @@ async function runSecretCommand(root, args) {
|
|
|
78
78
|
}
|
|
79
79
|
async function runCloudflareSecretCommand(root, args) {
|
|
80
80
|
if (args.projectName) throw new Error("secret: --project selects a Void platform project and is not used for direct Cloudflare apps.");
|
|
81
|
-
const { deleteCloudflareSecret, listCloudflareSecrets, putCloudflareSecret, resolveCloudflareOperationContext, syncCloudflareSecrets } = await import("./cloudflare-operations-
|
|
81
|
+
const { deleteCloudflareSecret, listCloudflareSecrets, putCloudflareSecret, resolveCloudflareOperationContext, syncCloudflareSecrets } = await import("./cloudflare-operations-BCdXSsmo.mjs");
|
|
82
82
|
const context = resolveCloudflareOperationContext(root);
|
|
83
83
|
if (args.action === "list") {
|
|
84
84
|
const secrets = await listCloudflareSecrets(context);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as join, l as relative } from "./dist-BVqXeR_h.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { L as log } from "./prompts-BNUoTiaf.mjs";
|
|
3
3
|
import { n as getPackageDir } from "./agents-B_pX_HmQ.mjs";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, readlinkSync, symlinkSync } from "node:fs";
|
|
5
5
|
//#region src/cli/skills.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { c as import_picocolors } from "./output-
|
|
1
|
+
import { $ as wrapTextWithPrefix, G as promptTitle, M as getGuide, V as optionText, b as S_RADIO_ACTIVE, d as S_CHECKBOX_SELECTED, i as S_BAR_END, it as wrapAnsi, j as formatInstructionFooter, n as SELECT_INSTRUCTIONS, r as S_BAR, t as MULTISELECT_INSTRUCTIONS, u as S_CHECKBOX_INACTIVE, w as S_STEP_SUBMIT } from "./prompts-BNUoTiaf.mjs";
|
|
2
|
+
import { c as import_picocolors } from "./output-CbM85T4k.mjs";
|
|
3
3
|
//#region src/cli/subcommand-prompt.ts
|
|
4
4
|
function promptSubcommand(command, subcommands) {
|
|
5
5
|
return new Promise((resolve) => {
|
|
@@ -45,16 +45,25 @@ function promptSubcommand(command, subcommands) {
|
|
|
45
45
|
}
|
|
46
46
|
return `${lines[0]}…`;
|
|
47
47
|
}
|
|
48
|
+
function guidePrefix() {
|
|
49
|
+
return getGuide() ? import_picocolors.default.gray(S_BAR) + " " : " ";
|
|
50
|
+
}
|
|
51
|
+
function renderOption(marker, label, focused, suffix = "") {
|
|
52
|
+
return guidePrefix() + optionText(stdout, marker + " ", label, focused ? (value) => import_picocolors.default.blue(import_picocolors.default.bold(value)) : import_picocolors.default.dim, suffix);
|
|
53
|
+
}
|
|
54
|
+
function instructions(items) {
|
|
55
|
+
return formatInstructionFooter(items, getGuide(), stdout);
|
|
56
|
+
}
|
|
48
57
|
function writeFrame(header, options, footer) {
|
|
49
|
-
const
|
|
58
|
+
const heading = header.trimEnd().split("\n");
|
|
59
|
+
const end = getGuide() ? [import_picocolors.default.gray(S_BAR_END)] : [];
|
|
60
|
+
const count = Math.max(1, Math.min(7, (stdout.rows || 24) - heading.length - footer.length - end.length - 1));
|
|
50
61
|
const start = Math.max(0, Math.min(cursor - Math.floor(count / 2), options.length - count));
|
|
51
62
|
previousFrame = [
|
|
52
|
-
truncate(
|
|
53
|
-
import_picocolors.default.gray(S_BAR),
|
|
63
|
+
...heading.map((line) => truncate(line)),
|
|
54
64
|
...options.slice(start, start + count).map((option) => truncate(option)),
|
|
55
|
-
import_picocolors.default.gray(S_BAR),
|
|
56
65
|
...footer.map((line) => truncate(line)),
|
|
57
|
-
|
|
66
|
+
...end
|
|
58
67
|
].join("\n");
|
|
59
68
|
stdout.write(previousFrame + "\n");
|
|
60
69
|
}
|
|
@@ -69,7 +78,7 @@ function promptSubcommand(command, subcommands) {
|
|
|
69
78
|
const title = command ? `void ${command}` : "void";
|
|
70
79
|
function headerLine() {
|
|
71
80
|
const argPart = selectedArg ? ` ${selectedArg}` : "";
|
|
72
|
-
return `${import_picocolors.default.
|
|
81
|
+
return promptTitle(`${import_picocolors.default.blue(title)} ${import_picocolors.default.dim("·")} ${selectedSub.name}${argPart}`, "active", { output: stdout });
|
|
73
82
|
}
|
|
74
83
|
function renderSelect() {
|
|
75
84
|
const lines = [];
|
|
@@ -78,22 +87,21 @@ function promptSubcommand(command, subcommands) {
|
|
|
78
87
|
for (let i = 0; i < subcommands.length; i++) {
|
|
79
88
|
const sub = subcommands[i];
|
|
80
89
|
const isFocused = i === cursor;
|
|
81
|
-
const radio = isFocused ? import_picocolors.default.
|
|
90
|
+
const radio = isFocused ? import_picocolors.default.blue(S_RADIO_ACTIVE) : import_picocolors.default.dim(" ");
|
|
82
91
|
const name = sub.name.padEnd(maxName);
|
|
83
92
|
let suffix = "";
|
|
84
|
-
if (sub.arg) {
|
|
85
|
-
if (isFocused && input.length > 0) suffix = ` ${import_picocolors.default.
|
|
93
|
+
if (isFocused && sub.arg) {
|
|
94
|
+
if (isFocused && input.length > 0) suffix = ` ${import_picocolors.default.blue(truncate(input, (stdout.columns || 80) - maxName - 9, true))}`;
|
|
86
95
|
else suffix = ` ${import_picocolors.default.dim(sub.arg)}`;
|
|
87
|
-
} else if (sub.hint) suffix = ` ${import_picocolors.default.dim(sub.hint)}`;
|
|
88
|
-
|
|
89
|
-
else lines.push(`${import_picocolors.default.gray(S_BAR)} ${radio} ${import_picocolors.default.dim(name)}${suffix}`);
|
|
96
|
+
} else if (isFocused && sub.hint) suffix = ` ${import_picocolors.default.dim(sub.hint)}`;
|
|
97
|
+
lines.push(renderOption(radio, name, isFocused, suffix));
|
|
90
98
|
}
|
|
91
|
-
const footer = [
|
|
99
|
+
const footer = [guidePrefix() + import_picocolors.default.dim(focused.description), ...instructions(SELECT_INSTRUCTIONS)];
|
|
92
100
|
if (focused.arg) {
|
|
93
|
-
if (focused.arg.startsWith("<")) footer.push(`${
|
|
94
|
-
else footer.push(`${
|
|
101
|
+
if (focused.arg.startsWith("<")) footer.push(`${guidePrefix()}${import_picocolors.default.dim(`Type ${focused.arg}, then press Enter`)}`);
|
|
102
|
+
else footer.push(`${guidePrefix()}${import_picocolors.default.dim(`Type ${focused.arg}, then press Enter, or press Enter to skip`)}`);
|
|
95
103
|
}
|
|
96
|
-
writeFrame(
|
|
104
|
+
writeFrame(promptTitle(import_picocolors.default.blue(title), "active", { output: stdout }), lines, footer);
|
|
97
105
|
}
|
|
98
106
|
function renderFlags() {
|
|
99
107
|
const flags = selectedSub.flags;
|
|
@@ -104,19 +112,19 @@ function promptSubcommand(command, subcommands) {
|
|
|
104
112
|
const flag = flags[i];
|
|
105
113
|
const state = flagStates[i];
|
|
106
114
|
const isFocused = i === cursor;
|
|
107
|
-
const checkbox = state.enabled ? import_picocolors.default.
|
|
115
|
+
const checkbox = state.enabled ? import_picocolors.default.blue(S_CHECKBOX_SELECTED) : isFocused ? import_picocolors.default.blue(S_CHECKBOX_INACTIVE) : import_picocolors.default.dim(S_CHECKBOX_INACTIVE);
|
|
108
116
|
const name = flag.name.padEnd(maxFlag);
|
|
109
117
|
let valueText = "";
|
|
110
118
|
if (flag.arg) {
|
|
111
119
|
if (state.enabled && state.value.length > 0) {
|
|
112
120
|
const value = truncate(state.value, (stdout.columns || 80) - maxFlag - 9, true);
|
|
113
|
-
valueText = ` ${isFocused ? import_picocolors.default.
|
|
121
|
+
valueText = ` ${isFocused ? import_picocolors.default.blue(value) : import_picocolors.default.dim(value)}`;
|
|
114
122
|
} else valueText = ` ${import_picocolors.default.dim(flag.arg)}`;
|
|
115
123
|
}
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
const pointer = isFocused ? import_picocolors.default.blue(S_RADIO_ACTIVE) : " ";
|
|
125
|
+
lines.push(renderOption(pointer + " " + checkbox, name, isFocused, valueText));
|
|
118
126
|
}
|
|
119
|
-
writeFrame(headerLine(), lines, [
|
|
127
|
+
writeFrame(headerLine(), lines, [guidePrefix() + import_picocolors.default.dim(focused.description), ...instructions(MULTISELECT_INSTRUCTIONS)]);
|
|
120
128
|
}
|
|
121
129
|
function renderMultiSelect() {
|
|
122
130
|
const options = selectedSub.followUp.options;
|
|
@@ -126,21 +134,21 @@ function promptSubcommand(command, subcommands) {
|
|
|
126
134
|
const opt = options[i];
|
|
127
135
|
const selected = multiSelectStates[i];
|
|
128
136
|
const isFocused = i === cursor;
|
|
129
|
-
const checkbox = selected ? import_picocolors.default.
|
|
137
|
+
const checkbox = selected ? import_picocolors.default.blue(S_CHECKBOX_SELECTED) : isFocused ? import_picocolors.default.blue(S_CHECKBOX_INACTIVE) : import_picocolors.default.dim(S_CHECKBOX_INACTIVE);
|
|
130
138
|
const label = opt.label.padEnd(maxLabel);
|
|
131
|
-
|
|
132
|
-
|
|
139
|
+
const pointer = isFocused ? import_picocolors.default.blue(S_RADIO_ACTIVE) : " ";
|
|
140
|
+
lines.push(renderOption(pointer + " " + checkbox, label, isFocused));
|
|
133
141
|
}
|
|
134
|
-
writeFrame(headerLine(), lines,
|
|
142
|
+
writeFrame(headerLine(), lines, instructions(MULTISELECT_INSTRUCTIONS));
|
|
135
143
|
}
|
|
136
144
|
function renderRepeatInput() {
|
|
137
145
|
const followUp = selectedSub.followUp;
|
|
138
146
|
const lines = [];
|
|
139
|
-
for (const entry of repeatEntries) lines.push(`${
|
|
140
|
-
if (repeatInput.length > 0) lines.push(`${
|
|
141
|
-
else lines.push(`${
|
|
147
|
+
for (const entry of repeatEntries) lines.push(`${guidePrefix()}${import_picocolors.default.dim(entry)}`);
|
|
148
|
+
if (repeatInput.length > 0) lines.push(`${guidePrefix()}${import_picocolors.default.blue(truncate(repeatInput, (stdout.columns || 80) - 4, true))}`);
|
|
149
|
+
else lines.push(`${guidePrefix()}${import_picocolors.default.dim(followUp.placeholder)}`);
|
|
142
150
|
cursor = lines.length - 1;
|
|
143
|
-
writeFrame(headerLine(), lines, [
|
|
151
|
+
writeFrame(headerLine(), lines, instructions(["Enter add", "Empty input finish"]));
|
|
144
152
|
}
|
|
145
153
|
function cleanup() {
|
|
146
154
|
if (resolved) return;
|
|
@@ -163,7 +171,7 @@ function promptSubcommand(command, subcommands) {
|
|
|
163
171
|
if (typeof value === "string") summary += ` ${value}`;
|
|
164
172
|
}
|
|
165
173
|
if (result.extraArgs && result.extraArgs.length > 0) summary += ` ${result.extraArgs.join(" ")}`;
|
|
166
|
-
stdout.write(`${import_picocolors.default.
|
|
174
|
+
stdout.write(wrapTextWithPrefix(stdout, `${import_picocolors.default.dim(title)} ${import_picocolors.default.dim("·")} ${import_picocolors.default.dim(summary)}`, " ", `${import_picocolors.default.gray(S_STEP_SUBMIT)} `) + "\n");
|
|
167
175
|
}
|
|
168
176
|
resolve(result);
|
|
169
177
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "void",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/voidzero-dev/void.git",
|
|
@@ -339,11 +339,11 @@
|
|
|
339
339
|
"@cloudflare/workers-auth": "0.9.5",
|
|
340
340
|
"@cloudflare/workers-types": "^4.20260702.1",
|
|
341
341
|
"@napi-rs/keyring": "2.1.0",
|
|
342
|
-
"@void/deploy-cloudflare": "0.
|
|
343
|
-
"@void/deploy-core": "0.
|
|
344
|
-
"@void/edge": "0.
|
|
345
|
-
"@void/isr": "0.
|
|
346
|
-
"@void/platform": "0.
|
|
342
|
+
"@void/deploy-cloudflare": "0.24.0",
|
|
343
|
+
"@void/deploy-core": "0.24.0",
|
|
344
|
+
"@void/edge": "0.24.0",
|
|
345
|
+
"@void/isr": "0.24.0",
|
|
346
|
+
"@void/platform": "0.24.0",
|
|
347
347
|
"acorn": "^8.18.0",
|
|
348
348
|
"better-auth": "^1.7.6",
|
|
349
349
|
"better-sqlite3": "^13.0.3",
|
|
@@ -370,13 +370,12 @@
|
|
|
370
370
|
"undici": "8.11.2"
|
|
371
371
|
},
|
|
372
372
|
"devDependencies": {
|
|
373
|
-
"@clack/core": "^1.5.1",
|
|
374
|
-
"@clack/prompts": "^1.8.1",
|
|
375
373
|
"@electric-sql/pglite": "0.5.8",
|
|
376
374
|
"@types/better-sqlite3": "^9.6.0",
|
|
377
375
|
"@types/node": "^26.6.3",
|
|
378
376
|
"@types/pg": "^8.23.1",
|
|
379
377
|
"@types/proper-lockfile": "^4.1.4",
|
|
378
|
+
"@voidzero-dev/vite-plus-prompts": "0.0.0",
|
|
380
379
|
"arktype": "^2.2.5",
|
|
381
380
|
"ci-info": "^4.4.0",
|
|
382
381
|
"estree-walker": "^3.0.3",
|
|
@@ -394,7 +393,7 @@
|
|
|
394
393
|
"zod": "^4.6.5"
|
|
395
394
|
},
|
|
396
395
|
"peerDependencies": {
|
|
397
|
-
"@void/md": "0.
|
|
396
|
+
"@void/md": "0.24.0",
|
|
398
397
|
"arktype": ">=2.0.0",
|
|
399
398
|
"valibot": ">=1.0.0-beta.7",
|
|
400
399
|
"vite": "^8.0.0",
|
package/skills/void/SKILL.md
CHANGED
|
@@ -16,7 +16,12 @@ workflows. Mention Wrangler only when the user needs to recognize a literal
|
|
|
16
16
|
configuration file or environment variable.
|
|
17
17
|
|
|
18
18
|
Use `void` and `@void/*` in imports, examples, and package manifests. Follow the
|
|
19
|
-
project's existing framework and deployment destination.
|
|
19
|
+
project's existing framework and deployment destination. Deploying to a Void
|
|
20
|
+
platform requires an explicit `void connect <url>` first; never infer a platform
|
|
21
|
+
from old examples, tokens, or project IDs.
|
|
22
|
+
For a one-time deployment elsewhere, connect to that platform, then set
|
|
23
|
+
`VOID_API_URL` for the deploy command and pass `--project <slug>`. This preserves
|
|
24
|
+
the app's existing saved destination, including when the target project is new.
|
|
20
25
|
|
|
21
26
|
## Task Routing
|
|
22
27
|
|
|
@@ -55,6 +55,23 @@ To set up deployment later, use `void connect --platform cloudflare` or `void co
|
|
|
55
55
|
|
|
56
56
|
Owners can [share a platform project](./project-collaboration.md) with readers, collaborators, and project administrators. This does not apply to direct Cloudflare deployments.
|
|
57
57
|
|
|
58
|
+
### Deploy to another Void platform
|
|
59
|
+
|
|
60
|
+
Connect to the additional platform once, then select it for the deployment:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
void connect https://second.example.com
|
|
64
|
+
VOID_API_URL=https://second.example.com void deploy --platform void --project my-app
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Void uses `my-app` on that platform and offers to create it if needed. Your saved
|
|
68
|
+
destination stays unchanged, including when a new project is created or deployment
|
|
69
|
+
fails. The next plain `void deploy` still uses your original destination.
|
|
70
|
+
|
|
71
|
+
Pass `--project` or `VOID_PROJECT` when selecting a different platform; project links
|
|
72
|
+
belong to their original platform. Each platform has its own projects, secrets, and
|
|
73
|
+
data. For an app without a saved destination, its first deployment still saves a link.
|
|
74
|
+
|
|
58
75
|
### Migrations
|
|
59
76
|
|
|
60
77
|
Deploy applies pending SQL migrations from `db/migrations/`. If your schema has changes without a migration, deploy stops. Run `void db generate`, review and commit the SQL, then deploy again. See the [Database guide](./database.md).
|
|
@@ -84,6 +101,11 @@ If none is set, Void asks you to choose a project. Direct Cloudflare deploys use
|
|
|
84
101
|
|
|
85
102
|
### CI preparation
|
|
86
103
|
|
|
104
|
+
For a Void platform, run `void connect "$VOID_API_URL" --no-login` in each fresh
|
|
105
|
+
CI environment before deployment. Set `VOID_API_URL` to the platform you selected;
|
|
106
|
+
there is no default hosted platform. The generated GitHub Actions workflow
|
|
107
|
+
includes this connection step.
|
|
108
|
+
|
|
87
109
|
If your CI pipeline runs typechecking or other static analysis before deploy, run `void prepare` after install to generate the `.void/` artifacts without booting Vite.
|
|
88
110
|
|
|
89
111
|
### Environment variables
|
|
@@ -35,7 +35,7 @@ Header rules do not apply to ISR cache responses.
|
|
|
35
35
|
|
|
36
36
|
### Blocked headers
|
|
37
37
|
|
|
38
|
-
`Set-Cookie` and `Clear-Site-Data` are ignored in header rules. On a shared domain such as `*.
|
|
38
|
+
`Set-Cookie` and `Clear-Site-Data` are ignored in header rules. On a shared domain such as `*.apps.example.com`, a rule could otherwise affect cookies or data belonging to another project's subdomain.
|
|
39
39
|
|
|
40
40
|
## Framework `_headers` files
|
|
41
41
|
|
|
@@ -50,7 +50,9 @@ Use a mail subdomain to keep existing mail on `acme.com` with its current provid
|
|
|
50
50
|
|
|
51
51
|
Sign in with `void cloudflare login`, or use a `CLOUDFLARE_API_TOKEN` with **Email Routing Edit** and **Email Sending Edit** in addition to deploy permissions. If your browser session lacks email permissions, log out and sign in again. Global API Keys aren't supported.
|
|
52
52
|
|
|
53
|
-
Run `void deploy --platform cloudflare`. Void shows the domain, routing, sending, DNS, and handler addresses it would configure. Accept to set up email and deploy. Later deploys reuse the setup.
|
|
53
|
+
Run `void deploy --platform cloudflare`. Void shows the domain, routing, sending, DNS, and handler addresses it would configure. Accept to set up email and deploy. Later deploys reuse the setup. If you decline the initial setup, the app deploys without email.
|
|
54
|
+
|
|
55
|
+
Without `email.from`, Void skips automatic setup and preserves authored `cloudflare.send_email` bindings and `cloudflare.addresses`; check their readiness yourself. `--require-email` still refuses deployment when automatic setup cannot be verified.
|
|
54
56
|
|
|
55
57
|
If subdomain setup needs a dashboard step, follow the checklist under **Email → Settings → Subdomains**, then retry. After DNS changes, check readiness with:
|
|
56
58
|
|
|
@@ -78,6 +80,8 @@ Setup enables the zone's plus addressing so `support+T-42@mail.acme.com` reaches
|
|
|
78
80
|
|
|
79
81
|
On Workers Free, `sendEmail()` can send to verified destinations listed under **Email Routing → Destination addresses** in Cloudflare.
|
|
80
82
|
|
|
83
|
+
Configure your sender domain's SPF, DKIM, and DMARC records using [Cloudflare's email authentication guidance](https://developers.cloudflare.com/email-service/concepts/email-authentication/), then check the authentication results in a received message's original headers. A successful `sendEmail()` result confirms provider acceptance; it does not confirm delivery or authentication readiness.
|
|
84
|
+
|
|
81
85
|
Sending to arbitrary recipients requires [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans) and Email Sending onboarding. After upgrading, run `void email setup --platform cloudflare`. Void doesn't retry onboarding during ordinary deploys.
|
|
82
86
|
|
|
83
87
|
Existing DMARC or bounce-domain records can block onboarding; the checklist identifies conflicts to resolve. Inbound mail remains available.
|
|
@@ -34,7 +34,7 @@ Check both failure shapes: `result.error` reports a request failure, while `resu
|
|
|
34
34
|
|
|
35
35
|
## Setup {#setup}
|
|
36
36
|
|
|
37
|
-
On a platform with email enabled, deploy without additional email configuration. Ask your administrator for its shared mail domain. Administrators [enable email during installation or upgrade](/guide/platform/installation/credentials#runtime-token-permissions)
|
|
37
|
+
On a platform with email enabled, deploy without additional email configuration. Ask your administrator for its shared mail domain. Administrators [enable email during installation or upgrade](/guide/platform/installation/credentials#runtime-token-permissions).
|
|
38
38
|
|
|
39
39
|
Each project on an email-enabled platform has:
|
|
40
40
|
|
|
@@ -8,6 +8,17 @@ Project Zero Trust puts Cloudflare Access in front of the hostnames of projects
|
|
|
8
8
|
|
|
9
9
|
This is separate from the Access login and protection for the platform API. Projects deployed directly to Cloudflare are not affected.
|
|
10
10
|
|
|
11
|
+
New installations choose app access during `void platform install`. The installer
|
|
12
|
+
reuses the platform policy or helps you select separate company rules, and finishes
|
|
13
|
+
setup before opening traffic. Existing installations keep their settings when
|
|
14
|
+
upgraded; use this page to configure app access if it has not been set up yet.
|
|
15
|
+
|
|
16
|
+
If you choose public apps in an account with Default-Deny, Void manages scoped
|
|
17
|
+
public rules instead. New projects and custom domains remain public automatically.
|
|
18
|
+
Keep these rules enabled while Default-Deny is on; removing them can block traffic.
|
|
19
|
+
Public-only installations need no identity providers or company policies until you
|
|
20
|
+
choose to protect apps. To renew their token in Admin, leave the policy fields blank.
|
|
21
|
+
|
|
11
22
|
## Requirements
|
|
12
23
|
|
|
13
24
|
- A Cloudflare Zero Trust organization in the account that hosts the platform, with the identity providers and reusable Access policies you want to use. Select at least one Allow policy that matches people by identity. Void rejects Bypass and Service Auth policies, and rules that allow Everyone or any service token.
|
|
@@ -116,22 +127,29 @@ If a project must accept such requests:
|
|
|
116
127
|
|
|
117
128
|
Void creates and owns these self-hosted applications in your Zero Trust organization:
|
|
118
129
|
|
|
119
|
-
| Application
|
|
120
|
-
|
|
|
121
|
-
| Shared project application
|
|
122
|
-
| Public
|
|
123
|
-
|
|
|
124
|
-
|
|
|
130
|
+
| Application | Covers | Policy | Exists |
|
|
131
|
+
| --------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------ |
|
|
132
|
+
| Shared project application | `*.<your domain>` and this installation's `workers.dev` testing URLs | Your selected policies and identity providers | Once for protected-app configurations |
|
|
133
|
+
| Public app management check | A reserved, unused dispatch check path | Deny Everyone; verifies management permissions without opening hostnames | Once, instead of the shared wildcard in public-only mode |
|
|
134
|
+
| Public exception | One public project's `<slug>.<your domain>` and `workers.dev` testing URL | A Bypass policy for Everyone, named `Void project is public` | One for each public project |
|
|
135
|
+
| Custom domain application | All managed custom domains of one project | Company policies for protected projects; Bypass for public ones | One for each project with managed custom domains |
|
|
136
|
+
| Health check exception | `void-platform-health.<your domain>/health` | A Bypass policy for Everyone, named `Void platform health check` | Once, while Zero Trust is enabled on an installation with a domain |
|
|
137
|
+
|
|
138
|
+
Installations configured through the installer also manage public custom-domain
|
|
139
|
+
rules. Their custom-domain application changes policy when a project switches
|
|
140
|
+
between public and protected access.
|
|
125
141
|
|
|
126
|
-
|
|
142
|
+
If the installer already configured the same health-check exception, Zero Trust
|
|
143
|
+
reuses it. Disabling project Zero Trust leaves that existing exception in place
|
|
144
|
+
so platform health checks continue to work.
|
|
127
145
|
|
|
128
146
|
The number of applications Void needs is:
|
|
129
147
|
|
|
130
148
|
```text
|
|
131
|
-
|
|
149
|
+
1 + health-check applications + public projects + projects with managed custom domains
|
|
132
150
|
```
|
|
133
151
|
|
|
134
|
-
|
|
152
|
+
The first application is the shared company policy or the public-app management check. Count a health exception once, including when it is shared with the installer. For example, 40 projects with one health exception, 10 public projects, and 5 projects with managed custom domains need 1 + 1 + 10 + 5 = 17 applications. Void stops with an error when the account has more than 500 Access applications.
|
|
135
153
|
|
|
136
154
|
#### Recognizing Void's Applications
|
|
137
155
|
|
|
@@ -49,7 +49,7 @@ void platform install \
|
|
|
49
49
|
--yes
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
Mutations require `--yes` in CI; a read-only `--plan` does not. Custom runtimes also require `--runtime <directory>`. For a new installation, run `--plan` with the same account, name, and domain options as the unattended install. If you use `--auth-config`, pass the same file to both commands. Register
|
|
52
|
+
Mutations require `--yes` in CI; a read-only `--plan` does not. Custom runtimes also require `--runtime <directory>`. For a new installation, run `--plan` with the same account, name, and domain options as the unattended install. If you use `--auth-config`, pass the same file to both commands. Register `<platform-api-url>/auth/callback` when creating a login provider's OAuth or OIDC client manually; automatic Access setup manages its own application. A custom API hostname is optional.
|
|
53
53
|
|
|
54
54
|
:::
|
|
55
55
|
|
|
@@ -8,15 +8,20 @@ Keep one password-manager entry for this platform. Paste the saved values into t
|
|
|
8
8
|
|
|
9
9
|
## Cloudflare API Tokens {#runtime-token-permissions}
|
|
10
10
|
|
|
11
|
-
For a domain installation,
|
|
11
|
+
For a domain installation or Cloudflare Access setup, the installer guides you through creating separate management and runtime tokens using Cloudflare's [API token setup](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/). Its links preselect the permissions and suggest names based on your platform's display name. Scope the tokens to your selected account and, when using a domain, its zone, save them in your password manager, and paste them into the masked CLI prompts.
|
|
12
12
|
|
|
13
|
-
For workers.dev testing with the default API hostname, browser login can authorize
|
|
13
|
+
For workers.dev testing with the default API hostname, browser login can authorize
|
|
14
|
+
infrastructure setup. Void also checks account-wide Access requirements; if the
|
|
15
|
+
current credential cannot read them, the installer asks for a scoped Access token.
|
|
16
|
+
Protected apps and public apps under Default-Deny need an ongoing app-management
|
|
17
|
+
token, stored encrypted. Access setup requires a management token even on
|
|
18
|
+
workers.dev. Skip zone permissions until you add a domain.
|
|
14
19
|
|
|
15
20
|
Browser login does not grant AI Gateway access. Include **Account → AI Gateway → Edit** on the runtime token so Void can verify and create that resource.
|
|
16
21
|
|
|
17
22
|
The management token lets your CLI install and maintain the platform. The runtime token is stored as a Worker secret so the platform can deploy apps after you close your terminal. They are separate credentials.
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
Compare each token's form with the permission checklist below, and select the indicated account and zone for a domain installation. The installer saves a management token entered at the prompt in this installation’s encrypted local checkpoint and reuses it on resume. Upgrades, repairs, and other lifecycle maintenance also use that saved management token. During installation, a rejected token can be replaced at the prompt. An explicit `CLOUDFLARE_API_TOKEN` or `CF_API_TOKEN` takes precedence. Keep your password-manager copy for maintenance or another machine; scripts supply it through `CLOUDFLARE_API_TOKEN`.
|
|
20
25
|
|
|
21
26
|
::: details Permissions to select for each token
|
|
22
27
|
|
|
@@ -39,6 +44,8 @@ Use the following permissions for the core platform. Cloudflare may label write
|
|
|
39
44
|
| Zone | Workers Routes | Edit | — |
|
|
40
45
|
| Zone | Cache Purge | — | Purge |
|
|
41
46
|
|
|
47
|
+
When Void configures Access in the installation account, the initial management-token link also selects **Account → Access: Apps and Policies → Edit** and **Account → Access: Organizations, Identity Providers, and Groups → Read**. Protection adds **Account → Access: Service Tokens → Edit**. When the authentication configuration or saved setup selects existing applications, the link requests Read access instead of Edit. These permissions belong to the management token; the runtime token does not need them.
|
|
48
|
+
|
|
42
49
|
The management token also needs **Zone Edit** with authority to create zones if you ask Void to create the zone. If it already exists, use the selected zone with Zone Read and DNS Edit. Nested application domains additionally need **SSL and Certificates: Read** on the management token. A custom runtime that enables custom project domains needs **SSL and Certificates: Edit** on the runtime token; the core runtime does not enable that feature.
|
|
43
50
|
|
|
44
51
|
Void checks access before provisioning. If it reports a missing permission, update the token's permissions for the selected account or zone and retry.
|
|
@@ -66,9 +66,14 @@ void platform repair <installation-id> --dashboard-url https://dash.example.com
|
|
|
66
66
|
|
|
67
67
|
The origin must contain no credentials, path, query, or fragment. Void saves it
|
|
68
68
|
for login callbacks and keeps it across upgrades and repairs. The command does
|
|
69
|
-
not create a dashboard Worker or DNS records
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
not create a dashboard Worker or DNS records. Follow the source app’s
|
|
70
|
+
[standalone dashboard preparation](https://github.com/voidzero-dev/void/tree/main/platform/packages/dashboard#standalone-deployment)
|
|
71
|
+
to deploy your own copy with an unused Worker name, your dashboard hostname,
|
|
72
|
+
and the installed API Worker’s service binding. Set its `API_URL` to the public
|
|
73
|
+
API origin, `DASHBOARD_URL` to the dashboard origin, and `SITE_DOMAIN` to the
|
|
74
|
+
installation’s application domain. Omit the option to keep the saved origin.
|
|
75
|
+
The dashboard provides sign-in, linked login methods, and sign-out; use the CLI
|
|
76
|
+
for user project and team management.
|
|
72
77
|
|
|
73
78
|
If Access protects the platform, its application must cover this dashboard
|
|
74
79
|
origin too. Configure the origin when installing protection. To change it on an
|
|
@@ -33,8 +33,8 @@ void project token create --name ci --expires-in 30
|
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
Store the printed `VOID_TOKEN` and `VOID_API_URL` in the CI secret manager, then
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
run `void connect "$VOID_API_URL" --no-login` before deploying in each fresh CI
|
|
37
|
+
environment. Project files do not replace this connection step. Rotate with `void project token renew <id>` and revoke with
|
|
38
38
|
`void project token revoke <id>`. A human login token is not a CI credential.
|
|
39
39
|
|
|
40
40
|
If Cloudflare Access protects the platform, Access proof and the project
|