@void/platform 0.27.0 → 1.0.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/browser-page.mjs +2 -1
- package/dist/index.d.mts +17 -0
- package/dist/index.mjs +96 -58
- package/dist/installer.mjs +23 -25
- package/dist/plans.mjs +8 -11
- package/dist/runtime/api/assets/admin/client.js +180 -28
- package/dist/runtime/api/assets/admin/style.css +1 -1
- package/dist/runtime/api/index.js +338 -299
- package/dist/runtime/dispatch/index.js +7 -7
- package/dist/runtime/drizzle/0059_oauth_clients.sql +44 -0
- package/dist/runtime/drizzle/compatibility.json +4 -0
- package/dist/runtime/drizzle/meta/_journal.json +7 -0
- package/dist/runtime/emailGateway/index.js +5 -5
- package/dist/runtime/manifest.json +28 -18
- package/dist/runtime/proxy/index.js +5 -5
- package/dist/runtime/tail/index.js +1 -1
- package/dist/validate-DbJR7Q0Z.mjs +30 -0
- package/package.json +4 -4
package/dist/browser-page.mjs
CHANGED
|
@@ -37,7 +37,8 @@ html[data-theme="dark"] { color-scheme: dark; }
|
|
|
37
37
|
.void-auth-page p { margin: 0; font: inherit; color: var(--auth-secondary); overflow-wrap: anywhere; }
|
|
38
38
|
.void-auth-page strong { font-weight: 600; color: var(--auth-text); }
|
|
39
39
|
.void-auth-page a:not(.void-auth-button) { color: var(--auth-text); text-underline-offset: 3px; }
|
|
40
|
-
.void-auth-page
|
|
40
|
+
.void-auth-page form { display: grid; gap: 12px; }
|
|
41
|
+
.void-auth-page .void-auth-actions { display: grid; gap: 8px; }
|
|
41
42
|
.void-auth-page .void-auth-button { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 44px; padding: 10px 16px; border: 1px solid var(--auth-border); border-radius: var(--auth-radius-element); background: var(--auth-body); color: var(--auth-text); font: inherit; font-weight: 550; line-height: 1.4; text-align: center; text-decoration: none; overflow-wrap: anywhere; cursor: pointer; }
|
|
42
43
|
.void-auth-page .void-auth-button-primary { background: var(--auth-accent); color: var(--auth-on-accent); border-color: var(--auth-accent); }
|
|
43
44
|
.void-auth-page .void-auth-button:hover { filter: brightness(.92); }
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
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/access-policy.d.ts
|
|
3
|
+
/** An exact email domain, such as `example.com`, without wildcards or an `@`. */
|
|
4
|
+
export declare function isPlatformAccessEmailDomain(value: unknown): value is string;
|
|
5
|
+
/** Whether signing in with this Access identity provider proves a company identity. */
|
|
6
|
+
export declare function isPlatformAccessCompanyIdentityProvider(provider: Readonly<Record<string, unknown>>): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Whether one Access include or require rule restricts people to company
|
|
9
|
+
* identities. The installer checks the policies that protect the platform and
|
|
10
|
+
* the API checks project Zero Trust policies with this same rule list.
|
|
11
|
+
*
|
|
12
|
+
* A `login_method` rule admits everyone who can use the identity provider it
|
|
13
|
+
* names, so it counts only when `companyLoginMethod` accepts that provider ID.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isPlatformAccessIdentityRule(rule: Readonly<Record<string, unknown>>, companyLoginMethod: (identityProviderId: string) => boolean): boolean;
|
|
16
|
+
//#endregion
|
|
2
17
|
//#region src/app-access.d.ts
|
|
3
18
|
export declare const PLATFORM_APP_ACCESS_SETUP_PROOF_PREFIX = "void-platform-app-access-v1";
|
|
19
|
+
/** Uninstall handoff that turns off installer-managed project Zero Trust before any user exists. */
|
|
20
|
+
export declare const PLATFORM_APP_ACCESS_TURN_OFF_PROOF_PREFIX = "void-platform-app-access-turn-off-v1";
|
|
4
21
|
/** Installer handoff. Token values belong only in encrypted recovery and request bodies. */
|
|
5
22
|
type PlatformAppAccessSetup = Readonly<{
|
|
6
23
|
version: 1;
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,62 @@
|
|
|
1
|
+
import { a as isSourceRevision, c as requiredString, i as isSandboxDrainProtocol, n as isPrintableText, o as isUsageProtocolVersion, s as record, t as assertRecord } from "./validate-DbJR7Q0Z.mjs";
|
|
1
2
|
import { BUILD_INSTANCE_FREE, BUILD_INSTANCE_LARGE, PLAN_EDITABLE_LIMIT_KEYS, PLAN_LIMITS, createDefaultPlanCatalog, parseBuildInstanceType, parsePlanLimitsPatch, parsePlanName, parsePlatformPlanCatalog, parsePlatformPlanId, validatePlanLimits } from "./plans.mjs";
|
|
3
|
+
//#region src/access-policy.ts
|
|
4
|
+
const COMPANY_IDENTITY_RULES = [
|
|
5
|
+
"email_list",
|
|
6
|
+
"gsuite",
|
|
7
|
+
"github-organization",
|
|
8
|
+
"saml",
|
|
9
|
+
"okta",
|
|
10
|
+
"azureAD",
|
|
11
|
+
"auth_context",
|
|
12
|
+
"group"
|
|
13
|
+
];
|
|
14
|
+
const COMPANY_IDENTITY_PROVIDER_TYPES = /* @__PURE__ */ new Set([
|
|
15
|
+
"azureAD",
|
|
16
|
+
"centrify",
|
|
17
|
+
"google-apps",
|
|
18
|
+
"okta",
|
|
19
|
+
"onelogin",
|
|
20
|
+
"pingone"
|
|
21
|
+
]);
|
|
22
|
+
function plainObject(value) {
|
|
23
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
/** An exact email domain, such as `example.com`, without wildcards or an `@`. */
|
|
26
|
+
function isPlatformAccessEmailDomain(value) {
|
|
27
|
+
return typeof value === "string" && /^(?:[a-z0-9-]+\.)+[a-z]{2,63}$/i.test(value);
|
|
28
|
+
}
|
|
29
|
+
/** Whether signing in with this Access identity provider proves a company identity. */
|
|
30
|
+
function isPlatformAccessCompanyIdentityProvider(provider) {
|
|
31
|
+
if (provider.type === "cloudflare") return plainObject(provider.config) && provider.config.restrict_to_account_members === true;
|
|
32
|
+
return COMPANY_IDENTITY_PROVIDER_TYPES.has(provider.type);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether one Access include or require rule restricts people to company
|
|
36
|
+
* identities. The installer checks the policies that protect the platform and
|
|
37
|
+
* the API checks project Zero Trust policies with this same rule list.
|
|
38
|
+
*
|
|
39
|
+
* A `login_method` rule admits everyone who can use the identity provider it
|
|
40
|
+
* names, so it counts only when `companyLoginMethod` accepts that provider ID.
|
|
41
|
+
*/
|
|
42
|
+
function isPlatformAccessIdentityRule(rule, companyLoginMethod) {
|
|
43
|
+
if (rule.email_domain) return plainObject(rule.email_domain) && isPlatformAccessEmailDomain(rule.email_domain.domain);
|
|
44
|
+
if (rule.email) return plainObject(rule.email) && typeof rule.email.email === "string" && /^[^\s*@]+@[^\s*@]+\.[^\s*@]+$/.test(rule.email.email);
|
|
45
|
+
if (rule.login_method) return plainObject(rule.login_method) && typeof rule.login_method.id === "string" && companyLoginMethod(rule.login_method.id);
|
|
46
|
+
if (rule.cloudflare_account_member) {
|
|
47
|
+
const member = rule.cloudflare_account_member;
|
|
48
|
+
return plainObject(member) && (member.account_id === void 0 || typeof member.account_id === "string" && /^[0-9a-f]{32}$/i.test(member.account_id));
|
|
49
|
+
}
|
|
50
|
+
return COMPANY_IDENTITY_RULES.some((key) => {
|
|
51
|
+
const value = Object.hasOwn(rule, key) ? rule[key] : void 0;
|
|
52
|
+
return plainObject(value) && Object.keys(value).length > 0;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
2
56
|
//#region src/app-access.ts
|
|
3
57
|
const PLATFORM_APP_ACCESS_SETUP_PROOF_PREFIX = "void-platform-app-access-v1";
|
|
58
|
+
/** Uninstall handoff that turns off installer-managed project Zero Trust before any user exists. */
|
|
59
|
+
const PLATFORM_APP_ACCESS_TURN_OFF_PROOF_PREFIX = "void-platform-app-access-turn-off-v1";
|
|
4
60
|
function parsePlatformAppAccessSetup(value) {
|
|
5
61
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid app access setup.");
|
|
6
62
|
const input = value;
|
|
@@ -125,12 +181,8 @@ function parsePlatformAuthenticationSetup(value) {
|
|
|
125
181
|
const DEFAULT_PLATFORM_SESSION_SECONDS = 2592e3;
|
|
126
182
|
const GOOGLE_OIDC_ISSUER = "https://accounts.google.com";
|
|
127
183
|
const PLATFORM_AUTH_SETUP_PROOF_PREFIX = "void.platform.auth.setup.v1";
|
|
128
|
-
function record(value, name) {
|
|
129
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${name} must be an object.`);
|
|
130
|
-
return value;
|
|
131
|
-
}
|
|
132
184
|
function string(value, name, maximum = 512) {
|
|
133
|
-
if (
|
|
185
|
+
if (!isPrintableText(value, maximum)) throw new Error(`${name} must be a nonempty string of at most ${maximum} characters.`);
|
|
134
186
|
return value.trim();
|
|
135
187
|
}
|
|
136
188
|
function strings(value, name, maximum = 100) {
|
|
@@ -262,13 +314,6 @@ const CONTROL_PLANE_DEFAULTS = {
|
|
|
262
314
|
dashboardHostname: null,
|
|
263
315
|
proxyHostname: null
|
|
264
316
|
};
|
|
265
|
-
function assertRecord$1(value, label) {
|
|
266
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object.`);
|
|
267
|
-
}
|
|
268
|
-
function requiredString$1(value, label) {
|
|
269
|
-
if (typeof value !== "string" || value.trim() === "") throw new Error(`${label} must be a non-empty string.`);
|
|
270
|
-
return value;
|
|
271
|
-
}
|
|
272
317
|
function normalizeInstallationSlug(value) {
|
|
273
318
|
const slug = value.trim().toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "").replaceAll(/-{2,}/g, "-");
|
|
274
319
|
if (!slug) throw new Error("The installation name must contain a letter or number.");
|
|
@@ -384,7 +429,7 @@ function createPlatformDeploymentManifest(input) {
|
|
|
384
429
|
dedicatedZone: input.application.dedicatedZone ?? false,
|
|
385
430
|
zoneName,
|
|
386
431
|
...workersDev ? { workersDev: { ...workersDev } } : {},
|
|
387
|
-
...input.application.zoneId ? { zoneId: requiredString
|
|
432
|
+
...input.application.zoneId ? { zoneId: requiredString(input.application.zoneId, "application.zoneId") } : {}
|
|
388
433
|
},
|
|
389
434
|
authentication: {
|
|
390
435
|
providers: [...providers],
|
|
@@ -392,7 +437,7 @@ function createPlatformDeploymentManifest(input) {
|
|
|
392
437
|
...input.authentication?.accessProtection ? { accessProtection: true } : {}
|
|
393
438
|
},
|
|
394
439
|
capabilities,
|
|
395
|
-
...input.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString
|
|
440
|
+
...input.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString(input.emailSharedZoneId, "emailSharedZoneId") } : {},
|
|
396
441
|
...input.emailSenderDomain !== void 0 ? { emailSenderDomain: normalizeApplicationDomain(input.emailSenderDomain) } : {},
|
|
397
442
|
controlPlane: {
|
|
398
443
|
...CONTROL_PLANE_DEFAULTS,
|
|
@@ -402,7 +447,7 @@ function createPlatformDeploymentManifest(input) {
|
|
|
402
447
|
dashboardHostname: input.controlPlane?.dashboardHostname ?? new URL(dashboardUrl).hostname
|
|
403
448
|
} : {}
|
|
404
449
|
},
|
|
405
|
-
displayName: requiredString
|
|
450
|
+
displayName: requiredString(input.displayName, "displayName").trim(),
|
|
406
451
|
installationSlug,
|
|
407
452
|
resources,
|
|
408
453
|
schemaVersion: input.appAccess !== void 0 ? 4 : configurable ? 3 : workersDev ? 2 : 1
|
|
@@ -416,30 +461,30 @@ function createPlatformDeploymentManifest(input) {
|
|
|
416
461
|
const hostname = new URL(manifest.controlPlane.dashboardUrl).hostname;
|
|
417
462
|
if (manifest.controlPlane.dashboardHostname !== hostname) throw new Error("The dashboard URL and dashboard hostname must agree.");
|
|
418
463
|
}
|
|
419
|
-
for (const [key, value] of Object.entries(manifest.resources)) requiredString
|
|
464
|
+
for (const [key, value] of Object.entries(manifest.resources)) requiredString(value, `resources.${key}`);
|
|
420
465
|
return manifest;
|
|
421
466
|
}
|
|
422
467
|
function parsePlatformDeploymentManifest(value) {
|
|
423
|
-
assertRecord
|
|
468
|
+
assertRecord(value, "Platform deployment manifest");
|
|
424
469
|
if (value.schemaVersion !== 1 && value.schemaVersion !== 2 && value.schemaVersion !== 3 && value.schemaVersion !== 4) throw new Error(`Unsupported platform deployment schema version: ${String(value.schemaVersion)}.`);
|
|
425
470
|
const application = value.application;
|
|
426
471
|
const authentication = value.authentication;
|
|
427
472
|
const rawCapabilities = value.capabilities;
|
|
428
473
|
const controlPlane = value.controlPlane;
|
|
429
474
|
const rawResources = value.resources;
|
|
430
|
-
assertRecord
|
|
475
|
+
assertRecord(application, "application");
|
|
431
476
|
let workersDev;
|
|
432
477
|
if (value.schemaVersion === 2 || (value.schemaVersion === 3 || value.schemaVersion === 4) && application.workersDev !== void 0) {
|
|
433
|
-
assertRecord
|
|
478
|
+
assertRecord(application.workersDev, "application.workersDev");
|
|
434
479
|
workersDev = {
|
|
435
|
-
subdomain: requiredString
|
|
436
|
-
installationId: requiredString
|
|
480
|
+
subdomain: requiredString(application.workersDev.subdomain, "workersDev.subdomain"),
|
|
481
|
+
installationId: requiredString(application.workersDev.installationId, "workersDev.installationId")
|
|
437
482
|
};
|
|
438
483
|
} else if (application.workersDev !== void 0) throw new Error("workers.dev requires platform deployment schema version 2.");
|
|
439
|
-
assertRecord
|
|
440
|
-
assertRecord
|
|
441
|
-
assertRecord
|
|
442
|
-
assertRecord
|
|
484
|
+
assertRecord(rawCapabilities, "capabilities");
|
|
485
|
+
assertRecord(controlPlane, "controlPlane");
|
|
486
|
+
assertRecord(authentication, "authentication");
|
|
487
|
+
assertRecord(rawResources, "resources");
|
|
443
488
|
const capabilityKeys = Object.keys(CORE_CAPABILITIES);
|
|
444
489
|
const capabilities = {};
|
|
445
490
|
for (const key of capabilityKeys) {
|
|
@@ -456,19 +501,19 @@ function parsePlatformDeploymentManifest(value) {
|
|
|
456
501
|
"custom"
|
|
457
502
|
].includes(String(value.appAccess)) : value.appAccess !== void 0) throw new Error("Guided app access requires deployment schema version 4 and a valid appAccess choice.");
|
|
458
503
|
if (authentication.configurable !== void 0 && authentication.configurable !== true) throw new Error("Invalid configurable authentication flag.");
|
|
459
|
-
const resourceDefaults = createPlatformResourceNames(requiredString
|
|
504
|
+
const resourceDefaults = createPlatformResourceNames(requiredString(value.installationSlug, "installationSlug"));
|
|
460
505
|
const resources = {};
|
|
461
|
-
for (const key of Object.keys(resourceDefaults)) resources[key] = requiredString
|
|
506
|
+
for (const key of Object.keys(resourceDefaults)) resources[key] = requiredString(rawResources[key] ?? (key === "emailGatewayWorker" || key === "deploymentQueue" ? resourceDefaults[key] : void 0), `resources.${key}`);
|
|
462
507
|
const readHostname = (key) => {
|
|
463
508
|
const hostname = controlPlane[key];
|
|
464
|
-
return hostname === null ? null : requiredString
|
|
509
|
+
return hostname === null ? null : requiredString(hostname, `controlPlane.${key}`);
|
|
465
510
|
};
|
|
466
511
|
return createPlatformDeploymentManifest({
|
|
467
512
|
...value.schemaVersion === 4 ? { appAccess: value.appAccess } : {},
|
|
468
513
|
application: {
|
|
469
|
-
baseDomain: requiredString
|
|
514
|
+
baseDomain: requiredString(application.baseDomain, "application.baseDomain"),
|
|
470
515
|
dedicatedZone: application.dedicatedZone === true,
|
|
471
|
-
zoneName: workersDev && application.zoneName === "" ? "" : requiredString
|
|
516
|
+
zoneName: workersDev && application.zoneName === "" ? "" : requiredString(application.zoneName, "application.zoneName"),
|
|
472
517
|
...workersDev ? { workersDev } : {},
|
|
473
518
|
...typeof application.zoneId === "string" ? { zoneId: application.zoneId } : {}
|
|
474
519
|
},
|
|
@@ -478,16 +523,16 @@ function parsePlatformDeploymentManifest(value) {
|
|
|
478
523
|
...authentication.accessProtection === true ? { accessProtection: true } : {}
|
|
479
524
|
},
|
|
480
525
|
capabilities,
|
|
481
|
-
...value.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString
|
|
482
|
-
...value.emailSenderDomain !== void 0 ? { emailSenderDomain: requiredString
|
|
526
|
+
...value.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString(value.emailSharedZoneId, "emailSharedZoneId") } : {},
|
|
527
|
+
...value.emailSenderDomain !== void 0 ? { emailSenderDomain: requiredString(value.emailSenderDomain, "emailSenderDomain") } : {},
|
|
483
528
|
controlPlane: {
|
|
484
529
|
apiHostname: readHostname("apiHostname"),
|
|
485
530
|
dashboardHostname: readHostname("dashboardHostname"),
|
|
486
|
-
...controlPlane.dashboardUrl !== void 0 ? { dashboardUrl: requiredString
|
|
531
|
+
...controlPlane.dashboardUrl !== void 0 ? { dashboardUrl: requiredString(controlPlane.dashboardUrl, "controlPlane.dashboardUrl") } : {},
|
|
487
532
|
proxyHostname: readHostname("proxyHostname")
|
|
488
533
|
},
|
|
489
|
-
displayName: requiredString
|
|
490
|
-
installationSlug: requiredString
|
|
534
|
+
displayName: requiredString(value.displayName, "displayName"),
|
|
535
|
+
installationSlug: requiredString(value.installationSlug, "installationSlug"),
|
|
491
536
|
resources
|
|
492
537
|
});
|
|
493
538
|
}
|
|
@@ -609,13 +654,6 @@ const STATUS_TRANSITIONS = {
|
|
|
609
654
|
"uninstalling"
|
|
610
655
|
]
|
|
611
656
|
};
|
|
612
|
-
function assertRecord(value, label) {
|
|
613
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object.`);
|
|
614
|
-
}
|
|
615
|
-
function requiredString(value, label) {
|
|
616
|
-
if (typeof value !== "string" || value.trim() === "") throw new Error(`${label} must be a non-empty string.`);
|
|
617
|
-
return value;
|
|
618
|
-
}
|
|
619
657
|
function isInstallationStatus(value) {
|
|
620
658
|
return typeof value === "string" && Object.hasOwn(STATUS_TRANSITIONS, value);
|
|
621
659
|
}
|
|
@@ -847,15 +885,14 @@ function parseAuthenticationResources(value) {
|
|
|
847
885
|
return resources;
|
|
848
886
|
}
|
|
849
887
|
function parseUsageProtocolVersion(value) {
|
|
850
|
-
if (value === void 0
|
|
851
|
-
if (value
|
|
852
|
-
|
|
853
|
-
throw new Error("usageProtocolVersion must be 0, 1, or 2.");
|
|
888
|
+
if (value === void 0) return 0;
|
|
889
|
+
if (!isUsageProtocolVersion(value)) throw new Error("usageProtocolVersion must be 0, 1, or 2.");
|
|
890
|
+
return value;
|
|
854
891
|
}
|
|
855
892
|
function parseSafetyProtocols(value) {
|
|
856
893
|
if (value === void 0) return { sandboxDrain: 0 };
|
|
857
894
|
assertRecord(value, "safetyProtocols");
|
|
858
|
-
if (value.sandboxDrain
|
|
895
|
+
if (!isSandboxDrainProtocol(value.sandboxDrain)) throw new Error("safetyProtocols.sandboxDrain must be 0, 1, 2, or 3.");
|
|
859
896
|
return { sandboxDrain: value.sandboxDrain };
|
|
860
897
|
}
|
|
861
898
|
function parsePlatformRuntimeProvenance(value) {
|
|
@@ -865,7 +902,7 @@ function parsePlatformRuntimeProvenance(value) {
|
|
|
865
902
|
const manifestSha256 = requiredString(value.manifestSha256, "runtime.manifestSha256");
|
|
866
903
|
if (!/^[0-9a-f]{64}$/.test(manifestSha256)) throw new Error("runtime.manifestSha256 must be a SHA-256 digest.");
|
|
867
904
|
const sourceRevision = value.sourceRevision === null || value.sourceRevision === void 0 ? null : requiredString(value.sourceRevision, "runtime.sourceRevision");
|
|
868
|
-
if (sourceRevision !== null && (sourceRevision
|
|
905
|
+
if (sourceRevision !== null && !isSourceRevision(sourceRevision)) throw new Error("runtime.sourceRevision is invalid.");
|
|
869
906
|
return {
|
|
870
907
|
manifestSha256,
|
|
871
908
|
source: value.source,
|
|
@@ -890,10 +927,14 @@ function readPlatformApplication(env) {
|
|
|
890
927
|
zoneName: baseDomain,
|
|
891
928
|
dedicatedZone: false
|
|
892
929
|
};
|
|
930
|
+
return parsePlatformApplication(JSON.parse(env.PLATFORM_APPLICATION));
|
|
931
|
+
}
|
|
932
|
+
/** Applies the deployment manifest's application rules to a parsed value. */
|
|
933
|
+
function parsePlatformApplication(value) {
|
|
893
934
|
return createPlatformDeploymentManifest({
|
|
894
935
|
installationSlug: "runtime",
|
|
895
936
|
displayName: "Runtime",
|
|
896
|
-
application:
|
|
937
|
+
application: value
|
|
897
938
|
}).application;
|
|
898
939
|
}
|
|
899
940
|
function platformWorkersDevAliasKey(hostname) {
|
|
@@ -968,7 +1009,7 @@ function createPlatformDiscoveryDocument(input) {
|
|
|
968
1009
|
if (!input.displayName.trim()) throw new Error("displayName must not be empty.");
|
|
969
1010
|
if (!input.platformVersion.trim()) throw new Error("platformVersion must not be empty.");
|
|
970
1011
|
if (input.applicationRouting) {
|
|
971
|
-
const application =
|
|
1012
|
+
const application = parsePlatformApplication(input.applicationRouting);
|
|
972
1013
|
if (!application.workersDev || application.baseDomain !== input.applicationDomain || application.workersDev.installationId !== input.installationId) throw new Error("Application routing must match the discovery domain and installation identity.");
|
|
973
1014
|
}
|
|
974
1015
|
const usageProtocolVersion = parseUsageProtocolVersion(input.usageProtocolVersion);
|
|
@@ -994,13 +1035,12 @@ function createPlatformDiscoveryDocument(input) {
|
|
|
994
1035
|
};
|
|
995
1036
|
}
|
|
996
1037
|
function parsePlatformDiscoveryDocument(value) {
|
|
997
|
-
|
|
998
|
-
const document = value;
|
|
1038
|
+
const document = record(value, "Platform discovery document");
|
|
999
1039
|
if (document.schemaVersion !== 1 && document.schemaVersion !== 2 && document.schemaVersion !== 3) throw new Error(`Unsupported platform discovery schema version: ${String(document.schemaVersion)}.`);
|
|
1000
1040
|
const capabilities = document.capabilities;
|
|
1001
1041
|
if (document.schemaVersion === 1 && document.applicationRouting !== void 0) throw new Error("Application routing requires discovery schema version 2.");
|
|
1002
1042
|
if (document.schemaVersion === 2 && document.applicationRouting === void 0) throw new Error("Discovery schema version 2 requires application routing.");
|
|
1003
|
-
|
|
1043
|
+
assertRecord(capabilities, "capabilities");
|
|
1004
1044
|
const capabilityNames = [
|
|
1005
1045
|
"ai",
|
|
1006
1046
|
"customDomains",
|
|
@@ -1032,7 +1072,7 @@ function parsePlatformDiscoveryDocument(value) {
|
|
|
1032
1072
|
return createPlatformDiscoveryDocument({
|
|
1033
1073
|
apiUrl,
|
|
1034
1074
|
applicationDomain: string("applicationDomain"),
|
|
1035
|
-
...document.applicationRouting !== void 0 ? { applicationRouting:
|
|
1075
|
+
...document.applicationRouting !== void 0 ? { applicationRouting: parsePlatformApplication(document.applicationRouting) } : {},
|
|
1036
1076
|
authenticationProviders: providers,
|
|
1037
1077
|
...authentication ? { authentication } : {},
|
|
1038
1078
|
capabilities: parsedCapabilities,
|
|
@@ -1045,8 +1085,7 @@ function parsePlatformDiscoveryDocument(value) {
|
|
|
1045
1085
|
});
|
|
1046
1086
|
}
|
|
1047
1087
|
function parseAuthentication(value) {
|
|
1048
|
-
|
|
1049
|
-
const authentication = value;
|
|
1088
|
+
const authentication = record(value, "Authentication discovery");
|
|
1050
1089
|
if (!Array.isArray(authentication.methods) || authentication.methods.length > 32 || typeof authentication.protectedByAccess !== "boolean" || authentication.setupPending !== void 0 && typeof authentication.setupPending !== "boolean") throw new Error("Authentication discovery requires login methods and a protection flag.");
|
|
1051
1090
|
const methods = authentication.methods.map(parsePlatformLoginDescriptor);
|
|
1052
1091
|
if (new Set(methods.map((method) => method.id)).size !== methods.length) throw new Error("Authentication connection IDs must be unique.");
|
|
@@ -1281,7 +1320,6 @@ function createPlatformWorkerConfigs(input) {
|
|
|
1281
1320
|
proxy,
|
|
1282
1321
|
emailGateway: {
|
|
1283
1322
|
...common,
|
|
1284
|
-
workers_dev: publicEndpoints,
|
|
1285
1323
|
preview_urls: false,
|
|
1286
1324
|
name: names.emailGatewayWorker,
|
|
1287
1325
|
main: runtimeEntrypoints.emailGateway,
|
|
@@ -1359,4 +1397,4 @@ function createPlatformWorkerConfigs(input) {
|
|
|
1359
1397
|
};
|
|
1360
1398
|
}
|
|
1361
1399
|
//#endregion
|
|
1362
|
-
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, parsePlatformLifecycleOperation, 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 };
|
|
1400
|
+
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_APP_ACCESS_TURN_OFF_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, isPlatformAccessCompanyIdentityProvider, isPlatformAccessEmailDomain, isPlatformAccessIdentityRule, isPlatformSignupAllowed, normalizeApplicationDomain, normalizeInstallationSlug, normalizePlatformDashboardUrl, parseBuildInstanceType, parsePlanLimitsPatch, parsePlanName, parsePlatformAccessProtection, parsePlatformAdmissionPolicy, parsePlatformAppAccessSetup, parsePlatformAuthenticationSetup, parsePlatformDeploymentManifest, parsePlatformDiscoveryDocument, parsePlatformIdentityUrl, parsePlatformInstallationManifest, parsePlatformLifecycleOperation, 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 };
|
package/dist/installer.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { a as isSourceRevision, i as isSandboxDrainProtocol, o as isUsageProtocolVersion, r as isRecord } from "./validate-DbJR7Q0Z.mjs";
|
|
1
2
|
import { createHash } from "node:crypto";
|
|
2
3
|
import { readFileSync, realpathSync, statSync } from "node:fs";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
@@ -105,26 +106,20 @@ function parsePlatformRuntimeManifest(value) {
|
|
|
105
106
|
}
|
|
106
107
|
function parseSafetyProtocols(value) {
|
|
107
108
|
if (value === void 0) return { sandboxDrain: 0 };
|
|
108
|
-
const
|
|
109
|
-
if (
|
|
110
|
-
return { sandboxDrain
|
|
109
|
+
const { sandboxDrain } = record(value, "runtime manifest safetyProtocols");
|
|
110
|
+
if (!isSandboxDrainProtocol(sandboxDrain)) throw new Error("runtime manifest safetyProtocols.sandboxDrain must be 0, 1, 2, or 3");
|
|
111
|
+
return { sandboxDrain };
|
|
111
112
|
}
|
|
112
113
|
function usageProtocolVersion(value) {
|
|
113
|
-
if (value === void 0
|
|
114
|
-
if (value
|
|
115
|
-
|
|
116
|
-
throw new Error("runtime manifest usageProtocolVersion must be 0, 1, or 2");
|
|
114
|
+
if (value === void 0) return 0;
|
|
115
|
+
if (!isUsageProtocolVersion(value)) throw new Error("runtime manifest usageProtocolVersion must be 0, 1, or 2");
|
|
116
|
+
return value;
|
|
117
117
|
}
|
|
118
118
|
function getPlatformRuntimeDirectory() {
|
|
119
119
|
return join(dirname(fileURLToPath(import.meta.url)), "runtime");
|
|
120
120
|
}
|
|
121
121
|
function readPlatformRuntimeManifest(runtimeDirectory = getPlatformRuntimeDirectory()) {
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
return parsePlatformRuntimeManifest(JSON.parse(readFileSync(path, "utf8")));
|
|
125
|
-
} catch (error) {
|
|
126
|
-
throw new Error(`Void Platform deployment artifacts are missing or invalid at ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
127
|
-
}
|
|
122
|
+
return readRuntimeManifestFile(join(runtimeDirectory, "manifest.json")).manifest;
|
|
128
123
|
}
|
|
129
124
|
function resolvePlatformRuntime(customRuntimeDirectory, baseDirectory = process.cwd()) {
|
|
130
125
|
const source = customRuntimeDirectory ? "custom" : "package";
|
|
@@ -136,22 +131,25 @@ function resolvePlatformRuntime(customRuntimeDirectory, baseDirectory = process.
|
|
|
136
131
|
} catch (error) {
|
|
137
132
|
throw new Error(`Void Platform runtime directory is unavailable at ${requestedDirectory}: ${error instanceof Error ? error.message : String(error)}`);
|
|
138
133
|
}
|
|
139
|
-
const
|
|
140
|
-
let manifestContents;
|
|
141
|
-
let manifest;
|
|
142
|
-
try {
|
|
143
|
-
manifestContents = readFileSync(manifestPath);
|
|
144
|
-
manifest = parsePlatformRuntimeManifest(JSON.parse(manifestContents.toString("utf8")));
|
|
145
|
-
} catch (error) {
|
|
146
|
-
throw new Error(`Void Platform deployment artifacts are missing or invalid at ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
147
|
-
}
|
|
134
|
+
const { contents, manifest } = readRuntimeManifestFile(join(directory, "manifest.json"));
|
|
148
135
|
return {
|
|
149
136
|
directory,
|
|
150
137
|
manifest,
|
|
151
|
-
manifestSha256: createHash("sha256").update(
|
|
138
|
+
manifestSha256: createHash("sha256").update(contents).digest("hex"),
|
|
152
139
|
source
|
|
153
140
|
};
|
|
154
141
|
}
|
|
142
|
+
function readRuntimeManifestFile(path) {
|
|
143
|
+
try {
|
|
144
|
+
const contents = readFileSync(path);
|
|
145
|
+
return {
|
|
146
|
+
contents,
|
|
147
|
+
manifest: parsePlatformRuntimeManifest(JSON.parse(contents.toString("utf8")))
|
|
148
|
+
};
|
|
149
|
+
} catch (error) {
|
|
150
|
+
throw new Error(`Void Platform deployment artifacts are missing or invalid at ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
155
153
|
function parseArtifact(value, name) {
|
|
156
154
|
const artifact = record(value, `runtime manifest artifact ${name}`);
|
|
157
155
|
const path = nonemptyString(artifact.path, `runtime manifest artifact ${name} path`);
|
|
@@ -179,7 +177,7 @@ function parseMigration(value, position) {
|
|
|
179
177
|
};
|
|
180
178
|
}
|
|
181
179
|
function record(value, name) {
|
|
182
|
-
if (!
|
|
180
|
+
if (!isRecord(value)) throw new Error(`${name} must be an object`);
|
|
183
181
|
return value;
|
|
184
182
|
}
|
|
185
183
|
function array(value, name) {
|
|
@@ -192,7 +190,7 @@ function nonemptyString(value, name) {
|
|
|
192
190
|
}
|
|
193
191
|
function sourceRevision(value) {
|
|
194
192
|
const revision = nonemptyString(value, "runtime manifest sourceRevision");
|
|
195
|
-
if (
|
|
193
|
+
if (!isSourceRevision(revision)) throw new Error("runtime manifest sourceRevision is invalid");
|
|
196
194
|
return revision;
|
|
197
195
|
}
|
|
198
196
|
function safeInteger(value, name) {
|
package/dist/plans.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as isPrintableText, s as record } from "./validate-DbJR7Q0Z.mjs";
|
|
1
2
|
//#region src/plans.ts
|
|
2
3
|
const GB = 1073741824;
|
|
3
4
|
const PLAN_LIMITS = {
|
|
@@ -119,15 +120,11 @@ function parsePlatformPlanId(value) {
|
|
|
119
120
|
return value;
|
|
120
121
|
}
|
|
121
122
|
function parsePlanName(value) {
|
|
122
|
-
if (
|
|
123
|
+
if (!isPrintableText(value, 80)) throw new Error("Plan names must contain 1 to 80 printable characters.");
|
|
123
124
|
return value.trim();
|
|
124
125
|
}
|
|
125
|
-
function object(value, label) {
|
|
126
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(label + " must be an object.");
|
|
127
|
-
return value;
|
|
128
|
-
}
|
|
129
126
|
function parsePlanLimitsPatch(value) {
|
|
130
|
-
const input =
|
|
127
|
+
const input = record(value, "Plan limits");
|
|
131
128
|
for (const [key, limit] of Object.entries(input)) {
|
|
132
129
|
if (!PLAN_EDITABLE_LIMIT_KEYS.includes(key)) throw new Error("Unknown or unenforced plan limit: " + key + ".");
|
|
133
130
|
if (!Number.isSafeInteger(limit) || limit < 0) throw new Error(key + " must be a nonnegative safe integer; 0 means unlimited.");
|
|
@@ -146,18 +143,18 @@ function parseBuildInstanceType(value) {
|
|
|
146
143
|
}
|
|
147
144
|
/** Strict saved-state validation: invalid configuration must not silently lift quotas. */
|
|
148
145
|
function parsePlatformPlanCatalog(value) {
|
|
149
|
-
const input =
|
|
146
|
+
const input = record(value, "Plan catalog");
|
|
150
147
|
if (!Number.isSafeInteger(input.revision) || input.revision < 0) throw new Error("Invalid plan catalog revision.");
|
|
151
148
|
if (!Array.isArray(input.plans) || input.plans.length === 0 || input.plans.length > 100) throw new Error("A plan catalog must contain between 1 and 100 plans.");
|
|
152
149
|
const ids = /* @__PURE__ */ new Set();
|
|
153
150
|
const plans = input.plans.map((value) => {
|
|
154
|
-
const plan =
|
|
151
|
+
const plan = record(value, "Plan");
|
|
155
152
|
const id = parsePlatformPlanId(plan.id);
|
|
156
153
|
if (ids.has(id)) throw new Error("Duplicate plan ID: " + id + ".");
|
|
157
154
|
ids.add(id);
|
|
158
155
|
if (typeof plan.archived !== "boolean") throw new Error("archived must be a boolean.");
|
|
159
156
|
if (typeof plan.allowShortSlugs !== "boolean") throw new Error("allowShortSlugs must be a boolean.");
|
|
160
|
-
const limits =
|
|
157
|
+
const limits = record(plan.limits, "Plan limits");
|
|
161
158
|
const keys = Object.keys(PLAN_LIMITS.free);
|
|
162
159
|
if (Object.keys(limits).length !== keys.length || keys.some((key) => !Object.hasOwn(limits, key))) throw new Error("Plan limits must contain all supported fields.");
|
|
163
160
|
validatePlanLimits(limits);
|
|
@@ -174,13 +171,13 @@ function parsePlatformPlanCatalog(value) {
|
|
|
174
171
|
if (!plans.some((plan) => plan.id === defaultPlanId && !plan.archived)) throw new Error("The default plan must exist and be active.");
|
|
175
172
|
let reconciliation = null;
|
|
176
173
|
if (input.reconciliation !== null) {
|
|
177
|
-
const operation =
|
|
174
|
+
const operation = record(input.reconciliation, "Plan reconciliation");
|
|
178
175
|
if (operation.revision !== input.revision || typeof operation.complete !== "boolean" || !(operation.cursor === null || typeof operation.cursor === "string") || !Array.isArray(operation.planIds) || operation.planIds.length > 100) throw new Error("Invalid plan reconciliation state.");
|
|
179
176
|
const planIds = operation.planIds.map(parsePlatformPlanId);
|
|
180
177
|
if (planIds.some((id) => !ids.has(id))) throw new Error("A reconciliation plan is missing.");
|
|
181
178
|
let error;
|
|
182
179
|
if (operation.error !== void 0) {
|
|
183
|
-
const failure =
|
|
180
|
+
const failure = record(operation.error, "Plan reconciliation failure");
|
|
184
181
|
if (typeof failure.accountId !== "string" || typeof failure.message !== "string" || failure.message.length > 1e3) throw new Error("Invalid plan reconciliation failure.");
|
|
185
182
|
error = {
|
|
186
183
|
accountId: failure.accountId,
|