@void/platform 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/README.md CHANGED
@@ -4,9 +4,17 @@ Public, target-neutral contracts and packaged runtime artifacts for installing a
4
4
 
5
5
  For a first installation, follow [Install a Void Platform](../../docs/guide/self-hosted-platform.md). It explains how to prepare the Cloudflare account, domain, PostgreSQL database, and credentials before deploying. Void creates the platform resources and database tables.
6
6
 
7
- The CLI provides direct credential setup links in plans and opens missing-credential pages during an approved interactive install. The runtime-token link preselects all required account permissions, including Workers Tail, Hyperdrive, and AI Gateway when needed, with a readable fallback summary. Local credential drafts preserve the final Worker names and OAuth callback before provisioning, with partial secrets encrypted by the existing recovery store. A completed credential-setup marker separates these drafts from database-claimed installation recovery.
7
+ The installer also chooses default app access, reuses eligible company Access
8
+ selections, and detects account-wide Default-Deny. App rules are configured and
9
+ verified before traffic opens. An app-management token is stored encrypted;
10
+ reusing an installer token requires explicit consent. Initial setup is resumable,
11
+ and later upgrades preserve administrator changes. Deployment schema 4 and the
12
+ runtime's `appAccessSetup` capability keep older installers or runtimes from skipping
13
+ this handoff.
8
14
 
9
- Interactive installation lists unfinished installs, including interrupted provisioning, and offers to continue one or start a new platform install. Entering an existing unfinished name asks to resume it; declining returns to name entry. New installs leave previous setup, credentials, and resources untouched. Completed platforms are excluded. Explicit `--resume` skips the choice; non-interactive recovery requires it. Read-only plans do not save drafts. Their printed install command preserves the API hostname choice, Hyperdrive selection, login methods, Access protection, and domain settings.
15
+ Plans list required credentials in a dedicated box. The CLI opens missing-credential setup pages during an approved interactive install. The runtime-token link preselects all required account permissions, including Workers Tail, Hyperdrive, and AI Gateway when needed, with a readable fallback summary. Local credential drafts preserve the final Worker names and OAuth callback before provisioning, with partial secrets encrypted by the existing recovery store. This includes prompted management API tokens, which are validated and reused on resume; rejected tokens can be replaced in the same run. A completed credential-setup marker separates these drafts from database-claimed installation recovery.
16
+
17
+ Interactive installation lists saved plans and unfinished installs, including interrupted provisioning, and offers to continue one or start a new platform install. Entering an existing unfinished name asks to resume it; declining returns to name entry. New installs leave previous setup, credentials, and resources untouched. Completed platforms are excluded. Explicit `--resume` skips the choice; non-interactive recovery requires it. Completed `--plan` previews save choices locally without secrets or Cloudflare changes. Selecting a saved plan checks the current Cloudflare state before confirmation. Once setup starts, its checkpoint takes precedence over the preview. The printed install command also preserves the API hostname choice, Hyperdrive selection, login methods, Access protection, and domain settings.
10
18
 
11
19
  New platforms use readable resource names such as `void-team-api` and `void-team-routing`, without random suffixes. Choose an installation name that is unused in the selected account. Conflicting resources are never silently adopted, overwritten, or bypassed by choosing random names. Existing installations keep their recorded resource names, including older suffixed names; application/user resource naming is independent.
12
20
 
@@ -34,13 +42,13 @@ The package contains:
34
42
 
35
43
  The `void` CLI consumes this package for `void platform install`, `repair`, `upgrade`, `discover`, and `uninstall`. Platform implementation sources remain under `platform/packages/*`; their deployable core output is bundled here so a user installs one normal public `void` package rather than cloning or deploying the repository.
36
44
 
37
- Interactive lifecycle operations authenticate the human operator through Cloudflare browser sign-in with OS-keychain storage. Wrangler browser OAuth has Zone Read, so plans that create a zone or DNS record require an explicit management API token with the corresponding Zone Edit and DNS Edit permissions. A new account must finish Workers onboarding and choose its workers.dev subdomain before planning. The installed control plane receives a separate scoped runtime token. Its core permissions include Hyperdrive: Write at account scope and Cache Purge: Purge on the application zone; SSL and Certificates: Edit is needed only by a custom runtime that enables custom project domains. The installer preflights account and Hyperdrive access and, for an existing zone, verifies cache-purge access with a unique nonexistent URL. Local recovery checkpoints are AES-256-GCM encrypted with a key held in the OS keychain; normal upgrades preserve existing Cloudflare Worker secrets rather than downloading or rewriting them.
45
+ Lifecycle maintenance uses an explicit environment API token first, then the selected installation’s saved management token, and finally Cloudflare browser sign-in with OS-keychain storage. Installation plans that create a zone or DNS record, or configure Access in the installation account, flag the management API token requirement. After plan confirmation, the installer opens a token-creation link and collects the token in a masked prompt; scripts use `CLOUDFLARE_API_TOKEN`. The initial token link includes the corresponding DNS and Access permissions. Access setup in the same account reuses the management token after checking Access reads before provisioning. Applications in another identity account may need a separate setup credential. A new account must finish Workers onboarding and choose its workers.dev subdomain before planning. The installed control plane receives a separate scoped runtime token. Its core permissions include Hyperdrive: Write at account scope and Cache Purge: Purge on the application zone; SSL and Certificates: Edit is needed only by a custom runtime that enables custom project domains. The installer preflights account and Hyperdrive access and, for an existing zone, verifies cache-purge access with a unique nonexistent URL. Local recovery checkpoints are AES-256-GCM encrypted with a key held in the OS keychain; normal upgrades preserve existing Cloudflare Worker secrets rather than downloading or rewriting them.
38
46
 
39
47
  Fresh installations require a unique JWT signing secret with at least 32 bytes of random material and a unique, canonical base64-encoded 32-byte project-encryption key from the operator's durable secret manager. The installer never makes an ephemeral workstation or CI registry the only custodian of these installation identity keys. Existing Workers preserve their deployed values during routine lifecycle operations.
40
48
 
41
49
  Email-enabled installations also need an independent email signing key. The installer generates it in encrypted recovery state, or accepts `VOID_PLATFORM_EMAIL_SIGNING_SECRET` from the operator's secret manager. Keep that original value for recovery on another machine and for headless upgrades without persistent recovery files.
42
50
 
43
- Browser OAuth cannot manage AI Gateway. Installation previews mark an inaccessible gateway as requiring inspection; apply rechecks it with the already-required runtime token (AI Gateway: Edit) before provisioning. All other provider operations keep the operator credential. Later OAuth lifecycle operations can reuse that token from encrypted local recovery storage. On another workstation, use a management API token with AI Gateway access or supply the runtime token explicitly for that check.
51
+ Browser OAuth cannot manage AI Gateway. Installation previews mark an inaccessible gateway as requiring inspection; apply rechecks it with the already-required runtime token (AI Gateway: Edit) before provisioning. All other provider operations keep the operator credential. Maintenance uses the saved management token for all provider operations when available. Without one, OAuth lifecycle operations can reuse the saved runtime token specifically for the AI Gateway check. On another workstation, use a management API token with AI Gateway access or supply the runtime token explicitly for that check.
44
52
 
45
53
  Runtime and installation manifests record the last usage protocol proven live across the complete Worker set. A protocol transition gates traffic before the first Worker update and opens it only after target health and immutable versions pass; interrupted transitions remain gated and resumable.
46
54
 
package/dist/index.d.mts CHANGED
@@ -1,4 +1,18 @@
1
1
  import { BUILD_INSTANCE_FREE, BUILD_INSTANCE_LARGE, BuildInstanceType, BuiltinPlanId, EditablePlanLimit, PLAN_EDITABLE_LIMIT_KEYS, PLAN_LIMITS, PlanId, PlanLimits, PlanLimitsPatch, PlatformPlanCatalog, PlatformPlanDefinition, PlatformPlanReconciliation, createDefaultPlanCatalog, parseBuildInstanceType, parsePlanLimitsPatch, parsePlanName, parsePlatformPlanCatalog, parsePlatformPlanId, validatePlanLimits } from "./plans.mjs";
2
+ //#region src/app-access.d.ts
3
+ export declare const PLATFORM_APP_ACCESS_SETUP_PROOF_PREFIX = "void-platform-app-access-v1";
4
+ /** Installer handoff. Token values belong only in encrypted recovery and request bodies. */
5
+ type PlatformAppAccessSetup = Readonly<{
6
+ version: 1;
7
+ accountId: string;
8
+ mode: "public" | "protected";
9
+ managed: boolean;
10
+ apiToken?: string;
11
+ identityProviderIds: ReadonlyArray<string>;
12
+ policyIds: ReadonlyArray<string>;
13
+ }>;
14
+ export declare function parsePlatformAppAccessSetup(value: unknown): PlatformAppAccessSetup;
15
+ //#endregion
2
16
  //#region src/authentication-recovery.d.ts
3
17
  /** Owner recovery capabilities authorize a provider test, never a platform session. */
4
18
  type PlatformAuthenticationRecovery = Readonly<{
@@ -199,7 +213,10 @@ type PlatformResourceNames = Readonly<{
199
213
  tailWorker: string;
200
214
  usageQueue: string;
201
215
  }>;
216
+ type PlatformAppAccess = "public" | "platform" | "custom";
202
217
  type PlatformDeploymentManifest = Readonly<{
218
+ /** Initial app-access choice. Omitted on installations created before guided setup. */
219
+ appAccess?: PlatformAppAccess;
203
220
  application: PlatformApplication;
204
221
  /** Zone that owns the installation's shared sender mail domain. */
205
222
  emailSharedZoneId?: string;
@@ -215,9 +232,10 @@ type PlatformDeploymentManifest = Readonly<{
215
232
  displayName: string;
216
233
  installationSlug: string;
217
234
  resources: PlatformResourceNames;
218
- schemaVersion: typeof PLATFORM_DEPLOYMENT_SCHEMA_VERSION | 2 | 3;
235
+ schemaVersion: typeof PLATFORM_DEPLOYMENT_SCHEMA_VERSION | 2 | 3 | 4;
219
236
  }>;
220
237
  type PlatformDeploymentManifestInput = Readonly<{
238
+ appAccess?: PlatformAppAccess;
221
239
  application: Readonly<{
222
240
  baseDomain: string;
223
241
  dedicatedZone?: boolean;
@@ -414,6 +432,7 @@ export declare function createPlatformWorkerConfigs(input: {
414
432
  installationId: string;
415
433
  ownershipNonce: string;
416
434
  platformVersion: string;
435
+ proxyHealthBinding?: boolean;
417
436
  publicEndpoints?: boolean;
418
437
  proxyUrl: string;
419
438
  emailGatewayUrl: string;
@@ -423,4 +442,4 @@ export declare function createPlatformWorkerConfigs(input: {
423
442
  trafficState?: "enabled" | "sandbox-drain" | "staging";
424
443
  }): PlatformWorkerConfigSet;
425
444
  //#endregion
426
- export { BUILD_INSTANCE_FREE, BUILD_INSTANCE_LARGE, BuildInstanceType, BuiltinPlanId, EditablePlanLimit, type InstallationResource, type InstallationResourceKind, type InstallationStatus, type InstallationStep, PLAN_EDITABLE_LIMIT_KEYS, PLAN_LIMITS, PlanId, PlanLimits, PlanLimitsPatch, type PlatformAccessProtection, type PlatformAdmissionPolicy, type PlatformApplication, type PlatformApplicationProject, type PlatformApplicationRoute, type PlatformAuthenticationDiscovery, type PlatformAuthenticationRecovery, type PlatformAuthenticationSetup, type PlatformCapabilities, type PlatformControlPlane, type PlatformDeploymentManifest, type PlatformDeploymentManifestInput, type PlatformDiscoveryDocument, type PlatformInstallationEndpoints, type PlatformInstallationManifest, type PlatformLoginConfiguration, type PlatformLoginDescriptor, type PlatformLoginKind, PlatformPlanCatalog, PlatformPlanDefinition, PlatformPlanReconciliation, type PlatformProvisionedResourceIds, type PlatformResourceNames, type PlatformResourceOwnershipMarker, type PlatformRuntimeProvenance, type PlatformSignupAllowlistEntry, type PlatformSignupIdentity, type PlatformWorkerConfigSet, type ResourceOwnership, createDefaultPlanCatalog, parseBuildInstanceType, parsePlanLimitsPatch, parsePlanName, parsePlatformPlanCatalog, parsePlatformPlanId, validatePlanLimits };
445
+ export { BUILD_INSTANCE_FREE, BUILD_INSTANCE_LARGE, BuildInstanceType, BuiltinPlanId, EditablePlanLimit, type InstallationResource, type InstallationResourceKind, type InstallationStatus, type InstallationStep, PLAN_EDITABLE_LIMIT_KEYS, PLAN_LIMITS, PlanId, PlanLimits, PlanLimitsPatch, type PlatformAccessProtection, type PlatformAdmissionPolicy, type PlatformAppAccess, type PlatformAppAccessSetup, type PlatformApplication, type PlatformApplicationProject, type PlatformApplicationRoute, type PlatformAuthenticationDiscovery, type PlatformAuthenticationRecovery, type PlatformAuthenticationSetup, type PlatformCapabilities, type PlatformControlPlane, type PlatformDeploymentManifest, type PlatformDeploymentManifestInput, type PlatformDiscoveryDocument, type PlatformInstallationEndpoints, type PlatformInstallationManifest, type PlatformLoginConfiguration, type PlatformLoginDescriptor, type PlatformLoginKind, PlatformPlanCatalog, PlatformPlanDefinition, PlatformPlanReconciliation, type PlatformProvisionedResourceIds, type PlatformResourceNames, type PlatformResourceOwnershipMarker, type PlatformRuntimeProvenance, type PlatformSignupAllowlistEntry, type PlatformSignupIdentity, type PlatformWorkerConfigSet, type ResourceOwnership, createDefaultPlanCatalog, parseBuildInstanceType, parsePlanLimitsPatch, parsePlanName, parsePlatformPlanCatalog, parsePlatformPlanId, validatePlanLimits };
package/dist/index.mjs CHANGED
@@ -1,4 +1,31 @@
1
1
  import { BUILD_INSTANCE_FREE, BUILD_INSTANCE_LARGE, PLAN_EDITABLE_LIMIT_KEYS, PLAN_LIMITS, createDefaultPlanCatalog, parseBuildInstanceType, parsePlanLimitsPatch, parsePlanName, parsePlatformPlanCatalog, parsePlatformPlanId, validatePlanLimits } from "./plans.mjs";
2
+ //#region src/app-access.ts
3
+ const PLATFORM_APP_ACCESS_SETUP_PROOF_PREFIX = "void-platform-app-access-v1";
4
+ function parsePlatformAppAccessSetup(value) {
5
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid app access setup.");
6
+ const input = value;
7
+ if (input.version !== 1 || !["public", "protected"].includes(String(input.mode)) || typeof input.managed !== "boolean" || typeof input.accountId !== "string" || !input.accountId) throw new Error("Invalid app access setup.");
8
+ const ids = (name) => {
9
+ const entries = input[name];
10
+ if (!Array.isArray(entries) || entries.length > 16 || entries.some((id) => typeof id !== "string" || !id.trim() || id.length > 128) || new Set(entries).size !== entries.length) throw new Error(`Invalid app access ${name}.`);
11
+ return [...entries];
12
+ };
13
+ const identityProviderIds = ids("identityProviderIds");
14
+ const policyIds = ids("policyIds");
15
+ if (input.mode === "protected" && (!input.managed || !identityProviderIds.length || !policyIds.length)) throw new Error("Protected apps require identity providers, policies, and an Access-management token.");
16
+ if (input.mode === "public" && (identityProviderIds.length || policyIds.length)) throw new Error("Public app access cannot include identity policies.");
17
+ if (input.managed ? typeof input.apiToken !== "string" || !input.apiToken.trim() || /\s/.test(input.apiToken) || input.apiToken.length > 8192 : input.apiToken !== void 0) throw new Error("Managed app access requires a token; unmanaged public access must not retain one.");
18
+ return {
19
+ version: 1,
20
+ accountId: input.accountId,
21
+ mode: input.mode,
22
+ managed: input.managed,
23
+ ...input.managed ? { apiToken: input.apiToken } : {},
24
+ identityProviderIds,
25
+ policyIds
26
+ };
27
+ }
28
+ //#endregion
2
29
  //#region src/authentication-recovery.ts
3
30
  function platformAuthenticationRecoveryMessage(value) {
4
31
  return JSON.stringify([
@@ -338,6 +365,11 @@ function createPlatformDeploymentManifest(input) {
338
365
  ...input.capabilities
339
366
  };
340
367
  if (capabilities.managedBuilds && !capabilities.githubActions) throw new Error("Managed builds require the GitHub Actions capability.");
368
+ if (input.appAccess !== void 0 && ![
369
+ "public",
370
+ "platform",
371
+ "custom"
372
+ ].includes(input.appAccess)) throw new Error("appAccess must be public, platform, or custom.");
341
373
  const providers = input.authentication?.providers ?? ["github"];
342
374
  if (providers.some((provider) => !PLATFORM_LOGIN_KINDS.includes(provider)) || new Set(providers).size !== providers.length) throw new Error("Authentication providers must be unique supported login kinds.");
343
375
  const configurable = input.authentication?.configurable === true || input.authentication?.accessProtection === true || providers.some((provider) => provider === "oidc" || provider === "cloudflare-access");
@@ -346,6 +378,7 @@ function createPlatformDeploymentManifest(input) {
346
378
  if (providers.includes("google") !== capabilities.googleOAuth) throw new Error("The Google provider and googleOAuth capability must agree.");
347
379
  const dashboardUrl = input.controlPlane?.dashboardUrl === void 0 ? void 0 : normalizePlatformDashboardUrl(input.controlPlane.dashboardUrl);
348
380
  const manifest = {
381
+ ...input.appAccess !== void 0 ? { appAccess: input.appAccess } : {},
349
382
  application: {
350
383
  baseDomain,
351
384
  dedicatedZone: input.application.dedicatedZone ?? false,
@@ -372,7 +405,7 @@ function createPlatformDeploymentManifest(input) {
372
405
  displayName: requiredString$1(input.displayName, "displayName").trim(),
373
406
  installationSlug,
374
407
  resources,
375
- schemaVersion: configurable ? 3 : workersDev ? 2 : 1
408
+ schemaVersion: input.appAccess !== void 0 ? 4 : configurable ? 3 : workersDev ? 2 : 1
376
409
  };
377
410
  createApplicationRoutes(manifest.application);
378
411
  for (const [key, value] of Object.entries(manifest.controlPlane)) {
@@ -389,7 +422,7 @@ function createPlatformDeploymentManifest(input) {
389
422
  }
390
423
  function parsePlatformDeploymentManifest(value) {
391
424
  assertRecord$1(value, "Platform deployment manifest");
392
- if (value.schemaVersion !== 1 && value.schemaVersion !== 2 && value.schemaVersion !== 3) throw new Error(`Unsupported platform deployment schema version: ${String(value.schemaVersion)}.`);
425
+ if (value.schemaVersion !== 1 && value.schemaVersion !== 2 && value.schemaVersion !== 3 && value.schemaVersion !== 4) throw new Error(`Unsupported platform deployment schema version: ${String(value.schemaVersion)}.`);
393
426
  const application = value.application;
394
427
  const authentication = value.authentication;
395
428
  const rawCapabilities = value.capabilities;
@@ -397,7 +430,7 @@ function parsePlatformDeploymentManifest(value) {
397
430
  const rawResources = value.resources;
398
431
  assertRecord$1(application, "application");
399
432
  let workersDev;
400
- if (value.schemaVersion === 2 || value.schemaVersion === 3 && application.workersDev !== void 0) {
433
+ if (value.schemaVersion === 2 || (value.schemaVersion === 3 || value.schemaVersion === 4) && application.workersDev !== void 0) {
401
434
  assertRecord$1(application.workersDev, "application.workersDev");
402
435
  workersDev = {
403
436
  subdomain: requiredString$1(application.workersDev.subdomain, "workersDev.subdomain"),
@@ -416,8 +449,14 @@ function parsePlatformDeploymentManifest(value) {
416
449
  capabilities[key] = entry;
417
450
  }
418
451
  const providers = authentication.providers;
419
- if (!Array.isArray(providers) || providers.some((provider) => !PLATFORM_LOGIN_KINDS.includes(provider) || value.schemaVersion !== 3 && provider !== "github" && provider !== "google")) throw new Error("authentication.providers must contain only github or google.");
420
- if (value.schemaVersion === 3 && authentication.configurable !== true || value.schemaVersion !== 3 && (authentication.configurable !== void 0 || authentication.accessProtection !== void 0) || authentication.accessProtection !== void 0 && authentication.accessProtection !== true) throw new Error("Configurable authentication requires deployment schema version 3.");
452
+ if (!Array.isArray(providers) || providers.some((provider) => !PLATFORM_LOGIN_KINDS.includes(provider) || value.schemaVersion !== 3 && value.schemaVersion !== 4 && provider !== "github" && provider !== "google")) throw new Error("authentication.providers must contain only github or google.");
453
+ if (value.schemaVersion === 3 && authentication.configurable !== true || value.schemaVersion !== 3 && value.schemaVersion !== 4 && (authentication.configurable !== void 0 || authentication.accessProtection !== void 0) || authentication.accessProtection !== void 0 && authentication.accessProtection !== true) throw new Error("Configurable authentication requires deployment schema version 3.");
454
+ if (value.schemaVersion === 4 ? ![
455
+ "public",
456
+ "platform",
457
+ "custom"
458
+ ].includes(String(value.appAccess)) : value.appAccess !== void 0) throw new Error("Guided app access requires deployment schema version 4 and a valid appAccess choice.");
459
+ if (authentication.configurable !== void 0 && authentication.configurable !== true) throw new Error("Invalid configurable authentication flag.");
421
460
  const resourceDefaults = createPlatformResourceNames(requiredString$1(value.installationSlug, "installationSlug"));
422
461
  const resources = {};
423
462
  for (const key of Object.keys(resourceDefaults)) resources[key] = requiredString$1(rawResources[key] ?? (key === "emailGatewayWorker" || key === "deploymentQueue" ? resourceDefaults[key] : void 0), `resources.${key}`);
@@ -426,6 +465,7 @@ function parsePlatformDeploymentManifest(value) {
426
465
  return hostname === null ? null : requiredString$1(hostname, `controlPlane.${key}`);
427
466
  };
428
467
  return createPlatformDeploymentManifest({
468
+ ...value.schemaVersion === 4 ? { appAccess: value.appAccess } : {},
429
469
  application: {
430
470
  baseDomain: requiredString$1(application.baseDomain, "application.baseDomain"),
431
471
  dedicatedZone: application.dedicatedZone === true,
@@ -959,7 +999,7 @@ function parsePlatformDiscoveryDocument(value) {
959
999
  return entry;
960
1000
  };
961
1001
  const apiUrl = string("apiUrl");
962
- const proxyUrl = typeof document.proxyUrl === "string" && document.proxyUrl.trim() ? document.proxyUrl : apiUrl === "https://api.void.cloud" ? "https://proxy.void.cloud" : apiUrl === "https://api.staging.void.cloud" ? "https://proxy.staging.void.cloud" : string("proxyUrl");
1002
+ const proxyUrl = string("proxyUrl");
963
1003
  return createPlatformDiscoveryDocument({
964
1004
  apiUrl,
965
1005
  applicationDomain: string("applicationDomain"),
@@ -1052,6 +1092,10 @@ function createPlatformWorkerConfigs(input) {
1052
1092
  ].some((url) => new URL(url).hostname.endsWith(".workers.dev"));
1053
1093
  const api = {
1054
1094
  ...common,
1095
+ ...input.proxyHealthBinding && publicEndpoints && trafficState === "enabled" ? { services: [{
1096
+ binding: "PLATFORM_PROXY",
1097
+ service: names.proxyWorker
1098
+ }] } : {},
1055
1099
  version_metadata: { binding: "VERSION_METADATA" },
1056
1100
  workers_dev: publicEndpoints && (!deployment.authentication.accessProtection || new URL(apiUrl).hostname.endsWith(".workers.dev")),
1057
1101
  name: names.apiWorker,
@@ -1155,6 +1199,7 @@ function createPlatformWorkerConfigs(input) {
1155
1199
  PLATFORM_DISPLAY_NAME: deployment.displayName,
1156
1200
  PLATFORM_ENV: "production",
1157
1201
  PLATFORM_HEALTH_PROBE_TOKEN: healthProbeToken,
1202
+ ...deployment.appAccess ? { PLATFORM_APP_ACCESS: deployment.appAccess } : {},
1158
1203
  PLATFORM_INSTALLATION_ID: installationId,
1159
1204
  PLATFORM_TRAFFIC_STATE: trafficState,
1160
1205
  ...ownershipVars("api-worker", names.apiWorker),
@@ -1289,4 +1334,4 @@ function createPlatformWorkerConfigs(input) {
1289
1334
  };
1290
1335
  }
1291
1336
  //#endregion
1292
- export { BUILD_INSTANCE_FREE, BUILD_INSTANCE_LARGE, DEFAULT_PLATFORM_SESSION_SECONDS, GOOGLE_OIDC_ISSUER, PLAN_EDITABLE_LIMIT_KEYS, PLAN_LIMITS, PLATFORM_APPLICATION_KEY, PLATFORM_AUTH_SETUP_PROOF_PREFIX, PLATFORM_DEPLOYMENT_SCHEMA_VERSION, PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE, PLATFORM_DISCOVERY_SCHEMA_VERSION, PLATFORM_HEALTH_HOSTNAME_LABEL, PLATFORM_INSTALLATION_SCHEMA_VERSION, PLATFORM_LOGIN_KINDS, PLATFORM_PROJECT_INGRESS_SOURCE, PLATFORM_R2_OWNERSHIP_MARKER_KEY, PLATFORM_REMOTE_INSTALLATION_MANIFEST_KEY, PLATFORM_RESOURCE_OWNERSHIP_SCHEMA_VERSION, PLATFORM_SANDBOX_DRAIN_KEY, PLATFORM_USAGE_PROTOCOL_VERSION, createApplicationRoutes, createDefaultPlanCatalog, createPlatformDeploymentManifest, createPlatformDiscoveryDocument, createPlatformInstallationManifest, createPlatformResourceNames, createPlatformResourceOwnershipMarker, createPlatformWorkerConfigs, isPlatformSignupAllowed, normalizeApplicationDomain, normalizeInstallationSlug, normalizePlatformDashboardUrl, parseBuildInstanceType, parsePlanLimitsPatch, parsePlanName, parsePlatformAccessProtection, parsePlatformAdmissionPolicy, parsePlatformAuthenticationSetup, parsePlatformDeploymentManifest, parsePlatformDiscoveryDocument, parsePlatformIdentityUrl, parsePlatformInstallationManifest, parsePlatformLoginConfiguration, parsePlatformLoginDescriptor, parsePlatformLoginId, parsePlatformPlanCatalog, parsePlatformPlanId, parsePlatformResourceOwnershipMarker, parsePlatformSignupAllowlistEntry, platformAuthenticationRecoveryMessage, platformDashboardUrl, platformHealthHostname, platformProjectHostname, platformProjectHostnames, platformProjectIngressName, platformProjectIngressPrefix, platformProjectWorkersDevHostname, platformProtectionProofMessage, platformWorkersDevAliasKey, readPlatformApplication, recordInstallationResource, recordInstallationStep, resolvePlatformApplicationEnvironment, setInstallationDesiredState, setInstallationEndpoints, transitionInstallation, validatePlanLimits, validatePlatformAdmissionPolicy };
1337
+ export { BUILD_INSTANCE_FREE, BUILD_INSTANCE_LARGE, DEFAULT_PLATFORM_SESSION_SECONDS, GOOGLE_OIDC_ISSUER, PLAN_EDITABLE_LIMIT_KEYS, PLAN_LIMITS, PLATFORM_APPLICATION_KEY, PLATFORM_APP_ACCESS_SETUP_PROOF_PREFIX, PLATFORM_AUTH_SETUP_PROOF_PREFIX, PLATFORM_DEPLOYMENT_SCHEMA_VERSION, PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE, PLATFORM_DISCOVERY_SCHEMA_VERSION, PLATFORM_HEALTH_HOSTNAME_LABEL, PLATFORM_INSTALLATION_SCHEMA_VERSION, PLATFORM_LOGIN_KINDS, PLATFORM_PROJECT_INGRESS_SOURCE, PLATFORM_R2_OWNERSHIP_MARKER_KEY, PLATFORM_REMOTE_INSTALLATION_MANIFEST_KEY, PLATFORM_RESOURCE_OWNERSHIP_SCHEMA_VERSION, PLATFORM_SANDBOX_DRAIN_KEY, PLATFORM_USAGE_PROTOCOL_VERSION, createApplicationRoutes, createDefaultPlanCatalog, createPlatformDeploymentManifest, createPlatformDiscoveryDocument, createPlatformInstallationManifest, createPlatformResourceNames, createPlatformResourceOwnershipMarker, createPlatformWorkerConfigs, isPlatformSignupAllowed, normalizeApplicationDomain, normalizeInstallationSlug, normalizePlatformDashboardUrl, parseBuildInstanceType, parsePlanLimitsPatch, parsePlanName, parsePlatformAccessProtection, parsePlatformAdmissionPolicy, parsePlatformAppAccessSetup, parsePlatformAuthenticationSetup, parsePlatformDeploymentManifest, parsePlatformDiscoveryDocument, parsePlatformIdentityUrl, parsePlatformInstallationManifest, parsePlatformLoginConfiguration, parsePlatformLoginDescriptor, parsePlatformLoginId, parsePlatformPlanCatalog, parsePlatformPlanId, parsePlatformResourceOwnershipMarker, parsePlatformSignupAllowlistEntry, platformAuthenticationRecoveryMessage, platformDashboardUrl, platformHealthHostname, platformProjectHostname, platformProjectHostnames, platformProjectIngressName, platformProjectIngressPrefix, platformProjectWorkersDevHostname, platformProtectionProofMessage, platformWorkersDevAliasKey, readPlatformApplication, recordInstallationResource, recordInstallationStep, resolvePlatformApplicationEnvironment, setInstallationDesiredState, setInstallationEndpoints, transitionInstallation, validatePlanLimits, validatePlatformAdmissionPolicy };
@@ -26,6 +26,7 @@ export type PlatformRuntimeDatabaseManifest = Readonly<{
26
26
  schemaDigest: string;
27
27
  }>;
28
28
  export type PlatformRuntimeManifest = Readonly<{
29
+ appAccessSetup?: 1;
29
30
  /** Durable deployment Queue payload and PostgreSQL operation journal contract. */
30
31
  deploymentExecution?: 1;
31
32
  authenticationProtocolVersion?: 1;
@@ -22,6 +22,7 @@ function platformDatabaseSchemaDigest(lineage, migrations) {
22
22
  function parsePlatformRuntimeManifest(value) {
23
23
  const root = record(value, "runtime manifest");
24
24
  if (root.schemaVersion !== 2) throw new Error("runtime manifest schemaVersion must be 2");
25
+ if (root.appAccessSetup !== void 0 && root.appAccessSetup !== 1) throw new Error("Unsupported app access setup protocol.");
25
26
  if (root.deploymentExecution !== void 0 && root.deploymentExecution !== 1) throw new Error("Unsupported deployment execution protocol.");
26
27
  if (root.authenticationProtocolVersion !== void 0 && root.authenticationProtocolVersion !== 1) throw new Error("Unsupported authentication protocol version.");
27
28
  if (root.emailProtocolVersion !== void 0 && root.emailProtocolVersion !== 1) throw new Error("Unsupported email protocol version.");
@@ -81,6 +82,7 @@ function parsePlatformRuntimeManifest(value) {
81
82
  if (rollbackSafeFrom.some((entry) => !prefixDigests.has(entry.schemaDigest))) throw new Error("runtime manifest database rollback compatibility must reference this migration lineage");
82
83
  return {
83
84
  artifacts,
85
+ ...root.appAccessSetup === 1 ? { appAccessSetup: 1 } : {},
84
86
  ...root.deploymentExecution === 1 ? { deploymentExecution: 1 } : {},
85
87
  ...assets ? { assets } : {},
86
88
  ...root.authenticationProtocolVersion === 1 ? { authenticationProtocolVersion: 1 } : {},
@@ -1 +1 @@
1
- This folder contains the built output assets for the worker "void-runtime-build-api" generated at 2026-10-02T09:44:01.246Z.
1
+ This folder contains the built output assets for the worker "void-runtime-build-api" generated at 2026-10-03T03:31:21.212Z.