@forgezero/agent 0.1.69 → 0.1.70

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.
@@ -749,7 +749,7 @@ async function postSignedNode(options, path, body) {
749
749
  }
750
750
 
751
751
  // src/version.ts
752
- var VERSION3 = "0.1.69";
752
+ var VERSION3 = "0.1.70";
753
753
 
754
754
  // src/agent-heartbeat.ts
755
755
  var unquote = (value) => value.replace(/^['"]|['"]$/g, "");
package/dist/bootstrap.js CHANGED
@@ -1396,7 +1396,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
1396
1396
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
1397
1397
 
1398
1398
  // src/version.ts
1399
- var VERSION = "0.1.69";
1399
+ var VERSION = "0.1.70";
1400
1400
 
1401
1401
  // src/software.ts
1402
1402
  var PINNED_BUN_VERSION = "1.3.14";
package/dist/fz-agent.js CHANGED
@@ -8588,7 +8588,7 @@ import { join as join3 } from "path";
8588
8588
  import { fileURLToPath } from "url";
8589
8589
 
8590
8590
  // src/version.ts
8591
- var VERSION2 = "0.1.69";
8591
+ var VERSION2 = "0.1.70";
8592
8592
 
8593
8593
  // src/ssh-bootstrap.ts
8594
8594
  class SshBootstrapError extends Error {
package/dist/fz.js CHANGED
@@ -4829,7 +4829,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
4829
4829
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
4830
4830
 
4831
4831
  // src/version.ts
4832
- var VERSION2 = "0.1.69";
4832
+ var VERSION2 = "0.1.70";
4833
4833
 
4834
4834
  // src/software.ts
4835
4835
  var PINNED_BUN_VERSION = "1.3.14";
@@ -18363,6 +18363,45 @@ function interactiveBootstrap(kind, genesisGuests, genesisCloudflareCheckpoint)
18363
18363
  } : {}
18364
18364
  };
18365
18365
  }
18366
+ async function runAttendedPlatformFleet(fleet, apply) {
18367
+ const plan = planOperatorPlatformFleetBootstrap(fleet, "apply");
18368
+ const cloudflare = readCloudflareBootstrapCommandConfig(fleet.cloudflareConfigFile, apply ? "apply" : "plan");
18369
+ const coordinates = operatorPlatformFleetCoordinates(fleet);
18370
+ if (cloudflare.coordinates.nodes.length !== coordinates.nodes.length || coordinates.nodes.some((node, index) => {
18371
+ const edge = cloudflare.coordinates.nodes[index];
18372
+ return edge?.nodeName !== node.computeReference || edge.hostname !== node.nodeHostname || edge.service !== "http://127.0.0.1:3000";
18373
+ })) {
18374
+ throw new Error("Cloudflare coordinates do not match the exact reviewed platform fleet");
18375
+ }
18376
+ const attendedPlan = {
18377
+ kind: "forgezero-attended-platform-bootstrap-plan",
18378
+ mutation: true,
18379
+ cloudflare: {
18380
+ checkpointFile: cloudflare.checkpointPath,
18381
+ nodes: cloudflare.coordinates.nodes.map(({ nodeName, hostname: hostname2 }) => ({ nodeName, hostname: hostname2 }))
18382
+ },
18383
+ fleet: plan,
18384
+ acceptanceFile: fleet.cloudflareAcceptanceFile,
18385
+ completion: ["public ingress verified", "initial custodian invitation printed"]
18386
+ };
18387
+ out.line(JSON.stringify(attendedPlan, null, 2));
18388
+ if (!apply) {
18389
+ out.step("Review the complete Tunnel, hostname, bundle, credential and three-node plan, then repeat with --apply.");
18390
+ return 0;
18391
+ }
18392
+ const first = readOperatorPlatformBootstrapRequest(fleet.requests[0]);
18393
+ const firstConfig = readBootstrapConfig(first.platformConfigFile);
18394
+ if (firstConfig.kind !== "platform")
18395
+ throw new Error("remote platform fleet requires platform configs");
18396
+ const secrets = await promptPlatformBootstrapSecrets(firstConfig);
18397
+ const result = await applyAttendedPlatformBootstrap(fleet, cloudflare, fleet.cloudflareAcceptanceFile, secrets);
18398
+ out.line(JSON.stringify(result, null, 2));
18399
+ if (!result.ok)
18400
+ return 1;
18401
+ out.line();
18402
+ out.step(`Initial custodian invitation: ${result.inviteUrl}`);
18403
+ return 0;
18404
+ }
18366
18405
  async function cmdBootstrap(options, args) {
18367
18406
  try {
18368
18407
  const operation = args[0] ?? "status";
@@ -18384,6 +18423,17 @@ async function cmdBootstrap(options, args) {
18384
18423
  out.line(JSON.stringify({ kind, ...writeMetalOperatorFiles(options.outputPath), mode: "0600" }, null, 2));
18385
18424
  return 0;
18386
18425
  }
18426
+ if (operation === "platform" && args[1] === "launch") {
18427
+ if (args[2] !== undefined || !options.outputPath || options.bootstrapConfigPath) {
18428
+ throw new Error("Usage: fz bootstrap platform launch --output <absolute-owner-only-directory> [--apply]");
18429
+ }
18430
+ const generated = writePlatformGenesisFleet(options.outputPath);
18431
+ const fleet = readOperatorPlatformBootstrapFleetRequest(generated.fleetRequest);
18432
+ if (options.apply && bootstrapAnswer("Type APPLY to run the reviewed Cloudflare and three-compute plan") !== "APPLY") {
18433
+ throw new Error("attended platform bootstrap was not confirmed");
18434
+ }
18435
+ return await runAttendedPlatformFleet(fleet, options.apply);
18436
+ }
18387
18437
  if (operation === "platform" && args[1] === "fleet") {
18388
18438
  const mode = args[2];
18389
18439
  if (!mode || !["apply", "status"].includes(mode) || args[3] !== undefined) {
@@ -18392,50 +18442,12 @@ async function cmdBootstrap(options, args) {
18392
18442
  if (!options.bootstrapConfigPath)
18393
18443
  throw new Error("remote platform fleet bootstrap requires --bootstrap-config");
18394
18444
  const fleet = readOperatorPlatformBootstrapFleetRequest(options.bootstrapConfigPath);
18395
- const plan2 = planOperatorPlatformFleetBootstrap(fleet, mode);
18396
- const cloudflare = readCloudflareBootstrapCommandConfig(fleet.cloudflareConfigFile, options.apply && mode === "apply" ? "apply" : "plan");
18397
- const coordinates = operatorPlatformFleetCoordinates(fleet);
18398
- if (cloudflare.coordinates.nodes.length !== coordinates.nodes.length || coordinates.nodes.some((node, index) => {
18399
- const edge = cloudflare.coordinates.nodes[index];
18400
- return edge?.nodeName !== node.computeReference || edge.hostname !== node.nodeHostname || edge.service !== "http://127.0.0.1:3000";
18401
- })) {
18402
- throw new Error("Cloudflare coordinates do not match the exact reviewed platform fleet");
18403
- }
18404
- if (!options.apply) {
18405
- out.line(JSON.stringify({
18406
- kind: "forgezero-attended-platform-bootstrap-plan",
18407
- mutation: true,
18408
- cloudflare: {
18409
- checkpointFile: cloudflare.checkpointPath,
18410
- nodes: cloudflare.coordinates.nodes.map(({ nodeName, hostname: hostname2 }) => ({ nodeName, hostname: hostname2 }))
18411
- },
18412
- fleet: plan2,
18413
- acceptanceFile: fleet.cloudflareAcceptanceFile,
18414
- completion: ["public ingress verified", "initial custodian invitation printed"]
18415
- }, null, 2));
18416
- out.step("Review the complete Tunnel, hostname, bundle, credential and three-node plan, then repeat with --apply.");
18417
- return 0;
18418
- }
18419
- const first = readOperatorPlatformBootstrapRequest(fleet.requests[0]);
18420
- const firstConfig = readBootstrapConfig(first.platformConfigFile);
18421
- if (firstConfig.kind !== "platform")
18422
- throw new Error("remote platform fleet requires platform configs");
18423
18445
  if (mode === "status") {
18424
- const result3 = await applyOperatorPlatformFleetBootstrap(fleet, mode);
18425
- out.line(JSON.stringify(result3, null, 2));
18426
- return result3.ok ? 0 : 1;
18427
- }
18428
- const secrets2 = mode === "apply" ? await promptPlatformBootstrapSecrets(firstConfig) : undefined;
18429
- if (!secrets2?.cloudflareTunnelToken || !secrets2.cloudflareApiToken) {
18430
- throw new Error("attended platform bootstrap requires both Cloudflare tokens");
18446
+ const result2 = await applyOperatorPlatformFleetBootstrap(fleet, mode);
18447
+ out.line(JSON.stringify(result2, null, 2));
18448
+ return result2.ok ? 0 : 1;
18431
18449
  }
18432
- const result2 = await applyAttendedPlatformBootstrap(fleet, cloudflare, fleet.cloudflareAcceptanceFile, secrets2);
18433
- out.line(JSON.stringify(result2, null, 2));
18434
- if (!result2.ok)
18435
- return 1;
18436
- out.line();
18437
- out.step(`Initial custodian invitation: ${result2.inviteUrl}`);
18438
- return 0;
18450
+ return await runAttendedPlatformFleet(fleet, options.apply);
18439
18451
  }
18440
18452
  if (operation === "platform" && args[1] === "remote") {
18441
18453
  const mode = args[2];
@@ -18583,7 +18595,7 @@ async function cmdBootstrap(options, args) {
18583
18595
  return 0;
18584
18596
  }
18585
18597
  if (!["platform", "repair"].includes(operation)) {
18586
- throw new Error("Usage: fz bootstrap config <metal|platform|cloudflare>|platform [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]");
18598
+ 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]");
18587
18599
  }
18588
18600
  const config = options.bootstrapConfigPath ? readBootstrapConfig(options.bootstrapConfigPath) : operation === "repair" ? (() => {
18589
18601
  throw new Error("repair requires --bootstrap-config so immutable coordinates are revalidated");
@@ -19158,6 +19170,9 @@ function usage() {
19158
19170
  local socket instead of holding an API key
19159
19171
  fz bootstrap platform bundle
19160
19172
  Build one clean exact-revision API Git bundle for genesis
19173
+ fz bootstrap platform launch
19174
+ Prompt, review and run the complete attended platform
19175
+ bootstrap; --output is the owner-only working directory
19161
19176
  fz bootstrap platform remote <apply|status>
19162
19177
  Run typed bootstrap from the operator laptop through
19163
19178
  a pinned host; apply copies and verifies that bundle
@@ -354,7 +354,7 @@ function systemdAgentEgressDirectives(loopbackTcpPorts = []) {
354
354
  }
355
355
 
356
356
  // src/version.ts
357
- var VERSION = "0.1.69";
357
+ var VERSION = "0.1.70";
358
358
 
359
359
  // src/otel-collector.ts
360
360
  var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
@@ -1396,7 +1396,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
1396
1396
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
1397
1397
 
1398
1398
  // src/version.ts
1399
- var VERSION = "0.1.69";
1399
+ var VERSION = "0.1.70";
1400
1400
 
1401
1401
  // src/software.ts
1402
1402
  var PINNED_BUN_VERSION = "1.3.14";
@@ -2125,7 +2125,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
2125
2125
  }
2126
2126
 
2127
2127
  // src/version.ts
2128
- var VERSION3 = "0.1.69";
2128
+ var VERSION3 = "0.1.70";
2129
2129
 
2130
2130
  // src/egress-policy.ts
2131
2131
  import { realpathSync as realpathSync3 } from "node:fs";
package/dist/provision.js CHANGED
@@ -2125,7 +2125,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
2125
2125
  }
2126
2126
 
2127
2127
  // src/version.ts
2128
- var VERSION3 = "0.1.69";
2128
+ var VERSION3 = "0.1.70";
2129
2129
 
2130
2130
  // src/egress-policy.ts
2131
2131
  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.69";
2
+ export declare const VERSION = "0.1.70";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgezero/agent",
3
- "version": "0.1.69",
3
+ "version": "0.1.70",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "check": "tsc --noEmit",