@forgezero/agent 0.1.55 → 0.1.56
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.js +1 -1
- package/dist/community-rehearsal-host.d.ts +7 -1
- package/dist/community-rehearsal-host.js +27 -1
- package/dist/fz-agent.js +25 -1
- package/dist/fz.js +49 -8
- package/dist/metal-bootstrap.js +1 -1
- package/dist/operator-bootstrap.d.ts +1 -1
- package/dist/operator-bootstrap.js +46 -5
- package/dist/platform-fleet-verification.js +1 -1
- package/dist/platform-genesis.d.ts +9 -0
- 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.js
CHANGED
|
@@ -2,6 +2,7 @@ import { type SoftwareExec } from './software';
|
|
|
2
2
|
export declare const COMMUNITY_REHEARSAL_VERSION = "3.11.14";
|
|
3
3
|
export declare const COMMUNITY_REHEARSAL_ROOT = "/opt/forgezero-rehearsals/community-cluster-api";
|
|
4
4
|
export declare const COMMUNITY_DATABASE_ROOT = "/var/lib/forgezero-rehearsal-cluster";
|
|
5
|
+
export declare const COMMUNITY_CREDENTIAL_PARENT = "/etc/forgezero-rehearsal";
|
|
5
6
|
export declare const COMMUNITY_CREDENTIAL_ROOT = "/etc/forgezero-rehearsal/creds";
|
|
6
7
|
export type CommunityRehearsalApiOperation = 'health' | 'init' | 'write' | 'read' | 'query' | 'cluster';
|
|
7
8
|
export type CommunityRehearsalHostRequest = {
|
|
@@ -13,6 +14,9 @@ export type CommunityRehearsalHostRequest = {
|
|
|
13
14
|
archivePath: string;
|
|
14
15
|
archiveSha256: string;
|
|
15
16
|
jwt: string;
|
|
17
|
+
} | {
|
|
18
|
+
action: 'cleanup';
|
|
19
|
+
node: string;
|
|
16
20
|
} | {
|
|
17
21
|
action: 'database-enable' | 'api-enable' | 'database-ready' | 'starter-ready' | 'api-ready' | 'database-status' | 'api-status';
|
|
18
22
|
node: string;
|
|
@@ -25,7 +29,7 @@ export type CommunityRehearsalHostRequest = {
|
|
|
25
29
|
};
|
|
26
30
|
export type CommunityHostOperation = {
|
|
27
31
|
kind: 'remove-tree';
|
|
28
|
-
path: typeof COMMUNITY_DATABASE_ROOT;
|
|
32
|
+
path: typeof COMMUNITY_DATABASE_ROOT | typeof COMMUNITY_REHEARSAL_ROOT | typeof COMMUNITY_CREDENTIAL_PARENT;
|
|
29
33
|
} | {
|
|
30
34
|
kind: 'write';
|
|
31
35
|
path: string;
|
|
@@ -49,5 +53,7 @@ export declare function parseCommunityRehearsalHostRequest(value: unknown): Comm
|
|
|
49
53
|
export declare function planCommunityRehearsalPrepare(request: Extract<CommunityRehearsalHostRequest, {
|
|
50
54
|
action: 'prepare';
|
|
51
55
|
}>): CommunityHostOperation[];
|
|
56
|
+
/** Remove only the dedicated rehearsal units, credentials, release and data. */
|
|
57
|
+
export declare function planCommunityRehearsalCleanup(): CommunityHostOperation[];
|
|
52
58
|
/** Execute only the dedicated four-node rehearsal operation selected by a typed request. */
|
|
53
59
|
export declare function runCommunityRehearsalHost(request: CommunityRehearsalHostRequest): Promise<Record<string, unknown>>;
|
|
@@ -285,6 +285,7 @@ import { dirname } from "node:path";
|
|
|
285
285
|
var COMMUNITY_REHEARSAL_VERSION = "3.11.14";
|
|
286
286
|
var COMMUNITY_REHEARSAL_ROOT = "/opt/forgezero-rehearsals/community-cluster-api";
|
|
287
287
|
var COMMUNITY_DATABASE_ROOT = "/var/lib/forgezero-rehearsal-cluster";
|
|
288
|
+
var COMMUNITY_CREDENTIAL_PARENT = "/etc/forgezero-rehearsal";
|
|
288
289
|
var COMMUNITY_CREDENTIAL_ROOT = "/etc/forgezero-rehearsal/creds";
|
|
289
290
|
var NODES = new Map([
|
|
290
291
|
["dev-fz-n1", { address: "10.42.0.21", agency: true }],
|
|
@@ -326,6 +327,12 @@ function parseCommunityRehearsalHostRequest(value) {
|
|
|
326
327
|
}
|
|
327
328
|
return row;
|
|
328
329
|
}
|
|
330
|
+
if (action === "cleanup") {
|
|
331
|
+
if (Object.keys(row).some((key) => !["action", "node"].includes(key))) {
|
|
332
|
+
throw new Error("community rehearsal cleanup has unknown fields");
|
|
333
|
+
}
|
|
334
|
+
return { action, node: node.name };
|
|
335
|
+
}
|
|
329
336
|
if (["database-enable", "api-enable", "database-ready", "starter-ready", "api-ready", "database-status", "api-status"].includes(String(action))) {
|
|
330
337
|
if (Object.keys(row).some((key) => !["action", "node"].includes(key)))
|
|
331
338
|
throw new Error("community rehearsal host action has unknown fields");
|
|
@@ -441,6 +448,19 @@ function planCommunityRehearsalPrepare(request) {
|
|
|
441
448
|
{ kind: "unlink", path: request.archivePath }
|
|
442
449
|
];
|
|
443
450
|
}
|
|
451
|
+
function planCommunityRehearsalCleanup() {
|
|
452
|
+
return [
|
|
453
|
+
{ kind: "exec", argv: ["/usr/bin/systemctl", "disable", "--now", "forgezero-community-api.service"], accepted: [0, 1, 5] },
|
|
454
|
+
{ kind: "exec", argv: ["/usr/bin/systemctl", "disable", "--now", "forgezero-rehearsal-db.service"], accepted: [0, 1, 5] },
|
|
455
|
+
{ kind: "unlink", path: "/etc/systemd/system/forgezero-community-api.service" },
|
|
456
|
+
{ kind: "unlink", path: "/etc/systemd/system/forgezero-rehearsal-db.service" },
|
|
457
|
+
{ kind: "remove-tree", path: COMMUNITY_DATABASE_ROOT },
|
|
458
|
+
{ kind: "remove-tree", path: COMMUNITY_REHEARSAL_ROOT },
|
|
459
|
+
{ kind: "remove-tree", path: COMMUNITY_CREDENTIAL_PARENT },
|
|
460
|
+
{ kind: "exec", argv: ["/usr/bin/systemctl", "daemon-reload"] },
|
|
461
|
+
{ kind: "exec", argv: ["/usr/bin/systemctl", "reset-failed", "forgezero-community-api.service", "forgezero-rehearsal-db.service"], accepted: [0, 1, 5] }
|
|
462
|
+
];
|
|
463
|
+
}
|
|
444
464
|
async function exec(argv, stdin) {
|
|
445
465
|
const child = Bun.spawn([...argv], { stdin: stdin === undefined ? "ignore" : "pipe", stdout: "pipe", stderr: "pipe" });
|
|
446
466
|
if (stdin !== undefined && child.stdin && typeof child.stdin !== "number") {
|
|
@@ -503,6 +523,10 @@ async function runCommunityRehearsalHost(request) {
|
|
|
503
523
|
if ((process.getuid?.() ?? -1) !== 0)
|
|
504
524
|
throw new Error("community-rehearsal must run as root");
|
|
505
525
|
const node = exactNode(request.node);
|
|
526
|
+
if (request.action === "cleanup") {
|
|
527
|
+
await applyOperations(planCommunityRehearsalCleanup());
|
|
528
|
+
return { ok: true, action: request.action, node: node.name };
|
|
529
|
+
}
|
|
506
530
|
if (request.action === "prepare") {
|
|
507
531
|
const metadata = lstatSync(request.archivePath);
|
|
508
532
|
if (!metadata.isFile() || metadata.isSymbolicLink() || metadata.size < 1 || metadata.size > 64 * 1024 * 1024 || createHash2("sha256").update(readFileSync2(request.archivePath)).digest("hex") !== request.archiveSha256) {
|
|
@@ -554,10 +578,12 @@ async function runCommunityRehearsalHost(request) {
|
|
|
554
578
|
export {
|
|
555
579
|
runCommunityRehearsalHost,
|
|
556
580
|
planCommunityRehearsalPrepare,
|
|
581
|
+
planCommunityRehearsalCleanup,
|
|
557
582
|
parseCommunityRehearsalHostRequest,
|
|
558
583
|
ensureCommunityRehearsalArango,
|
|
559
584
|
COMMUNITY_REHEARSAL_VERSION,
|
|
560
585
|
COMMUNITY_REHEARSAL_ROOT,
|
|
561
586
|
COMMUNITY_DATABASE_ROOT,
|
|
562
|
-
COMMUNITY_CREDENTIAL_ROOT
|
|
587
|
+
COMMUNITY_CREDENTIAL_ROOT,
|
|
588
|
+
COMMUNITY_CREDENTIAL_PARENT
|
|
563
589
|
};
|
package/dist/fz-agent.js
CHANGED
|
@@ -8448,7 +8448,7 @@ function assertSupportedGuestImage(imageKey) {
|
|
|
8448
8448
|
}
|
|
8449
8449
|
|
|
8450
8450
|
// src/version.ts
|
|
8451
|
-
var VERSION2 = "0.1.
|
|
8451
|
+
var VERSION2 = "0.1.56";
|
|
8452
8452
|
|
|
8453
8453
|
// src/ssh-bootstrap.ts
|
|
8454
8454
|
class SshBootstrapError extends Error {
|
|
@@ -15003,6 +15003,7 @@ import { dirname as dirname11 } from "path";
|
|
|
15003
15003
|
var COMMUNITY_REHEARSAL_VERSION = "3.11.14";
|
|
15004
15004
|
var COMMUNITY_REHEARSAL_ROOT = "/opt/forgezero-rehearsals/community-cluster-api";
|
|
15005
15005
|
var COMMUNITY_DATABASE_ROOT = "/var/lib/forgezero-rehearsal-cluster";
|
|
15006
|
+
var COMMUNITY_CREDENTIAL_PARENT = "/etc/forgezero-rehearsal";
|
|
15006
15007
|
var COMMUNITY_CREDENTIAL_ROOT = "/etc/forgezero-rehearsal/creds";
|
|
15007
15008
|
var NODES = new Map([
|
|
15008
15009
|
["dev-fz-n1", { address: "10.42.0.21", agency: true }],
|
|
@@ -15044,6 +15045,12 @@ function parseCommunityRehearsalHostRequest(value) {
|
|
|
15044
15045
|
}
|
|
15045
15046
|
return row2;
|
|
15046
15047
|
}
|
|
15048
|
+
if (action === "cleanup") {
|
|
15049
|
+
if (Object.keys(row2).some((key) => !["action", "node"].includes(key))) {
|
|
15050
|
+
throw new Error("community rehearsal cleanup has unknown fields");
|
|
15051
|
+
}
|
|
15052
|
+
return { action, node: node.name };
|
|
15053
|
+
}
|
|
15047
15054
|
if (["database-enable", "api-enable", "database-ready", "starter-ready", "api-ready", "database-status", "api-status"].includes(String(action))) {
|
|
15048
15055
|
if (Object.keys(row2).some((key) => !["action", "node"].includes(key)))
|
|
15049
15056
|
throw new Error("community rehearsal host action has unknown fields");
|
|
@@ -15159,6 +15166,19 @@ function planCommunityRehearsalPrepare(request) {
|
|
|
15159
15166
|
{ kind: "unlink", path: request.archivePath }
|
|
15160
15167
|
];
|
|
15161
15168
|
}
|
|
15169
|
+
function planCommunityRehearsalCleanup() {
|
|
15170
|
+
return [
|
|
15171
|
+
{ kind: "exec", argv: ["/usr/bin/systemctl", "disable", "--now", "forgezero-community-api.service"], accepted: [0, 1, 5] },
|
|
15172
|
+
{ kind: "exec", argv: ["/usr/bin/systemctl", "disable", "--now", "forgezero-rehearsal-db.service"], accepted: [0, 1, 5] },
|
|
15173
|
+
{ kind: "unlink", path: "/etc/systemd/system/forgezero-community-api.service" },
|
|
15174
|
+
{ kind: "unlink", path: "/etc/systemd/system/forgezero-rehearsal-db.service" },
|
|
15175
|
+
{ kind: "remove-tree", path: COMMUNITY_DATABASE_ROOT },
|
|
15176
|
+
{ kind: "remove-tree", path: COMMUNITY_REHEARSAL_ROOT },
|
|
15177
|
+
{ kind: "remove-tree", path: COMMUNITY_CREDENTIAL_PARENT },
|
|
15178
|
+
{ kind: "exec", argv: ["/usr/bin/systemctl", "daemon-reload"] },
|
|
15179
|
+
{ kind: "exec", argv: ["/usr/bin/systemctl", "reset-failed", "forgezero-community-api.service", "forgezero-rehearsal-db.service"], accepted: [0, 1, 5] }
|
|
15180
|
+
];
|
|
15181
|
+
}
|
|
15162
15182
|
async function exec(argv2, stdin) {
|
|
15163
15183
|
const child = Bun.spawn([...argv2], { stdin: stdin === undefined ? "ignore" : "pipe", stdout: "pipe", stderr: "pipe" });
|
|
15164
15184
|
if (stdin !== undefined && child.stdin && typeof child.stdin !== "number") {
|
|
@@ -15221,6 +15241,10 @@ async function runCommunityRehearsalHost(request) {
|
|
|
15221
15241
|
if ((process.getuid?.() ?? -1) !== 0)
|
|
15222
15242
|
throw new Error("community-rehearsal must run as root");
|
|
15223
15243
|
const node = exactNode(request.node);
|
|
15244
|
+
if (request.action === "cleanup") {
|
|
15245
|
+
await applyOperations(planCommunityRehearsalCleanup());
|
|
15246
|
+
return { ok: true, action: request.action, node: node.name };
|
|
15247
|
+
}
|
|
15224
15248
|
if (request.action === "prepare") {
|
|
15225
15249
|
const metadata = lstatSync6(request.archivePath);
|
|
15226
15250
|
if (!metadata.isFile() || metadata.isSymbolicLink() || metadata.size < 1 || metadata.size > 64 * 1024 * 1024 || createHash10("sha256").update(readFileSync17(request.archivePath)).digest("hex") !== request.archiveSha256) {
|
package/dist/fz.js
CHANGED
|
@@ -4830,7 +4830,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
|
|
|
4830
4830
|
var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
|
|
4831
4831
|
|
|
4832
4832
|
// src/version.ts
|
|
4833
|
-
var VERSION2 = "0.1.
|
|
4833
|
+
var VERSION2 = "0.1.56";
|
|
4834
4834
|
|
|
4835
4835
|
// src/software.ts
|
|
4836
4836
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -15413,6 +15413,12 @@ var PLATFORM_GENESIS_FLEETS = {
|
|
|
15413
15413
|
...developmentShape
|
|
15414
15414
|
}))
|
|
15415
15415
|
};
|
|
15416
|
+
var DEVELOPMENT_COMMUNITY_REHEARSAL_GUEST = {
|
|
15417
|
+
name: "dev-fz-n4",
|
|
15418
|
+
address: "10.42.0.24",
|
|
15419
|
+
cpuPoolKey: "node7",
|
|
15420
|
+
...developmentShape
|
|
15421
|
+
};
|
|
15416
15422
|
var publicKey = (value) => {
|
|
15417
15423
|
const normalized = value.trim();
|
|
15418
15424
|
if (!/^ssh-(?:ed25519|rsa) [A-Za-z0-9+/]+={0,3}(?: [^\r\n]+)?$/.test(normalized)) {
|
|
@@ -15451,6 +15457,36 @@ function platformGenesisClaims(environment, sshPublicKeys) {
|
|
|
15451
15457
|
}
|
|
15452
15458
|
}));
|
|
15453
15459
|
}
|
|
15460
|
+
function platformCommunityRehearsalClaims(sshPublicKeys) {
|
|
15461
|
+
const keys = [...new Set(sshPublicKeys.map(publicKey))];
|
|
15462
|
+
if (keys.length === 0)
|
|
15463
|
+
throw new Error("platform genesis requires at least one operator SSH public key");
|
|
15464
|
+
const seed = platformGenesisClaims("development", keys);
|
|
15465
|
+
const guest = DEVELOPMENT_COMMUNITY_REHEARSAL_GUEST;
|
|
15466
|
+
return [...seed, {
|
|
15467
|
+
computeKey: `platform:${guest.name}`,
|
|
15468
|
+
claimToken: "offline-platform-genesis",
|
|
15469
|
+
claimExpiresAtTs: Number.MAX_SAFE_INTEGER,
|
|
15470
|
+
attempt: 1,
|
|
15471
|
+
action: "create",
|
|
15472
|
+
bootstrap: { kind: "platform-genesis" },
|
|
15473
|
+
access: { sshUser: "forgezero", sshPublicKeys: keys },
|
|
15474
|
+
spec: {
|
|
15475
|
+
reference: `platform:${guest.name}`,
|
|
15476
|
+
imageKey: SUPPORTED_GUEST_IMAGE.key,
|
|
15477
|
+
guestName: guest.name,
|
|
15478
|
+
guestAddress: guest.address,
|
|
15479
|
+
cpuPoolKey: guest.cpuPoolKey,
|
|
15480
|
+
physicalCores: guest.physicalCores,
|
|
15481
|
+
vcpu: guest.vcpu,
|
|
15482
|
+
memoryGib: guest.memoryGib,
|
|
15483
|
+
diskGib: guest.diskGib,
|
|
15484
|
+
egressGuaranteedMbps: guest.egressGuaranteedMbps,
|
|
15485
|
+
egressBurstMbps: guest.egressBurstMbps,
|
|
15486
|
+
confidential: true
|
|
15487
|
+
}
|
|
15488
|
+
}];
|
|
15489
|
+
}
|
|
15454
15490
|
|
|
15455
15491
|
// src/operator-bootstrap.ts
|
|
15456
15492
|
var REQUEST_LIMIT = 64 * 1024;
|
|
@@ -15604,13 +15640,17 @@ function readOperatorMetalBootstrapRequest(path) {
|
|
|
15604
15640
|
}
|
|
15605
15641
|
function planOperatorMetalBootstrap(request, mode) {
|
|
15606
15642
|
const config = readMetalBootstrapConfig(request.metalConfigFile);
|
|
15607
|
-
|
|
15643
|
+
if (mode === "rehearsal" && request.genesis.environment !== "development") {
|
|
15644
|
+
throw new Error("the disposable four-node Community rehearsal is development-only");
|
|
15645
|
+
}
|
|
15646
|
+
const keys = request.genesis.sshPublicKeyFiles.map((path) => publicIdentity(path));
|
|
15647
|
+
const claims = mode === "rehearsal" ? platformCommunityRehearsalClaims(keys) : platformGenesisClaims(request.genesis.environment, keys);
|
|
15608
15648
|
return {
|
|
15609
15649
|
kind: "metal-remote",
|
|
15610
15650
|
mode,
|
|
15611
15651
|
mutation: mode !== "status",
|
|
15612
15652
|
target: { address: request.target.address, port: request.target.port, user: request.target.user },
|
|
15613
|
-
steps: mode === "status" ? ["verify pinned SSH transport", "run typed fz bootstrap status"] : mode === "genesis" ? ["verify pinned SSH transport", "send three fixed platform-genesis claims to the constrained Metal helper"] : [
|
|
15653
|
+
steps: mode === "status" ? ["verify pinned SSH transport", "run typed fz bootstrap status"] : mode === "genesis" || mode === "rehearsal" ? ["verify pinned SSH transport", mode === "rehearsal" ? "send the fixed three-node seed plus ordinary n4 Community rehearsal claim to the constrained Metal helper" : "send three fixed platform-genesis claims to the constrained Metal helper"] : [
|
|
15614
15654
|
"verify pinned SSH transport and caller-approved SSH agent",
|
|
15615
15655
|
"copy pinned Bun and packaged fz artifacts to private staging",
|
|
15616
15656
|
"stage the strict owner-only metal config and optional seed handoff",
|
|
@@ -15905,10 +15945,11 @@ async function applyOperatorMetalBootstrap(request, mode, options = {}) {
|
|
|
15905
15945
|
const output2 = await remote(exec, request, knownHosts, ["/usr/bin/sudo", "-n", "/usr/local/bin/fz", "bootstrap", "status"], "remote metal status");
|
|
15906
15946
|
return { plan, output: output2 };
|
|
15907
15947
|
}
|
|
15908
|
-
if (mode === "genesis") {
|
|
15948
|
+
if (mode === "genesis" || mode === "rehearsal") {
|
|
15909
15949
|
const keys = request.genesis.sshPublicKeyFiles.map((path) => publicIdentity(path));
|
|
15910
15950
|
const outputs = [];
|
|
15911
|
-
|
|
15951
|
+
const claims = mode === "rehearsal" ? platformCommunityRehearsalClaims(keys) : platformGenesisClaims(request.genesis.environment, keys);
|
|
15952
|
+
for (const claim of claims) {
|
|
15912
15953
|
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)}
|
|
15913
15954
|
`));
|
|
15914
15955
|
}
|
|
@@ -17279,8 +17320,8 @@ async function cmdBootstrap(options, args) {
|
|
|
17279
17320
|
}
|
|
17280
17321
|
if (operation === "metal" && args[1] === "remote") {
|
|
17281
17322
|
const mode = args[2];
|
|
17282
|
-
if (!mode || !["apply", "genesis", "status"].includes(mode) || args[3] !== undefined) {
|
|
17283
|
-
throw new Error("Usage: fz bootstrap metal remote <apply|genesis|status> --bootstrap-config <owner-only-request.json> [--apply]");
|
|
17323
|
+
if (!mode || !["apply", "genesis", "rehearsal", "status"].includes(mode) || args[3] !== undefined) {
|
|
17324
|
+
throw new Error("Usage: fz bootstrap metal remote <apply|genesis|rehearsal|status> --bootstrap-config <owner-only-request.json> [--apply]");
|
|
17284
17325
|
}
|
|
17285
17326
|
if (!options.bootstrapConfigPath)
|
|
17286
17327
|
throw new Error("remote metal bootstrap requires --bootstrap-config");
|
|
@@ -17969,7 +18010,7 @@ function usage() {
|
|
|
17969
18010
|
Persist secret-free public-node acceptance, then remove
|
|
17970
18011
|
the capability-bearing checkpoint and node handoffs
|
|
17971
18012
|
fz bootstrap metal Plan/install an identity-only physical provisioner
|
|
17972
|
-
fz bootstrap metal remote <apply|genesis|status>
|
|
18013
|
+
fz bootstrap metal remote <apply|genesis|rehearsal|status>
|
|
17973
18014
|
Install/bootstrap one pinned blank metal target, then
|
|
17974
18015
|
provision the exact selected three-node genesis seed
|
|
17975
18016
|
fz bootstrap status Verify persisted profile and supervised units
|
package/dist/metal-bootstrap.js
CHANGED
|
@@ -292,7 +292,7 @@ function systemdAgentEgressDirectives(loopbackTcpPorts = []) {
|
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
// src/version.ts
|
|
295
|
-
var VERSION = "0.1.
|
|
295
|
+
var VERSION = "0.1.56";
|
|
296
296
|
|
|
297
297
|
// src/otel-collector.ts
|
|
298
298
|
var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
|
|
@@ -25,7 +25,7 @@ export interface OperatorMetalBootstrapRequest {
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
export type OperatorPlatformBootstrapMode = 'prepare' | 'apply' | 'status';
|
|
28
|
-
export type OperatorMetalBootstrapMode = 'apply' | 'genesis' | 'status';
|
|
28
|
+
export type OperatorMetalBootstrapMode = 'apply' | 'genesis' | 'rehearsal' | 'status';
|
|
29
29
|
export interface OperatorPlatformBootstrapPlan {
|
|
30
30
|
kind: 'platform-remote';
|
|
31
31
|
mode: OperatorPlatformBootstrapMode;
|
|
@@ -1207,7 +1207,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
|
|
|
1207
1207
|
var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
|
|
1208
1208
|
|
|
1209
1209
|
// src/version.ts
|
|
1210
|
-
var VERSION = "0.1.
|
|
1210
|
+
var VERSION = "0.1.56";
|
|
1211
1211
|
|
|
1212
1212
|
// src/software.ts
|
|
1213
1213
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -5273,6 +5273,12 @@ var PLATFORM_GENESIS_FLEETS = {
|
|
|
5273
5273
|
...developmentShape
|
|
5274
5274
|
}))
|
|
5275
5275
|
};
|
|
5276
|
+
var DEVELOPMENT_COMMUNITY_REHEARSAL_GUEST = {
|
|
5277
|
+
name: "dev-fz-n4",
|
|
5278
|
+
address: "10.42.0.24",
|
|
5279
|
+
cpuPoolKey: "node7",
|
|
5280
|
+
...developmentShape
|
|
5281
|
+
};
|
|
5276
5282
|
var publicKey = (value) => {
|
|
5277
5283
|
const normalized = value.trim();
|
|
5278
5284
|
if (!/^ssh-(?:ed25519|rsa) [A-Za-z0-9+/]+={0,3}(?: [^\r\n]+)?$/.test(normalized)) {
|
|
@@ -5311,6 +5317,36 @@ function platformGenesisClaims(environment, sshPublicKeys) {
|
|
|
5311
5317
|
}
|
|
5312
5318
|
}));
|
|
5313
5319
|
}
|
|
5320
|
+
function platformCommunityRehearsalClaims(sshPublicKeys) {
|
|
5321
|
+
const keys = [...new Set(sshPublicKeys.map(publicKey))];
|
|
5322
|
+
if (keys.length === 0)
|
|
5323
|
+
throw new Error("platform genesis requires at least one operator SSH public key");
|
|
5324
|
+
const seed = platformGenesisClaims("development", keys);
|
|
5325
|
+
const guest = DEVELOPMENT_COMMUNITY_REHEARSAL_GUEST;
|
|
5326
|
+
return [...seed, {
|
|
5327
|
+
computeKey: `platform:${guest.name}`,
|
|
5328
|
+
claimToken: "offline-platform-genesis",
|
|
5329
|
+
claimExpiresAtTs: Number.MAX_SAFE_INTEGER,
|
|
5330
|
+
attempt: 1,
|
|
5331
|
+
action: "create",
|
|
5332
|
+
bootstrap: { kind: "platform-genesis" },
|
|
5333
|
+
access: { sshUser: "forgezero", sshPublicKeys: keys },
|
|
5334
|
+
spec: {
|
|
5335
|
+
reference: `platform:${guest.name}`,
|
|
5336
|
+
imageKey: SUPPORTED_GUEST_IMAGE.key,
|
|
5337
|
+
guestName: guest.name,
|
|
5338
|
+
guestAddress: guest.address,
|
|
5339
|
+
cpuPoolKey: guest.cpuPoolKey,
|
|
5340
|
+
physicalCores: guest.physicalCores,
|
|
5341
|
+
vcpu: guest.vcpu,
|
|
5342
|
+
memoryGib: guest.memoryGib,
|
|
5343
|
+
diskGib: guest.diskGib,
|
|
5344
|
+
egressGuaranteedMbps: guest.egressGuaranteedMbps,
|
|
5345
|
+
egressBurstMbps: guest.egressBurstMbps,
|
|
5346
|
+
confidential: true
|
|
5347
|
+
}
|
|
5348
|
+
}];
|
|
5349
|
+
}
|
|
5314
5350
|
|
|
5315
5351
|
// src/operator-bootstrap.ts
|
|
5316
5352
|
var REQUEST_LIMIT = 64 * 1024;
|
|
@@ -5464,13 +5500,17 @@ function readOperatorMetalBootstrapRequest(path) {
|
|
|
5464
5500
|
}
|
|
5465
5501
|
function planOperatorMetalBootstrap(request, mode) {
|
|
5466
5502
|
const config = readMetalBootstrapConfig(request.metalConfigFile);
|
|
5467
|
-
|
|
5503
|
+
if (mode === "rehearsal" && request.genesis.environment !== "development") {
|
|
5504
|
+
throw new Error("the disposable four-node Community rehearsal is development-only");
|
|
5505
|
+
}
|
|
5506
|
+
const keys = request.genesis.sshPublicKeyFiles.map((path) => publicIdentity(path));
|
|
5507
|
+
const claims = mode === "rehearsal" ? platformCommunityRehearsalClaims(keys) : platformGenesisClaims(request.genesis.environment, keys);
|
|
5468
5508
|
return {
|
|
5469
5509
|
kind: "metal-remote",
|
|
5470
5510
|
mode,
|
|
5471
5511
|
mutation: mode !== "status",
|
|
5472
5512
|
target: { address: request.target.address, port: request.target.port, user: request.target.user },
|
|
5473
|
-
steps: mode === "status" ? ["verify pinned SSH transport", "run typed fz bootstrap status"] : mode === "genesis" ? ["verify pinned SSH transport", "send three fixed platform-genesis claims to the constrained Metal helper"] : [
|
|
5513
|
+
steps: mode === "status" ? ["verify pinned SSH transport", "run typed fz bootstrap status"] : mode === "genesis" || mode === "rehearsal" ? ["verify pinned SSH transport", mode === "rehearsal" ? "send the fixed three-node seed plus ordinary n4 Community rehearsal claim to the constrained Metal helper" : "send three fixed platform-genesis claims to the constrained Metal helper"] : [
|
|
5474
5514
|
"verify pinned SSH transport and caller-approved SSH agent",
|
|
5475
5515
|
"copy pinned Bun and packaged fz artifacts to private staging",
|
|
5476
5516
|
"stage the strict owner-only metal config and optional seed handoff",
|
|
@@ -5765,10 +5805,11 @@ async function applyOperatorMetalBootstrap(request, mode, options = {}) {
|
|
|
5765
5805
|
const output2 = await remote(exec, request, knownHosts, ["/usr/bin/sudo", "-n", "/usr/local/bin/fz", "bootstrap", "status"], "remote metal status");
|
|
5766
5806
|
return { plan, output: output2 };
|
|
5767
5807
|
}
|
|
5768
|
-
if (mode === "genesis") {
|
|
5808
|
+
if (mode === "genesis" || mode === "rehearsal") {
|
|
5769
5809
|
const keys = request.genesis.sshPublicKeyFiles.map((path) => publicIdentity(path));
|
|
5770
5810
|
const outputs = [];
|
|
5771
|
-
|
|
5811
|
+
const claims = mode === "rehearsal" ? platformCommunityRehearsalClaims(keys) : platformGenesisClaims(request.genesis.environment, keys);
|
|
5812
|
+
for (const claim of claims) {
|
|
5772
5813
|
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)}
|
|
5773
5814
|
`));
|
|
5774
5815
|
}
|
|
@@ -2086,7 +2086,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
|
|
|
2086
2086
|
}
|
|
2087
2087
|
|
|
2088
2088
|
// src/version.ts
|
|
2089
|
-
var VERSION3 = "0.1.
|
|
2089
|
+
var VERSION3 = "0.1.56";
|
|
2090
2090
|
|
|
2091
2091
|
// src/egress-policy.ts
|
|
2092
2092
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
@@ -14,4 +14,13 @@ export interface PlatformGenesisGuest {
|
|
|
14
14
|
}
|
|
15
15
|
/** Package-owned provisioning coordinates for the exact three-node platform seed. */
|
|
16
16
|
export declare const PLATFORM_GENESIS_FLEETS: Record<PlatformGenesisEnvironment, readonly PlatformGenesisGuest[]>;
|
|
17
|
+
/**
|
|
18
|
+
* The disposable Community acceptance fleet adds one ordinary post-genesis
|
|
19
|
+
* Coordinator/DBServer host. It is deliberately not part of the three-member
|
|
20
|
+
* platform seed and never acquires Agency authority from this provisioning
|
|
21
|
+
* claim. The rehearsal controller installs that database role later.
|
|
22
|
+
*/
|
|
23
|
+
export declare const DEVELOPMENT_COMMUNITY_REHEARSAL_GUEST: PlatformGenesisGuest;
|
|
17
24
|
export declare function platformGenesisClaims(environment: PlatformGenesisEnvironment, sshPublicKeys: readonly string[]): readonly RemoteProvisionClaim[];
|
|
25
|
+
/** Exact disposable four-host development fleet: three seed guests plus n4. */
|
|
26
|
+
export declare function platformCommunityRehearsalClaims(sshPublicKeys: readonly string[]): readonly RemoteProvisionClaim[];
|
package/dist/provision.js
CHANGED
|
@@ -2086,7 +2086,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
|
|
|
2086
2086
|
}
|
|
2087
2087
|
|
|
2088
2088
|
// src/version.ts
|
|
2089
|
-
var VERSION3 = "0.1.
|
|
2089
|
+
var VERSION3 = "0.1.56";
|
|
2090
2090
|
|
|
2091
2091
|
// src/egress-policy.ts
|
|
2092
2092
|
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.56";
|