@forgezero/agent 0.1.115 → 0.1.117
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/agent-heartbeat.js +1 -1
- package/dist/bootstrap.d.ts +1 -2
- package/dist/bootstrap.js +7 -27
- package/dist/fz-agent.js +1 -1
- package/dist/fz.js +35 -52
- package/dist/metal-bootstrap.js +1 -1
- package/dist/metal-provision.d.ts +1 -1
- package/dist/operator-bootstrap.d.ts +1 -1
- package/dist/operator-bootstrap.js +11 -31
- package/dist/platform-bootstrap-runtime.d.ts +1 -11
- package/dist/platform-bootstrap-runtime.js +3 -5
- package/dist/platform-fleet-verification.js +4 -6
- package/dist/platform-genesis.d.ts +2 -0
- package/dist/platform-genesis.js +4 -0
- package/dist/platform-launch-env.d.ts +0 -1
- package/dist/platform-launch-profile.d.ts +0 -4
- package/dist/provision.js +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -229,8 +229,8 @@ import {
|
|
|
229
229
|
ForgeZero,
|
|
230
230
|
} from '@forgezero/vault';
|
|
231
231
|
|
|
232
|
-
const fz = new ForgeZero({ project: '
|
|
233
|
-
await fz.get('
|
|
232
|
+
const fz = new ForgeZero({ project: 'payments-api', environment: 'production' });
|
|
233
|
+
await fz.get('PAYMENT_PROVIDER');
|
|
234
234
|
```
|
|
235
235
|
|
|
236
236
|
## A local copy, not a cache
|
package/dist/agent-heartbeat.js
CHANGED
package/dist/bootstrap.d.ts
CHANGED
|
@@ -89,7 +89,7 @@ export interface EnrolledComputeActivationConfig {
|
|
|
89
89
|
profile?: string;
|
|
90
90
|
deployRoot?: string;
|
|
91
91
|
software?: SoftwareRequirement[];
|
|
92
|
-
/** Compatibility-only per-node SSH deploy key
|
|
92
|
+
/** Compatibility-only per-node SSH deploy key for non-provider sources. */
|
|
93
93
|
gitDeployKey?: boolean;
|
|
94
94
|
installCloudflared?: boolean;
|
|
95
95
|
installWarp?: boolean;
|
|
@@ -115,7 +115,6 @@ export interface PlatformBootstrapSecrets {
|
|
|
115
115
|
backupS3Secret?: string;
|
|
116
116
|
cloudflareTunnelToken?: string;
|
|
117
117
|
cloudflareApiToken?: string;
|
|
118
|
-
githubOAuthClientSecret: string;
|
|
119
118
|
}
|
|
120
119
|
export interface EnrolledComputeBootstrapSecrets {
|
|
121
120
|
enrolmentToken: string;
|
package/dist/bootstrap.js
CHANGED
|
@@ -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.117";
|
|
1464
1464
|
|
|
1465
1465
|
// src/software.ts
|
|
1466
1466
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -3127,6 +3127,9 @@ function platformGenesisClaims(guests, sshPublicKeys) {
|
|
|
3127
3127
|
throw new Error("platform genesis requires at least one operator SSH public key");
|
|
3128
3128
|
return reviewed.map((guest) => claimFor(guest, keys, "create"));
|
|
3129
3129
|
}
|
|
3130
|
+
function platformGenesisDeletionClaims(guests) {
|
|
3131
|
+
return validatePlatformGenesisGuests(guests).map((guest) => claimFor(guest, [], "delete"));
|
|
3132
|
+
}
|
|
3130
3133
|
function platformCommunityRehearsalClaims(seedGuests, rehearsalGuest, sshPublicKeys) {
|
|
3131
3134
|
const reviewed = validatePlatformGenesisGuests([...seedGuests, rehearsalGuest], 4);
|
|
3132
3135
|
const keys = [...new Set(sshPublicKeys.map(publicKey))];
|
|
@@ -3269,9 +3272,6 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
3269
3272
|
} else if (input.email !== undefined) {
|
|
3270
3273
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
3271
3274
|
}
|
|
3272
|
-
if (!input.githubOAuth || !/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubOAuth.clientId)) {
|
|
3273
|
-
throw new Error("GitHub OAuth client id is malformed.");
|
|
3274
|
-
}
|
|
3275
3275
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
3276
3276
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
3277
3277
|
throw new Error("seedSyncMembers must contain 3 to 64 unique physical host identities.");
|
|
@@ -3402,7 +3402,6 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
3402
3402
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
3403
3403
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
3404
3404
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
3405
|
-
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
3406
3405
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
3407
3406
|
};
|
|
3408
3407
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -3414,7 +3413,6 @@ function platformApiCredentialSpecs(options) {
|
|
|
3414
3413
|
const optional = [
|
|
3415
3414
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
3416
3415
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
3417
|
-
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
3418
3416
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
3419
3417
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
3420
3418
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -3811,15 +3809,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3811
3809
|
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
3812
3810
|
throw new Error("bootstrap credential input must be an object");
|
|
3813
3811
|
const source = input;
|
|
3814
|
-
const allowed = [
|
|
3815
|
-
"clusterBootstrapCode",
|
|
3816
|
-
"emailSecret",
|
|
3817
|
-
"enrolmentToken",
|
|
3818
|
-
"backupS3Secret",
|
|
3819
|
-
"cloudflareTunnelToken",
|
|
3820
|
-
"cloudflareApiToken",
|
|
3821
|
-
"githubOAuthClientSecret"
|
|
3822
|
-
];
|
|
3812
|
+
const allowed = ["clusterBootstrapCode", "emailSecret", "enrolmentToken", "backupS3Secret", "cloudflareTunnelToken", "cloudflareApiToken"];
|
|
3823
3813
|
const unknown = Object.keys(source).filter((key) => !allowed.includes(key));
|
|
3824
3814
|
if (unknown.length)
|
|
3825
3815
|
throw new Error(`bootstrap credential input contains unsupported field ${unknown[0]}`);
|
|
@@ -3829,7 +3819,6 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3829
3819
|
const backupS3Secret = typeof source.backupS3Secret === "string" ? source.backupS3Secret.trim() : undefined;
|
|
3830
3820
|
const cloudflareTunnelToken = typeof source.cloudflareTunnelToken === "string" ? source.cloudflareTunnelToken.trim() : undefined;
|
|
3831
3821
|
const cloudflareApiToken = typeof source.cloudflareApiToken === "string" ? source.cloudflareApiToken.trim() : undefined;
|
|
3832
|
-
const githubOAuthClientSecret = typeof source.githubOAuthClientSecret === "string" ? source.githubOAuthClientSecret.trim() : "";
|
|
3833
3822
|
if (!/^[a-f0-9]{64}$/i.test(clusterBootstrapCode))
|
|
3834
3823
|
throw new Error("cluster bootstrap code must contain exactly 64 hexadecimal characters");
|
|
3835
3824
|
if (!emailSecret || emailSecret.length > 16384 || /[\r\n\0]/.test(emailSecret))
|
|
@@ -3849,16 +3838,12 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3849
3838
|
}
|
|
3850
3839
|
if (cloudflareTunnelToken)
|
|
3851
3840
|
validateCloudflareBootstrapSecretPair({ cloudflareTunnelToken, cloudflareApiToken });
|
|
3852
|
-
if (githubOAuthClientSecret.length < 20 || githubOAuthClientSecret.length > 512 || /[\r\n\0]/.test(githubOAuthClientSecret)) {
|
|
3853
|
-
throw new Error("GitHub OAuth client secret is malformed");
|
|
3854
|
-
}
|
|
3855
3841
|
return {
|
|
3856
3842
|
clusterBootstrapCode,
|
|
3857
3843
|
emailSecret,
|
|
3858
3844
|
...enrolmentToken ? { enrolmentToken } : {},
|
|
3859
3845
|
...backupS3Secret ? { backupS3Secret } : {},
|
|
3860
|
-
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {}
|
|
3861
|
-
githubOAuthClientSecret
|
|
3846
|
+
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {}
|
|
3862
3847
|
};
|
|
3863
3848
|
}
|
|
3864
3849
|
var platformBootstrapRunner = (config) => config.kind === "platform" && config.database.role === "master";
|
|
@@ -4781,8 +4766,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4781
4766
|
enrolmentToken: checked4.enrolmentToken,
|
|
4782
4767
|
backup: checked4.backupS3Secret,
|
|
4783
4768
|
cloudflareTunnelToken: checked4.cloudflareTunnelToken,
|
|
4784
|
-
cloudflareApiToken: checked4.cloudflareApiToken
|
|
4785
|
-
githubOAuthClientSecret: checked4.githubOAuthClientSecret
|
|
4769
|
+
cloudflareApiToken: checked4.cloudflareApiToken
|
|
4786
4770
|
};
|
|
4787
4771
|
})() : undefined;
|
|
4788
4772
|
const enrolledPrivate = config.kind === "enrolled-compute" ? validateEnrolledComputeBootstrapSecrets(config, secrets) : undefined;
|
|
@@ -4883,7 +4867,6 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4883
4867
|
const emailCredentialName = config.runtime.environment.email?.provider === "smtp" ? "fz_smtp.password" : config.runtime.environment.email?.provider === "jetemail" ? "fz_jetemail.apiKey" : undefined;
|
|
4884
4868
|
for (const [name, source] of Object.entries({
|
|
4885
4869
|
...emailCredentialName ? { [emailCredentialName]: platformPrivate.email } : {},
|
|
4886
|
-
"fz_oauth.github.clientSecret": platformPrivate.githubOAuthClientSecret,
|
|
4887
4870
|
"backup.s3.secretAccessKey": platformPrivate.backup
|
|
4888
4871
|
})) {
|
|
4889
4872
|
if (source) {
|
|
@@ -4900,7 +4883,6 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4900
4883
|
const credentials = platformApiCredentialSpecs({
|
|
4901
4884
|
emailProvider: runtime.environment.email?.provider,
|
|
4902
4885
|
cloudflareKv: cloudflareConfigured,
|
|
4903
|
-
githubOAuth: true,
|
|
4904
4886
|
realtime: Boolean(runtime.environment.realtime)
|
|
4905
4887
|
});
|
|
4906
4888
|
const units = renderPlatformApiUnits({
|
|
@@ -5148,7 +5130,6 @@ function strictBootstrapDocument(value) {
|
|
|
5148
5130
|
"agentOtlpEndpoint",
|
|
5149
5131
|
"custodianEmail",
|
|
5150
5132
|
"email",
|
|
5151
|
-
"githubOAuth",
|
|
5152
5133
|
"deployProfile",
|
|
5153
5134
|
"otlpFlushIntervalMs",
|
|
5154
5135
|
"otlpTraceSampleRatio",
|
|
@@ -5159,7 +5140,6 @@ function strictBootstrapDocument(value) {
|
|
|
5159
5140
|
"databaseReadPreferredCoordinators"
|
|
5160
5141
|
], "runtime environment");
|
|
5161
5142
|
const environment = runtime.environment;
|
|
5162
|
-
exactKeys(environment.githubOAuth, ["clientId"], "GitHub OAuth config");
|
|
5163
5143
|
if (environment.initialInventory !== undefined) {
|
|
5164
5144
|
const inventory = exactKeys(environment.initialInventory, ["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"], "initial inventory");
|
|
5165
5145
|
if (inventory.metalIdentity !== undefined) {
|
package/dist/fz-agent.js
CHANGED
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.21";
|
|
4638
4638
|
var init_dist = __esm(() => {
|
|
4639
4639
|
init_identity();
|
|
4640
4640
|
VaultError = class VaultError extends Error {
|
|
@@ -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.117";
|
|
4845
4845
|
|
|
4846
4846
|
// src/software.ts
|
|
4847
4847
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -12238,6 +12238,9 @@ function platformGenesisClaims(guests, sshPublicKeys) {
|
|
|
12238
12238
|
throw new Error("platform genesis requires at least one operator SSH public key");
|
|
12239
12239
|
return reviewed.map((guest) => claimFor(guest, keys, "create"));
|
|
12240
12240
|
}
|
|
12241
|
+
function platformGenesisDeletionClaims(guests) {
|
|
12242
|
+
return validatePlatformGenesisGuests(guests).map((guest) => claimFor(guest, [], "delete"));
|
|
12243
|
+
}
|
|
12241
12244
|
function platformCommunityRehearsalClaims(seedGuests, rehearsalGuest, sshPublicKeys) {
|
|
12242
12245
|
const reviewed = validatePlatformGenesisGuests([...seedGuests, rehearsalGuest], 4);
|
|
12243
12246
|
const keys = [...new Set(sshPublicKeys.map(publicKey))];
|
|
@@ -12380,9 +12383,6 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
12380
12383
|
} else if (input.email !== undefined) {
|
|
12381
12384
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
12382
12385
|
}
|
|
12383
|
-
if (!input.githubOAuth || !/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubOAuth.clientId)) {
|
|
12384
|
-
throw new Error("GitHub OAuth client id is malformed.");
|
|
12385
|
-
}
|
|
12386
12386
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
12387
12387
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
12388
12388
|
throw new Error("seedSyncMembers must contain 3 to 64 unique physical host identities.");
|
|
@@ -12513,7 +12513,6 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
12513
12513
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
12514
12514
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
12515
12515
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
12516
|
-
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
12517
12516
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
12518
12517
|
};
|
|
12519
12518
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -12525,7 +12524,6 @@ function platformApiCredentialSpecs(options) {
|
|
|
12525
12524
|
const optional = [
|
|
12526
12525
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
12527
12526
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
12528
|
-
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
12529
12527
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
12530
12528
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
12531
12529
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -14198,15 +14196,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14198
14196
|
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
14199
14197
|
throw new Error("bootstrap credential input must be an object");
|
|
14200
14198
|
const source = input;
|
|
14201
|
-
const allowed = [
|
|
14202
|
-
"clusterBootstrapCode",
|
|
14203
|
-
"emailSecret",
|
|
14204
|
-
"enrolmentToken",
|
|
14205
|
-
"backupS3Secret",
|
|
14206
|
-
"cloudflareTunnelToken",
|
|
14207
|
-
"cloudflareApiToken",
|
|
14208
|
-
"githubOAuthClientSecret"
|
|
14209
|
-
];
|
|
14199
|
+
const allowed = ["clusterBootstrapCode", "emailSecret", "enrolmentToken", "backupS3Secret", "cloudflareTunnelToken", "cloudflareApiToken"];
|
|
14210
14200
|
const unknown = Object.keys(source).filter((key) => !allowed.includes(key));
|
|
14211
14201
|
if (unknown.length)
|
|
14212
14202
|
throw new Error(`bootstrap credential input contains unsupported field ${unknown[0]}`);
|
|
@@ -14216,7 +14206,6 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14216
14206
|
const backupS3Secret = typeof source.backupS3Secret === "string" ? source.backupS3Secret.trim() : undefined;
|
|
14217
14207
|
const cloudflareTunnelToken = typeof source.cloudflareTunnelToken === "string" ? source.cloudflareTunnelToken.trim() : undefined;
|
|
14218
14208
|
const cloudflareApiToken = typeof source.cloudflareApiToken === "string" ? source.cloudflareApiToken.trim() : undefined;
|
|
14219
|
-
const githubOAuthClientSecret = typeof source.githubOAuthClientSecret === "string" ? source.githubOAuthClientSecret.trim() : "";
|
|
14220
14209
|
if (!/^[a-f0-9]{64}$/i.test(clusterBootstrapCode))
|
|
14221
14210
|
throw new Error("cluster bootstrap code must contain exactly 64 hexadecimal characters");
|
|
14222
14211
|
if (!emailSecret || emailSecret.length > 16384 || /[\r\n\0]/.test(emailSecret))
|
|
@@ -14236,16 +14225,12 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
14236
14225
|
}
|
|
14237
14226
|
if (cloudflareTunnelToken)
|
|
14238
14227
|
validateCloudflareBootstrapSecretPair({ cloudflareTunnelToken, cloudflareApiToken });
|
|
14239
|
-
if (githubOAuthClientSecret.length < 20 || githubOAuthClientSecret.length > 512 || /[\r\n\0]/.test(githubOAuthClientSecret)) {
|
|
14240
|
-
throw new Error("GitHub OAuth client secret is malformed");
|
|
14241
|
-
}
|
|
14242
14228
|
return {
|
|
14243
14229
|
clusterBootstrapCode,
|
|
14244
14230
|
emailSecret,
|
|
14245
14231
|
...enrolmentToken ? { enrolmentToken } : {},
|
|
14246
14232
|
...backupS3Secret ? { backupS3Secret } : {},
|
|
14247
|
-
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {}
|
|
14248
|
-
githubOAuthClientSecret
|
|
14233
|
+
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {}
|
|
14249
14234
|
};
|
|
14250
14235
|
}
|
|
14251
14236
|
var platformBootstrapRunner = (config) => config.kind === "platform" && config.database.role === "master";
|
|
@@ -15168,8 +15153,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
15168
15153
|
enrolmentToken: checked4.enrolmentToken,
|
|
15169
15154
|
backup: checked4.backupS3Secret,
|
|
15170
15155
|
cloudflareTunnelToken: checked4.cloudflareTunnelToken,
|
|
15171
|
-
cloudflareApiToken: checked4.cloudflareApiToken
|
|
15172
|
-
githubOAuthClientSecret: checked4.githubOAuthClientSecret
|
|
15156
|
+
cloudflareApiToken: checked4.cloudflareApiToken
|
|
15173
15157
|
};
|
|
15174
15158
|
})() : undefined;
|
|
15175
15159
|
const enrolledPrivate = config.kind === "enrolled-compute" ? validateEnrolledComputeBootstrapSecrets(config, secrets) : undefined;
|
|
@@ -15270,7 +15254,6 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
15270
15254
|
const emailCredentialName = config.runtime.environment.email?.provider === "smtp" ? "fz_smtp.password" : config.runtime.environment.email?.provider === "jetemail" ? "fz_jetemail.apiKey" : undefined;
|
|
15271
15255
|
for (const [name, source] of Object.entries({
|
|
15272
15256
|
...emailCredentialName ? { [emailCredentialName]: platformPrivate.email } : {},
|
|
15273
|
-
"fz_oauth.github.clientSecret": platformPrivate.githubOAuthClientSecret,
|
|
15274
15257
|
"backup.s3.secretAccessKey": platformPrivate.backup
|
|
15275
15258
|
})) {
|
|
15276
15259
|
if (source) {
|
|
@@ -15287,7 +15270,6 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
15287
15270
|
const credentials = platformApiCredentialSpecs({
|
|
15288
15271
|
emailProvider: runtime.environment.email?.provider,
|
|
15289
15272
|
cloudflareKv: cloudflareConfigured,
|
|
15290
|
-
githubOAuth: true,
|
|
15291
15273
|
realtime: Boolean(runtime.environment.realtime)
|
|
15292
15274
|
});
|
|
15293
15275
|
const units = renderPlatformApiUnits({
|
|
@@ -15535,7 +15517,6 @@ function strictBootstrapDocument(value) {
|
|
|
15535
15517
|
"agentOtlpEndpoint",
|
|
15536
15518
|
"custodianEmail",
|
|
15537
15519
|
"email",
|
|
15538
|
-
"githubOAuth",
|
|
15539
15520
|
"deployProfile",
|
|
15540
15521
|
"otlpFlushIntervalMs",
|
|
15541
15522
|
"otlpTraceSampleRatio",
|
|
@@ -15546,7 +15527,6 @@ function strictBootstrapDocument(value) {
|
|
|
15546
15527
|
"databaseReadPreferredCoordinators"
|
|
15547
15528
|
], "runtime environment");
|
|
15548
15529
|
const environment = runtime.environment;
|
|
15549
|
-
exactKeys2(environment.githubOAuth, ["clientId"], "GitHub OAuth config");
|
|
15550
15530
|
if (environment.initialInventory !== undefined) {
|
|
15551
15531
|
const inventory = exactKeys2(environment.initialInventory, ["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"], "initial inventory");
|
|
15552
15532
|
if (inventory.metalIdentity !== undefined) {
|
|
@@ -17363,14 +17343,14 @@ function planOperatorMetalBootstrap(request, mode) {
|
|
|
17363
17343
|
if ((mode === "rehearsal" || mode === "rehearsal-cleanup") && !request.genesis.rehearsalNode) {
|
|
17364
17344
|
throw new Error("the reviewed metal request has no rehearsal node");
|
|
17365
17345
|
}
|
|
17366
|
-
const claims = mode === "rehearsal" || mode === "rehearsal-cleanup" ? mode === "rehearsal-cleanup" ? platformCommunityRehearsalDeletionClaims(request.genesis.nodes, request.genesis.rehearsalNode) : platformCommunityRehearsalClaims(request.genesis.nodes, request.genesis.rehearsalNode, keys) : platformGenesisClaims(request.genesis.nodes, keys);
|
|
17346
|
+
const claims = mode === "genesis-cleanup" ? platformGenesisDeletionClaims(request.genesis.nodes) : mode === "rehearsal" || mode === "rehearsal-cleanup" ? mode === "rehearsal-cleanup" ? platformCommunityRehearsalDeletionClaims(request.genesis.nodes, request.genesis.rehearsalNode) : platformCommunityRehearsalClaims(request.genesis.nodes, request.genesis.rehearsalNode, keys) : platformGenesisClaims(request.genesis.nodes, keys);
|
|
17367
17347
|
const genesisNodes = mode === "host-keys" ? request.genesis.nodes.map(({ name }) => name) : mode === "rehearsal-host-keys" ? guestRows(request).map(({ name }) => name) : claims.map((claim) => claim.spec.guestName).filter((name) => Boolean(name));
|
|
17368
17348
|
return {
|
|
17369
17349
|
kind: "metal-remote",
|
|
17370
17350
|
mode,
|
|
17371
17351
|
mutation: !["status", "host-keys", "rehearsal-host-keys"].includes(mode),
|
|
17372
17352
|
target: { address: request.target.address, port: request.target.port, user: request.target.user },
|
|
17373
|
-
steps: mode === "status" ? ["verify pinned SSH transport", "run typed fz bootstrap status"] : mode === "host-keys" || mode === "rehearsal-host-keys" ? ["verify pinned SSH transport", "collect exact Ed25519 host keys for the reviewed guest addresses"] : mode === "genesis" || mode === "rehearsal" || mode === "rehearsal-cleanup" ? ["verify pinned SSH transport", mode === "rehearsal" ? "send the three reviewed seed claims plus the reviewed fourth Community rehearsal claim to the constrained Metal helper" : mode === "rehearsal-cleanup" ? "delete the exact four reviewed disposable guests and their owned disks, units, seed data and inventory" : "send the three reviewed platform-genesis claims to the constrained Metal helper"] : [
|
|
17353
|
+
steps: mode === "status" ? ["verify pinned SSH transport", "run typed fz bootstrap status"] : mode === "host-keys" || mode === "rehearsal-host-keys" ? ["verify pinned SSH transport", "collect exact Ed25519 host keys for the reviewed guest addresses"] : mode === "genesis" || mode === "genesis-cleanup" || mode === "rehearsal" || mode === "rehearsal-cleanup" ? ["verify pinned SSH transport", mode === "rehearsal" ? "send the three reviewed seed claims plus the reviewed fourth Community rehearsal claim to the constrained Metal helper" : mode === "genesis-cleanup" ? "delete the exact three reviewed platform guests and their owned disks, units, seed data and inventory" : mode === "rehearsal-cleanup" ? "delete the exact four reviewed disposable guests and their owned disks, units, seed data and inventory" : "send the three reviewed platform-genesis claims to the constrained Metal helper"] : [
|
|
17374
17354
|
"verify pinned SSH transport and caller-approved SSH agent",
|
|
17375
17355
|
"copy pinned Bun and packaged fz artifacts to private staging",
|
|
17376
17356
|
"stage the strict owner-only metal config and optional seed handoff",
|
|
@@ -17968,13 +17948,13 @@ async function applyOperatorMetalBootstrap(request, mode, options = {}) {
|
|
|
17968
17948
|
output: JSON.stringify(await collectOperatorGuestHostKeys(request, { ...options, exec }, mode === "rehearsal-host-keys"))
|
|
17969
17949
|
};
|
|
17970
17950
|
}
|
|
17971
|
-
if (mode === "genesis" || mode === "rehearsal" || mode === "rehearsal-cleanup") {
|
|
17951
|
+
if (mode === "genesis" || mode === "genesis-cleanup" || mode === "rehearsal" || mode === "rehearsal-cleanup") {
|
|
17972
17952
|
const keys = request.genesis.sshPublicKeyFiles.map((path) => publicIdentity(path));
|
|
17973
17953
|
if ((mode === "rehearsal" || mode === "rehearsal-cleanup") && !request.genesis.rehearsalNode) {
|
|
17974
17954
|
throw new Error("the reviewed metal request has no rehearsal node");
|
|
17975
17955
|
}
|
|
17976
17956
|
const outputs = [];
|
|
17977
|
-
const claims = mode === "rehearsal" || mode === "rehearsal-cleanup" ? mode === "rehearsal-cleanup" ? platformCommunityRehearsalDeletionClaims(request.genesis.nodes, request.genesis.rehearsalNode) : platformCommunityRehearsalClaims(request.genesis.nodes, request.genesis.rehearsalNode, keys) : platformGenesisClaims(request.genesis.nodes, keys);
|
|
17957
|
+
const claims = mode === "genesis-cleanup" ? platformGenesisDeletionClaims(request.genesis.nodes) : mode === "rehearsal" || mode === "rehearsal-cleanup" ? mode === "rehearsal-cleanup" ? platformCommunityRehearsalDeletionClaims(request.genesis.nodes, request.genesis.rehearsalNode) : platformCommunityRehearsalClaims(request.genesis.nodes, request.genesis.rehearsalNode, keys) : platformGenesisClaims(request.genesis.nodes, keys);
|
|
17978
17958
|
for (const claim of claims) {
|
|
17979
17959
|
outputs.push(await remote(exec, request, knownHosts, ["/usr/bin/sudo", "-n", "/usr/local/bin/fz-agent", "metal-apply", "--claim=-"], `provision ${claim.spec.guestName}`, false, `${JSON.stringify(claim)}
|
|
17980
17960
|
`));
|
|
@@ -18260,7 +18240,6 @@ function forgeZeroLaunchTemplate(profile, guests, bundle, owner) {
|
|
|
18260
18240
|
otlpTraceSampleRatio: 0.1,
|
|
18261
18241
|
custodianEmail: owner.custodianEmail,
|
|
18262
18242
|
email: owner.email,
|
|
18263
|
-
githubOAuth: owner.githubOAuth,
|
|
18264
18243
|
deployProfile: profile.environment
|
|
18265
18244
|
},
|
|
18266
18245
|
serviceUser: "forgezero-api",
|
|
@@ -18648,18 +18627,15 @@ function readPlatformLaunchEnvironment(path) {
|
|
|
18648
18627
|
throw new Error(`bootstrap secret environment is missing ${name}`);
|
|
18649
18628
|
return value;
|
|
18650
18629
|
};
|
|
18651
|
-
const githubOAuth = { clientId: requiredValue("FZ_GITHUB_OAUTH_CLIENT_ID") };
|
|
18652
18630
|
const owner = {
|
|
18653
18631
|
custodianEmail: "info@axxra.in",
|
|
18654
|
-
email: { provider: "jetemail", from: "noreply@forgezero.net", eu: false }
|
|
18655
|
-
githubOAuth
|
|
18632
|
+
email: { provider: "jetemail", from: "noreply@forgezero.net", eu: false }
|
|
18656
18633
|
};
|
|
18657
18634
|
return {
|
|
18658
18635
|
owner,
|
|
18659
18636
|
emailSecret: requiredValue("FZ_JETEMAIL_API_KEY"),
|
|
18660
18637
|
cloudflareTunnelToken: requiredValue("CF_TUNNEL_TOKEN"),
|
|
18661
|
-
cloudflareApiToken: requiredValue("CF_API_TOKEN")
|
|
18662
|
-
githubOAuthClientSecret: requiredValue("FZ_GITHUB_OAUTH_CLIENT_SECRET")
|
|
18638
|
+
cloudflareApiToken: requiredValue("CF_API_TOKEN")
|
|
18663
18639
|
};
|
|
18664
18640
|
}
|
|
18665
18641
|
|
|
@@ -18878,7 +18854,9 @@ function parseOptions(argv2) {
|
|
|
18878
18854
|
options.bootstrapConfigPath = argv2[++index];
|
|
18879
18855
|
else if (token === "--secrets-env-file")
|
|
18880
18856
|
options.bootstrapSecretsEnvFile = argv2[++index];
|
|
18881
|
-
else if (token
|
|
18857
|
+
else if (token.startsWith("--confirm-disposable-fleet=")) {
|
|
18858
|
+
options.disposableFleetConfirmation = token.slice("--confirm-disposable-fleet=".length);
|
|
18859
|
+
} else if (token === "--output")
|
|
18882
18860
|
options.outputPath = argv2[++index];
|
|
18883
18861
|
else if (token === "--query")
|
|
18884
18862
|
options.queries.push(argv2[++index] ?? "");
|
|
@@ -19483,8 +19461,7 @@ async function promptPlatformBootstrapSecrets(config, generatedClusterBootstrapC
|
|
|
19483
19461
|
...config.cloudflareHandoff || config.runtime.environment.cloudflare ? {
|
|
19484
19462
|
cloudflareTunnelToken: await bootstrapSecret("CF_TUNNEL_TOKEN"),
|
|
19485
19463
|
cloudflareApiToken: await bootstrapSecret("CF_API_TOKEN")
|
|
19486
|
-
} : {}
|
|
19487
|
-
githubOAuthClientSecret: await bootstrapSecret("GitHub OAuth client secret")
|
|
19464
|
+
} : {}
|
|
19488
19465
|
});
|
|
19489
19466
|
}
|
|
19490
19467
|
var bootstrapList = (question, fallback) => bootstrapAnswer(question, fallback).split(",").map((value) => value.trim()).filter(Boolean);
|
|
@@ -19782,11 +19759,9 @@ function selectedForgeZeroLaunchEnvironment(value) {
|
|
|
19782
19759
|
return value;
|
|
19783
19760
|
}
|
|
19784
19761
|
function forgeZeroLaunchOwnerInput() {
|
|
19785
|
-
const githubOAuth = { clientId: bootstrapAnswer("GitHub OAuth client ID") };
|
|
19786
19762
|
return {
|
|
19787
19763
|
custodianEmail: "info@axxra.in",
|
|
19788
|
-
email: { provider: "jetemail", from: "noreply@forgezero.net", eu: false }
|
|
19789
|
-
githubOAuth
|
|
19764
|
+
email: { provider: "jetemail", from: "noreply@forgezero.net", eu: false }
|
|
19790
19765
|
};
|
|
19791
19766
|
}
|
|
19792
19767
|
async function prepareForgeZeroPlatformLaunch(environment, outputDirectory, projectRoot, owner) {
|
|
@@ -19855,7 +19830,6 @@ function interactiveBootstrap(kind, genesisGuests, genesisCloudflareCheckpoint)
|
|
|
19855
19830
|
const backupRegion = backupEndpoint ? bootstrapAnswer("Backup S3 region") : undefined;
|
|
19856
19831
|
const backupBucket = backupEndpoint ? bootstrapAnswer("Backup S3 bucket") : undefined;
|
|
19857
19832
|
const backupAccessKeyId = backupEndpoint ? bootstrapAnswer("Backup S3 access-key id") : undefined;
|
|
19858
|
-
const githubOAuthClientId = bootstrapAnswer("GitHub OAuth client ID");
|
|
19859
19833
|
const cloudflareHandoffFile = genesis ? cloudflareHostHandoffPath(genesisCloudflareCheckpoint, computeReference) : bootstrapAnswer("Node-specific Cloudflare host handoff (blank for no public edge)", "");
|
|
19860
19834
|
const cloudflareNodeName = cloudflareHandoffFile ? genesis ? computeReference : bootstrapAnswer("Cloudflare handoff node name", computeReference) : undefined;
|
|
19861
19835
|
const databaseNetworkMode = "private-lan";
|
|
@@ -19910,7 +19884,6 @@ function interactiveBootstrap(kind, genesisGuests, genesisCloudflareCheckpoint)
|
|
|
19910
19884
|
otlpTraceSampleRatio: 0.1,
|
|
19911
19885
|
custodianEmail: role === "master" ? bootstrapAnswer("First custodian email") : undefined,
|
|
19912
19886
|
email: emailProvider === "smtp" ? { provider: "smtp", host: smtpHost, port: smtpPort, user: smtpUser, from: emailFrom } : { provider: "jetemail", from: emailFrom, eu: jetemailEu },
|
|
19913
|
-
githubOAuth: { clientId: githubOAuthClientId },
|
|
19914
19887
|
...backupEndpoint && backupRegion && backupBucket && backupAccessKeyId ? {
|
|
19915
19888
|
backup: { endpoint: backupEndpoint, region: backupRegion, bucket: backupBucket, accessKeyId: backupAccessKeyId }
|
|
19916
19889
|
} : {},
|
|
@@ -19970,8 +19943,7 @@ async function runAttendedPlatformFleet(fleet, apply, generatedClusterBootstrapC
|
|
|
19970
19943
|
clusterBootstrapCode: generatedClusterBootstrapCode,
|
|
19971
19944
|
emailSecret: environmentInput.emailSecret,
|
|
19972
19945
|
cloudflareTunnelToken: environmentInput.cloudflareTunnelToken,
|
|
19973
|
-
cloudflareApiToken: environmentInput.cloudflareApiToken
|
|
19974
|
-
githubOAuthClientSecret: environmentInput.githubOAuthClientSecret
|
|
19946
|
+
cloudflareApiToken: environmentInput.cloudflareApiToken
|
|
19975
19947
|
}) : await promptPlatformBootstrapSecrets(firstConfig, generatedClusterBootstrapCode);
|
|
19976
19948
|
const cloudflare = await resolveCloudflareBootstrapCommandConfig(fleet.cloudflareConfigFile, {
|
|
19977
19949
|
tunnelToken: secrets.cloudflareTunnelToken,
|
|
@@ -20075,8 +20047,8 @@ async function cmdBootstrap(options, args) {
|
|
|
20075
20047
|
}
|
|
20076
20048
|
if (operation === "metal" && args[1] === "remote") {
|
|
20077
20049
|
const mode = args[2];
|
|
20078
|
-
if (!mode || !["apply", "genesis", "rehearsal", "rehearsal-cleanup", "host-keys", "rehearsal-host-keys", "status"].includes(mode) || args[3] !== undefined) {
|
|
20079
|
-
throw new Error("Usage: fz bootstrap metal remote <apply|genesis|rehearsal|rehearsal-cleanup|host-keys|rehearsal-host-keys|status> --bootstrap-config <owner-only-request.json> [--output <owner-only-evidence.json>] [--apply]");
|
|
20050
|
+
if (!mode || !["apply", "genesis", "genesis-cleanup", "rehearsal", "rehearsal-cleanup", "host-keys", "rehearsal-host-keys", "status"].includes(mode) || args[3] !== undefined) {
|
|
20051
|
+
throw new Error("Usage: fz bootstrap metal remote <apply|genesis|genesis-cleanup|rehearsal|rehearsal-cleanup|host-keys|rehearsal-host-keys|status> --bootstrap-config <owner-only-request.json> [--output <owner-only-evidence.json>] [--confirm-disposable-fleet=<exact-names>] [--apply]");
|
|
20080
20052
|
}
|
|
20081
20053
|
if (!options.bootstrapConfigPath)
|
|
20082
20054
|
throw new Error("remote metal bootstrap requires --bootstrap-config");
|
|
@@ -20087,6 +20059,17 @@ async function cmdBootstrap(options, args) {
|
|
|
20087
20059
|
validateMetalConfig: mode === "apply"
|
|
20088
20060
|
});
|
|
20089
20061
|
const plan2 = planOperatorMetalBootstrap(request, mode);
|
|
20062
|
+
if (mode === "genesis-cleanup") {
|
|
20063
|
+
const expected = plan2.genesisNodes.join(",");
|
|
20064
|
+
if (!options.apply) {
|
|
20065
|
+
out.line(JSON.stringify({ ...plan2, requiredConfirmation: expected }, null, 2));
|
|
20066
|
+
out.step(`Repeat with --confirm-disposable-fleet=${expected} --apply to delete only this reviewed fleet.`);
|
|
20067
|
+
return 0;
|
|
20068
|
+
}
|
|
20069
|
+
if (options.disposableFleetConfirmation !== expected) {
|
|
20070
|
+
throw new Error(`genesis cleanup requires --confirm-disposable-fleet=${expected}`);
|
|
20071
|
+
}
|
|
20072
|
+
}
|
|
20090
20073
|
if (!options.apply) {
|
|
20091
20074
|
out.line(JSON.stringify(plan2, null, 2));
|
|
20092
20075
|
out.step("Review the pinned metal target and exact genesis nodes, then repeat with --apply to contact the host.");
|
|
@@ -20188,7 +20171,7 @@ async function cmdBootstrap(options, args) {
|
|
|
20188
20171
|
return 0;
|
|
20189
20172
|
}
|
|
20190
20173
|
if (!["platform", "repair"].includes(operation)) {
|
|
20191
|
-
throw new Error("Usage: fz bootstrap config <metal|platform|cloudflare>|platform [launch|bundle|fleet <apply|status>|remote <apply|status>|cloudflare [verify|finalize]]|metal [remote <apply|genesis|rehearsal|rehearsal-cleanup|host-keys|rehearsal-host-keys|status>]|status|repair [--bootstrap-config <path>] [--apply]");
|
|
20174
|
+
throw new Error("Usage: fz bootstrap config <metal|platform|cloudflare>|platform [launch|bundle|fleet <apply|status>|remote <apply|status>|cloudflare [verify|finalize]]|metal [remote <apply|genesis|genesis-cleanup|rehearsal|rehearsal-cleanup|host-keys|rehearsal-host-keys|status>]|status|repair [--bootstrap-config <path>] [--apply]");
|
|
20192
20175
|
}
|
|
20193
20176
|
const config = options.bootstrapConfigPath ? readBootstrapConfig(options.bootstrapConfigPath) : operation === "repair" ? (() => {
|
|
20194
20177
|
throw new Error("repair requires --bootstrap-config so immutable coordinates are revalidated");
|
|
@@ -20858,7 +20841,7 @@ function usage() {
|
|
|
20858
20841
|
Persist secret-free public-node acceptance, then remove
|
|
20859
20842
|
the completed non-secret checkpoint and node handoffs
|
|
20860
20843
|
fz bootstrap metal Plan/install an identity-only physical provisioner
|
|
20861
|
-
fz bootstrap metal remote <apply|genesis|rehearsal|rehearsal-cleanup|host-keys|rehearsal-host-keys|status>
|
|
20844
|
+
fz bootstrap metal remote <apply|genesis|genesis-cleanup|rehearsal|rehearsal-cleanup|host-keys|rehearsal-host-keys|status>
|
|
20862
20845
|
Install/bootstrap one pinned blank metal target, then
|
|
20863
20846
|
provision the exact selected three-node genesis seed
|
|
20864
20847
|
fz bootstrap status Verify persisted profile and supervised units
|
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.117";
|
|
370
370
|
|
|
371
371
|
// src/otel-collector.ts
|
|
372
372
|
var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
|
|
@@ -8,7 +8,7 @@ export interface MetalCpuPool {
|
|
|
8
8
|
key: string;
|
|
9
9
|
/** Linux CPU-list syntax, including every SMT sibling in this pool. */
|
|
10
10
|
cpus: string;
|
|
11
|
-
/** Real cores represented by cpus; checked against the
|
|
11
|
+
/** Real cores represented by cpus; checked against the sellable capacity promise. */
|
|
12
12
|
physicalCores: number;
|
|
13
13
|
/** Linux NUMA node-list syntax. Optional on a non-NUMA machine. */
|
|
14
14
|
memoryNodes?: string;
|
|
@@ -90,7 +90,7 @@ export interface OperatorPlatformFleetCoordinates {
|
|
|
90
90
|
}[];
|
|
91
91
|
}
|
|
92
92
|
export type OperatorPlatformBootstrapMode = 'apply' | 'status';
|
|
93
|
-
export type OperatorMetalBootstrapMode = 'apply' | 'genesis' | 'rehearsal' | 'rehearsal-cleanup' | 'host-keys' | 'rehearsal-host-keys' | 'status';
|
|
93
|
+
export type OperatorMetalBootstrapMode = 'apply' | 'genesis' | 'genesis-cleanup' | 'rehearsal' | 'rehearsal-cleanup' | 'host-keys' | 'rehearsal-host-keys' | 'status';
|
|
94
94
|
export interface OperatorPlatformBootstrapPlan {
|
|
95
95
|
kind: 'platform-remote';
|
|
96
96
|
mode: OperatorPlatformBootstrapMode;
|
|
@@ -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.117";
|
|
1464
1464
|
|
|
1465
1465
|
// src/software.ts
|
|
1466
1466
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -3127,6 +3127,9 @@ function platformGenesisClaims(guests, sshPublicKeys) {
|
|
|
3127
3127
|
throw new Error("platform genesis requires at least one operator SSH public key");
|
|
3128
3128
|
return reviewed.map((guest) => claimFor(guest, keys, "create"));
|
|
3129
3129
|
}
|
|
3130
|
+
function platformGenesisDeletionClaims(guests) {
|
|
3131
|
+
return validatePlatformGenesisGuests(guests).map((guest) => claimFor(guest, [], "delete"));
|
|
3132
|
+
}
|
|
3130
3133
|
function platformCommunityRehearsalClaims(seedGuests, rehearsalGuest, sshPublicKeys) {
|
|
3131
3134
|
const reviewed = validatePlatformGenesisGuests([...seedGuests, rehearsalGuest], 4);
|
|
3132
3135
|
const keys = [...new Set(sshPublicKeys.map(publicKey))];
|
|
@@ -3269,9 +3272,6 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
3269
3272
|
} else if (input.email !== undefined) {
|
|
3270
3273
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
3271
3274
|
}
|
|
3272
|
-
if (!input.githubOAuth || !/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubOAuth.clientId)) {
|
|
3273
|
-
throw new Error("GitHub OAuth client id is malformed.");
|
|
3274
|
-
}
|
|
3275
3275
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
3276
3276
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
3277
3277
|
throw new Error("seedSyncMembers must contain 3 to 64 unique physical host identities.");
|
|
@@ -3402,7 +3402,6 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
3402
3402
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
3403
3403
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
3404
3404
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
3405
|
-
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
3406
3405
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
3407
3406
|
};
|
|
3408
3407
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -3414,7 +3413,6 @@ function platformApiCredentialSpecs(options) {
|
|
|
3414
3413
|
const optional = [
|
|
3415
3414
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
3416
3415
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
3417
|
-
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
3418
3416
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
3419
3417
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
3420
3418
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -3811,15 +3809,7 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3811
3809
|
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
3812
3810
|
throw new Error("bootstrap credential input must be an object");
|
|
3813
3811
|
const source = input;
|
|
3814
|
-
const allowed = [
|
|
3815
|
-
"clusterBootstrapCode",
|
|
3816
|
-
"emailSecret",
|
|
3817
|
-
"enrolmentToken",
|
|
3818
|
-
"backupS3Secret",
|
|
3819
|
-
"cloudflareTunnelToken",
|
|
3820
|
-
"cloudflareApiToken",
|
|
3821
|
-
"githubOAuthClientSecret"
|
|
3822
|
-
];
|
|
3812
|
+
const allowed = ["clusterBootstrapCode", "emailSecret", "enrolmentToken", "backupS3Secret", "cloudflareTunnelToken", "cloudflareApiToken"];
|
|
3823
3813
|
const unknown = Object.keys(source).filter((key) => !allowed.includes(key));
|
|
3824
3814
|
if (unknown.length)
|
|
3825
3815
|
throw new Error(`bootstrap credential input contains unsupported field ${unknown[0]}`);
|
|
@@ -3829,7 +3819,6 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3829
3819
|
const backupS3Secret = typeof source.backupS3Secret === "string" ? source.backupS3Secret.trim() : undefined;
|
|
3830
3820
|
const cloudflareTunnelToken = typeof source.cloudflareTunnelToken === "string" ? source.cloudflareTunnelToken.trim() : undefined;
|
|
3831
3821
|
const cloudflareApiToken = typeof source.cloudflareApiToken === "string" ? source.cloudflareApiToken.trim() : undefined;
|
|
3832
|
-
const githubOAuthClientSecret = typeof source.githubOAuthClientSecret === "string" ? source.githubOAuthClientSecret.trim() : "";
|
|
3833
3822
|
if (!/^[a-f0-9]{64}$/i.test(clusterBootstrapCode))
|
|
3834
3823
|
throw new Error("cluster bootstrap code must contain exactly 64 hexadecimal characters");
|
|
3835
3824
|
if (!emailSecret || emailSecret.length > 16384 || /[\r\n\0]/.test(emailSecret))
|
|
@@ -3849,16 +3838,12 @@ function validatePlatformBootstrapSecrets(config, input) {
|
|
|
3849
3838
|
}
|
|
3850
3839
|
if (cloudflareTunnelToken)
|
|
3851
3840
|
validateCloudflareBootstrapSecretPair({ cloudflareTunnelToken, cloudflareApiToken });
|
|
3852
|
-
if (githubOAuthClientSecret.length < 20 || githubOAuthClientSecret.length > 512 || /[\r\n\0]/.test(githubOAuthClientSecret)) {
|
|
3853
|
-
throw new Error("GitHub OAuth client secret is malformed");
|
|
3854
|
-
}
|
|
3855
3841
|
return {
|
|
3856
3842
|
clusterBootstrapCode,
|
|
3857
3843
|
emailSecret,
|
|
3858
3844
|
...enrolmentToken ? { enrolmentToken } : {},
|
|
3859
3845
|
...backupS3Secret ? { backupS3Secret } : {},
|
|
3860
|
-
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {}
|
|
3861
|
-
githubOAuthClientSecret
|
|
3846
|
+
...cloudflareTunnelToken ? { cloudflareTunnelToken, cloudflareApiToken } : {}
|
|
3862
3847
|
};
|
|
3863
3848
|
}
|
|
3864
3849
|
var platformBootstrapRunner = (config) => config.kind === "platform" && config.database.role === "master";
|
|
@@ -4781,8 +4766,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4781
4766
|
enrolmentToken: checked4.enrolmentToken,
|
|
4782
4767
|
backup: checked4.backupS3Secret,
|
|
4783
4768
|
cloudflareTunnelToken: checked4.cloudflareTunnelToken,
|
|
4784
|
-
cloudflareApiToken: checked4.cloudflareApiToken
|
|
4785
|
-
githubOAuthClientSecret: checked4.githubOAuthClientSecret
|
|
4769
|
+
cloudflareApiToken: checked4.cloudflareApiToken
|
|
4786
4770
|
};
|
|
4787
4771
|
})() : undefined;
|
|
4788
4772
|
const enrolledPrivate = config.kind === "enrolled-compute" ? validateEnrolledComputeBootstrapSecrets(config, secrets) : undefined;
|
|
@@ -4883,7 +4867,6 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4883
4867
|
const emailCredentialName = config.runtime.environment.email?.provider === "smtp" ? "fz_smtp.password" : config.runtime.environment.email?.provider === "jetemail" ? "fz_jetemail.apiKey" : undefined;
|
|
4884
4868
|
for (const [name, source] of Object.entries({
|
|
4885
4869
|
...emailCredentialName ? { [emailCredentialName]: platformPrivate.email } : {},
|
|
4886
|
-
"fz_oauth.github.clientSecret": platformPrivate.githubOAuthClientSecret,
|
|
4887
4870
|
"backup.s3.secretAccessKey": platformPrivate.backup
|
|
4888
4871
|
})) {
|
|
4889
4872
|
if (source) {
|
|
@@ -4900,7 +4883,6 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
|
|
|
4900
4883
|
const credentials = platformApiCredentialSpecs({
|
|
4901
4884
|
emailProvider: runtime.environment.email?.provider,
|
|
4902
4885
|
cloudflareKv: cloudflareConfigured,
|
|
4903
|
-
githubOAuth: true,
|
|
4904
4886
|
realtime: Boolean(runtime.environment.realtime)
|
|
4905
4887
|
});
|
|
4906
4888
|
const units = renderPlatformApiUnits({
|
|
@@ -5148,7 +5130,6 @@ function strictBootstrapDocument(value) {
|
|
|
5148
5130
|
"agentOtlpEndpoint",
|
|
5149
5131
|
"custodianEmail",
|
|
5150
5132
|
"email",
|
|
5151
|
-
"githubOAuth",
|
|
5152
5133
|
"deployProfile",
|
|
5153
5134
|
"otlpFlushIntervalMs",
|
|
5154
5135
|
"otlpTraceSampleRatio",
|
|
@@ -5159,7 +5140,6 @@ function strictBootstrapDocument(value) {
|
|
|
5159
5140
|
"databaseReadPreferredCoordinators"
|
|
5160
5141
|
], "runtime environment");
|
|
5161
5142
|
const environment = runtime.environment;
|
|
5162
|
-
exactKeys(environment.githubOAuth, ["clientId"], "GitHub OAuth config");
|
|
5163
5143
|
if (environment.initialInventory !== undefined) {
|
|
5164
5144
|
const inventory = exactKeys(environment.initialInventory, ["metalHostname", "metalIdentity", "region", "computes", "attestation", "deployment"], "initial inventory");
|
|
5165
5145
|
if (inventory.metalIdentity !== undefined) {
|
|
@@ -6712,14 +6692,14 @@ function planOperatorMetalBootstrap(request, mode) {
|
|
|
6712
6692
|
if ((mode === "rehearsal" || mode === "rehearsal-cleanup") && !request.genesis.rehearsalNode) {
|
|
6713
6693
|
throw new Error("the reviewed metal request has no rehearsal node");
|
|
6714
6694
|
}
|
|
6715
|
-
const claims = mode === "rehearsal" || mode === "rehearsal-cleanup" ? mode === "rehearsal-cleanup" ? platformCommunityRehearsalDeletionClaims(request.genesis.nodes, request.genesis.rehearsalNode) : platformCommunityRehearsalClaims(request.genesis.nodes, request.genesis.rehearsalNode, keys) : platformGenesisClaims(request.genesis.nodes, keys);
|
|
6695
|
+
const claims = mode === "genesis-cleanup" ? platformGenesisDeletionClaims(request.genesis.nodes) : mode === "rehearsal" || mode === "rehearsal-cleanup" ? mode === "rehearsal-cleanup" ? platformCommunityRehearsalDeletionClaims(request.genesis.nodes, request.genesis.rehearsalNode) : platformCommunityRehearsalClaims(request.genesis.nodes, request.genesis.rehearsalNode, keys) : platformGenesisClaims(request.genesis.nodes, keys);
|
|
6716
6696
|
const genesisNodes = mode === "host-keys" ? request.genesis.nodes.map(({ name }) => name) : mode === "rehearsal-host-keys" ? guestRows(request).map(({ name }) => name) : claims.map((claim) => claim.spec.guestName).filter((name) => Boolean(name));
|
|
6717
6697
|
return {
|
|
6718
6698
|
kind: "metal-remote",
|
|
6719
6699
|
mode,
|
|
6720
6700
|
mutation: !["status", "host-keys", "rehearsal-host-keys"].includes(mode),
|
|
6721
6701
|
target: { address: request.target.address, port: request.target.port, user: request.target.user },
|
|
6722
|
-
steps: mode === "status" ? ["verify pinned SSH transport", "run typed fz bootstrap status"] : mode === "host-keys" || mode === "rehearsal-host-keys" ? ["verify pinned SSH transport", "collect exact Ed25519 host keys for the reviewed guest addresses"] : mode === "genesis" || mode === "rehearsal" || mode === "rehearsal-cleanup" ? ["verify pinned SSH transport", mode === "rehearsal" ? "send the three reviewed seed claims plus the reviewed fourth Community rehearsal claim to the constrained Metal helper" : mode === "rehearsal-cleanup" ? "delete the exact four reviewed disposable guests and their owned disks, units, seed data and inventory" : "send the three reviewed platform-genesis claims to the constrained Metal helper"] : [
|
|
6702
|
+
steps: mode === "status" ? ["verify pinned SSH transport", "run typed fz bootstrap status"] : mode === "host-keys" || mode === "rehearsal-host-keys" ? ["verify pinned SSH transport", "collect exact Ed25519 host keys for the reviewed guest addresses"] : mode === "genesis" || mode === "genesis-cleanup" || mode === "rehearsal" || mode === "rehearsal-cleanup" ? ["verify pinned SSH transport", mode === "rehearsal" ? "send the three reviewed seed claims plus the reviewed fourth Community rehearsal claim to the constrained Metal helper" : mode === "genesis-cleanup" ? "delete the exact three reviewed platform guests and their owned disks, units, seed data and inventory" : mode === "rehearsal-cleanup" ? "delete the exact four reviewed disposable guests and their owned disks, units, seed data and inventory" : "send the three reviewed platform-genesis claims to the constrained Metal helper"] : [
|
|
6723
6703
|
"verify pinned SSH transport and caller-approved SSH agent",
|
|
6724
6704
|
"copy pinned Bun and packaged fz artifacts to private staging",
|
|
6725
6705
|
"stage the strict owner-only metal config and optional seed handoff",
|
|
@@ -7412,13 +7392,13 @@ async function applyOperatorMetalBootstrap(request, mode, options = {}) {
|
|
|
7412
7392
|
output: JSON.stringify(await collectOperatorGuestHostKeys(request, { ...options, exec }, mode === "rehearsal-host-keys"))
|
|
7413
7393
|
};
|
|
7414
7394
|
}
|
|
7415
|
-
if (mode === "genesis" || mode === "rehearsal" || mode === "rehearsal-cleanup") {
|
|
7395
|
+
if (mode === "genesis" || mode === "genesis-cleanup" || mode === "rehearsal" || mode === "rehearsal-cleanup") {
|
|
7416
7396
|
const keys = request.genesis.sshPublicKeyFiles.map((path) => publicIdentity(path));
|
|
7417
7397
|
if ((mode === "rehearsal" || mode === "rehearsal-cleanup") && !request.genesis.rehearsalNode) {
|
|
7418
7398
|
throw new Error("the reviewed metal request has no rehearsal node");
|
|
7419
7399
|
}
|
|
7420
7400
|
const outputs = [];
|
|
7421
|
-
const claims = mode === "rehearsal" || mode === "rehearsal-cleanup" ? mode === "rehearsal-cleanup" ? platformCommunityRehearsalDeletionClaims(request.genesis.nodes, request.genesis.rehearsalNode) : platformCommunityRehearsalClaims(request.genesis.nodes, request.genesis.rehearsalNode, keys) : platformGenesisClaims(request.genesis.nodes, keys);
|
|
7401
|
+
const claims = mode === "genesis-cleanup" ? platformGenesisDeletionClaims(request.genesis.nodes) : mode === "rehearsal" || mode === "rehearsal-cleanup" ? mode === "rehearsal-cleanup" ? platformCommunityRehearsalDeletionClaims(request.genesis.nodes, request.genesis.rehearsalNode) : platformCommunityRehearsalClaims(request.genesis.nodes, request.genesis.rehearsalNode, keys) : platformGenesisClaims(request.genesis.nodes, keys);
|
|
7422
7402
|
for (const claim of claims) {
|
|
7423
7403
|
outputs.push(await remote(exec, request, knownHosts, ["/usr/bin/sudo", "-n", "/usr/local/bin/fz-agent", "metal-apply", "--claim=-"], `provision ${claim.spec.guestName}`, false, `${JSON.stringify(claim)}
|
|
7424
7404
|
`));
|
|
@@ -68,14 +68,6 @@ export type PlatformBootstrapEmail = {
|
|
|
68
68
|
from: string;
|
|
69
69
|
eu: boolean;
|
|
70
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 PlatformBootstrapGitHubOAuth {
|
|
77
|
-
clientId: string;
|
|
78
|
-
}
|
|
79
71
|
export interface PlatformSharedEnvironment {
|
|
80
72
|
softwareProfile: PlatformSoftwareProfile;
|
|
81
73
|
databaseRole: PlatformDatabaseRole;
|
|
@@ -107,7 +99,6 @@ export interface PlatformSharedEnvironment {
|
|
|
107
99
|
otlpTraceSampleRatio: number;
|
|
108
100
|
custodianEmail?: string;
|
|
109
101
|
email?: PlatformBootstrapEmail;
|
|
110
|
-
githubOAuth: PlatformBootstrapGitHubOAuth;
|
|
111
102
|
backup?: {
|
|
112
103
|
endpoint: string;
|
|
113
104
|
region: string;
|
|
@@ -135,13 +126,12 @@ export declare function validatePlatformSharedEnvironment(input: PlatformSharedE
|
|
|
135
126
|
/** Render only non-secret runtime coordinates. Passwords/tokens have no field in this contract. */
|
|
136
127
|
export declare function renderPlatformSharedEnvironment(input: PlatformSharedEnvironment): string;
|
|
137
128
|
export interface SystemdCredentialSpec {
|
|
138
|
-
name: 'arangodb-jwt' | 'arangodb-root-password' | 'seed-sync-root' | 'fz_smtp.password' | 'fz_jetemail.apiKey' | '
|
|
129
|
+
name: 'arangodb-jwt' | 'arangodb-root-password' | 'seed-sync-root' | 'fz_smtp.password' | 'fz_jetemail.apiKey' | 'CF_API_TOKEN' | 'CF_TUNNEL_TOKEN' | 'REALTIME_PUBLISH_SECRET' | 'REALTIME_TICKET_SECRET';
|
|
139
130
|
encryptedPath: string;
|
|
140
131
|
required: boolean;
|
|
141
132
|
}
|
|
142
133
|
export declare function platformApiCredentialSpecs(options: {
|
|
143
134
|
emailProvider?: PlatformBootstrapEmail['provider'];
|
|
144
|
-
githubOAuth: boolean;
|
|
145
135
|
cloudflareKv: boolean;
|
|
146
136
|
realtime: boolean;
|
|
147
137
|
}): SystemdCredentialSpec[];
|
|
@@ -669,6 +669,9 @@ function platformGenesisClaims(guests, sshPublicKeys) {
|
|
|
669
669
|
throw new Error("platform genesis requires at least one operator SSH public key");
|
|
670
670
|
return reviewed.map((guest) => claimFor(guest, keys, "create"));
|
|
671
671
|
}
|
|
672
|
+
function platformGenesisDeletionClaims(guests) {
|
|
673
|
+
return validatePlatformGenesisGuests(guests).map((guest) => claimFor(guest, [], "delete"));
|
|
674
|
+
}
|
|
672
675
|
function platformCommunityRehearsalClaims(seedGuests, rehearsalGuest, sshPublicKeys) {
|
|
673
676
|
const reviewed = validatePlatformGenesisGuests([...seedGuests, rehearsalGuest], 4);
|
|
674
677
|
const keys = [...new Set(sshPublicKeys.map(publicKey))];
|
|
@@ -828,9 +831,6 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
828
831
|
} else if (input.email !== undefined) {
|
|
829
832
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
830
833
|
}
|
|
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.");
|
|
833
|
-
}
|
|
834
834
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
835
835
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
836
836
|
throw new Error("seedSyncMembers must contain 3 to 64 unique physical host identities.");
|
|
@@ -961,7 +961,6 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
961
961
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
962
962
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
963
963
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
964
|
-
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
965
964
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
966
965
|
};
|
|
967
966
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -973,7 +972,6 @@ function platformApiCredentialSpecs(options) {
|
|
|
973
972
|
const optional = [
|
|
974
973
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
975
974
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
976
|
-
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
977
975
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
978
976
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
979
977
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -3009,7 +3009,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
|
|
|
3009
3009
|
}
|
|
3010
3010
|
|
|
3011
3011
|
// src/version.ts
|
|
3012
|
-
var VERSION3 = "0.1.
|
|
3012
|
+
var VERSION3 = "0.1.117";
|
|
3013
3013
|
|
|
3014
3014
|
// src/egress-policy.ts
|
|
3015
3015
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
@@ -4185,6 +4185,9 @@ function platformGenesisClaims(guests, sshPublicKeys) {
|
|
|
4185
4185
|
throw new Error("platform genesis requires at least one operator SSH public key");
|
|
4186
4186
|
return reviewed.map((guest) => claimFor(guest, keys, "create"));
|
|
4187
4187
|
}
|
|
4188
|
+
function platformGenesisDeletionClaims(guests) {
|
|
4189
|
+
return validatePlatformGenesisGuests(guests).map((guest) => claimFor(guest, [], "delete"));
|
|
4190
|
+
}
|
|
4188
4191
|
function platformCommunityRehearsalClaims(seedGuests, rehearsalGuest, sshPublicKeys) {
|
|
4189
4192
|
const reviewed = validatePlatformGenesisGuests([...seedGuests, rehearsalGuest], 4);
|
|
4190
4193
|
const keys = [...new Set(sshPublicKeys.map(publicKey))];
|
|
@@ -4344,9 +4347,6 @@ function validatePlatformSharedEnvironment(input) {
|
|
|
4344
4347
|
} else if (input.email !== undefined) {
|
|
4345
4348
|
throw new Error("Bootstrap email provider must be smtp or jetemail.");
|
|
4346
4349
|
}
|
|
4347
|
-
if (!input.githubOAuth || !/^(?:Iv1\.[A-Fa-f0-9]{16}|Ov23li[A-Za-z0-9]{14,})$/.test(input.githubOAuth.clientId)) {
|
|
4348
|
-
throw new Error("GitHub OAuth client id is malformed.");
|
|
4349
|
-
}
|
|
4350
4350
|
boundedInteger("publicApiPort", input.publicApiPort, 1024, 65533);
|
|
4351
4351
|
if (!Array.isArray(input.seedSyncMembers) || input.seedSyncMembers.length < 3 || input.seedSyncMembers.length > 64 || new Set(input.seedSyncMembers).size !== input.seedSyncMembers.length) {
|
|
4352
4352
|
throw new Error("seedSyncMembers must contain 3 to 64 unique physical host identities.");
|
|
@@ -4477,7 +4477,6 @@ function renderPlatformSharedEnvironment(input) {
|
|
|
4477
4477
|
FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
|
|
4478
4478
|
FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
|
|
4479
4479
|
FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
|
|
4480
|
-
FZ_GITHUB_OAUTH_CLIENT_ID: value.githubOAuth.clientId,
|
|
4481
4480
|
FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
|
|
4482
4481
|
};
|
|
4483
4482
|
return `# Generated by fz bootstrap platform. Non-secret coordinates only.
|
|
@@ -4489,7 +4488,6 @@ function platformApiCredentialSpecs(options) {
|
|
|
4489
4488
|
const optional = [
|
|
4490
4489
|
["fz_smtp.password", options.emailProvider === "smtp"],
|
|
4491
4490
|
["fz_jetemail.apiKey", options.emailProvider === "jetemail"],
|
|
4492
|
-
["fz_oauth.github.clientSecret", options.githubOAuth],
|
|
4493
4491
|
["CF_API_TOKEN", options.cloudflareKv],
|
|
4494
4492
|
["CF_TUNNEL_TOKEN", options.cloudflareKv],
|
|
4495
4493
|
["REALTIME_PUBLISH_SECRET", options.realtime],
|
|
@@ -21,6 +21,8 @@ export interface PlatformGenesisGuest {
|
|
|
21
21
|
export declare function validatePlatformGenesisGuests(guests: readonly PlatformGenesisGuest[], expectedCount?: number): readonly PlatformGenesisGuest[];
|
|
22
22
|
/** Convert reviewed desired state into the ordinary Metal provisioning claim. */
|
|
23
23
|
export declare function platformGenesisClaims(guests: readonly PlatformGenesisGuest[], sshPublicKeys: readonly string[]): readonly RemoteProvisionClaim[];
|
|
24
|
+
/** Exact inverse of the reviewed three-node platform seed. */
|
|
25
|
+
export declare function platformGenesisDeletionClaims(guests: readonly PlatformGenesisGuest[]): readonly RemoteProvisionClaim[];
|
|
24
26
|
/** Add one explicitly reviewed disposable node to the same three guest requests. */
|
|
25
27
|
export declare function platformCommunityRehearsalClaims(seedGuests: readonly PlatformGenesisGuest[], rehearsalGuest: PlatformGenesisGuest, sshPublicKeys: readonly string[]): readonly RemoteProvisionClaim[];
|
|
26
28
|
/** Exact inverse of the reviewed disposable four-host request. */
|
package/dist/platform-genesis.js
CHANGED
|
@@ -669,6 +669,9 @@ function platformGenesisClaims(guests, sshPublicKeys) {
|
|
|
669
669
|
throw new Error("platform genesis requires at least one operator SSH public key");
|
|
670
670
|
return reviewed.map((guest) => claimFor(guest, keys, "create"));
|
|
671
671
|
}
|
|
672
|
+
function platformGenesisDeletionClaims(guests) {
|
|
673
|
+
return validatePlatformGenesisGuests(guests).map((guest) => claimFor(guest, [], "delete"));
|
|
674
|
+
}
|
|
672
675
|
function platformCommunityRehearsalClaims(seedGuests, rehearsalGuest, sshPublicKeys) {
|
|
673
676
|
const reviewed = validatePlatformGenesisGuests([...seedGuests, rehearsalGuest], 4);
|
|
674
677
|
const keys = [...new Set(sshPublicKeys.map(publicKey))];
|
|
@@ -681,6 +684,7 @@ function platformCommunityRehearsalDeletionClaims(seedGuests, rehearsalGuest) {
|
|
|
681
684
|
}
|
|
682
685
|
export {
|
|
683
686
|
validatePlatformGenesisGuests,
|
|
687
|
+
platformGenesisDeletionClaims,
|
|
684
688
|
platformGenesisClaims,
|
|
685
689
|
platformCommunityRehearsalDeletionClaims,
|
|
686
690
|
platformCommunityRehearsalClaims
|
|
@@ -45,10 +45,6 @@ export interface ForgeZeroLaunchOwnerInput {
|
|
|
45
45
|
from: string;
|
|
46
46
|
eu: boolean;
|
|
47
47
|
};
|
|
48
|
-
/** Required bootstrap identity provider. Repository automation is configured after genesis. */
|
|
49
|
-
githubOAuth: {
|
|
50
|
-
clientId: string;
|
|
51
|
-
};
|
|
52
48
|
}
|
|
53
49
|
/**
|
|
54
50
|
* ForgeZero's own genesis public coordinates. They are reviewed source data,
|
package/dist/provision.js
CHANGED
|
@@ -3009,7 +3009,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
|
|
|
3009
3009
|
}
|
|
3010
3010
|
|
|
3011
3011
|
// src/version.ts
|
|
3012
|
-
var VERSION3 = "0.1.
|
|
3012
|
+
var VERSION3 = "0.1.117";
|
|
3013
3013
|
|
|
3014
3014
|
// src/egress-policy.ts
|
|
3015
3015
|
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.117";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgezero/agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.117",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"check": "tsc --noEmit",
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
"typescript": "^5.6.0",
|
|
12
12
|
"@types/bun": "latest",
|
|
13
13
|
"@types/node": "^22.0.0",
|
|
14
|
-
"@forgezero/access": "0.1.
|
|
14
|
+
"@forgezero/access": "0.1.11",
|
|
15
15
|
"@noble/curves": "^2.2.0",
|
|
16
16
|
"@noble/post-quantum": "^0.6.1"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@forgezero/runtime": "0.1.
|
|
20
|
-
"@forgezero/vault": "0.1.
|
|
19
|
+
"@forgezero/runtime": "0.1.16",
|
|
20
|
+
"@forgezero/vault": "0.1.21",
|
|
21
21
|
"@noble/curves": "2.2.0",
|
|
22
22
|
"@noble/hashes": "2.2.0",
|
|
23
23
|
"@noble/post-quantum": "0.6.1",
|