@forgezero/agent 0.1.129 → 0.1.130

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.
@@ -917,7 +917,7 @@ async function postSignedNode(options, path, body) {
917
917
  }
918
918
 
919
919
  // src/version.ts
920
- var VERSION3 = "0.1.129";
920
+ var VERSION3 = "0.1.130";
921
921
 
922
922
  // src/agent-heartbeat.ts
923
923
  function readAgentHostMetrics() {
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.129";
1463
+ var VERSION = "0.1.130";
1464
1464
 
1465
1465
  // src/software.ts
1466
1466
  var PINNED_BUN_VERSION = "1.3.14";
@@ -4664,6 +4664,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
4664
4664
  installed = parseStoredState(host.read(STATE_PATH));
4665
4665
  let bootstrapManifest;
4666
4666
  let releaseEvidence;
4667
+ let redundantBootstrapBundle = false;
4667
4668
  if (config.kind === "platform") {
4668
4669
  const staged = host.exists(config.bootstrapBundle.bundleFile) || host.exists(config.bootstrapBundle.manifestFile);
4669
4670
  if (staged && !(host.exists(config.bootstrapBundle.bundleFile) && host.exists(config.bootstrapBundle.manifestFile))) {
@@ -4684,8 +4685,11 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
4684
4685
  if (typeof evidence.revision !== "string" || !/^[a-f0-9]{40}$/.test(evidence.revision) || typeof evidence.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(evidence.sha256) || typeof evidence.branch !== "string")
4685
4686
  throw new Error("bootstrap release evidence is malformed");
4686
4687
  releaseEvidence = { revision: evidence.revision, sha256: evidence.sha256, branch: evidence.branch };
4687
- if (evidence.revision !== reviewed.revision || evidence.sha256 !== reviewed.sha256 || evidence.branch !== reviewed.branch)
4688
+ if (evidence.revision !== reviewed.revision || evidence.branch !== reviewed.branch) {
4688
4689
  bootstrapManifest = reviewed;
4690
+ } else {
4691
+ redundantBootstrapBundle = true;
4692
+ }
4689
4693
  } else if (host.exists(BOOTSTRAP_RELEASE_EVIDENCE)) {
4690
4694
  let evidence;
4691
4695
  try {
@@ -4962,6 +4966,46 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
4962
4966
  await checked3(host, ["nginx", "-t"], "nginx configuration");
4963
4967
  await checked3(host, ["systemctl", "daemon-reload"], "systemd reload");
4964
4968
  await checked3(host, ["systemctl", "enable", "--now", "nginx.service"], "nginx supervision");
4969
+ if (alreadyEnrolled && !bootstrapManifest) {
4970
+ const healthCommand = [
4971
+ "curl",
4972
+ "--fail",
4973
+ "--silent",
4974
+ "--show-error",
4975
+ "--max-time",
4976
+ "10",
4977
+ `http://127.0.0.1:${runtime.environment.publicApiPort}${runtime.healthPath}`
4978
+ ];
4979
+ const health = await host.exec(healthCommand);
4980
+ if (health.exitCode !== 0) {
4981
+ const activeSlotFile = `${runtime.slotsDirectory}/.active`;
4982
+ if (!host.exists(activeSlotFile))
4983
+ throw new Error("enrolled platform active API slot evidence is missing");
4984
+ const activeSlot = host.read(activeSlotFile).trim();
4985
+ if (activeSlot !== "blue" && activeSlot !== "green") {
4986
+ throw new Error("enrolled platform active API slot evidence is malformed");
4987
+ }
4988
+ await checked3(host, ["systemctl", "start", `forgezero@${activeSlot}.service`], "active API slot repair");
4989
+ let ready = false;
4990
+ let lastHealthOutput = "";
4991
+ for (let attempt = 0;attempt < 30; attempt += 1) {
4992
+ const repairedHealth = await host.exec(healthCommand);
4993
+ if (repairedHealth.exitCode === 0) {
4994
+ ready = true;
4995
+ break;
4996
+ }
4997
+ lastHealthOutput = repairedHealth.output.trim();
4998
+ if (attempt < 29)
4999
+ await (host.sleep?.(1000) ?? Bun.sleep(1000));
5000
+ }
5001
+ if (!ready)
5002
+ throw new Error(`repaired API health failed: ${lastHealthOutput || "readiness deadline exceeded"}`);
5003
+ }
5004
+ if (redundantBootstrapBundle) {
5005
+ host.remove(config.bootstrapBundle.bundleFile);
5006
+ host.remove(config.bootstrapBundle.manifestFile);
5007
+ }
5008
+ }
4965
5009
  if (config.database.role === "master") {
4966
5010
  const invite = `${runtime.environment.sharedDirectory}/platform-invite.token`;
4967
5011
  if (!host.exists(invite)) {
package/dist/fz-agent.js CHANGED
@@ -9640,7 +9640,7 @@ async function writeAndCloseProcessInput(input, value) {
9640
9640
  }
9641
9641
 
9642
9642
  // src/version.ts
9643
- var VERSION2 = "0.1.129";
9643
+ var VERSION2 = "0.1.130";
9644
9644
 
9645
9645
  // src/ssh-bootstrap.ts
9646
9646
  function deriveMetalAdmissionProvisioning(lscpu) {
package/dist/fz.js CHANGED
@@ -5788,7 +5788,7 @@ var VaultRuntimeClientError, json = (value) => ({ method: "POST", body: JSON.str
5788
5788
  } catch {
5789
5789
  return;
5790
5790
  }
5791
- }, VERSION = "0.1.26";
5791
+ }, VERSION = "0.1.27";
5792
5792
  var init_dist = __esm(() => {
5793
5793
  init_vault_runtime();
5794
5794
  init_identity();
@@ -6007,7 +6007,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
6007
6007
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
6008
6008
 
6009
6009
  // src/version.ts
6010
- var VERSION2 = "0.1.129";
6010
+ var VERSION2 = "0.1.130";
6011
6011
 
6012
6012
  // src/software.ts
6013
6013
  var PINNED_BUN_VERSION = "1.3.14";
@@ -15284,6 +15284,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
15284
15284
  installed = parseStoredState(host.read(STATE_PATH));
15285
15285
  let bootstrapManifest;
15286
15286
  let releaseEvidence;
15287
+ let redundantBootstrapBundle = false;
15287
15288
  if (config.kind === "platform") {
15288
15289
  const staged = host.exists(config.bootstrapBundle.bundleFile) || host.exists(config.bootstrapBundle.manifestFile);
15289
15290
  if (staged && !(host.exists(config.bootstrapBundle.bundleFile) && host.exists(config.bootstrapBundle.manifestFile))) {
@@ -15304,8 +15305,11 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
15304
15305
  if (typeof evidence.revision !== "string" || !/^[a-f0-9]{40}$/.test(evidence.revision) || typeof evidence.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(evidence.sha256) || typeof evidence.branch !== "string")
15305
15306
  throw new Error("bootstrap release evidence is malformed");
15306
15307
  releaseEvidence = { revision: evidence.revision, sha256: evidence.sha256, branch: evidence.branch };
15307
- if (evidence.revision !== reviewed.revision || evidence.sha256 !== reviewed.sha256 || evidence.branch !== reviewed.branch)
15308
+ if (evidence.revision !== reviewed.revision || evidence.branch !== reviewed.branch) {
15308
15309
  bootstrapManifest = reviewed;
15310
+ } else {
15311
+ redundantBootstrapBundle = true;
15312
+ }
15309
15313
  } else if (host.exists(BOOTSTRAP_RELEASE_EVIDENCE)) {
15310
15314
  let evidence;
15311
15315
  try {
@@ -15582,6 +15586,46 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
15582
15586
  await checked3(host, ["nginx", "-t"], "nginx configuration");
15583
15587
  await checked3(host, ["systemctl", "daemon-reload"], "systemd reload");
15584
15588
  await checked3(host, ["systemctl", "enable", "--now", "nginx.service"], "nginx supervision");
15589
+ if (alreadyEnrolled && !bootstrapManifest) {
15590
+ const healthCommand = [
15591
+ "curl",
15592
+ "--fail",
15593
+ "--silent",
15594
+ "--show-error",
15595
+ "--max-time",
15596
+ "10",
15597
+ `http://127.0.0.1:${runtime.environment.publicApiPort}${runtime.healthPath}`
15598
+ ];
15599
+ const health = await host.exec(healthCommand);
15600
+ if (health.exitCode !== 0) {
15601
+ const activeSlotFile = `${runtime.slotsDirectory}/.active`;
15602
+ if (!host.exists(activeSlotFile))
15603
+ throw new Error("enrolled platform active API slot evidence is missing");
15604
+ const activeSlot = host.read(activeSlotFile).trim();
15605
+ if (activeSlot !== "blue" && activeSlot !== "green") {
15606
+ throw new Error("enrolled platform active API slot evidence is malformed");
15607
+ }
15608
+ await checked3(host, ["systemctl", "start", `forgezero@${activeSlot}.service`], "active API slot repair");
15609
+ let ready = false;
15610
+ let lastHealthOutput = "";
15611
+ for (let attempt = 0;attempt < 30; attempt += 1) {
15612
+ const repairedHealth = await host.exec(healthCommand);
15613
+ if (repairedHealth.exitCode === 0) {
15614
+ ready = true;
15615
+ break;
15616
+ }
15617
+ lastHealthOutput = repairedHealth.output.trim();
15618
+ if (attempt < 29)
15619
+ await (host.sleep?.(1000) ?? Bun.sleep(1000));
15620
+ }
15621
+ if (!ready)
15622
+ throw new Error(`repaired API health failed: ${lastHealthOutput || "readiness deadline exceeded"}`);
15623
+ }
15624
+ if (redundantBootstrapBundle) {
15625
+ host.remove(config.bootstrapBundle.bundleFile);
15626
+ host.remove(config.bootstrapBundle.manifestFile);
15627
+ }
15628
+ }
15585
15629
  if (config.database.role === "master") {
15586
15630
  const invite = `${runtime.environment.sharedDirectory}/platform-invite.token`;
15587
15631
  if (!host.exists(invite)) {
@@ -18174,7 +18218,7 @@ async function applyOperatorPlatformBootstrap(request, mode, options = {}) {
18174
18218
  ` : undefined, mode === "apply");
18175
18219
  return { plan, output };
18176
18220
  } finally {
18177
- if (knownHosts) {
18221
+ if (knownHosts && mode !== "status") {
18178
18222
  await remote(exec, request, knownHosts, ["/usr/bin/sudo", "-n", "/usr/bin/rm", "-rf", "--", REMOTE_STAGE, remoteTemp], "remote bootstrap cleanup", true).catch(() => {
18179
18223
  return;
18180
18224
  });
@@ -366,7 +366,7 @@ function systemdAgentEgressDirectives(loopbackTcpPorts = []) {
366
366
  }
367
367
 
368
368
  // src/version.ts
369
- var VERSION = "0.1.129";
369
+ var VERSION = "0.1.130";
370
370
 
371
371
  // src/otel-collector.ts
372
372
  var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
@@ -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.129";
1463
+ var VERSION = "0.1.130";
1464
1464
 
1465
1465
  // src/software.ts
1466
1466
  var PINNED_BUN_VERSION = "1.3.14";
@@ -4664,6 +4664,7 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
4664
4664
  installed = parseStoredState(host.read(STATE_PATH));
4665
4665
  let bootstrapManifest;
4666
4666
  let releaseEvidence;
4667
+ let redundantBootstrapBundle = false;
4667
4668
  if (config.kind === "platform") {
4668
4669
  const staged = host.exists(config.bootstrapBundle.bundleFile) || host.exists(config.bootstrapBundle.manifestFile);
4669
4670
  if (staged && !(host.exists(config.bootstrapBundle.bundleFile) && host.exists(config.bootstrapBundle.manifestFile))) {
@@ -4684,8 +4685,11 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
4684
4685
  if (typeof evidence.revision !== "string" || !/^[a-f0-9]{40}$/.test(evidence.revision) || typeof evidence.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(evidence.sha256) || typeof evidence.branch !== "string")
4685
4686
  throw new Error("bootstrap release evidence is malformed");
4686
4687
  releaseEvidence = { revision: evidence.revision, sha256: evidence.sha256, branch: evidence.branch };
4687
- if (evidence.revision !== reviewed.revision || evidence.sha256 !== reviewed.sha256 || evidence.branch !== reviewed.branch)
4688
+ if (evidence.revision !== reviewed.revision || evidence.branch !== reviewed.branch) {
4688
4689
  bootstrapManifest = reviewed;
4690
+ } else {
4691
+ redundantBootstrapBundle = true;
4692
+ }
4689
4693
  } else if (host.exists(BOOTSTRAP_RELEASE_EVIDENCE)) {
4690
4694
  let evidence;
4691
4695
  try {
@@ -4962,6 +4966,46 @@ async function applyBootstrap(input, host = localBootstrapHost(), secrets, depen
4962
4966
  await checked3(host, ["nginx", "-t"], "nginx configuration");
4963
4967
  await checked3(host, ["systemctl", "daemon-reload"], "systemd reload");
4964
4968
  await checked3(host, ["systemctl", "enable", "--now", "nginx.service"], "nginx supervision");
4969
+ if (alreadyEnrolled && !bootstrapManifest) {
4970
+ const healthCommand = [
4971
+ "curl",
4972
+ "--fail",
4973
+ "--silent",
4974
+ "--show-error",
4975
+ "--max-time",
4976
+ "10",
4977
+ `http://127.0.0.1:${runtime.environment.publicApiPort}${runtime.healthPath}`
4978
+ ];
4979
+ const health = await host.exec(healthCommand);
4980
+ if (health.exitCode !== 0) {
4981
+ const activeSlotFile = `${runtime.slotsDirectory}/.active`;
4982
+ if (!host.exists(activeSlotFile))
4983
+ throw new Error("enrolled platform active API slot evidence is missing");
4984
+ const activeSlot = host.read(activeSlotFile).trim();
4985
+ if (activeSlot !== "blue" && activeSlot !== "green") {
4986
+ throw new Error("enrolled platform active API slot evidence is malformed");
4987
+ }
4988
+ await checked3(host, ["systemctl", "start", `forgezero@${activeSlot}.service`], "active API slot repair");
4989
+ let ready = false;
4990
+ let lastHealthOutput = "";
4991
+ for (let attempt = 0;attempt < 30; attempt += 1) {
4992
+ const repairedHealth = await host.exec(healthCommand);
4993
+ if (repairedHealth.exitCode === 0) {
4994
+ ready = true;
4995
+ break;
4996
+ }
4997
+ lastHealthOutput = repairedHealth.output.trim();
4998
+ if (attempt < 29)
4999
+ await (host.sleep?.(1000) ?? Bun.sleep(1000));
5000
+ }
5001
+ if (!ready)
5002
+ throw new Error(`repaired API health failed: ${lastHealthOutput || "readiness deadline exceeded"}`);
5003
+ }
5004
+ if (redundantBootstrapBundle) {
5005
+ host.remove(config.bootstrapBundle.bundleFile);
5006
+ host.remove(config.bootstrapBundle.manifestFile);
5007
+ }
5008
+ }
4965
5009
  if (config.database.role === "master") {
4966
5010
  const invite = `${runtime.environment.sharedDirectory}/platform-invite.token`;
4967
5011
  if (!host.exists(invite)) {
@@ -7353,7 +7397,7 @@ async function applyOperatorPlatformBootstrap(request, mode, options = {}) {
7353
7397
  ` : undefined, mode === "apply");
7354
7398
  return { plan, output };
7355
7399
  } finally {
7356
- if (knownHosts) {
7400
+ if (knownHosts && mode !== "status") {
7357
7401
  await remote(exec, request, knownHosts, ["/usr/bin/sudo", "-n", "/usr/bin/rm", "-rf", "--", REMOTE_STAGE, remoteTemp], "remote bootstrap cleanup", true).catch(() => {
7358
7402
  return;
7359
7403
  });
@@ -3020,7 +3020,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
3020
3020
  }
3021
3021
 
3022
3022
  // src/version.ts
3023
- var VERSION3 = "0.1.129";
3023
+ var VERSION3 = "0.1.130";
3024
3024
 
3025
3025
  // src/egress-policy.ts
3026
3026
  import { realpathSync as realpathSync3 } from "node:fs";
package/dist/provision.js CHANGED
@@ -3020,7 +3020,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
3020
3020
  }
3021
3021
 
3022
3022
  // src/version.ts
3023
- var VERSION3 = "0.1.129";
3023
+ var VERSION3 = "0.1.130";
3024
3024
 
3025
3025
  // src/egress-policy.ts
3026
3026
  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.129";
2
+ export declare const VERSION = "0.1.130";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgezero/agent",
3
- "version": "0.1.129",
3
+ "version": "0.1.130",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "check": "tsc --noEmit",
@@ -16,8 +16,8 @@
16
16
  "@noble/post-quantum": "^0.6.1"
17
17
  },
18
18
  "dependencies": {
19
- "@forgezero/runtime": "0.1.20",
20
- "@forgezero/vault": "0.1.26",
19
+ "@forgezero/runtime": "0.1.21",
20
+ "@forgezero/vault": "0.1.27",
21
21
  "@noble/curves": "2.2.0",
22
22
  "@noble/hashes": "2.2.0",
23
23
  "@noble/post-quantum": "0.6.1",