@forgezero/agent 0.1.107 → 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.d.ts +1 -4
- package/dist/bootstrap.js +16 -41
- package/dist/fz-agent.js +1 -1
- package/dist/fz.js +32 -126
- package/dist/metal-bootstrap.js +1 -1
- package/dist/operator-bootstrap.js +16 -41
- package/dist/platform-bootstrap-runtime.d.ts +4 -6
- package/dist/platform-bootstrap-runtime.js +4 -10
- package/dist/platform-fleet-verification.js +6 -12
- package/dist/platform-launch-env.d.ts +1 -3
- package/dist/platform-launch-profile.d.ts +2 -3
- package/dist/provision.js +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/agent-heartbeat.js
CHANGED
package/dist/bootstrap.d.ts
CHANGED
|
@@ -115,10 +115,7 @@ export interface PlatformBootstrapSecrets {
|
|
|
115
115
|
backupS3Secret?: string;
|
|
116
116
|
cloudflareTunnelToken?: string;
|
|
117
117
|
cloudflareApiToken?: string;
|
|
118
|
-
|
|
119
|
-
/** One-line base64 form accepted by prompts/env; decoded before systemd sealing. */
|
|
120
|
-
githubPrivateKeyBase64?: string;
|
|
121
|
-
githubWebhookSecret?: string;
|
|
118
|
+
githubOAuthClientSecret: string;
|
|
122
119
|
}
|
|
123
120
|
export interface EnrolledComputeBootstrapSecrets {
|
|
124
121
|
enrolmentToken: string;
|
package/dist/bootstrap.js
CHANGED
|
@@ -1426,7 +1426,7 @@ async function refreshBootstrapBundle(input, exec = run) {
|
|
|
1426
1426
|
}
|
|
1427
1427
|
|
|
1428
1428
|
// src/bootstrap.ts
|
|
1429
|
-
import { createHash as createHash2, createHmac as createHmac2,
|
|
1429
|
+
import { createHash as createHash2, createHmac as createHmac2, randomBytes as randomBytes3 } from "crypto";
|
|
1430
1430
|
import {
|
|
1431
1431
|
chmodSync as chmodSync3,
|
|
1432
1432
|
existsSync as existsSync5,
|
|
@@ -1460,7 +1460,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
|
|
|
1460
1460
|
var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
|
|
1461
1461
|
|
|
1462
1462
|
// src/version.ts
|
|
1463
|
-
var VERSION = "0.1.
|
|
1463
|
+
var VERSION = "0.1.108";
|
|
1464
1464
|
|
|
1465
1465
|
// src/software.ts
|
|
1466
1466
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -3228,10 +3228,8 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
3228
3228
|
} else if (input.email !== undefined) {
|
|
3229
3229
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
3230
3230
|
}
|
|
3231
|
-
if (input.
|
|
3232
|
-
|
|
3233
|
-
throw new Error("GitHub App client id, app id or slug is malformed.");
|
|
3234
|
-
}
|
|
3231
|
+
if (!input.githubOAuth || !/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubOAuth.clientId)) {
|
|
3232
|
+
throw new Error("GitHub OAuth client id is malformed.");
|
|
3235
3233
|
}
|
|
3236
3234
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
3237
3235
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
@@ -3363,9 +3361,7 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
3363
3361
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
3364
3362
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
3365
3363
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
3366
|
-
|
|
3367
|
-
FZ_GITHUB_APP_ID: value.githubApp?.appId ?? "",
|
|
3368
|
-
FZ_GITHUB_APP_SLUG: value.githubApp?.slug ?? "",
|
|
3364
|
+
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
3369
3365
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
3370
3366
|
};
|
|
3371
3367
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -3377,9 +3373,7 @@ function platformApiCredentialSpecs(options) {
|
|
|
3377
3373
|
const optional = [
|
|
3378
3374
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
3379
3375
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
3380
|
-
["
|
|
3381
|
-
["fz_github.privateKey", options.githubApp],
|
|
3382
|
-
["fz_github.webhookSecret", options.githubApp],
|
|
3376
|
+
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
3383
3377
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
3384
3378
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
3385
3379
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -3783,9 +3777,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3783
3777
|
"backupS3Secret",
|
|
3784
3778
|
"cloudflareTunnelToken",
|
|
3785
3779
|
"cloudflareApiToken",
|
|
3786
|
-
"
|
|
3787
|
-
"githubPrivateKeyBase64",
|
|
3788
|
-
"githubWebhookSecret"
|
|
3780
|
+
"githubOAuthClientSecret"
|
|
3789
3781
|
];
|
|
3790
3782
|
const unknown = Object.keys(source).filter((key) => !allowed.includes(key));
|
|
3791
3783
|
if (unknown.length)
|
|
@@ -3796,9 +3788,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3796
3788
|
const backupS3Secret = typeof source.backupS3Secret === "string" ? source.backupS3Secret.trim() : undefined;
|
|
3797
3789
|
const cloudflareTunnelToken = typeof source.cloudflareTunnelToken === "string" ? source.cloudflareTunnelToken.trim() : undefined;
|
|
3798
3790
|
const cloudflareApiToken = typeof source.cloudflareApiToken === "string" ? source.cloudflareApiToken.trim() : undefined;
|
|
3799
|
-
const
|
|
3800
|
-
const githubPrivateKeyBase64 = typeof source.githubPrivateKeyBase64 === "string" ? source.githubPrivateKeyBase64.trim() : undefined;
|
|
3801
|
-
const githubWebhookSecret = typeof source.githubWebhookSecret === "string" ? source.githubWebhookSecret.trim() : undefined;
|
|
3791
|
+
const githubOAuthClientSecret = typeof source.githubOAuthClientSecret === "string" ? source.githubOAuthClientSecret.trim() : "";
|
|
3802
3792
|
if (!/^[a-f0-9]{64}$/i.test(clusterBootstrapCode))
|
|
3803
3793
|
throw new Error("cluster bootstrap code must contain exactly 64 hexadecimal characters");
|
|
3804
3794
|
if (!emailSecret || emailSecret.length > 16384 || /[\r\n\0]/.test(emailSecret))
|
|
@@ -3818,21 +3808,8 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3818
3808
|
}
|
|
3819
3809
|
if (cloudflareTunnelToken)
|
|
3820
3810
|
validateCloudflareBootstrapSecretPair({ cloudflareTunnelToken, cloudflareApiToken });
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
throw new Error("GitHub App coordinates require client secret, private key and webhook secret together");
|
|
3824
|
-
}
|
|
3825
|
-
if (githubConfigured) {
|
|
3826
|
-
if (githubClientSecret.length < 20 || githubClientSecret.length > 512 || /[\r\n\0]/.test(githubClientSecret) || githubWebhookSecret.length < 32 || githubWebhookSecret.length > 512 || /[\r\n\0]/.test(githubWebhookSecret)) {
|
|
3827
|
-
throw new Error("GitHub App client or webhook secret is malformed");
|
|
3828
|
-
}
|
|
3829
|
-
try {
|
|
3830
|
-
const pem = Buffer.from(githubPrivateKeyBase64, "base64").toString("utf8");
|
|
3831
|
-
if (createPrivateKey(pem).asymmetricKeyType !== "rsa")
|
|
3832
|
-
throw new Error("not RSA");
|
|
3833
|
-
} catch {
|
|
3834
|
-
throw new Error("GitHub App private key must be a base64-encoded RSA private key");
|
|
3835
|
-
}
|
|
3811
|
+
if (githubOAuthClientSecret.length < 20 || githubOAuthClientSecret.length > 512 || /[\r\n\0]/.test(githubOAuthClientSecret)) {
|
|
3812
|
+
throw new Error("GitHub OAuth client secret is malformed");
|
|
3836
3813
|
}
|
|
3837
3814
|
return {
|
|
3838
3815
|
clusterBootstrapCode,
|
|
@@ -3840,7 +3817,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3840
3817
|
...enrolmentToken ? { enrolmentToken } : {},
|
|
3841
3818
|
...backupS3Secret ? { backupS3Secret } : {},
|
|
3842
3819
|
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {},
|
|
3843
|
-
|
|
3820
|
+
githubOAuthClientSecret
|
|
3844
3821
|
};
|
|
3845
3822
|
}
|
|
3846
3823
|
var platformBootstrapRunner = (config) => config.kind === "platform" && config.database.role === "master";
|
|
@@ -4764,9 +4741,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4764
4741
|
backup: checked4.backupS3Secret,
|
|
4765
4742
|
cloudflareTunnelToken: checked4.cloudflareTunnelToken,
|
|
4766
4743
|
cloudflareApiToken: checked4.cloudflareApiToken,
|
|
4767
|
-
|
|
4768
|
-
githubPrivateKey: checked4.githubPrivateKeyBase64 ? Buffer.from(checked4.githubPrivateKeyBase64, "base64").toString("utf8") : undefined,
|
|
4769
|
-
githubWebhookSecret: checked4.githubWebhookSecret
|
|
4744
|
+
githubOAuthClientSecret: checked4.githubOAuthClientSecret
|
|
4770
4745
|
};
|
|
4771
4746
|
})() : undefined;
|
|
4772
4747
|
const enrolledPrivate = config.kind === "enrolled-compute" ? validateEnrolledComputeBootstrapSecrets(config, secrets) : undefined;
|
|
@@ -4867,9 +4842,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4867
4842
|
const emailCredentialName = config.runtime.environment.email?.provider === "smtp" ? "fz_smtp.password" : config.runtime.environment.email?.provider === "jetemail" ? "fz_jetemail.apiKey" : undefined;
|
|
4868
4843
|
for (const [name, source] of Object.entries({
|
|
4869
4844
|
...emailCredentialName ? { [emailCredentialName]: platformPrivate.email } : {},
|
|
4870
|
-
"
|
|
4871
|
-
"fz_github.privateKey": platformPrivate.githubPrivateKey,
|
|
4872
|
-
"fz_github.webhookSecret": platformPrivate.githubWebhookSecret,
|
|
4845
|
+
"fz_oauth.github.clientSecret": platformPrivate.githubOAuthClientSecret,
|
|
4873
4846
|
"backup.s3.secretAccessKey": platformPrivate.backup
|
|
4874
4847
|
})) {
|
|
4875
4848
|
if (source) {
|
|
@@ -4886,7 +4859,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4886
4859
|
const credentials = platformApiCredentialSpecs({
|
|
4887
4860
|
emailProvider: runtime.environment.email?.provider,
|
|
4888
4861
|
cloudflareKv: cloudflareConfigured,
|
|
4889
|
-
|
|
4862
|
+
githubOAuth: true,
|
|
4890
4863
|
realtime: Boolean(runtime.environment.realtime)
|
|
4891
4864
|
});
|
|
4892
4865
|
const units = renderPlatformApiUnits({
|
|
@@ -5134,6 +5107,7 @@ function strictBootstrapDocument(value) {
|
|
|
5134
5107
|
"agentOtlpEndpoint",
|
|
5135
5108
|
"custodianEmail",
|
|
5136
5109
|
"email",
|
|
5110
|
+
"githubOAuth",
|
|
5137
5111
|
"deployProfile",
|
|
5138
5112
|
"otlpFlushIntervalMs",
|
|
5139
5113
|
"otlpTraceSampleRatio",
|
|
@@ -5144,6 +5118,7 @@ function strictBootstrapDocument(value) {
|
|
|
5144
5118
|
"databaseReadPreferredCoordinators"
|
|
5145
5119
|
], "runtime environment");
|
|
5146
5120
|
const environment = runtime.environment;
|
|
5121
|
+
exactKeys(environment.githubOAuth, ["clientId"], "GitHub OAuth config");
|
|
5147
5122
|
if (environment.initialInventory !== undefined) {
|
|
5148
5123
|
const inventory = exactKeys(environment.initialInventory, ["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"], "initial inventory");
|
|
5149
5124
|
if (inventory.metalIdentity !== undefined) {
|
package/dist/fz-agent.js
CHANGED
package/dist/fz.js
CHANGED
|
@@ -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],
|
|
@@ -14168,9 +14162,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14168
14162
|
"backupS3Secret",
|
|
14169
14163
|
"cloudflareTunnelToken",
|
|
14170
14164
|
"cloudflareApiToken",
|
|
14171
|
-
"
|
|
14172
|
-
"githubPrivateKeyBase64",
|
|
14173
|
-
"githubWebhookSecret"
|
|
14165
|
+
"githubOAuthClientSecret"
|
|
14174
14166
|
];
|
|
14175
14167
|
const unknown = Object.keys(source).filter((key) => !allowed.includes(key));
|
|
14176
14168
|
if (unknown.length)
|
|
@@ -14181,9 +14173,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14181
14173
|
const backupS3Secret = typeof source.backupS3Secret === "string" ? source.backupS3Secret.trim() : undefined;
|
|
14182
14174
|
const cloudflareTunnelToken = typeof source.cloudflareTunnelToken === "string" ? source.cloudflareTunnelToken.trim() : undefined;
|
|
14183
14175
|
const cloudflareApiToken = typeof source.cloudflareApiToken === "string" ? source.cloudflareApiToken.trim() : undefined;
|
|
14184
|
-
const
|
|
14185
|
-
const githubPrivateKeyBase64 = typeof source.githubPrivateKeyBase64 === "string" ? source.githubPrivateKeyBase64.trim() : undefined;
|
|
14186
|
-
const githubWebhookSecret = typeof source.githubWebhookSecret === "string" ? source.githubWebhookSecret.trim() : undefined;
|
|
14176
|
+
const githubOAuthClientSecret = typeof source.githubOAuthClientSecret === "string" ? source.githubOAuthClientSecret.trim() : "";
|
|
14187
14177
|
if (!/^[a-f0-9]{64}$/i.test(clusterBootstrapCode))
|
|
14188
14178
|
throw new Error("cluster bootstrap code must contain exactly 64 hexadecimal characters");
|
|
14189
14179
|
if (!emailSecret || emailSecret.length > 16384 || /[\r\n\0]/.test(emailSecret))
|
|
@@ -14203,21 +14193,8 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14203
14193
|
}
|
|
14204
14194
|
if (cloudflareTunnelToken)
|
|
14205
14195
|
validateCloudflareBootstrapSecretPair({ cloudflareTunnelToken, cloudflareApiToken });
|
|
14206
|
-
|
|
14207
|
-
|
|
14208
|
-
throw new Error("GitHub App coordinates require client secret, private key and webhook secret together");
|
|
14209
|
-
}
|
|
14210
|
-
if (githubConfigured) {
|
|
14211
|
-
if (githubClientSecret.length < 20 || githubClientSecret.length > 512 || /[\r\n\0]/.test(githubClientSecret) || githubWebhookSecret.length < 32 || githubWebhookSecret.length > 512 || /[\r\n\0]/.test(githubWebhookSecret)) {
|
|
14212
|
-
throw new Error("GitHub App client or webhook secret is malformed");
|
|
14213
|
-
}
|
|
14214
|
-
try {
|
|
14215
|
-
const pem = Buffer.from(githubPrivateKeyBase64, "base64").toString("utf8");
|
|
14216
|
-
if (createPrivateKey(pem).asymmetricKeyType !== "rsa")
|
|
14217
|
-
throw new Error("not RSA");
|
|
14218
|
-
} catch {
|
|
14219
|
-
throw new Error("GitHub App private key must be a base64-encoded RSA private key");
|
|
14220
|
-
}
|
|
14196
|
+
if (githubOAuthClientSecret.length < 20 || githubOAuthClientSecret.length > 512 || /[\r\n\0]/.test(githubOAuthClientSecret)) {
|
|
14197
|
+
throw new Error("GitHub OAuth client secret is malformed");
|
|
14221
14198
|
}
|
|
14222
14199
|
return {
|
|
14223
14200
|
clusterBootstrapCode,
|
|
@@ -14225,7 +14202,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14225
14202
|
...enrolmentToken ? { enrolmentToken } : {},
|
|
14226
14203
|
...backupS3Secret ? { backupS3Secret } : {},
|
|
14227
14204
|
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {},
|
|
14228
|
-
|
|
14205
|
+
githubOAuthClientSecret
|
|
14229
14206
|
};
|
|
14230
14207
|
}
|
|
14231
14208
|
var platformBootstrapRunner = (config) => config.kind === "platform" && config.database.role === "master";
|
|
@@ -15149,9 +15126,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
15149
15126
|
backup: checked4.backupS3Secret,
|
|
15150
15127
|
cloudflareTunnelToken: checked4.cloudflareTunnelToken,
|
|
15151
15128
|
cloudflareApiToken: checked4.cloudflareApiToken,
|
|
15152
|
-
|
|
15153
|
-
githubPrivateKey: checked4.githubPrivateKeyBase64 ? Buffer.from(checked4.githubPrivateKeyBase64, "base64").toString("utf8") : undefined,
|
|
15154
|
-
githubWebhookSecret: checked4.githubWebhookSecret
|
|
15129
|
+
githubOAuthClientSecret: checked4.githubOAuthClientSecret
|
|
15155
15130
|
};
|
|
15156
15131
|
})() : undefined;
|
|
15157
15132
|
const enrolledPrivate = config.kind === "enrolled-compute" ? validateEnrolledComputeBootstrapSecrets(config, secrets) : undefined;
|
|
@@ -15252,9 +15227,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
15252
15227
|
const emailCredentialName = config.runtime.environment.email?.provider === "smtp" ? "fz_smtp.password" : config.runtime.environment.email?.provider === "jetemail" ? "fz_jetemail.apiKey" : undefined;
|
|
15253
15228
|
for (const [name, source] of Object.entries({
|
|
15254
15229
|
...emailCredentialName ? { [emailCredentialName]: platformPrivate.email } : {},
|
|
15255
|
-
"
|
|
15256
|
-
"fz_github.privateKey": platformPrivate.githubPrivateKey,
|
|
15257
|
-
"fz_github.webhookSecret": platformPrivate.githubWebhookSecret,
|
|
15230
|
+
"fz_oauth.github.clientSecret": platformPrivate.githubOAuthClientSecret,
|
|
15258
15231
|
"backup.s3.secretAccessKey": platformPrivate.backup
|
|
15259
15232
|
})) {
|
|
15260
15233
|
if (source) {
|
|
@@ -15271,7 +15244,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
15271
15244
|
const credentials = platformApiCredentialSpecs({
|
|
15272
15245
|
emailProvider: runtime.environment.email?.provider,
|
|
15273
15246
|
cloudflareKv: cloudflareConfigured,
|
|
15274
|
-
|
|
15247
|
+
githubOAuth: true,
|
|
15275
15248
|
realtime: Boolean(runtime.environment.realtime)
|
|
15276
15249
|
});
|
|
15277
15250
|
const units = renderPlatformApiUnits({
|
|
@@ -15519,6 +15492,7 @@ function strictBootstrapDocument(value) {
|
|
|
15519
15492
|
"agentOtlpEndpoint",
|
|
15520
15493
|
"custodianEmail",
|
|
15521
15494
|
"email",
|
|
15495
|
+
"githubOAuth",
|
|
15522
15496
|
"deployProfile",
|
|
15523
15497
|
"otlpFlushIntervalMs",
|
|
15524
15498
|
"otlpTraceSampleRatio",
|
|
@@ -15529,6 +15503,7 @@ function strictBootstrapDocument(value) {
|
|
|
15529
15503
|
"databaseReadPreferredCoordinators"
|
|
15530
15504
|
], "runtime environment");
|
|
15531
15505
|
const environment = runtime.environment;
|
|
15506
|
+
exactKeys2(environment.githubOAuth, ["clientId"], "GitHub OAuth config");
|
|
15532
15507
|
if (environment.initialInventory !== undefined) {
|
|
15533
15508
|
const inventory = exactKeys2(environment.initialInventory, ["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"], "initial inventory");
|
|
15534
15509
|
if (inventory.metalIdentity !== undefined) {
|
|
@@ -18234,7 +18209,7 @@ function forgeZeroLaunchTemplate(profile, guests, bundle, owner) {
|
|
|
18234
18209
|
otlpTraceSampleRatio: 0.1,
|
|
18235
18210
|
custodianEmail: owner.custodianEmail,
|
|
18236
18211
|
email: owner.email,
|
|
18237
|
-
|
|
18212
|
+
githubOAuth: owner.githubOAuth,
|
|
18238
18213
|
deployProfile: profile.environment
|
|
18239
18214
|
},
|
|
18240
18215
|
serviceUser: "forgezero-api",
|
|
@@ -18594,16 +18569,6 @@ function planAppBuild(input) {
|
|
|
18594
18569
|
// src/platform-launch-env.ts
|
|
18595
18570
|
import { lstatSync as lstatSync10, readFileSync as readFileSync16 } from "fs";
|
|
18596
18571
|
import { resolve as resolve12 } from "path";
|
|
18597
|
-
var booleanValue = (values, name, fallback) => {
|
|
18598
|
-
const raw = values.get(name)?.trim().toLowerCase();
|
|
18599
|
-
if (raw === undefined || raw === "")
|
|
18600
|
-
return fallback;
|
|
18601
|
-
if (raw === "true")
|
|
18602
|
-
return true;
|
|
18603
|
-
if (raw === "false")
|
|
18604
|
-
return false;
|
|
18605
|
-
throw new Error(`${name} must be true or false`);
|
|
18606
|
-
};
|
|
18607
18572
|
function readPlatformLaunchEnvironment(path) {
|
|
18608
18573
|
const absolute2 = resolve12(path);
|
|
18609
18574
|
const stat2 = lstatSync10(absolute2);
|
|
@@ -18632,48 +18597,18 @@ function readPlatformLaunchEnvironment(path) {
|
|
|
18632
18597
|
throw new Error(`bootstrap secret environment is missing ${name}`);
|
|
18633
18598
|
return value;
|
|
18634
18599
|
};
|
|
18635
|
-
const
|
|
18636
|
-
|
|
18637
|
-
|
|
18638
|
-
|
|
18639
|
-
|
|
18640
|
-
throw new Error("FZ_SMTP_PORT must be an integer from 1 through 65535");
|
|
18641
|
-
}
|
|
18642
|
-
const githubEnabled = booleanValue(values, "FZ_GITHUB_ENABLED", false);
|
|
18643
|
-
const githubApp = githubEnabled ? {
|
|
18644
|
-
clientId: requiredValue("FZ_GITHUB_CLIENT_ID"),
|
|
18645
|
-
appId: requiredValue("FZ_GITHUB_APP_ID"),
|
|
18646
|
-
slug: requiredValue("FZ_GITHUB_APP_SLUG")
|
|
18647
|
-
} : undefined;
|
|
18648
|
-
const owner = provider === "jetemail" ? {
|
|
18649
|
-
custodianEmail: requiredValue("FZ_BOOTSTRAP_CUSTODIAN_EMAIL"),
|
|
18650
|
-
email: {
|
|
18651
|
-
provider,
|
|
18652
|
-
from: requiredValue("FZ_EMAIL_FROM"),
|
|
18653
|
-
eu: booleanValue(values, "FZ_JETEMAIL_EU", false)
|
|
18654
|
-
},
|
|
18655
|
-
...githubApp ? { githubApp } : {}
|
|
18656
|
-
} : {
|
|
18657
|
-
custodianEmail: requiredValue("FZ_BOOTSTRAP_CUSTODIAN_EMAIL"),
|
|
18658
|
-
email: {
|
|
18659
|
-
provider,
|
|
18660
|
-
from: requiredValue("FZ_EMAIL_FROM"),
|
|
18661
|
-
host: requiredValue("FZ_SMTP_HOST"),
|
|
18662
|
-
port: smtpPort,
|
|
18663
|
-
user: requiredValue("FZ_SMTP_USER")
|
|
18664
|
-
},
|
|
18665
|
-
...githubApp ? { githubApp } : {}
|
|
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
|
|
18666
18605
|
};
|
|
18667
18606
|
return {
|
|
18668
18607
|
owner,
|
|
18669
|
-
emailSecret: requiredValue(
|
|
18608
|
+
emailSecret: requiredValue("FZ_JETEMAIL_API_KEY"),
|
|
18670
18609
|
cloudflareTunnelToken: requiredValue("CF_TUNNEL_TOKEN"),
|
|
18671
18610
|
cloudflareApiToken: requiredValue("CF_API_TOKEN"),
|
|
18672
|
-
|
|
18673
|
-
githubClientSecret: requiredValue("FZ_GITHUB_CLIENT_SECRET"),
|
|
18674
|
-
githubPrivateKeyBase64: requiredValue("FZ_GITHUB_PRIVATE_KEY_BASE64"),
|
|
18675
|
-
githubWebhookSecret: requiredValue("FZ_GITHUB_WEBHOOK_SECRET")
|
|
18676
|
-
} : {}
|
|
18611
|
+
githubOAuthClientSecret: requiredValue("FZ_GITHUB_OAUTH_CLIENT_SECRET")
|
|
18677
18612
|
};
|
|
18678
18613
|
}
|
|
18679
18614
|
|
|
@@ -19498,11 +19433,7 @@ async function promptPlatformBootstrapSecrets(config, generatedClusterBootstrapC
|
|
|
19498
19433
|
cloudflareTunnelToken: await bootstrapSecret("CF_TUNNEL_TOKEN"),
|
|
19499
19434
|
cloudflareApiToken: await bootstrapSecret("CF_API_TOKEN")
|
|
19500
19435
|
} : {},
|
|
19501
|
-
|
|
19502
|
-
githubClientSecret: await bootstrapSecret("GitHub App client secret"),
|
|
19503
|
-
githubPrivateKeyBase64: await bootstrapSecret("GitHub App RSA private key (base64)"),
|
|
19504
|
-
githubWebhookSecret: await bootstrapSecret("GitHub App webhook secret")
|
|
19505
|
-
} : {}
|
|
19436
|
+
githubOAuthClientSecret: await bootstrapSecret("GitHub OAuth client secret")
|
|
19506
19437
|
});
|
|
19507
19438
|
}
|
|
19508
19439
|
var bootstrapList = (question, fallback) => bootstrapAnswer(question, fallback).split(",").map((value) => value.trim()).filter(Boolean);
|
|
@@ -19800,34 +19731,11 @@ function selectedForgeZeroLaunchEnvironment(value) {
|
|
|
19800
19731
|
return value;
|
|
19801
19732
|
}
|
|
19802
19733
|
function forgeZeroLaunchOwnerInput() {
|
|
19803
|
-
const
|
|
19804
|
-
const provider = bootstrapAnswer("Bootstrap email provider (smtp/jetemail)", "jetemail");
|
|
19805
|
-
if (provider !== "smtp" && provider !== "jetemail") {
|
|
19806
|
-
throw new Error("Bootstrap email provider must be smtp or jetemail");
|
|
19807
|
-
}
|
|
19808
|
-
const from = bootstrapAnswer("Bootstrap email From address");
|
|
19809
|
-
const githubApp = bootstrapBoolean("Configure the platform GitHub App now?", "no") ? {
|
|
19810
|
-
clientId: bootstrapAnswer("GitHub App client ID"),
|
|
19811
|
-
appId: bootstrapAnswer("GitHub App ID"),
|
|
19812
|
-
slug: bootstrapAnswer("GitHub App slug")
|
|
19813
|
-
} : undefined;
|
|
19814
|
-
if (provider === "jetemail") {
|
|
19815
|
-
return {
|
|
19816
|
-
custodianEmail,
|
|
19817
|
-
email: { provider, from, eu: bootstrapBoolean("Use JetEmail EU processing?", "no") },
|
|
19818
|
-
...githubApp ? { githubApp } : {}
|
|
19819
|
-
};
|
|
19820
|
-
}
|
|
19734
|
+
const githubOAuth = { clientId: bootstrapAnswer("GitHub OAuth client ID") };
|
|
19821
19735
|
return {
|
|
19822
|
-
custodianEmail,
|
|
19823
|
-
email: {
|
|
19824
|
-
|
|
19825
|
-
from,
|
|
19826
|
-
host: bootstrapAnswer("SMTP host"),
|
|
19827
|
-
port: bootstrapNumber("SMTP port", "587"),
|
|
19828
|
-
user: bootstrapAnswer("SMTP user")
|
|
19829
|
-
},
|
|
19830
|
-
...githubApp ? { githubApp } : {}
|
|
19736
|
+
custodianEmail: "info@axxra.in",
|
|
19737
|
+
email: { provider: "jetemail", from: "noreply@forgezero.net", eu: false },
|
|
19738
|
+
githubOAuth
|
|
19831
19739
|
};
|
|
19832
19740
|
}
|
|
19833
19741
|
async function prepareForgeZeroPlatformLaunch(environment, outputDirectory, projectRoot, owner) {
|
|
@@ -19896,6 +19804,7 @@ function interactiveBootstrap(kind, genesisGuests, genesisCloudflareCheckpoint)
|
|
|
19896
19804
|
const backupRegion = backupEndpoint ? bootstrapAnswer("Backup S3 region") : undefined;
|
|
19897
19805
|
const backupBucket = backupEndpoint ? bootstrapAnswer("Backup S3 bucket") : undefined;
|
|
19898
19806
|
const backupAccessKeyId = backupEndpoint ? bootstrapAnswer("Backup S3 access-key id") : undefined;
|
|
19807
|
+
const githubOAuthClientId = bootstrapAnswer("GitHub OAuth client ID");
|
|
19899
19808
|
const cloudflareHandoffFile = genesis ? cloudflareHostHandoffPath(genesisCloudflareCheckpoint, computeReference) : bootstrapAnswer("Node-specific Cloudflare host handoff (blank for no public edge)", "");
|
|
19900
19809
|
const cloudflareNodeName = cloudflareHandoffFile ? genesis ? computeReference : bootstrapAnswer("Cloudflare handoff node name", computeReference) : undefined;
|
|
19901
19810
|
const databaseNetworkMode = "private-lan";
|
|
@@ -19950,6 +19859,7 @@ function interactiveBootstrap(kind, genesisGuests, genesisCloudflareCheckpoint)
|
|
|
19950
19859
|
otlpTraceSampleRatio: 0.1,
|
|
19951
19860
|
custodianEmail: role === "master" ? bootstrapAnswer("First custodian email") : undefined,
|
|
19952
19861
|
email: emailProvider === "smtp" ? { provider: "smtp", host: smtpHost, port: smtpPort, user: smtpUser, from: emailFrom } : { provider: "jetemail", from: emailFrom, eu: jetemailEu },
|
|
19862
|
+
githubOAuth: { clientId: githubOAuthClientId },
|
|
19953
19863
|
...backupEndpoint && backupRegion && backupBucket && backupAccessKeyId ? {
|
|
19954
19864
|
backup: { endpoint: backupEndpoint, region: backupRegion, bucket: backupBucket, accessKeyId: backupAccessKeyId }
|
|
19955
19865
|
} : {},
|
|
@@ -20010,11 +19920,7 @@ async function runAttendedPlatformFleet(fleet, apply, generatedClusterBootstrapC
|
|
|
20010
19920
|
emailSecret: environmentInput.emailSecret,
|
|
20011
19921
|
cloudflareTunnelToken: environmentInput.cloudflareTunnelToken,
|
|
20012
19922
|
cloudflareApiToken: environmentInput.cloudflareApiToken,
|
|
20013
|
-
|
|
20014
|
-
githubClientSecret: environmentInput.githubClientSecret,
|
|
20015
|
-
githubPrivateKeyBase64: environmentInput.githubPrivateKeyBase64,
|
|
20016
|
-
githubWebhookSecret: environmentInput.githubWebhookSecret
|
|
20017
|
-
} : {}
|
|
19923
|
+
githubOAuthClientSecret: environmentInput.githubOAuthClientSecret
|
|
20018
19924
|
}) : await promptPlatformBootstrapSecrets(firstConfig, generatedClusterBootstrapCode);
|
|
20019
19925
|
const cloudflare = await resolveCloudflareBootstrapCommandConfig(fleet.cloudflareConfigFile, {
|
|
20020
19926
|
tunnelToken: secrets.cloudflareTunnelToken,
|
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";
|
|
@@ -1426,7 +1426,7 @@ async function refreshBootstrapBundle(input, exec = run) {
|
|
|
1426
1426
|
}
|
|
1427
1427
|
|
|
1428
1428
|
// src/bootstrap.ts
|
|
1429
|
-
import { createHash as createHash2, createHmac as createHmac2,
|
|
1429
|
+
import { createHash as createHash2, createHmac as createHmac2, randomBytes as randomBytes3 } from "crypto";
|
|
1430
1430
|
import {
|
|
1431
1431
|
chmodSync as chmodSync3,
|
|
1432
1432
|
existsSync as existsSync5,
|
|
@@ -1460,7 +1460,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
|
|
|
1460
1460
|
var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
|
|
1461
1461
|
|
|
1462
1462
|
// src/version.ts
|
|
1463
|
-
var VERSION = "0.1.
|
|
1463
|
+
var VERSION = "0.1.108";
|
|
1464
1464
|
|
|
1465
1465
|
// src/software.ts
|
|
1466
1466
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -3228,10 +3228,8 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
3228
3228
|
} else if (input.email !== undefined) {
|
|
3229
3229
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
3230
3230
|
}
|
|
3231
|
-
if (input.
|
|
3232
|
-
|
|
3233
|
-
throw new Error("GitHub App client id, app id or slug is malformed.");
|
|
3234
|
-
}
|
|
3231
|
+
if (!input.githubOAuth || !/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubOAuth.clientId)) {
|
|
3232
|
+
throw new Error("GitHub OAuth client id is malformed.");
|
|
3235
3233
|
}
|
|
3236
3234
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
3237
3235
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
@@ -3363,9 +3361,7 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
3363
3361
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
3364
3362
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
3365
3363
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
3366
|
-
|
|
3367
|
-
FZ_GITHUB_APP_ID: value.githubApp?.appId ?? "",
|
|
3368
|
-
FZ_GITHUB_APP_SLUG: value.githubApp?.slug ?? "",
|
|
3364
|
+
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
3369
3365
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
3370
3366
|
};
|
|
3371
3367
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -3377,9 +3373,7 @@ function platformApiCredentialSpecs(options) {
|
|
|
3377
3373
|
const optional = [
|
|
3378
3374
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
3379
3375
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
3380
|
-
["
|
|
3381
|
-
["fz_github.privateKey", options.githubApp],
|
|
3382
|
-
["fz_github.webhookSecret", options.githubApp],
|
|
3376
|
+
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
3383
3377
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
3384
3378
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
3385
3379
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -3783,9 +3777,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3783
3777
|
"backupS3Secret",
|
|
3784
3778
|
"cloudflareTunnelToken",
|
|
3785
3779
|
"cloudflareApiToken",
|
|
3786
|
-
"
|
|
3787
|
-
"githubPrivateKeyBase64",
|
|
3788
|
-
"githubWebhookSecret"
|
|
3780
|
+
"githubOAuthClientSecret"
|
|
3789
3781
|
];
|
|
3790
3782
|
const unknown = Object.keys(source).filter((key) => !allowed.includes(key));
|
|
3791
3783
|
if (unknown.length)
|
|
@@ -3796,9 +3788,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3796
3788
|
const backupS3Secret = typeof source.backupS3Secret === "string" ? source.backupS3Secret.trim() : undefined;
|
|
3797
3789
|
const cloudflareTunnelToken = typeof source.cloudflareTunnelToken === "string" ? source.cloudflareTunnelToken.trim() : undefined;
|
|
3798
3790
|
const cloudflareApiToken = typeof source.cloudflareApiToken === "string" ? source.cloudflareApiToken.trim() : undefined;
|
|
3799
|
-
const
|
|
3800
|
-
const githubPrivateKeyBase64 = typeof source.githubPrivateKeyBase64 === "string" ? source.githubPrivateKeyBase64.trim() : undefined;
|
|
3801
|
-
const githubWebhookSecret = typeof source.githubWebhookSecret === "string" ? source.githubWebhookSecret.trim() : undefined;
|
|
3791
|
+
const githubOAuthClientSecret = typeof source.githubOAuthClientSecret === "string" ? source.githubOAuthClientSecret.trim() : "";
|
|
3802
3792
|
if (!/^[a-f0-9]{64}$/i.test(clusterBootstrapCode))
|
|
3803
3793
|
throw new Error("cluster bootstrap code must contain exactly 64 hexadecimal characters");
|
|
3804
3794
|
if (!emailSecret || emailSecret.length > 16384 || /[\r\n\0]/.test(emailSecret))
|
|
@@ -3818,21 +3808,8 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3818
3808
|
}
|
|
3819
3809
|
if (cloudflareTunnelToken)
|
|
3820
3810
|
validateCloudflareBootstrapSecretPair({ cloudflareTunnelToken, cloudflareApiToken });
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
throw new Error("GitHub App coordinates require client secret, private key and webhook secret together");
|
|
3824
|
-
}
|
|
3825
|
-
if (githubConfigured) {
|
|
3826
|
-
if (githubClientSecret.length < 20 || githubClientSecret.length > 512 || /[\r\n\0]/.test(githubClientSecret) || githubWebhookSecret.length < 32 || githubWebhookSecret.length > 512 || /[\r\n\0]/.test(githubWebhookSecret)) {
|
|
3827
|
-
throw new Error("GitHub App client or webhook secret is malformed");
|
|
3828
|
-
}
|
|
3829
|
-
try {
|
|
3830
|
-
const pem = Buffer.from(githubPrivateKeyBase64, "base64").toString("utf8");
|
|
3831
|
-
if (createPrivateKey(pem).asymmetricKeyType !== "rsa")
|
|
3832
|
-
throw new Error("not RSA");
|
|
3833
|
-
} catch {
|
|
3834
|
-
throw new Error("GitHub App private key must be a base64-encoded RSA private key");
|
|
3835
|
-
}
|
|
3811
|
+
if (githubOAuthClientSecret.length < 20 || githubOAuthClientSecret.length > 512 || /[\r\n\0]/.test(githubOAuthClientSecret)) {
|
|
3812
|
+
throw new Error("GitHub OAuth client secret is malformed");
|
|
3836
3813
|
}
|
|
3837
3814
|
return {
|
|
3838
3815
|
clusterBootstrapCode,
|
|
@@ -3840,7 +3817,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3840
3817
|
...enrolmentToken ? { enrolmentToken } : {},
|
|
3841
3818
|
...backupS3Secret ? { backupS3Secret } : {},
|
|
3842
3819
|
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {},
|
|
3843
|
-
|
|
3820
|
+
githubOAuthClientSecret
|
|
3844
3821
|
};
|
|
3845
3822
|
}
|
|
3846
3823
|
var platformBootstrapRunner = (config) => config.kind === "platform" && config.database.role === "master";
|
|
@@ -4764,9 +4741,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4764
4741
|
backup: checked4.backupS3Secret,
|
|
4765
4742
|
cloudflareTunnelToken: checked4.cloudflareTunnelToken,
|
|
4766
4743
|
cloudflareApiToken: checked4.cloudflareApiToken,
|
|
4767
|
-
|
|
4768
|
-
githubPrivateKey: checked4.githubPrivateKeyBase64 ? Buffer.from(checked4.githubPrivateKeyBase64, "base64").toString("utf8") : undefined,
|
|
4769
|
-
githubWebhookSecret: checked4.githubWebhookSecret
|
|
4744
|
+
githubOAuthClientSecret: checked4.githubOAuthClientSecret
|
|
4770
4745
|
};
|
|
4771
4746
|
})() : undefined;
|
|
4772
4747
|
const enrolledPrivate = config.kind === "enrolled-compute" ? validateEnrolledComputeBootstrapSecrets(config, secrets) : undefined;
|
|
@@ -4867,9 +4842,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4867
4842
|
const emailCredentialName = config.runtime.environment.email?.provider === "smtp" ? "fz_smtp.password" : config.runtime.environment.email?.provider === "jetemail" ? "fz_jetemail.apiKey" : undefined;
|
|
4868
4843
|
for (const [name, source] of Object.entries({
|
|
4869
4844
|
...emailCredentialName ? { [emailCredentialName]: platformPrivate.email } : {},
|
|
4870
|
-
"
|
|
4871
|
-
"fz_github.privateKey": platformPrivate.githubPrivateKey,
|
|
4872
|
-
"fz_github.webhookSecret": platformPrivate.githubWebhookSecret,
|
|
4845
|
+
"fz_oauth.github.clientSecret": platformPrivate.githubOAuthClientSecret,
|
|
4873
4846
|
"backup.s3.secretAccessKey": platformPrivate.backup
|
|
4874
4847
|
})) {
|
|
4875
4848
|
if (source) {
|
|
@@ -4886,7 +4859,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4886
4859
|
const credentials = platformApiCredentialSpecs({
|
|
4887
4860
|
emailProvider: runtime.environment.email?.provider,
|
|
4888
4861
|
cloudflareKv: cloudflareConfigured,
|
|
4889
|
-
|
|
4862
|
+
githubOAuth: true,
|
|
4890
4863
|
realtime: Boolean(runtime.environment.realtime)
|
|
4891
4864
|
});
|
|
4892
4865
|
const units = renderPlatformApiUnits({
|
|
@@ -5134,6 +5107,7 @@ function strictBootstrapDocument(value) {
|
|
|
5134
5107
|
"agentOtlpEndpoint",
|
|
5135
5108
|
"custodianEmail",
|
|
5136
5109
|
"email",
|
|
5110
|
+
"githubOAuth",
|
|
5137
5111
|
"deployProfile",
|
|
5138
5112
|
"otlpFlushIntervalMs",
|
|
5139
5113
|
"otlpTraceSampleRatio",
|
|
@@ -5144,6 +5118,7 @@ function strictBootstrapDocument(value) {
|
|
|
5144
5118
|
"databaseReadPreferredCoordinators"
|
|
5145
5119
|
], "runtime environment");
|
|
5146
5120
|
const environment = runtime.environment;
|
|
5121
|
+
exactKeys(environment.githubOAuth, ["clientId"], "GitHub OAuth config");
|
|
5147
5122
|
if (environment.initialInventory !== undefined) {
|
|
5148
5123
|
const inventory = exactKeys(environment.initialInventory, ["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"], "initial inventory");
|
|
5149
5124
|
if (inventory.metalIdentity !== undefined) {
|
|
@@ -73,10 +73,8 @@ export type PlatformBootstrapEmail = {
|
|
|
73
73
|
* webhook secret are attended inputs sealed as systemd credentials and later
|
|
74
74
|
* imported into the unlocked platform Vault.
|
|
75
75
|
*/
|
|
76
|
-
export interface
|
|
76
|
+
export interface PlatformBootstrapGitHubOAuth {
|
|
77
77
|
clientId: string;
|
|
78
|
-
appId: string;
|
|
79
|
-
slug: string;
|
|
80
78
|
}
|
|
81
79
|
export interface PlatformSharedEnvironment {
|
|
82
80
|
softwareProfile: PlatformSoftwareProfile;
|
|
@@ -109,7 +107,7 @@ export interface PlatformSharedEnvironment {
|
|
|
109
107
|
otlpTraceSampleRatio: number;
|
|
110
108
|
custodianEmail?: string;
|
|
111
109
|
email?: PlatformBootstrapEmail;
|
|
112
|
-
|
|
110
|
+
githubOAuth: PlatformBootstrapGitHubOAuth;
|
|
113
111
|
backup?: {
|
|
114
112
|
endpoint: string;
|
|
115
113
|
region: string;
|
|
@@ -137,13 +135,13 @@ export declare function validatePlatformSharedEnvironment(input: PlatformSharedE
|
|
|
137
135
|
/** Render only non-secret runtime coordinates. Passwords/tokens have no field in this contract. */
|
|
138
136
|
export declare function renderPlatformSharedEnvironment(input: PlatformSharedEnvironment): string;
|
|
139
137
|
export interface SystemdCredentialSpec {
|
|
140
|
-
name: 'arangodb-jwt' | 'arangodb-root-password' | 'seed-sync-root' | 'fz_smtp.password' | 'fz_jetemail.apiKey' | '
|
|
138
|
+
name: 'arangodb-jwt' | 'arangodb-root-password' | 'seed-sync-root' | 'fz_smtp.password' | 'fz_jetemail.apiKey' | 'fz_oauth.github.clientSecret' | 'CF_API_TOKEN' | 'CF_TUNNEL_TOKEN' | 'REALTIME_PUBLISH_SECRET' | 'REALTIME_TICKET_SECRET';
|
|
141
139
|
encryptedPath: string;
|
|
142
140
|
required: boolean;
|
|
143
141
|
}
|
|
144
142
|
export declare function platformApiCredentialSpecs(options: {
|
|
145
143
|
emailProvider?: PlatformBootstrapEmail['provider'];
|
|
146
|
-
|
|
144
|
+
githubOAuth: boolean;
|
|
147
145
|
cloudflareKv: boolean;
|
|
148
146
|
realtime: boolean;
|
|
149
147
|
}): SystemdCredentialSpec[];
|
|
@@ -828,10 +828,8 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
828
828
|
} else if (input.email !== undefined) {
|
|
829
829
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
830
830
|
}
|
|
831
|
-
if (input.
|
|
832
|
-
|
|
833
|
-
throw new Error("GitHub App client id, app id or slug is malformed.");
|
|
834
|
-
}
|
|
831
|
+
if (!input.githubOAuth || !/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubOAuth.clientId)) {
|
|
832
|
+
throw new Error("GitHub OAuth client id is malformed.");
|
|
835
833
|
}
|
|
836
834
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
837
835
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
@@ -963,9 +961,7 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
963
961
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
964
962
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
965
963
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
966
|
-
|
|
967
|
-
FZ_GITHUB_APP_ID: value.githubApp?.appId ?? "",
|
|
968
|
-
FZ_GITHUB_APP_SLUG: value.githubApp?.slug ?? "",
|
|
964
|
+
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
969
965
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
970
966
|
};
|
|
971
967
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -977,9 +973,7 @@ function platformApiCredentialSpecs(options) {
|
|
|
977
973
|
const optional = [
|
|
978
974
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
979
975
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
980
|
-
["
|
|
981
|
-
["fz_github.privateKey", options.githubApp],
|
|
982
|
-
["fz_github.webhookSecret", options.githubApp],
|
|
976
|
+
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
983
977
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
984
978
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
985
979
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -3004,7 +3004,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
|
|
|
3004
3004
|
}
|
|
3005
3005
|
|
|
3006
3006
|
// src/version.ts
|
|
3007
|
-
var VERSION3 = "0.1.
|
|
3007
|
+
var VERSION3 = "0.1.108";
|
|
3008
3008
|
|
|
3009
3009
|
// src/egress-policy.ts
|
|
3010
3010
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
@@ -4336,10 +4336,8 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
4336
4336
|
} else if (input.email !== undefined) {
|
|
4337
4337
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
4338
4338
|
}
|
|
4339
|
-
if (input.
|
|
4340
|
-
|
|
4341
|
-
throw new Error("GitHub App client id, app id or slug is malformed.");
|
|
4342
|
-
}
|
|
4339
|
+
if (!input.githubOAuth || !/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubOAuth.clientId)) {
|
|
4340
|
+
throw new Error("GitHub OAuth client id is malformed.");
|
|
4343
4341
|
}
|
|
4344
4342
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
4345
4343
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
@@ -4471,9 +4469,7 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
4471
4469
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
4472
4470
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
4473
4471
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
4474
|
-
|
|
4475
|
-
FZ_GITHUB_APP_ID: value.githubApp?.appId ?? "",
|
|
4476
|
-
FZ_GITHUB_APP_SLUG: value.githubApp?.slug ?? "",
|
|
4472
|
+
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
4477
4473
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
4478
4474
|
};
|
|
4479
4475
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -4485,9 +4481,7 @@ function platformApiCredentialSpecs(options) {
|
|
|
4485
4481
|
const optional = [
|
|
4486
4482
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
4487
4483
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
4488
|
-
["
|
|
4489
|
-
["fz_github.privateKey", options.githubApp],
|
|
4490
|
-
["fz_github.webhookSecret", options.githubApp],
|
|
4484
|
+
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
4491
4485
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
4492
4486
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
4493
4487
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -4842,7 +4836,7 @@ function planLocalOtlpProof(endpoint, collectorUnit) {
|
|
|
4842
4836
|
import { lstatSync as lstatSync5 } from "node:fs";
|
|
4843
4837
|
|
|
4844
4838
|
// src/bootstrap.ts
|
|
4845
|
-
import { createHash as createHash7, createHmac as createHmac2,
|
|
4839
|
+
import { createHash as createHash7, createHmac as createHmac2, randomBytes as randomBytes3 } from "node:crypto";
|
|
4846
4840
|
import {
|
|
4847
4841
|
chmodSync as chmodSync9,
|
|
4848
4842
|
existsSync as existsSync11,
|
|
@@ -4,9 +4,7 @@ export interface PlatformLaunchEnvironmentInput {
|
|
|
4
4
|
emailSecret: string;
|
|
5
5
|
cloudflareTunnelToken: string;
|
|
6
6
|
cloudflareApiToken: string;
|
|
7
|
-
|
|
8
|
-
githubPrivateKeyBase64?: string;
|
|
9
|
-
githubWebhookSecret?: string;
|
|
7
|
+
githubOAuthClientSecret: string;
|
|
10
8
|
}
|
|
11
9
|
/**
|
|
12
10
|
* Read the development-only attended-launch adapter.
|
|
@@ -45,10 +45,9 @@ export interface ForgeZeroLaunchOwnerInput {
|
|
|
45
45
|
from: string;
|
|
46
46
|
eu: boolean;
|
|
47
47
|
};
|
|
48
|
-
|
|
48
|
+
/** Required bootstrap identity provider. Repository automation is configured after genesis. */
|
|
49
|
+
githubOAuth: {
|
|
49
50
|
clientId: string;
|
|
50
|
-
appId: string;
|
|
51
|
-
slug: string;
|
|
52
51
|
};
|
|
53
52
|
}
|
|
54
53
|
/**
|
package/dist/provision.js
CHANGED
|
@@ -3004,7 +3004,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
|
|
|
3004
3004
|
}
|
|
3005
3005
|
|
|
3006
3006
|
// src/version.ts
|
|
3007
|
-
var VERSION3 = "0.1.
|
|
3007
|
+
var VERSION3 = "0.1.108";
|
|
3008
3008
|
|
|
3009
3009
|
// src/egress-policy.ts
|
|
3010
3010
|
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.108";
|