@forgezero/agent 0.1.101 → 0.1.103
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/agent-heartbeat.js +1 -1
- package/dist/bootstrap.d.ts +6 -2
- package/dist/bootstrap.js +72 -6
- package/dist/fz-agent.js +1 -1
- package/dist/fz.js +172 -18
- package/dist/metal-bootstrap.d.ts +8 -0
- package/dist/metal-bootstrap.js +10 -3
- package/dist/operator-bootstrap.d.ts +10 -0
- package/dist/operator-bootstrap.js +127 -9
- package/dist/platform-bootstrap-runtime.d.ts +21 -1
- package/dist/platform-bootstrap-runtime.js +19 -1
- package/dist/platform-fleet-verification.js +21 -3
- package/dist/platform-genesis-config.d.ts +1 -1
- package/dist/platform-launch-profile.d.ts +5 -0
- package/dist/provision.js +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1386,7 +1386,7 @@ async function buildBootstrapBundle(input, exec = run) {
|
|
|
1386
1386
|
}
|
|
1387
1387
|
|
|
1388
1388
|
// src/bootstrap.ts
|
|
1389
|
-
import { createHash as createHash2, createHmac as createHmac2, randomBytes as randomBytes3 } from "crypto";
|
|
1389
|
+
import { createHash as createHash2, createHmac as createHmac2, createPrivateKey, randomBytes as randomBytes3 } from "crypto";
|
|
1390
1390
|
import {
|
|
1391
1391
|
chmodSync as chmodSync3,
|
|
1392
1392
|
existsSync as existsSync5,
|
|
@@ -1420,7 +1420,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
|
|
|
1420
1420
|
var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
|
|
1421
1421
|
|
|
1422
1422
|
// src/version.ts
|
|
1423
|
-
var VERSION = "0.1.
|
|
1423
|
+
var VERSION = "0.1.103";
|
|
1424
1424
|
|
|
1425
1425
|
// src/software.ts
|
|
1426
1426
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -3090,10 +3090,16 @@ var httpsOrigin = (name, raw) => {
|
|
|
3090
3090
|
};
|
|
3091
3091
|
var agentTelemetryOrigin = (raw) => raw === "http://127.0.0.1:4318" ? raw : httpsOrigin("agentOtlpEndpoint", raw);
|
|
3092
3092
|
function validatePlatformInitialInventory(value) {
|
|
3093
|
-
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "region", "computes", "attestation", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
|
|
3093
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
|
|
3094
3094
|
throw new Error("initial platform inventory coordinates are invalid");
|
|
3095
3095
|
}
|
|
3096
3096
|
safeAtom("initialInventory.region.label", value.region.label);
|
|
3097
|
+
if (value.metalIdentity !== undefined) {
|
|
3098
|
+
const identity = value.metalIdentity;
|
|
3099
|
+
if (!identity || typeof identity !== "object" || Array.isArray(identity) || Object.keys(identity).some((key) => !["nodeKey", "publicKeys"].includes(key)) || !/^[A-Za-z0-9_-]{43}$/.test(identity.nodeKey) || !identity.publicKeys || identity.publicKeys.ed25519 !== identity.nodeKey || !/^[A-Za-z0-9_-]{1,8192}$/.test(identity.publicKeys.mlDsa) || Object.keys(identity.publicKeys).some((key) => !["ed25519", "mlDsa"].includes(key))) {
|
|
3100
|
+
throw new Error("initial platform Metal identity is invalid");
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3097
3103
|
if (value.region.city !== undefined)
|
|
3098
3104
|
safeAtom("initialInventory.region.city", value.region.city);
|
|
3099
3105
|
if (value.deployment !== undefined && (!value.deployment || typeof value.deployment !== "object" || Array.isArray(value.deployment) || Object.keys(value.deployment).some((key) => !["source", "branch", "revision", "bundleSha256"].includes(key)) || value.deployment.source !== "bootstrap-bundle" || !["dev", "main"].includes(value.deployment.branch) || !/^[a-f0-9]{40}$/.test(value.deployment.revision) || !/^[a-f0-9]{64}$/.test(value.deployment.bundleSha256)))
|
|
@@ -3128,6 +3134,7 @@ function validatePlatformInitialInventory(value) {
|
|
|
3128
3134
|
}
|
|
3129
3135
|
return {
|
|
3130
3136
|
metalHostname: value.metalHostname,
|
|
3137
|
+
...value.metalIdentity ? { metalIdentity: structuredClone(value.metalIdentity) } : {},
|
|
3131
3138
|
region: { ...value.region },
|
|
3132
3139
|
computes: value.computes.map((compute, index) => ({
|
|
3133
3140
|
...computes[index],
|
|
@@ -3181,6 +3188,11 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
3181
3188
|
} else if (input.email !== undefined) {
|
|
3182
3189
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
3183
3190
|
}
|
|
3191
|
+
if (input.githubApp) {
|
|
3192
|
+
if (!/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubApp.clientId) || !/^[1-9][0-9]{0,19}$/.test(input.githubApp.appId) || !/^[a-z0-9][a-z0-9-]{0,99}$/.test(input.githubApp.slug)) {
|
|
3193
|
+
throw new Error("GitHub App client id, app id or slug is malformed.");
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3184
3196
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
3185
3197
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
3186
3198
|
throw new Error("seedSyncMembers must contain 3 to 64 unique physical host identities.");
|
|
@@ -3311,6 +3323,9 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
3311
3323
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
3312
3324
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
3313
3325
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
3326
|
+
FZ_GITHUB_CLIENT_ID: value.githubApp?.clientId ?? "",
|
|
3327
|
+
FZ_GITHUB_APP_ID: value.githubApp?.appId ?? "",
|
|
3328
|
+
FZ_GITHUB_APP_SLUG: value.githubApp?.slug ?? "",
|
|
3314
3329
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
3315
3330
|
};
|
|
3316
3331
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -3322,6 +3337,9 @@ function platformApiCredentialSpecs(options) {
|
|
|
3322
3337
|
const optional = [
|
|
3323
3338
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
3324
3339
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
3340
|
+
["fz_github.clientSecret", options.githubApp],
|
|
3341
|
+
["fz_github.privateKey", options.githubApp],
|
|
3342
|
+
["fz_github.webhookSecret", options.githubApp],
|
|
3325
3343
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
3326
3344
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
3327
3345
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -3717,7 +3735,17 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3717
3735
|
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
3718
3736
|
throw new Error("bootstrap credential input must be an object");
|
|
3719
3737
|
const source = input;
|
|
3720
|
-
const allowed = [
|
|
3738
|
+
const allowed = [
|
|
3739
|
+
"clusterBootstrapCode",
|
|
3740
|
+
"emailSecret",
|
|
3741
|
+
"enrolmentToken",
|
|
3742
|
+
"backupS3Secret",
|
|
3743
|
+
"cloudflareTunnelToken",
|
|
3744
|
+
"cloudflareApiToken",
|
|
3745
|
+
"githubClientSecret",
|
|
3746
|
+
"githubPrivateKeyBase64",
|
|
3747
|
+
"githubWebhookSecret"
|
|
3748
|
+
];
|
|
3721
3749
|
const unknown = Object.keys(source).filter((key) => !allowed.includes(key));
|
|
3722
3750
|
if (unknown.length)
|
|
3723
3751
|
throw new Error(`bootstrap credential input contains unsupported field ${unknown[0]}`);
|
|
@@ -3727,6 +3755,9 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3727
3755
|
const backupS3Secret = typeof source.backupS3Secret === "string" ? source.backupS3Secret.trim() : undefined;
|
|
3728
3756
|
const cloudflareTunnelToken = typeof source.cloudflareTunnelToken === "string" ? source.cloudflareTunnelToken.trim() : undefined;
|
|
3729
3757
|
const cloudflareApiToken = typeof source.cloudflareApiToken === "string" ? source.cloudflareApiToken.trim() : undefined;
|
|
3758
|
+
const githubClientSecret = typeof source.githubClientSecret === "string" ? source.githubClientSecret.trim() : undefined;
|
|
3759
|
+
const githubPrivateKeyBase64 = typeof source.githubPrivateKeyBase64 === "string" ? source.githubPrivateKeyBase64.trim() : undefined;
|
|
3760
|
+
const githubWebhookSecret = typeof source.githubWebhookSecret === "string" ? source.githubWebhookSecret.trim() : undefined;
|
|
3730
3761
|
if (!/^[a-f0-9]{64}$/i.test(clusterBootstrapCode))
|
|
3731
3762
|
throw new Error("cluster bootstrap code must contain exactly 64 hexadecimal characters");
|
|
3732
3763
|
if (!emailSecret || emailSecret.length > 16384 || /[\r\n\0]/.test(emailSecret))
|
|
@@ -3746,12 +3777,29 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3746
3777
|
}
|
|
3747
3778
|
if (cloudflareTunnelToken)
|
|
3748
3779
|
validateCloudflareBootstrapSecretPair({ cloudflareTunnelToken, cloudflareApiToken });
|
|
3780
|
+
const githubConfigured = Boolean(config.runtime.environment.githubApp);
|
|
3781
|
+
if (githubConfigured !== Boolean(githubClientSecret && githubPrivateKeyBase64 && githubWebhookSecret)) {
|
|
3782
|
+
throw new Error("GitHub App coordinates require client secret, private key and webhook secret together");
|
|
3783
|
+
}
|
|
3784
|
+
if (githubConfigured) {
|
|
3785
|
+
if (githubClientSecret.length < 20 || githubClientSecret.length > 512 || /[\r\n\0]/.test(githubClientSecret) || githubWebhookSecret.length < 32 || githubWebhookSecret.length > 512 || /[\r\n\0]/.test(githubWebhookSecret)) {
|
|
3786
|
+
throw new Error("GitHub App client or webhook secret is malformed");
|
|
3787
|
+
}
|
|
3788
|
+
try {
|
|
3789
|
+
const pem = Buffer.from(githubPrivateKeyBase64, "base64").toString("utf8");
|
|
3790
|
+
if (createPrivateKey(pem).asymmetricKeyType !== "rsa")
|
|
3791
|
+
throw new Error("not RSA");
|
|
3792
|
+
} catch {
|
|
3793
|
+
throw new Error("GitHub App private key must be a base64-encoded RSA private key");
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3749
3796
|
return {
|
|
3750
3797
|
clusterBootstrapCode,
|
|
3751
3798
|
emailSecret,
|
|
3752
3799
|
...enrolmentToken ? { enrolmentToken } : {},
|
|
3753
3800
|
...backupS3Secret ? { backupS3Secret } : {},
|
|
3754
|
-
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {}
|
|
3801
|
+
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {},
|
|
3802
|
+
...githubConfigured ? { githubClientSecret, githubPrivateKeyBase64, githubWebhookSecret } : {}
|
|
3755
3803
|
};
|
|
3756
3804
|
}
|
|
3757
3805
|
var platformBootstrapRunner = (config) => config.kind === "platform" && config.database.role === "master";
|
|
@@ -4303,6 +4351,17 @@ function approvedPlatformRepairIdentityDigests(config) {
|
|
|
4303
4351
|
delete beforeAttestation.runtime.environment.initialInventory.attestation;
|
|
4304
4352
|
prior.push(beforeAttestation);
|
|
4305
4353
|
}
|
|
4354
|
+
const metalIdentity = config.runtime.environment.initialInventory?.metalIdentity;
|
|
4355
|
+
if (metalIdentity && config.enrolment.source === "genesis-derived") {
|
|
4356
|
+
const beforeMetalIdentity = structuredClone(config);
|
|
4357
|
+
delete beforeMetalIdentity.runtime.environment.initialInventory.metalIdentity;
|
|
4358
|
+
prior.push(beforeMetalIdentity);
|
|
4359
|
+
}
|
|
4360
|
+
if (config.database.role === "joiner" && config.enrolment.source === "genesis-derived" && config.runtime.environment.custodianEmail) {
|
|
4361
|
+
const beforeReplicaCustodianEmail = structuredClone(config);
|
|
4362
|
+
delete beforeReplicaCustodianEmail.runtime.environment.custodianEmail;
|
|
4363
|
+
prior.push(beforeReplicaCustodianEmail);
|
|
4364
|
+
}
|
|
4306
4365
|
const telemetryMigration = config.environment === "development" && config.telemetryEndpoint === LOCAL_DEBUG_OTEL_EXPORT && config.runtime.environment.agentOtlpEndpoint === "http://127.0.0.1:4318";
|
|
4307
4366
|
if (telemetryMigration) {
|
|
4308
4367
|
const beforeTelemetry = structuredClone(config);
|
|
@@ -4655,7 +4714,10 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4655
4714
|
enrolmentToken: checked4.enrolmentToken,
|
|
4656
4715
|
backup: checked4.backupS3Secret,
|
|
4657
4716
|
cloudflareTunnelToken: checked4.cloudflareTunnelToken,
|
|
4658
|
-
cloudflareApiToken: checked4.cloudflareApiToken
|
|
4717
|
+
cloudflareApiToken: checked4.cloudflareApiToken,
|
|
4718
|
+
githubClientSecret: checked4.githubClientSecret,
|
|
4719
|
+
githubPrivateKey: checked4.githubPrivateKeyBase64 ? Buffer.from(checked4.githubPrivateKeyBase64, "base64").toString("utf8") : undefined,
|
|
4720
|
+
githubWebhookSecret: checked4.githubWebhookSecret
|
|
4659
4721
|
};
|
|
4660
4722
|
})() : undefined;
|
|
4661
4723
|
const enrolledPrivate = config.kind === "enrolled-compute" ? validateEnrolledComputeBootstrapSecrets(config, secrets) : undefined;
|
|
@@ -4753,6 +4815,9 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4753
4815
|
const emailCredentialName = config.runtime.environment.email?.provider === "smtp" ? "fz_smtp.password" : config.runtime.environment.email?.provider === "jetemail" ? "fz_jetemail.apiKey" : undefined;
|
|
4754
4816
|
for (const [name, source] of Object.entries({
|
|
4755
4817
|
...emailCredentialName ? { [emailCredentialName]: platformPrivate.email } : {},
|
|
4818
|
+
"fz_github.clientSecret": platformPrivate.githubClientSecret,
|
|
4819
|
+
"fz_github.privateKey": platformPrivate.githubPrivateKey,
|
|
4820
|
+
"fz_github.webhookSecret": platformPrivate.githubWebhookSecret,
|
|
4756
4821
|
"backup.s3.secretAccessKey": platformPrivate.backup
|
|
4757
4822
|
})) {
|
|
4758
4823
|
if (source) {
|
|
@@ -4769,6 +4834,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4769
4834
|
const credentials = platformApiCredentialSpecs({
|
|
4770
4835
|
emailProvider: runtime.environment.email?.provider,
|
|
4771
4836
|
cloudflareKv: cloudflareConfigured,
|
|
4837
|
+
githubApp: Boolean(runtime.environment.githubApp),
|
|
4772
4838
|
realtime: Boolean(runtime.environment.realtime)
|
|
4773
4839
|
});
|
|
4774
4840
|
const units = renderPlatformApiUnits({
|
|
@@ -5496,7 +5562,7 @@ var SUPPORTED_BUN_RELEASE_SHA256 = "951ee2aee855f08595aeec6225226a298d3fea83a3dc
|
|
|
5496
5562
|
|
|
5497
5563
|
class MetalBootstrapError extends Error {
|
|
5498
5564
|
}
|
|
5499
|
-
function
|
|
5565
|
+
function parseMetalPublicIdentity(value) {
|
|
5500
5566
|
let parsed;
|
|
5501
5567
|
try {
|
|
5502
5568
|
parsed = JSON.parse(value);
|
|
@@ -5511,7 +5577,13 @@ function normalizeMetalPublicIdentity(value) {
|
|
|
5511
5577
|
if (Object.keys(identity).some((key) => !["nodeKey", "publicKeys"].includes(key)) || typeof identity.nodeKey !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(identity.nodeKey) || !keys || Object.keys(keys).some((key) => !["ed25519", "mlDsa"].includes(key)) || keys.ed25519 !== identity.nodeKey || typeof keys.mlDsa !== "string" || !/^[A-Za-z0-9_-]{1,8192}$/.test(keys.mlDsa)) {
|
|
5512
5578
|
throw new MetalBootstrapError("metal public identity proof was invalid");
|
|
5513
5579
|
}
|
|
5514
|
-
return
|
|
5580
|
+
return {
|
|
5581
|
+
nodeKey: identity.nodeKey,
|
|
5582
|
+
publicKeys: { ed25519: keys.ed25519, mlDsa: keys.mlDsa }
|
|
5583
|
+
};
|
|
5584
|
+
}
|
|
5585
|
+
function normalizeMetalPublicIdentity(value) {
|
|
5586
|
+
return JSON.stringify(parseMetalPublicIdentity(value));
|
|
5515
5587
|
}
|
|
5516
5588
|
var defaultExec2 = async (argv, stdin) => {
|
|
5517
5589
|
const child = Bun.spawn([...argv], {
|
|
@@ -6407,7 +6479,7 @@ function writeOperatorPlatformBootstrapFleetRequest(path, requestFiles, cloudfla
|
|
|
6407
6479
|
return writeOwnerJson2(path, request, "operator fleet request");
|
|
6408
6480
|
}
|
|
6409
6481
|
var validateMetalRequestValue = (value, options = {}) => {
|
|
6410
|
-
const root = exactKeys3(value, ["kind", "target", "metalConfigFile", "genesis"], "operator metal request");
|
|
6482
|
+
const root = exactKeys3(value, ["kind", "target", "metalConfigFile", "metalIdentityEvidenceFile", "genesis"], "operator metal request");
|
|
6411
6483
|
if (root.kind !== "metal-remote")
|
|
6412
6484
|
throw new Error("operator metal bootstrap kind must be metal-remote");
|
|
6413
6485
|
const targetValue = exactKeys3(root.target, ["address", "port", "user", "hostKey", "hostKeySha256", "identityPublicKeyFile", "agentSocket"], "operator metal target");
|
|
@@ -6426,6 +6498,12 @@ var validateMetalRequestValue = (value, options = {}) => {
|
|
|
6426
6498
|
if (typeof root.metalConfigFile !== "string")
|
|
6427
6499
|
throw new Error("metalConfigFile must be an absolute path");
|
|
6428
6500
|
canonicalOutputPath(root.metalConfigFile, "metalConfigFile");
|
|
6501
|
+
if (root.metalIdentityEvidenceFile !== undefined && typeof root.metalIdentityEvidenceFile !== "string") {
|
|
6502
|
+
throw new Error("metalIdentityEvidenceFile must be an absolute path");
|
|
6503
|
+
}
|
|
6504
|
+
if (typeof root.metalIdentityEvidenceFile === "string") {
|
|
6505
|
+
canonicalOutputPath(root.metalIdentityEvidenceFile, "metalIdentityEvidenceFile");
|
|
6506
|
+
}
|
|
6429
6507
|
if (options.validateMetalConfig !== false)
|
|
6430
6508
|
readMetalBootstrapConfig(root.metalConfigFile);
|
|
6431
6509
|
const genesis = exactKeys3(root.genesis, ["nodes", "rehearsalNode", "sshPublicKeyFiles"], "operator metal genesis");
|
|
@@ -6474,6 +6552,7 @@ var validateMetalRequestValue = (value, options = {}) => {
|
|
|
6474
6552
|
return {
|
|
6475
6553
|
kind: "metal-remote",
|
|
6476
6554
|
metalConfigFile: root.metalConfigFile,
|
|
6555
|
+
...typeof root.metalIdentityEvidenceFile === "string" ? { metalIdentityEvidenceFile: root.metalIdentityEvidenceFile } : {},
|
|
6477
6556
|
target: {
|
|
6478
6557
|
...target,
|
|
6479
6558
|
identityPublicKeyFile: targetValue.identityPublicKeyFile,
|
|
@@ -6494,6 +6573,25 @@ function writeOperatorMetalBootstrapRequest(path, request) {
|
|
|
6494
6573
|
validateMetalRequestValue(request);
|
|
6495
6574
|
return writeOwnerJson2(path, request, "operator metal request");
|
|
6496
6575
|
}
|
|
6576
|
+
function readOperatorMetalIdentityEvidence(path, request) {
|
|
6577
|
+
const value = JSON.parse(new TextDecoder().decode(ownerFile(path, REQUEST_LIMIT, "operator metal identity evidence")));
|
|
6578
|
+
const root = exactKeys3(value, ["format", "kind", "metalHostname", "metalHostKeySha256", "nodeKey", "publicKeys"], "operator metal identity evidence");
|
|
6579
|
+
if (root.format !== 1 || root.kind !== "forgezero-operator-metal-identity" || typeof root.metalHostname !== "string" || typeof root.metalHostKeySha256 !== "string" || typeof root.nodeKey !== "string" || !root.publicKeys || typeof root.publicKeys !== "object") {
|
|
6580
|
+
throw new Error("operator metal identity evidence is malformed");
|
|
6581
|
+
}
|
|
6582
|
+
const identity = parseMetalPublicIdentity(JSON.stringify({ nodeKey: root.nodeKey, publicKeys: root.publicKeys }));
|
|
6583
|
+
const config = readMetalBootstrapConfig(request.metalConfigFile, { allowHistoricalRelease: true });
|
|
6584
|
+
if (root.metalHostname !== config.metalHostname || root.metalHostKeySha256 !== request.target.hostKeySha256) {
|
|
6585
|
+
throw new Error("operator metal identity evidence does not match the reviewed Metal target");
|
|
6586
|
+
}
|
|
6587
|
+
return {
|
|
6588
|
+
format: 1,
|
|
6589
|
+
kind: "forgezero-operator-metal-identity",
|
|
6590
|
+
metalHostname: root.metalHostname,
|
|
6591
|
+
metalHostKeySha256: root.metalHostKeySha256,
|
|
6592
|
+
...identity
|
|
6593
|
+
};
|
|
6594
|
+
}
|
|
6497
6595
|
var validateGuestHostKeyEvidenceValue = (value, request) => {
|
|
6498
6596
|
const root = exactKeys3(value, ["format", "kind", "metalHostKeySha256", "nodes"], "operator guest host-key evidence");
|
|
6499
6597
|
if (root.format !== 1 || root.kind !== "forgezero-operator-guest-host-keys" || typeof root.metalHostKeySha256 !== "string" || !Array.isArray(root.nodes)) {
|
|
@@ -7274,6 +7372,25 @@ async function applyOperatorMetalBootstrap(request, mode, options = {}) {
|
|
|
7274
7372
|
`${REMOTE_STAGE}/metal-config.json`,
|
|
7275
7373
|
"--apply"
|
|
7276
7374
|
], "remote typed metal bootstrap");
|
|
7375
|
+
if (request.metalIdentityEvidenceFile) {
|
|
7376
|
+
let applied;
|
|
7377
|
+
try {
|
|
7378
|
+
applied = JSON.parse(output);
|
|
7379
|
+
} catch {
|
|
7380
|
+
throw new Error("remote Metal bootstrap did not return identity evidence");
|
|
7381
|
+
}
|
|
7382
|
+
const publicIdentity2 = applied?.publicIdentity;
|
|
7383
|
+
if (typeof publicIdentity2 !== "string")
|
|
7384
|
+
throw new Error("remote Metal bootstrap omitted its public identity");
|
|
7385
|
+
const identity = parseMetalPublicIdentity(publicIdentity2);
|
|
7386
|
+
writeOwnerJson2(request.metalIdentityEvidenceFile, {
|
|
7387
|
+
format: 1,
|
|
7388
|
+
kind: "forgezero-operator-metal-identity",
|
|
7389
|
+
metalHostname: config.metalHostname,
|
|
7390
|
+
metalHostKeySha256: request.target.hostKeySha256,
|
|
7391
|
+
...identity
|
|
7392
|
+
}, "operator metal identity evidence");
|
|
7393
|
+
}
|
|
7277
7394
|
return { plan, output };
|
|
7278
7395
|
} finally {
|
|
7279
7396
|
if (knownHosts) {
|
|
@@ -7294,6 +7411,7 @@ export {
|
|
|
7294
7411
|
redactOperatorSecretDiagnostic,
|
|
7295
7412
|
readOperatorPlatformBootstrapRequest,
|
|
7296
7413
|
readOperatorPlatformBootstrapFleetRequest,
|
|
7414
|
+
readOperatorMetalIdentityEvidence,
|
|
7297
7415
|
readOperatorMetalBootstrapRequest,
|
|
7298
7416
|
readOperatorGuestHostKeyEvidence,
|
|
7299
7417
|
planOperatorPlatformFleetBootstrap,
|
|
@@ -19,6 +19,14 @@ export interface PlatformInitialInventoryCompute {
|
|
|
19
19
|
}
|
|
20
20
|
export interface PlatformInitialInventory {
|
|
21
21
|
metalHostname: string;
|
|
22
|
+
/** Hybrid public identity proved by the pinned Metal bootstrap transport. */
|
|
23
|
+
metalIdentity?: {
|
|
24
|
+
nodeKey: string;
|
|
25
|
+
publicKeys: {
|
|
26
|
+
ed25519: string;
|
|
27
|
+
mlDsa: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
22
30
|
region: {
|
|
23
31
|
key: string;
|
|
24
32
|
label: string;
|
|
@@ -60,6 +68,16 @@ export type PlatformBootstrapEmail = {
|
|
|
60
68
|
from: string;
|
|
61
69
|
eu: boolean;
|
|
62
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* Public coordinates for one GitHub App. Its client secret, RSA private key and
|
|
73
|
+
* webhook secret are attended inputs sealed as systemd credentials and later
|
|
74
|
+
* imported into the unlocked platform Vault.
|
|
75
|
+
*/
|
|
76
|
+
export interface PlatformBootstrapGitHubApp {
|
|
77
|
+
clientId: string;
|
|
78
|
+
appId: string;
|
|
79
|
+
slug: string;
|
|
80
|
+
}
|
|
63
81
|
export interface PlatformSharedEnvironment {
|
|
64
82
|
softwareProfile: PlatformSoftwareProfile;
|
|
65
83
|
databaseRole: PlatformDatabaseRole;
|
|
@@ -91,6 +109,7 @@ export interface PlatformSharedEnvironment {
|
|
|
91
109
|
otlpTraceSampleRatio: number;
|
|
92
110
|
custodianEmail?: string;
|
|
93
111
|
email?: PlatformBootstrapEmail;
|
|
112
|
+
githubApp?: PlatformBootstrapGitHubApp;
|
|
94
113
|
backup?: {
|
|
95
114
|
endpoint: string;
|
|
96
115
|
region: string;
|
|
@@ -118,12 +137,13 @@ export declare function validatePlatformSharedEnvironment(input: PlatformSharedE
|
|
|
118
137
|
/** Render only non-secret runtime coordinates. Passwords/tokens have no field in this contract. */
|
|
119
138
|
export declare function renderPlatformSharedEnvironment(input: PlatformSharedEnvironment): string;
|
|
120
139
|
export interface SystemdCredentialSpec {
|
|
121
|
-
name: 'arangodb-jwt' | 'seed-sync-root' | 'fz_smtp.password' | 'fz_jetemail.apiKey' | 'CF_API_TOKEN' | 'CF_TUNNEL_TOKEN' | 'REALTIME_PUBLISH_SECRET' | 'REALTIME_TICKET_SECRET';
|
|
140
|
+
name: 'arangodb-jwt' | 'seed-sync-root' | 'fz_smtp.password' | 'fz_jetemail.apiKey' | 'fz_github.clientSecret' | 'fz_github.privateKey' | 'fz_github.webhookSecret' | 'CF_API_TOKEN' | 'CF_TUNNEL_TOKEN' | 'REALTIME_PUBLISH_SECRET' | 'REALTIME_TICKET_SECRET';
|
|
122
141
|
encryptedPath: string;
|
|
123
142
|
required: boolean;
|
|
124
143
|
}
|
|
125
144
|
export declare function platformApiCredentialSpecs(options: {
|
|
126
145
|
emailProvider?: PlatformBootstrapEmail['provider'];
|
|
146
|
+
githubApp: boolean;
|
|
127
147
|
cloudflareKv: boolean;
|
|
128
148
|
realtime: boolean;
|
|
129
149
|
}): SystemdCredentialSpec[];
|
|
@@ -730,10 +730,16 @@ var httpsOrigin = (name, raw) => {
|
|
|
730
730
|
};
|
|
731
731
|
var agentTelemetryOrigin = (raw) => raw === "http://127.0.0.1:4318" ? raw : httpsOrigin("agentOtlpEndpoint", raw);
|
|
732
732
|
function validatePlatformInitialInventory(value) {
|
|
733
|
-
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "region", "computes", "attestation", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
|
|
733
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
|
|
734
734
|
throw new Error("initial platform inventory coordinates are invalid");
|
|
735
735
|
}
|
|
736
736
|
safeAtom("initialInventory.region.label", value.region.label);
|
|
737
|
+
if (value.metalIdentity !== undefined) {
|
|
738
|
+
const identity = value.metalIdentity;
|
|
739
|
+
if (!identity || typeof identity !== "object" || Array.isArray(identity) || Object.keys(identity).some((key) => !["nodeKey", "publicKeys"].includes(key)) || !/^[A-Za-z0-9_-]{43}$/.test(identity.nodeKey) || !identity.publicKeys || identity.publicKeys.ed25519 !== identity.nodeKey || !/^[A-Za-z0-9_-]{1,8192}$/.test(identity.publicKeys.mlDsa) || Object.keys(identity.publicKeys).some((key) => !["ed25519", "mlDsa"].includes(key))) {
|
|
740
|
+
throw new Error("initial platform Metal identity is invalid");
|
|
741
|
+
}
|
|
742
|
+
}
|
|
737
743
|
if (value.region.city !== undefined)
|
|
738
744
|
safeAtom("initialInventory.region.city", value.region.city);
|
|
739
745
|
if (value.deployment !== undefined && (!value.deployment || typeof value.deployment !== "object" || Array.isArray(value.deployment) || Object.keys(value.deployment).some((key) => !["source", "branch", "revision", "bundleSha256"].includes(key)) || value.deployment.source !== "bootstrap-bundle" || !["dev", "main"].includes(value.deployment.branch) || !/^[a-f0-9]{40}$/.test(value.deployment.revision) || !/^[a-f0-9]{64}$/.test(value.deployment.bundleSha256)))
|
|
@@ -768,6 +774,7 @@ function validatePlatformInitialInventory(value) {
|
|
|
768
774
|
}
|
|
769
775
|
return {
|
|
770
776
|
metalHostname: value.metalHostname,
|
|
777
|
+
...value.metalIdentity ? { metalIdentity: structuredClone(value.metalIdentity) } : {},
|
|
771
778
|
region: { ...value.region },
|
|
772
779
|
computes: value.computes.map((compute, index) => ({
|
|
773
780
|
...computes[index],
|
|
@@ -821,6 +828,11 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
821
828
|
} else if (input.email !== undefined) {
|
|
822
829
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
823
830
|
}
|
|
831
|
+
if (input.githubApp) {
|
|
832
|
+
if (!/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubApp.clientId) || !/^[1-9][0-9]{0,19}$/.test(input.githubApp.appId) || !/^[a-z0-9][a-z0-9-]{0,99}$/.test(input.githubApp.slug)) {
|
|
833
|
+
throw new Error("GitHub App client id, app id or slug is malformed.");
|
|
834
|
+
}
|
|
835
|
+
}
|
|
824
836
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
825
837
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
826
838
|
throw new Error("seedSyncMembers must contain 3 to 64 unique physical host identities.");
|
|
@@ -951,6 +963,9 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
951
963
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
952
964
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
953
965
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
966
|
+
FZ_GITHUB_CLIENT_ID: value.githubApp?.clientId ?? "",
|
|
967
|
+
FZ_GITHUB_APP_ID: value.githubApp?.appId ?? "",
|
|
968
|
+
FZ_GITHUB_APP_SLUG: value.githubApp?.slug ?? "",
|
|
954
969
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
955
970
|
};
|
|
956
971
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -962,6 +977,9 @@ function platformApiCredentialSpecs(options) {
|
|
|
962
977
|
const optional = [
|
|
963
978
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
964
979
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
980
|
+
["fz_github.clientSecret", options.githubApp],
|
|
981
|
+
["fz_github.privateKey", options.githubApp],
|
|
982
|
+
["fz_github.webhookSecret", options.githubApp],
|
|
965
983
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
966
984
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
967
985
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -2908,7 +2908,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
|
|
|
2908
2908
|
}
|
|
2909
2909
|
|
|
2910
2910
|
// src/version.ts
|
|
2911
|
-
var VERSION3 = "0.1.
|
|
2911
|
+
var VERSION3 = "0.1.103";
|
|
2912
2912
|
|
|
2913
2913
|
// src/egress-policy.ts
|
|
2914
2914
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
@@ -4142,10 +4142,16 @@ var httpsOrigin = (name, raw) => {
|
|
|
4142
4142
|
};
|
|
4143
4143
|
var agentTelemetryOrigin = (raw) => raw === "http://127.0.0.1:4318" ? raw : httpsOrigin("agentOtlpEndpoint", raw);
|
|
4144
4144
|
function validatePlatformInitialInventory(value) {
|
|
4145
|
-
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "region", "computes", "attestation", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
|
|
4145
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
|
|
4146
4146
|
throw new Error("initial platform inventory coordinates are invalid");
|
|
4147
4147
|
}
|
|
4148
4148
|
safeAtom("initialInventory.region.label", value.region.label);
|
|
4149
|
+
if (value.metalIdentity !== undefined) {
|
|
4150
|
+
const identity = value.metalIdentity;
|
|
4151
|
+
if (!identity || typeof identity !== "object" || Array.isArray(identity) || Object.keys(identity).some((key) => !["nodeKey", "publicKeys"].includes(key)) || !/^[A-Za-z0-9_-]{43}$/.test(identity.nodeKey) || !identity.publicKeys || identity.publicKeys.ed25519 !== identity.nodeKey || !/^[A-Za-z0-9_-]{1,8192}$/.test(identity.publicKeys.mlDsa) || Object.keys(identity.publicKeys).some((key) => !["ed25519", "mlDsa"].includes(key))) {
|
|
4152
|
+
throw new Error("initial platform Metal identity is invalid");
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4149
4155
|
if (value.region.city !== undefined)
|
|
4150
4156
|
safeAtom("initialInventory.region.city", value.region.city);
|
|
4151
4157
|
if (value.deployment !== undefined && (!value.deployment || typeof value.deployment !== "object" || Array.isArray(value.deployment) || Object.keys(value.deployment).some((key) => !["source", "branch", "revision", "bundleSha256"].includes(key)) || value.deployment.source !== "bootstrap-bundle" || !["dev", "main"].includes(value.deployment.branch) || !/^[a-f0-9]{40}$/.test(value.deployment.revision) || !/^[a-f0-9]{64}$/.test(value.deployment.bundleSha256)))
|
|
@@ -4180,6 +4186,7 @@ function validatePlatformInitialInventory(value) {
|
|
|
4180
4186
|
}
|
|
4181
4187
|
return {
|
|
4182
4188
|
metalHostname: value.metalHostname,
|
|
4189
|
+
...value.metalIdentity ? { metalIdentity: structuredClone(value.metalIdentity) } : {},
|
|
4183
4190
|
region: { ...value.region },
|
|
4184
4191
|
computes: value.computes.map((compute, index) => ({
|
|
4185
4192
|
...computes[index],
|
|
@@ -4233,6 +4240,11 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
4233
4240
|
} else if (input.email !== undefined) {
|
|
4234
4241
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
4235
4242
|
}
|
|
4243
|
+
if (input.githubApp) {
|
|
4244
|
+
if (!/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubApp.clientId) || !/^[1-9][0-9]{0,19}$/.test(input.githubApp.appId) || !/^[a-z0-9][a-z0-9-]{0,99}$/.test(input.githubApp.slug)) {
|
|
4245
|
+
throw new Error("GitHub App client id, app id or slug is malformed.");
|
|
4246
|
+
}
|
|
4247
|
+
}
|
|
4236
4248
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
4237
4249
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
4238
4250
|
throw new Error("seedSyncMembers must contain 3 to 64 unique physical host identities.");
|
|
@@ -4363,6 +4375,9 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
4363
4375
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
4364
4376
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
4365
4377
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
4378
|
+
FZ_GITHUB_CLIENT_ID: value.githubApp?.clientId ?? "",
|
|
4379
|
+
FZ_GITHUB_APP_ID: value.githubApp?.appId ?? "",
|
|
4380
|
+
FZ_GITHUB_APP_SLUG: value.githubApp?.slug ?? "",
|
|
4366
4381
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
4367
4382
|
};
|
|
4368
4383
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -4374,6 +4389,9 @@ function platformApiCredentialSpecs(options) {
|
|
|
4374
4389
|
const optional = [
|
|
4375
4390
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
4376
4391
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
4392
|
+
["fz_github.clientSecret", options.githubApp],
|
|
4393
|
+
["fz_github.privateKey", options.githubApp],
|
|
4394
|
+
["fz_github.webhookSecret", options.githubApp],
|
|
4377
4395
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
4378
4396
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
4379
4397
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -4727,7 +4745,7 @@ function planLocalOtlpProof(endpoint, collectorUnit) {
|
|
|
4727
4745
|
import { lstatSync as lstatSync5 } from "node:fs";
|
|
4728
4746
|
|
|
4729
4747
|
// src/bootstrap.ts
|
|
4730
|
-
import { createHash as createHash7, createHmac as createHmac2, randomBytes as randomBytes3 } from "node:crypto";
|
|
4748
|
+
import { createHash as createHash7, createHmac as createHmac2, createPrivateKey, randomBytes as randomBytes3 } from "node:crypto";
|
|
4731
4749
|
import {
|
|
4732
4750
|
chmodSync as chmodSync9,
|
|
4733
4751
|
existsSync as existsSync11,
|
|
@@ -15,4 +15,4 @@ export declare function platformGenesisBootstrapConfigs(template: PlatformBootst
|
|
|
15
15
|
branch: 'dev' | 'main';
|
|
16
16
|
revision: string;
|
|
17
17
|
bundleSha256: string;
|
|
18
|
-
}, attestation?: import('./platform-bootstrap-runtime').PlatformInitialInventory['attestation']): readonly PlatformBootstrapConfig[];
|
|
18
|
+
}, attestation?: import('./platform-bootstrap-runtime').PlatformInitialInventory['attestation'], metalIdentity?: NonNullable<import('./platform-bootstrap-runtime').PlatformInitialInventory['metalIdentity']>): readonly PlatformBootstrapConfig[];
|
|
@@ -45,6 +45,11 @@ export interface ForgeZeroLaunchOwnerInput {
|
|
|
45
45
|
from: string;
|
|
46
46
|
eu: boolean;
|
|
47
47
|
};
|
|
48
|
+
githubApp?: {
|
|
49
|
+
clientId: string;
|
|
50
|
+
appId: string;
|
|
51
|
+
slug: string;
|
|
52
|
+
};
|
|
48
53
|
}
|
|
49
54
|
/**
|
|
50
55
|
* ForgeZero's own genesis public coordinates. They are reviewed source data,
|
package/dist/provision.js
CHANGED
|
@@ -2908,7 +2908,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
|
|
|
2908
2908
|
}
|
|
2909
2909
|
|
|
2910
2910
|
// src/version.ts
|
|
2911
|
-
var VERSION3 = "0.1.
|
|
2911
|
+
var VERSION3 = "0.1.103";
|
|
2912
2912
|
|
|
2913
2913
|
// src/egress-policy.ts
|
|
2914
2914
|
import { realpathSync as realpathSync3 } from "node:fs";
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** One package version shared by both public binaries. Pinned to package.json by tests. */
|
|
2
|
-
export declare const VERSION = "0.1.
|
|
2
|
+
export declare const VERSION = "0.1.103";
|