@forgezero/agent 0.1.103 → 0.1.108
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-bundle.d.ts +6 -0
- package/dist/bootstrap-bundle.js +41 -0
- package/dist/bootstrap.d.ts +1 -4
- package/dist/bootstrap.js +75 -44
- package/dist/database-auth-verify.d.ts +6 -0
- package/dist/deployment-connectivity.d.ts +21 -0
- package/dist/deployment-connectivity.js +117 -21
- package/dist/deployment-pull.d.ts +1 -1
- package/dist/deployment-topology.d.ts +2 -0
- package/dist/deployment-topology.js +2 -0
- package/dist/deployment.d.ts +18 -1
- package/dist/fz-agent.js +251 -34
- package/dist/fz.js +148 -175
- package/dist/metal-bootstrap.js +1 -1
- package/dist/operator-bootstrap.js +75 -44
- package/dist/platform-bootstrap-runtime.d.ts +4 -6
- package/dist/platform-bootstrap-runtime.js +5 -10
- package/dist/platform-fleet-verification.js +134 -37
- package/dist/platform-launch-env.d.ts +17 -0
- package/dist/platform-launch-profile.d.ts +2 -3
- package/dist/provision.js +120 -24
- package/dist/software-helper.js +117 -21
- package/dist/version.d.ts +1 -1
- package/package.json +2 -2
package/dist/fz.js
CHANGED
|
@@ -4634,7 +4634,7 @@ var VaultError, runtimeEnvironment = () => typeof process !== "undefined" && pro
|
|
|
4634
4634
|
} catch {
|
|
4635
4635
|
return;
|
|
4636
4636
|
}
|
|
4637
|
-
}, VERSION = "0.1.
|
|
4637
|
+
}, VERSION = "0.1.20";
|
|
4638
4638
|
var init_dist = __esm(() => {
|
|
4639
4639
|
init_identity();
|
|
4640
4640
|
VaultError = class VaultError extends Error {
|
|
@@ -4810,9 +4810,9 @@ async function spawnWith(command, env, report = () => {}, options = {}) {
|
|
|
4810
4810
|
}
|
|
4811
4811
|
|
|
4812
4812
|
// src/cli/index.ts
|
|
4813
|
-
import { existsSync as existsSync13, lstatSync as
|
|
4813
|
+
import { existsSync as existsSync13, lstatSync as lstatSync11, mkdirSync as mkdirSync13, readFileSync as readFileSync17, renameSync as renameSync10, rmSync as rmSync8, writeFileSync as writeFileSync13 } from "fs";
|
|
4814
4814
|
import { randomBytes as randomBytes10 } from "crypto";
|
|
4815
|
-
import { basename as basename3, dirname as dirname14, isAbsolute as isAbsolute7, join as join13, resolve as
|
|
4815
|
+
import { basename as basename3, dirname as dirname14, isAbsolute as isAbsolute7, join as join13, resolve as resolve13 } from "path";
|
|
4816
4816
|
|
|
4817
4817
|
// src/process-input.ts
|
|
4818
4818
|
async function writeAndCloseProcessInput(input, value) {
|
|
@@ -4841,7 +4841,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
|
|
|
4841
4841
|
var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
|
|
4842
4842
|
|
|
4843
4843
|
// src/version.ts
|
|
4844
|
-
var VERSION2 = "0.1.
|
|
4844
|
+
var VERSION2 = "0.1.108";
|
|
4845
4845
|
|
|
4846
4846
|
// src/software.ts
|
|
4847
4847
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -12058,7 +12058,7 @@ function removeSession(api, realm, path = defaultSessionPath()) {
|
|
|
12058
12058
|
}
|
|
12059
12059
|
|
|
12060
12060
|
// src/bootstrap.ts
|
|
12061
|
-
import { createHash as createHash4, createHmac as createHmac2,
|
|
12061
|
+
import { createHash as createHash4, createHmac as createHmac2, randomBytes as randomBytes7 } from "crypto";
|
|
12062
12062
|
import {
|
|
12063
12063
|
chmodSync as chmodSync4,
|
|
12064
12064
|
existsSync as existsSync9,
|
|
@@ -12337,10 +12337,8 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
12337
12337
|
} else if (input.email !== undefined) {
|
|
12338
12338
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
12339
12339
|
}
|
|
12340
|
-
if (input.
|
|
12341
|
-
|
|
12342
|
-
throw new Error("GitHub App client id, app id or slug is malformed.");
|
|
12343
|
-
}
|
|
12340
|
+
if (!input.githubOAuth || !/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubOAuth.clientId)) {
|
|
12341
|
+
throw new Error("GitHub OAuth client id is malformed.");
|
|
12344
12342
|
}
|
|
12345
12343
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
12346
12344
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
@@ -12472,9 +12470,7 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
12472
12470
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
12473
12471
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
12474
12472
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
12475
|
-
|
|
12476
|
-
FZ_GITHUB_APP_ID: value.githubApp?.appId ?? "",
|
|
12477
|
-
FZ_GITHUB_APP_SLUG: value.githubApp?.slug ?? "",
|
|
12473
|
+
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
12478
12474
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
12479
12475
|
};
|
|
12480
12476
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -12486,9 +12482,7 @@ function platformApiCredentialSpecs(options) {
|
|
|
12486
12482
|
const optional = [
|
|
12487
12483
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
12488
12484
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
12489
|
-
["
|
|
12490
|
-
["fz_github.privateKey", options.githubApp],
|
|
12491
|
-
["fz_github.webhookSecret", options.githubApp],
|
|
12485
|
+
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
12492
12486
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
12493
12487
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
12494
12488
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -12496,6 +12490,7 @@ function platformApiCredentialSpecs(options) {
|
|
|
12496
12490
|
];
|
|
12497
12491
|
return [
|
|
12498
12492
|
{ name: "arangodb-jwt", encryptedPath: "/etc/forgezero/creds/arangodb-jwt.cred", required: true },
|
|
12493
|
+
{ name: "arangodb-root-password", encryptedPath: "/etc/forgezero/creds/arangodb-root-password.cred", required: true },
|
|
12499
12494
|
{ name: "seed-sync-root", encryptedPath: "/etc/forgezero/creds/seed-sync-root.cred", required: true },
|
|
12500
12495
|
...optional.filter(([, present]) => present).map(([name]) => ({
|
|
12501
12496
|
name,
|
|
@@ -14079,6 +14074,46 @@ async function buildBootstrapBundle(input, exec = run) {
|
|
|
14079
14074
|
throw cause;
|
|
14080
14075
|
}
|
|
14081
14076
|
}
|
|
14077
|
+
async function refreshBootstrapBundle(input, exec = run) {
|
|
14078
|
+
const outputPath = resolve6(input.outputPath);
|
|
14079
|
+
const manifestPath = `${outputPath}.json`;
|
|
14080
|
+
if (existsSync8(outputPath) !== existsSync8(manifestPath)) {
|
|
14081
|
+
throw new Error("bootstrap bundle and manifest must either both exist or both be absent");
|
|
14082
|
+
}
|
|
14083
|
+
const candidatePath = `${outputPath}.candidate.${process.pid}.${randomBytes6(6).toString("hex")}`;
|
|
14084
|
+
const candidate = await buildBootstrapBundle({ ...input, outputPath: candidatePath }, exec);
|
|
14085
|
+
try {
|
|
14086
|
+
if (!existsSync8(outputPath)) {
|
|
14087
|
+
renameSync7(candidate.bundlePath, outputPath);
|
|
14088
|
+
renameSync7(candidate.manifestPath, manifestPath);
|
|
14089
|
+
return readBootstrapBundle(outputPath);
|
|
14090
|
+
}
|
|
14091
|
+
const current2 = await readBootstrapBundle(outputPath);
|
|
14092
|
+
if (current2.manifest.branch === candidate.manifest.branch && current2.manifest.revision === candidate.manifest.revision) {
|
|
14093
|
+
rmSync5(candidate.bundlePath, { force: true });
|
|
14094
|
+
rmSync5(candidate.manifestPath, { force: true });
|
|
14095
|
+
return current2;
|
|
14096
|
+
}
|
|
14097
|
+
const archivePath = `${outputPath}.before-${current2.manifest.revision.slice(0, 7)}-${Date.now()}`;
|
|
14098
|
+
const archiveManifestPath = `${archivePath}.json`;
|
|
14099
|
+
renameSync7(outputPath, archivePath);
|
|
14100
|
+
renameSync7(manifestPath, archiveManifestPath);
|
|
14101
|
+
try {
|
|
14102
|
+
renameSync7(candidate.bundlePath, outputPath);
|
|
14103
|
+
renameSync7(candidate.manifestPath, manifestPath);
|
|
14104
|
+
return readBootstrapBundle(outputPath);
|
|
14105
|
+
} catch (cause) {
|
|
14106
|
+
rmSync5(outputPath, { force: true });
|
|
14107
|
+
rmSync5(manifestPath, { force: true });
|
|
14108
|
+
renameSync7(archivePath, outputPath);
|
|
14109
|
+
renameSync7(archiveManifestPath, manifestPath);
|
|
14110
|
+
throw cause;
|
|
14111
|
+
}
|
|
14112
|
+
} finally {
|
|
14113
|
+
rmSync5(candidate.bundlePath, { force: true });
|
|
14114
|
+
rmSync5(candidate.manifestPath, { force: true });
|
|
14115
|
+
}
|
|
14116
|
+
}
|
|
14082
14117
|
|
|
14083
14118
|
// src/bootstrap.ts
|
|
14084
14119
|
var PLATFORM_BOOTSTRAP_PROFILES = [
|
|
@@ -14127,9 +14162,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14127
14162
|
"backupS3Secret",
|
|
14128
14163
|
"cloudflareTunnelToken",
|
|
14129
14164
|
"cloudflareApiToken",
|
|
14130
|
-
"
|
|
14131
|
-
"githubPrivateKeyBase64",
|
|
14132
|
-
"githubWebhookSecret"
|
|
14165
|
+
"githubOAuthClientSecret"
|
|
14133
14166
|
];
|
|
14134
14167
|
const unknown = Object.keys(source).filter((key) => !allowed.includes(key));
|
|
14135
14168
|
if (unknown.length)
|
|
@@ -14140,9 +14173,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14140
14173
|
const backupS3Secret = typeof source.backupS3Secret === "string" ? source.backupS3Secret.trim() : undefined;
|
|
14141
14174
|
const cloudflareTunnelToken = typeof source.cloudflareTunnelToken === "string" ? source.cloudflareTunnelToken.trim() : undefined;
|
|
14142
14175
|
const cloudflareApiToken = typeof source.cloudflareApiToken === "string" ? source.cloudflareApiToken.trim() : undefined;
|
|
14143
|
-
const
|
|
14144
|
-
const githubPrivateKeyBase64 = typeof source.githubPrivateKeyBase64 === "string" ? source.githubPrivateKeyBase64.trim() : undefined;
|
|
14145
|
-
const githubWebhookSecret = typeof source.githubWebhookSecret === "string" ? source.githubWebhookSecret.trim() : undefined;
|
|
14176
|
+
const githubOAuthClientSecret = typeof source.githubOAuthClientSecret === "string" ? source.githubOAuthClientSecret.trim() : "";
|
|
14146
14177
|
if (!/^[a-f0-9]{64}$/i.test(clusterBootstrapCode))
|
|
14147
14178
|
throw new Error("cluster bootstrap code must contain exactly 64 hexadecimal characters");
|
|
14148
14179
|
if (!emailSecret || emailSecret.length > 16384 || /[\r\n\0]/.test(emailSecret))
|
|
@@ -14162,21 +14193,8 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14162
14193
|
}
|
|
14163
14194
|
if (cloudflareTunnelToken)
|
|
14164
14195
|
validateCloudflareBootstrapSecretPair({ cloudflareTunnelToken, cloudflareApiToken });
|
|
14165
|
-
|
|
14166
|
-
|
|
14167
|
-
throw new Error("GitHub App coordinates require client secret, private key and webhook secret together");
|
|
14168
|
-
}
|
|
14169
|
-
if (githubConfigured) {
|
|
14170
|
-
if (githubClientSecret.length < 20 || githubClientSecret.length > 512 || /[\r\n\0]/.test(githubClientSecret) || githubWebhookSecret.length < 32 || githubWebhookSecret.length > 512 || /[\r\n\0]/.test(githubWebhookSecret)) {
|
|
14171
|
-
throw new Error("GitHub App client or webhook secret is malformed");
|
|
14172
|
-
}
|
|
14173
|
-
try {
|
|
14174
|
-
const pem = Buffer.from(githubPrivateKeyBase64, "base64").toString("utf8");
|
|
14175
|
-
if (createPrivateKey(pem).asymmetricKeyType !== "rsa")
|
|
14176
|
-
throw new Error("not RSA");
|
|
14177
|
-
} catch {
|
|
14178
|
-
throw new Error("GitHub App private key must be a base64-encoded RSA private key");
|
|
14179
|
-
}
|
|
14196
|
+
if (githubOAuthClientSecret.length < 20 || githubOAuthClientSecret.length > 512 || /[\r\n\0]/.test(githubOAuthClientSecret)) {
|
|
14197
|
+
throw new Error("GitHub OAuth client secret is malformed");
|
|
14180
14198
|
}
|
|
14181
14199
|
return {
|
|
14182
14200
|
clusterBootstrapCode,
|
|
@@ -14184,7 +14202,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14184
14202
|
...enrolmentToken ? { enrolmentToken } : {},
|
|
14185
14203
|
...backupS3Secret ? { backupS3Secret } : {},
|
|
14186
14204
|
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {},
|
|
14187
|
-
|
|
14205
|
+
githubOAuthClientSecret
|
|
14188
14206
|
};
|
|
14189
14207
|
}
|
|
14190
14208
|
var platformBootstrapRunner = (config) => config.kind === "platform" && config.database.role === "master";
|
|
@@ -14199,6 +14217,7 @@ var STATE_PATH = BOOTSTRAP_STATE_PATH;
|
|
|
14199
14217
|
var INTENT_PATH = "/var/lib/forgezero/bootstrap.intent.json";
|
|
14200
14218
|
var CREDS = "/etc/forgezero/creds";
|
|
14201
14219
|
var JWT_CREDENTIAL = `${CREDS}/arangodb-jwt.cred`;
|
|
14220
|
+
var ARANGO_ROOT_CREDENTIAL = `${CREDS}/arangodb-root-password.cred`;
|
|
14202
14221
|
var ENROL_CREDENTIAL = `${CREDS}/enrol-token.cred`;
|
|
14203
14222
|
var TUNNEL_CREDENTIAL = `${CREDS}/CF_TUNNEL_CONNECTOR_TOKEN.cred`;
|
|
14204
14223
|
var CF_API_CREDENTIAL = `${CREDS}/CF_API_TOKEN.cred`;
|
|
@@ -14484,7 +14503,7 @@ WantedBy=multi-user.target
|
|
|
14484
14503
|
function databaseVerifyUnit(config) {
|
|
14485
14504
|
const { address } = config.database;
|
|
14486
14505
|
return `[Unit]
|
|
14487
|
-
Description=
|
|
14506
|
+
Description=Secure and verify ForgeZero ArangoDB Community 3.11.14 writable Coordinator
|
|
14488
14507
|
Requires=forgezero-db.service
|
|
14489
14508
|
After=forgezero-db.service
|
|
14490
14509
|
PartOf=forgezero-db.service
|
|
@@ -14494,7 +14513,9 @@ Type=oneshot
|
|
|
14494
14513
|
User=arangodb
|
|
14495
14514
|
Group=arangodb
|
|
14496
14515
|
LoadCredentialEncrypted=arangodb-jwt:${JWT_CREDENTIAL}
|
|
14497
|
-
|
|
14516
|
+
LoadCredentialEncrypted=arangodb-root-password:${ARANGO_ROOT_CREDENTIAL}
|
|
14517
|
+
ExecStart=/usr/bin/arangosh --server.endpoint tcp://${unitEscape(address)}:8529 --server.jwt-secret-keyfile %d/arangodb-jwt --javascript.execute-string 'const c=require("@arangodb").db._connection;let last;let ok=false;for(let i=0;i<90;i++){try{const v=c.GET("/_api/version?details=true");const s=c.GET("/_admin/status");const m=c.GET("/_admin/server/mode");if(!v.error&&v.version==="3.11.14"&&v.details&&v.details.license==="community"&&!s.error&&s.serverInfo&&s.serverInfo.role==="COORDINATOR"&&!m.error&&m.mode==="default"){ok=true;break;}last={v,s,m};}catch(e){last=String(e);}require("internal").wait(2);}if(!ok)throw new Error("writable Community Coordinator verification failed: "+JSON.stringify(last));const password=require("fs").read("%d/arangodb-root-password").trim();if(password.length<48)throw new Error("ArangoDB root credential is malformed");require("@arangodb/users").update("root",password,true);'
|
|
14518
|
+
ExecStart=/usr/local/bin/fz-agent database-auth-verify --endpoint=http://${unitEscape(address)}:8529
|
|
14498
14519
|
RemainAfterExit=yes
|
|
14499
14520
|
TimeoutStartSec=200
|
|
14500
14521
|
NoNewPrivileges=true
|
|
@@ -14961,6 +14982,11 @@ async function bootstrapStatus(host = localBootstrapHost()) {
|
|
|
14961
14982
|
if (nginx.exitCode !== 0)
|
|
14962
14983
|
problems.push("nginx configuration is invalid");
|
|
14963
14984
|
if (state.databaseRole !== "none") {
|
|
14985
|
+
for (const credential of [JWT_CREDENTIAL, ARANGO_ROOT_CREDENTIAL]) {
|
|
14986
|
+
services[credential] = host.exists(credential);
|
|
14987
|
+
if (!services[credential])
|
|
14988
|
+
problems.push(`${credential} is missing`);
|
|
14989
|
+
}
|
|
14964
14990
|
const unitPath = "/etc/systemd/system/forgezero-db.service";
|
|
14965
14991
|
const expectsNoAgency = state.databaseAgency === "none";
|
|
14966
14992
|
const unitHasNoAgency = host.exists(unitPath) && host.read(unitPath).includes("--cluster.start-agent=false");
|
|
@@ -15100,9 +15126,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
15100
15126
|
backup: checked4.backupS3Secret,
|
|
15101
15127
|
cloudflareTunnelToken: checked4.cloudflareTunnelToken,
|
|
15102
15128
|
cloudflareApiToken: checked4.cloudflareApiToken,
|
|
15103
|
-
|
|
15104
|
-
githubPrivateKey: checked4.githubPrivateKeyBase64 ? Buffer.from(checked4.githubPrivateKeyBase64, "base64").toString("utf8") : undefined,
|
|
15105
|
-
githubWebhookSecret: checked4.githubWebhookSecret
|
|
15129
|
+
githubOAuthClientSecret: checked4.githubOAuthClientSecret
|
|
15106
15130
|
};
|
|
15107
15131
|
})() : undefined;
|
|
15108
15132
|
const enrolledPrivate = config.kind === "enrolled-compute" ? validateEnrolledComputeBootstrapSecrets(config, secrets) : undefined;
|
|
@@ -15195,14 +15219,15 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
15195
15219
|
if (!host.exists(JWT_CREDENTIAL)) {
|
|
15196
15220
|
await seal(host, "arangodb-jwt", JWT_CREDENTIAL, derive(root, "forgezero/cluster/arangodb-jwt/v1"));
|
|
15197
15221
|
}
|
|
15222
|
+
if (!host.exists(ARANGO_ROOT_CREDENTIAL)) {
|
|
15223
|
+
await seal(host, "arangodb-root-password", ARANGO_ROOT_CREDENTIAL, `fzr_${derive(root, "forgezero/cluster/arangodb-root-password/v1")}`);
|
|
15224
|
+
}
|
|
15198
15225
|
await seal(host, "seed-sync-root", SEED_CREDENTIAL, derive(root, "forgezero/cluster/seed-mesh/v1"));
|
|
15199
15226
|
await seal(host, "backup-recovery-root", BACKUP_RECOVERY_CREDENTIAL, derive(root, "forgezero/backup/recovery-root/v1"));
|
|
15200
15227
|
const emailCredentialName = config.runtime.environment.email?.provider === "smtp" ? "fz_smtp.password" : config.runtime.environment.email?.provider === "jetemail" ? "fz_jetemail.apiKey" : undefined;
|
|
15201
15228
|
for (const [name, source] of Object.entries({
|
|
15202
15229
|
...emailCredentialName ? { [emailCredentialName]: platformPrivate.email } : {},
|
|
15203
|
-
"
|
|
15204
|
-
"fz_github.privateKey": platformPrivate.githubPrivateKey,
|
|
15205
|
-
"fz_github.webhookSecret": platformPrivate.githubWebhookSecret,
|
|
15230
|
+
"fz_oauth.github.clientSecret": platformPrivate.githubOAuthClientSecret,
|
|
15206
15231
|
"backup.s3.secretAccessKey": platformPrivate.backup
|
|
15207
15232
|
})) {
|
|
15208
15233
|
if (source) {
|
|
@@ -15219,7 +15244,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
15219
15244
|
const credentials = platformApiCredentialSpecs({
|
|
15220
15245
|
emailProvider: runtime.environment.email?.provider,
|
|
15221
15246
|
cloudflareKv: cloudflareConfigured,
|
|
15222
|
-
|
|
15247
|
+
githubOAuth: true,
|
|
15223
15248
|
realtime: Boolean(runtime.environment.realtime)
|
|
15224
15249
|
});
|
|
15225
15250
|
const units = renderPlatformApiUnits({
|
|
@@ -15467,6 +15492,7 @@ function strictBootstrapDocument(value) {
|
|
|
15467
15492
|
"agentOtlpEndpoint",
|
|
15468
15493
|
"custodianEmail",
|
|
15469
15494
|
"email",
|
|
15495
|
+
"githubOAuth",
|
|
15470
15496
|
"deployProfile",
|
|
15471
15497
|
"otlpFlushIntervalMs",
|
|
15472
15498
|
"otlpTraceSampleRatio",
|
|
@@ -15477,8 +15503,13 @@ function strictBootstrapDocument(value) {
|
|
|
15477
15503
|
"databaseReadPreferredCoordinators"
|
|
15478
15504
|
], "runtime environment");
|
|
15479
15505
|
const environment = runtime.environment;
|
|
15506
|
+
exactKeys2(environment.githubOAuth, ["clientId"], "GitHub OAuth config");
|
|
15480
15507
|
if (environment.initialInventory !== undefined) {
|
|
15481
|
-
const inventory = exactKeys2(environment.initialInventory, ["metalHostname", "region", "computes", "attestation", "deployment"], "initial inventory");
|
|
15508
|
+
const inventory = exactKeys2(environment.initialInventory, ["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"], "initial inventory");
|
|
15509
|
+
if (inventory.metalIdentity !== undefined) {
|
|
15510
|
+
const identity = exactKeys2(inventory.metalIdentity, ["nodeKey", "publicKeys"], "initial Metal identity");
|
|
15511
|
+
exactKeys2(identity.publicKeys, ["ed25519", "mlDsa"], "initial Metal public keys");
|
|
15512
|
+
}
|
|
15482
15513
|
exactKeys2(inventory.region, ["key", "label", "country", "city", "confidentialCapable"], "initial inventory region");
|
|
15483
15514
|
if (inventory.attestation !== undefined) {
|
|
15484
15515
|
const attestation = exactKeys2(inventory.attestation, ["measurement", "tcbFloor"], "initial attestation evidence");
|
|
@@ -18178,7 +18209,7 @@ function forgeZeroLaunchTemplate(profile, guests, bundle, owner) {
|
|
|
18178
18209
|
otlpTraceSampleRatio: 0.1,
|
|
18179
18210
|
custodianEmail: owner.custodianEmail,
|
|
18180
18211
|
email: owner.email,
|
|
18181
|
-
|
|
18212
|
+
githubOAuth: owner.githubOAuth,
|
|
18182
18213
|
deployProfile: profile.environment
|
|
18183
18214
|
},
|
|
18184
18215
|
serviceUser: "forgezero-api",
|
|
@@ -18535,6 +18566,52 @@ function planAppBuild(input) {
|
|
|
18535
18566
|
};
|
|
18536
18567
|
}
|
|
18537
18568
|
|
|
18569
|
+
// src/platform-launch-env.ts
|
|
18570
|
+
import { lstatSync as lstatSync10, readFileSync as readFileSync16 } from "fs";
|
|
18571
|
+
import { resolve as resolve12 } from "path";
|
|
18572
|
+
function readPlatformLaunchEnvironment(path) {
|
|
18573
|
+
const absolute2 = resolve12(path);
|
|
18574
|
+
const stat2 = lstatSync10(absolute2);
|
|
18575
|
+
if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.nlink !== 1 || typeof process.getuid === "function" && stat2.uid !== process.getuid() || (stat2.mode & 63) !== 0) {
|
|
18576
|
+
throw new Error(`bootstrap secret environment must be one owner-only regular file: ${absolute2}`);
|
|
18577
|
+
}
|
|
18578
|
+
const values = new Map;
|
|
18579
|
+
for (const [index, raw] of readFileSync16(absolute2, "utf8").split(/\r?\n/).entries()) {
|
|
18580
|
+
const line = raw.trim();
|
|
18581
|
+
if (!line || line.startsWith("#"))
|
|
18582
|
+
continue;
|
|
18583
|
+
const match = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
|
|
18584
|
+
if (!match)
|
|
18585
|
+
throw new Error(`invalid environment assignment at ${absolute2}:${index + 1}`);
|
|
18586
|
+
if (values.has(match[1]))
|
|
18587
|
+
throw new Error(`duplicate environment assignment ${match[1]} at ${absolute2}:${index + 1}`);
|
|
18588
|
+
let value = match[2].trim();
|
|
18589
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
18590
|
+
value = value.slice(1, -1);
|
|
18591
|
+
}
|
|
18592
|
+
values.set(match[1], value);
|
|
18593
|
+
}
|
|
18594
|
+
const requiredValue = (name) => {
|
|
18595
|
+
const value = values.get(name)?.trim();
|
|
18596
|
+
if (!value)
|
|
18597
|
+
throw new Error(`bootstrap secret environment is missing ${name}`);
|
|
18598
|
+
return value;
|
|
18599
|
+
};
|
|
18600
|
+
const githubOAuth = { clientId: requiredValue("FZ_GITHUB_OAUTH_CLIENT_ID") };
|
|
18601
|
+
const owner = {
|
|
18602
|
+
custodianEmail: "info@axxra.in",
|
|
18603
|
+
email: { provider: "jetemail", from: "noreply@forgezero.net", eu: false },
|
|
18604
|
+
githubOAuth
|
|
18605
|
+
};
|
|
18606
|
+
return {
|
|
18607
|
+
owner,
|
|
18608
|
+
emailSecret: requiredValue("FZ_JETEMAIL_API_KEY"),
|
|
18609
|
+
cloudflareTunnelToken: requiredValue("CF_TUNNEL_TOKEN"),
|
|
18610
|
+
cloudflareApiToken: requiredValue("CF_API_TOKEN"),
|
|
18611
|
+
githubOAuthClientSecret: requiredValue("FZ_GITHUB_OAUTH_CLIENT_SECRET")
|
|
18612
|
+
};
|
|
18613
|
+
}
|
|
18614
|
+
|
|
18538
18615
|
// src/cli/index.ts
|
|
18539
18616
|
var DEFAULT_MODE = (THRESHOLD_MODES.find((mode) => mode.threshold === 1 && mode.total === 1) ?? THRESHOLD_MODES[0]).id;
|
|
18540
18617
|
var PACKAGED_AGENT_BIN2 = operatorPackagedAgentPath();
|
|
@@ -18847,7 +18924,7 @@ async function api(options, path, init) {
|
|
|
18847
18924
|
return { status: response.status, body };
|
|
18848
18925
|
}
|
|
18849
18926
|
function sleep(ms) {
|
|
18850
|
-
return new Promise((
|
|
18927
|
+
return new Promise((resolve14) => setTimeout(resolve14, ms));
|
|
18851
18928
|
}
|
|
18852
18929
|
function browserCommand(url) {
|
|
18853
18930
|
if (process.platform === "darwin")
|
|
@@ -18932,7 +19009,7 @@ function requireSession() {
|
|
|
18932
19009
|
function readOwnerOnlySecret(path, label) {
|
|
18933
19010
|
let metadata;
|
|
18934
19011
|
try {
|
|
18935
|
-
metadata =
|
|
19012
|
+
metadata = lstatSync11(path);
|
|
18936
19013
|
} catch {
|
|
18937
19014
|
throw new Error(`The ${label} file ${path} is unreadable.`);
|
|
18938
19015
|
}
|
|
@@ -18946,7 +19023,7 @@ function readOwnerOnlySecret(path, label) {
|
|
|
18946
19023
|
if (uid !== undefined && uid !== 0 && metadata.uid !== uid) {
|
|
18947
19024
|
throw new Error(`The ${label} file ${path} is not owned by the current user.`);
|
|
18948
19025
|
}
|
|
18949
|
-
const value =
|
|
19026
|
+
const value = readFileSync17(path, "utf8").trim();
|
|
18950
19027
|
if (!value)
|
|
18951
19028
|
throw new Error(`The ${label} file ${path} is empty.`);
|
|
18952
19029
|
return value;
|
|
@@ -19127,7 +19204,7 @@ async function cmdApi(options, args) {
|
|
|
19127
19204
|
let body = undefined;
|
|
19128
19205
|
if (options.data !== undefined && options.dataFile)
|
|
19129
19206
|
throw new Error("Use only one of --data or --data-file.");
|
|
19130
|
-
const encoded = options.data === "-" ? await Bun.stdin.text() : options.dataFile ?
|
|
19207
|
+
const encoded = options.data === "-" ? await Bun.stdin.text() : options.dataFile ? readFileSync17(options.dataFile, "utf8") : options.data;
|
|
19131
19208
|
if (encoded !== undefined)
|
|
19132
19209
|
body = JSON.parse(encoded);
|
|
19133
19210
|
const result = await api(options, `${url.pathname}${url.search}`, { method, body });
|
|
@@ -19306,7 +19383,7 @@ async function cmdAgent(options, args) {
|
|
|
19306
19383
|
out.line();
|
|
19307
19384
|
out.line(" Compatibility SSH deploy public key:");
|
|
19308
19385
|
out.line();
|
|
19309
|
-
out.line(` ${
|
|
19386
|
+
out.line(` ${readFileSync17(gitIdentity.gitPublicKeyPath, "utf8").trim()}`);
|
|
19310
19387
|
out.line();
|
|
19311
19388
|
}
|
|
19312
19389
|
return 0;
|
|
@@ -19346,78 +19423,6 @@ async function bootstrapSecret(question) {
|
|
|
19346
19423
|
throw new Error(`${question} was not provided`);
|
|
19347
19424
|
return value;
|
|
19348
19425
|
}
|
|
19349
|
-
function readPlatformLaunchEnvironment(path) {
|
|
19350
|
-
const absolute2 = resolve12(path);
|
|
19351
|
-
const stat2 = lstatSync10(absolute2);
|
|
19352
|
-
if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.nlink !== 1 || typeof process.getuid === "function" && stat2.uid !== process.getuid() || (stat2.mode & 63) !== 0) {
|
|
19353
|
-
throw new Error(`bootstrap secret environment must be one owner-only regular file: ${absolute2}`);
|
|
19354
|
-
}
|
|
19355
|
-
const values = new Map;
|
|
19356
|
-
for (const [index, raw] of readFileSync16(absolute2, "utf8").split(/\r?\n/).entries()) {
|
|
19357
|
-
const line = raw.trim();
|
|
19358
|
-
if (!line || line.startsWith("#"))
|
|
19359
|
-
continue;
|
|
19360
|
-
const match = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
|
|
19361
|
-
if (!match)
|
|
19362
|
-
throw new Error(`invalid environment assignment at ${absolute2}:${index + 1}`);
|
|
19363
|
-
if (values.has(match[1]))
|
|
19364
|
-
throw new Error(`duplicate environment assignment ${match[1]} at ${absolute2}:${index + 1}`);
|
|
19365
|
-
let value = match[2].trim();
|
|
19366
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
19367
|
-
value = value.slice(1, -1);
|
|
19368
|
-
}
|
|
19369
|
-
values.set(match[1], value);
|
|
19370
|
-
}
|
|
19371
|
-
const requiredValue = (name) => {
|
|
19372
|
-
const value = values.get(name)?.trim();
|
|
19373
|
-
if (!value)
|
|
19374
|
-
throw new Error(`bootstrap secret environment is missing ${name}`);
|
|
19375
|
-
return value;
|
|
19376
|
-
};
|
|
19377
|
-
const provider = requiredValue("FZ_EMAIL_PROVIDER");
|
|
19378
|
-
if (provider !== "smtp" && provider !== "jetemail")
|
|
19379
|
-
throw new Error("FZ_EMAIL_PROVIDER must be smtp or jetemail");
|
|
19380
|
-
const smtpPort = provider === "smtp" ? Number(requiredValue("FZ_SMTP_PORT")) : undefined;
|
|
19381
|
-
if (smtpPort !== undefined && (!Number.isInteger(smtpPort) || smtpPort < 1 || smtpPort > 65535)) {
|
|
19382
|
-
throw new Error("FZ_SMTP_PORT must be an integer from 1 through 65535");
|
|
19383
|
-
}
|
|
19384
|
-
const githubEnabled = (values.get("FZ_GITHUB_ENABLED") ?? "false").trim().toLowerCase() === "true";
|
|
19385
|
-
const githubApp = githubEnabled ? {
|
|
19386
|
-
clientId: requiredValue("FZ_GITHUB_CLIENT_ID"),
|
|
19387
|
-
appId: requiredValue("FZ_GITHUB_APP_ID"),
|
|
19388
|
-
slug: requiredValue("FZ_GITHUB_APP_SLUG")
|
|
19389
|
-
} : undefined;
|
|
19390
|
-
const owner = provider === "jetemail" ? {
|
|
19391
|
-
custodianEmail: requiredValue("FZ_BOOTSTRAP_CUSTODIAN_EMAIL"),
|
|
19392
|
-
email: {
|
|
19393
|
-
provider,
|
|
19394
|
-
from: requiredValue("FZ_EMAIL_FROM"),
|
|
19395
|
-
eu: (values.get("FZ_JETEMAIL_EU") ?? "false").trim().toLowerCase() === "true"
|
|
19396
|
-
},
|
|
19397
|
-
...githubApp ? { githubApp } : {}
|
|
19398
|
-
} : {
|
|
19399
|
-
custodianEmail: requiredValue("FZ_BOOTSTRAP_CUSTODIAN_EMAIL"),
|
|
19400
|
-
email: {
|
|
19401
|
-
provider,
|
|
19402
|
-
from: requiredValue("FZ_EMAIL_FROM"),
|
|
19403
|
-
host: requiredValue("FZ_SMTP_HOST"),
|
|
19404
|
-
port: smtpPort,
|
|
19405
|
-
user: requiredValue("FZ_SMTP_USER")
|
|
19406
|
-
},
|
|
19407
|
-
...githubApp ? { githubApp } : {}
|
|
19408
|
-
};
|
|
19409
|
-
return {
|
|
19410
|
-
owner,
|
|
19411
|
-
emailSecret: requiredValue(provider === "jetemail" ? "FZ_JETEMAIL_API_KEY" : "FZ_SMTP_PASSWORD"),
|
|
19412
|
-
cloudflareTunnelToken: requiredValue("CF_TUNNEL_TOKEN"),
|
|
19413
|
-
cloudflareApiToken: requiredValue("CF_API_TOKEN"),
|
|
19414
|
-
...githubEnabled ? {
|
|
19415
|
-
githubClientSecret: requiredValue("FZ_GITHUB_CLIENT_SECRET"),
|
|
19416
|
-
githubPrivateKeyBase64: requiredValue("FZ_GITHUB_PRIVATE_KEY_BASE64"),
|
|
19417
|
-
githubWebhookSecret: requiredValue("FZ_GITHUB_WEBHOOK_SECRET")
|
|
19418
|
-
} : {}
|
|
19419
|
-
};
|
|
19420
|
-
}
|
|
19421
19426
|
async function promptPlatformBootstrapSecrets(config, generatedClusterBootstrapCode) {
|
|
19422
19427
|
return validatePlatformBootstrapSecrets(config, {
|
|
19423
19428
|
clusterBootstrapCode: generatedClusterBootstrapCode ?? await bootstrapSecret("Shared 64-hex cluster bootstrap code"),
|
|
@@ -19428,11 +19433,7 @@ async function promptPlatformBootstrapSecrets(config, generatedClusterBootstrapC
|
|
|
19428
19433
|
cloudflareTunnelToken: await bootstrapSecret("CF_TUNNEL_TOKEN"),
|
|
19429
19434
|
cloudflareApiToken: await bootstrapSecret("CF_API_TOKEN")
|
|
19430
19435
|
} : {},
|
|
19431
|
-
|
|
19432
|
-
githubClientSecret: await bootstrapSecret("GitHub App client secret"),
|
|
19433
|
-
githubPrivateKeyBase64: await bootstrapSecret("GitHub App RSA private key (base64)"),
|
|
19434
|
-
githubWebhookSecret: await bootstrapSecret("GitHub App webhook secret")
|
|
19435
|
-
} : {}
|
|
19436
|
+
githubOAuthClientSecret: await bootstrapSecret("GitHub OAuth client secret")
|
|
19436
19437
|
});
|
|
19437
19438
|
}
|
|
19438
19439
|
var bootstrapList = (question, fallback) => bootstrapAnswer(question, fallback).split(",").map((value) => value.trim()).filter(Boolean);
|
|
@@ -19493,7 +19494,7 @@ function interactiveMetalBootstrap() {
|
|
|
19493
19494
|
});
|
|
19494
19495
|
}
|
|
19495
19496
|
function writeBootstrapConfig(path, config) {
|
|
19496
|
-
if (!isAbsolute7(path) ||
|
|
19497
|
+
if (!isAbsolute7(path) || resolve13(path) !== path)
|
|
19497
19498
|
throw new Error("--output must be a canonical absolute path");
|
|
19498
19499
|
mkdirSync13(dirname14(path), { recursive: true, mode: 448 });
|
|
19499
19500
|
writeFileSync13(path, `${JSON.stringify(config, null, 2)}
|
|
@@ -19557,11 +19558,11 @@ async function interactiveCloudflareBootstrap() {
|
|
|
19557
19558
|
});
|
|
19558
19559
|
}
|
|
19559
19560
|
function genesisOutputDirectory(path) {
|
|
19560
|
-
if (!isAbsolute7(path) ||
|
|
19561
|
+
if (!isAbsolute7(path) || resolve13(path) !== path)
|
|
19561
19562
|
throw new Error("--output must be a canonical absolute directory");
|
|
19562
19563
|
if (!existsSync13(path))
|
|
19563
19564
|
mkdirSync13(path, { recursive: true, mode: 448 });
|
|
19564
|
-
const metadata =
|
|
19565
|
+
const metadata = lstatSync11(path);
|
|
19565
19566
|
const uid = process.getuid?.();
|
|
19566
19567
|
if (!metadata.isDirectory() || metadata.isSymbolicLink() || (metadata.mode & 63) !== 0 || uid !== undefined && uid !== 0 && metadata.uid !== uid) {
|
|
19567
19568
|
throw new Error("platform genesis output must be an owner-only directory owned by the current user");
|
|
@@ -19730,34 +19731,11 @@ function selectedForgeZeroLaunchEnvironment(value) {
|
|
|
19730
19731
|
return value;
|
|
19731
19732
|
}
|
|
19732
19733
|
function forgeZeroLaunchOwnerInput() {
|
|
19733
|
-
const
|
|
19734
|
-
const provider = bootstrapAnswer("Bootstrap email provider (smtp/jetemail)", "jetemail");
|
|
19735
|
-
if (provider !== "smtp" && provider !== "jetemail") {
|
|
19736
|
-
throw new Error("Bootstrap email provider must be smtp or jetemail");
|
|
19737
|
-
}
|
|
19738
|
-
const from = bootstrapAnswer("Bootstrap email From address");
|
|
19739
|
-
const githubApp = bootstrapBoolean("Configure the platform GitHub App now?", "no") ? {
|
|
19740
|
-
clientId: bootstrapAnswer("GitHub App client ID"),
|
|
19741
|
-
appId: bootstrapAnswer("GitHub App ID"),
|
|
19742
|
-
slug: bootstrapAnswer("GitHub App slug")
|
|
19743
|
-
} : undefined;
|
|
19744
|
-
if (provider === "jetemail") {
|
|
19745
|
-
return {
|
|
19746
|
-
custodianEmail,
|
|
19747
|
-
email: { provider, from, eu: bootstrapBoolean("Use JetEmail EU processing?", "no") },
|
|
19748
|
-
...githubApp ? { githubApp } : {}
|
|
19749
|
-
};
|
|
19750
|
-
}
|
|
19734
|
+
const githubOAuth = { clientId: bootstrapAnswer("GitHub OAuth client ID") };
|
|
19751
19735
|
return {
|
|
19752
|
-
custodianEmail,
|
|
19753
|
-
email: {
|
|
19754
|
-
|
|
19755
|
-
from,
|
|
19756
|
-
host: bootstrapAnswer("SMTP host"),
|
|
19757
|
-
port: bootstrapNumber("SMTP port", "587"),
|
|
19758
|
-
user: bootstrapAnswer("SMTP user")
|
|
19759
|
-
},
|
|
19760
|
-
...githubApp ? { githubApp } : {}
|
|
19736
|
+
custodianEmail: "info@axxra.in",
|
|
19737
|
+
email: { provider: "jetemail", from: "noreply@forgezero.net", eu: false },
|
|
19738
|
+
githubOAuth
|
|
19761
19739
|
};
|
|
19762
19740
|
}
|
|
19763
19741
|
async function prepareForgeZeroPlatformLaunch(environment, outputDirectory, projectRoot, owner) {
|
|
@@ -19772,14 +19750,11 @@ async function prepareForgeZeroPlatformLaunch(environment, outputDirectory, proj
|
|
|
19772
19750
|
if (!existsSync13(path))
|
|
19773
19751
|
throw new Error(`${label} is missing at ${path}`);
|
|
19774
19752
|
}
|
|
19775
|
-
const root =
|
|
19753
|
+
const root = resolve13(projectRoot);
|
|
19776
19754
|
const nestedApi = join13(root, "api");
|
|
19777
19755
|
const repositoryRoot = existsSync13(join13(nestedApi, "package.json")) ? nestedApi : root;
|
|
19778
19756
|
const bundlePath = join13(base, "api.bundle");
|
|
19779
|
-
const bundle =
|
|
19780
|
-
if (bundle.manifest.branch !== profile.branch) {
|
|
19781
|
-
throw new Error(`existing bootstrap bundle is for ${bundle.manifest.branch}, expected ${profile.branch}`);
|
|
19782
|
-
}
|
|
19757
|
+
const bundle = await refreshBootstrapBundle({ repositoryRoot, outputPath: bundlePath, branch: profile.branch });
|
|
19783
19758
|
return writePlatformGenesisFleet(outputDirectory, {
|
|
19784
19759
|
profile,
|
|
19785
19760
|
metalRequestFile,
|
|
@@ -19829,6 +19804,7 @@ function interactiveBootstrap(kind, genesisGuests, genesisCloudflareCheckpoint)
|
|
|
19829
19804
|
const backupRegion = backupEndpoint ? bootstrapAnswer("Backup S3 region") : undefined;
|
|
19830
19805
|
const backupBucket = backupEndpoint ? bootstrapAnswer("Backup S3 bucket") : undefined;
|
|
19831
19806
|
const backupAccessKeyId = backupEndpoint ? bootstrapAnswer("Backup S3 access-key id") : undefined;
|
|
19807
|
+
const githubOAuthClientId = bootstrapAnswer("GitHub OAuth client ID");
|
|
19832
19808
|
const cloudflareHandoffFile = genesis ? cloudflareHostHandoffPath(genesisCloudflareCheckpoint, computeReference) : bootstrapAnswer("Node-specific Cloudflare host handoff (blank for no public edge)", "");
|
|
19833
19809
|
const cloudflareNodeName = cloudflareHandoffFile ? genesis ? computeReference : bootstrapAnswer("Cloudflare handoff node name", computeReference) : undefined;
|
|
19834
19810
|
const databaseNetworkMode = "private-lan";
|
|
@@ -19883,6 +19859,7 @@ function interactiveBootstrap(kind, genesisGuests, genesisCloudflareCheckpoint)
|
|
|
19883
19859
|
otlpTraceSampleRatio: 0.1,
|
|
19884
19860
|
custodianEmail: role === "master" ? bootstrapAnswer("First custodian email") : undefined,
|
|
19885
19861
|
email: emailProvider === "smtp" ? { provider: "smtp", host: smtpHost, port: smtpPort, user: smtpUser, from: emailFrom } : { provider: "jetemail", from: emailFrom, eu: jetemailEu },
|
|
19862
|
+
githubOAuth: { clientId: githubOAuthClientId },
|
|
19886
19863
|
...backupEndpoint && backupRegion && backupBucket && backupAccessKeyId ? {
|
|
19887
19864
|
backup: { endpoint: backupEndpoint, region: backupRegion, bucket: backupBucket, accessKeyId: backupAccessKeyId }
|
|
19888
19865
|
} : {},
|
|
@@ -19943,11 +19920,7 @@ async function runAttendedPlatformFleet(fleet, apply, generatedClusterBootstrapC
|
|
|
19943
19920
|
emailSecret: environmentInput.emailSecret,
|
|
19944
19921
|
cloudflareTunnelToken: environmentInput.cloudflareTunnelToken,
|
|
19945
19922
|
cloudflareApiToken: environmentInput.cloudflareApiToken,
|
|
19946
|
-
|
|
19947
|
-
githubClientSecret: environmentInput.githubClientSecret,
|
|
19948
|
-
githubPrivateKeyBase64: environmentInput.githubPrivateKeyBase64,
|
|
19949
|
-
githubWebhookSecret: environmentInput.githubWebhookSecret
|
|
19950
|
-
} : {}
|
|
19923
|
+
githubOAuthClientSecret: environmentInput.githubOAuthClientSecret
|
|
19951
19924
|
}) : await promptPlatformBootstrapSecrets(firstConfig, generatedClusterBootstrapCode);
|
|
19952
19925
|
const cloudflare = await resolveCloudflareBootstrapCommandConfig(fleet.cloudflareConfigFile, {
|
|
19953
19926
|
tunnelToken: secrets.cloudflareTunnelToken,
|
|
@@ -20261,7 +20234,7 @@ async function cmdUnlock(options) {
|
|
|
20261
20234
|
if (options.key || options.userExplicit) {
|
|
20262
20235
|
throw new Error("SSH/user unlock coordinates are not accepted. SSH keys cannot open a WebAuthn-PRF custody envelope; use --phrase-file or --phrase-stdin.");
|
|
20263
20236
|
}
|
|
20264
|
-
const phraseText = options.phraseFile ? readOwnerOnlySecret(options.phraseFile, "recovery phrase") : options.phraseStdin ?
|
|
20237
|
+
const phraseText = options.phraseFile ? readOwnerOnlySecret(options.phraseFile, "recovery phrase") : options.phraseStdin ? readFileSync17(0, "utf8").trim() : "";
|
|
20265
20238
|
const phrase = phraseText ? phraseText.split(/\s+/) : [];
|
|
20266
20239
|
if (phrase.length !== 24) {
|
|
20267
20240
|
throw new Error(`Recovery phrase must contain exactly 24 words; received ${phrase.length}. Use --phrase-file or --phrase-stdin.`);
|
|
@@ -20494,7 +20467,7 @@ function projectFromCheckout(options) {
|
|
|
20494
20467
|
try {
|
|
20495
20468
|
return loadConfig({
|
|
20496
20469
|
cwd: options.projectRoot,
|
|
20497
|
-
readFile: (path) => existsSync13(path) ?
|
|
20470
|
+
readFile: (path) => existsSync13(path) ? readFileSync17(path, "utf8") : undefined
|
|
20498
20471
|
}).config.project;
|
|
20499
20472
|
} catch (cause) {
|
|
20500
20473
|
throw new Error(`No --project was given and the checkout has no usable .fz/config.json: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
@@ -20561,7 +20534,7 @@ async function cmdDeploy(options, args) {
|
|
|
20561
20534
|
throw new Error("typed runtime initialization selects its tested software and attestation from --runtime/--isolation; do not combine --software or --attestation");
|
|
20562
20535
|
}
|
|
20563
20536
|
initializeTypeScriptDeployment(options.projectRoot, {
|
|
20564
|
-
name: options.projectName ?? basename3(
|
|
20537
|
+
name: options.projectName ?? basename3(resolve13(options.projectRoot)),
|
|
20565
20538
|
force: options.force,
|
|
20566
20539
|
runtime: options.deployRuntime,
|
|
20567
20540
|
operatingSystem: options.deployOperatingSystem,
|
|
@@ -20616,7 +20589,7 @@ async function cmdDeploy(options, args) {
|
|
|
20616
20589
|
return problems.length === 0 ? 0 : 1;
|
|
20617
20590
|
}
|
|
20618
20591
|
if (operation === "check" || operation === "sync") {
|
|
20619
|
-
if (existsSync13(
|
|
20592
|
+
if (existsSync13(resolve13(options.projectRoot, DEPLOY_SOURCE_FILE))) {
|
|
20620
20593
|
const expected = await compileDeploymentProject(options.projectRoot, { write: false });
|
|
20621
20594
|
const actual = inspectCompiledDeployment(options.projectRoot);
|
|
20622
20595
|
const current2 = canonicalJson(expected.plan) === canonicalJson(actual.plan);
|
|
@@ -20692,7 +20665,7 @@ async function cmdDeploy(options, args) {
|
|
|
20692
20665
|
branch: options.branch,
|
|
20693
20666
|
cloneUrl: required(options.cloneUrl, "--clone-url"),
|
|
20694
20667
|
sourceAuth,
|
|
20695
|
-
...options.knownHostsFile ? { knownHosts:
|
|
20668
|
+
...options.knownHostsFile ? { knownHosts: readFileSync17(options.knownHostsFile, "utf8") } : {},
|
|
20696
20669
|
projectKey
|
|
20697
20670
|
} });
|
|
20698
20671
|
const pipelineKey2 = String(created.pipelineKey);
|
package/dist/metal-bootstrap.js
CHANGED
|
@@ -366,7 +366,7 @@ function systemdAgentEgressDirectives(loopbackTcpPorts = []) {
|
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
// src/version.ts
|
|
369
|
-
var VERSION = "0.1.
|
|
369
|
+
var VERSION = "0.1.108";
|
|
370
370
|
|
|
371
371
|
// src/otel-collector.ts
|
|
372
372
|
var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
|