@forgezero/agent 0.1.71 → 0.1.72

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 CHANGED
@@ -1025,7 +1025,7 @@ import type {
1025
1025
  <a id="forgezero-agent-metal-bootstrap"></a>
1026
1026
  ## @forgezero/agent/metal-bootstrap
1027
1027
 
1028
- Physical-metal bootstrap planning, application and status evidence. This entry exposes 10 named value exports and 6 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
1028
+ Physical-metal bootstrap planning, application and status evidence. This entry exposes 10 named value exports and 7 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
1029
1029
 
1030
1030
  ```text
1031
1031
  import {
@@ -1048,6 +1048,7 @@ import type {
1048
1048
  MetalBootstrapPlan,
1049
1049
  MetalBootstrapResult,
1050
1050
  MetalBootstrapStatus,
1051
+ MetalBootstrapValidationOptions,
1051
1052
  } from '@forgezero/agent/metal-bootstrap';
1052
1053
  ```
1053
1054
 
@@ -749,7 +749,7 @@ async function postSignedNode(options, path, body) {
749
749
  }
750
750
 
751
751
  // src/version.ts
752
- var VERSION3 = "0.1.71";
752
+ var VERSION3 = "0.1.72";
753
753
 
754
754
  // src/agent-heartbeat.ts
755
755
  var unquote = (value) => value.replace(/^['"]|['"]$/g, "");
package/dist/bootstrap.js CHANGED
@@ -1416,7 +1416,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
1416
1416
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
1417
1417
 
1418
1418
  // src/version.ts
1419
- var VERSION = "0.1.71";
1419
+ var VERSION = "0.1.72";
1420
1420
 
1421
1421
  // src/software.ts
1422
1422
  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.71";
8591
+ var VERSION2 = "0.1.72";
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.71";
4832
+ var VERSION2 = "0.1.72";
4833
4833
 
4834
4834
  // src/software.ts
4835
4835
  var PINNED_BUN_VERSION = "1.3.14";
@@ -15522,7 +15522,7 @@ var validUnit = (unit) => {
15522
15522
  throw new MetalBootstrapError("the OTLP collector must be independently supervised");
15523
15523
  }
15524
15524
  };
15525
- function validateMetalBootstrapConfig(config) {
15525
+ function validateMetalBootstrapConfig(config, options = {}) {
15526
15526
  if (!config || typeof config !== "object")
15527
15527
  throw new MetalBootstrapError("metal bootstrap config must be an object");
15528
15528
  exactKeys4(config, ["kind", "metalHostname", "profile", "hostTelemetryEndpoint", "hostTelemetryUnit", "agentSeedFile"], "metal bootstrap config");
@@ -15566,7 +15566,7 @@ function validateMetalBootstrapConfig(config) {
15566
15566
  for (const image of Object.values(config.profile.images))
15567
15567
  if (!image.path.startsWith("/var/lib/forgezero/images/") || resolve8(image.path) !== image.path || /[\0\r\n]/.test(image.path))
15568
15568
  throw new MetalBootstrapError("every pinned guest image must use the fixed image directory");
15569
- if (config.profile.bunVersion !== SUPPORTED_BUN_VERSION || config.profile.bunReleaseSha256 !== SUPPORTED_BUN_RELEASE_SHA256 || config.profile.agentVersion !== VERSION2) {
15569
+ if (!options.allowHistoricalRelease && (config.profile.bunVersion !== SUPPORTED_BUN_VERSION || config.profile.bunReleaseSha256 !== SUPPORTED_BUN_RELEASE_SHA256 || config.profile.agentVersion !== VERSION2)) {
15570
15570
  throw new MetalBootstrapError("metal guest runtime must use the package-owned Bun and Agent release coordinates");
15571
15571
  }
15572
15572
  let api;
@@ -15612,7 +15612,7 @@ function validateOwnerOnlyPath(path, requireRootOwner) {
15612
15612
  throw new MetalBootstrapError(requireRootOwner ? "private bootstrap file must be root-owned" : "private bootstrap file has an unexpected owner");
15613
15613
  }
15614
15614
  }
15615
- function readMetalBootstrapConfig(path) {
15615
+ function readMetalBootstrapConfig(path, options = {}) {
15616
15616
  validateOwnerOnlyPath(path, false);
15617
15617
  const metadata = statSync(path);
15618
15618
  if (metadata.size < 2 || metadata.size > MAX_CONFIG_BYTES)
@@ -15623,7 +15623,7 @@ function readMetalBootstrapConfig(path) {
15623
15623
  } catch {
15624
15624
  throw new MetalBootstrapError("metal bootstrap config is not valid JSON");
15625
15625
  }
15626
- return validateMetalBootstrapConfig(parsed);
15626
+ return validateMetalBootstrapConfig(parsed, options);
15627
15627
  }
15628
15628
  function planMetalBootstrap(config) {
15629
15629
  validateMetalBootstrapConfig(config);
@@ -18331,11 +18331,13 @@ function writeMetalOperatorFiles(directory) {
18331
18331
  function writePlatformGenesisFleet(directory) {
18332
18332
  const output = genesisOutputDirectory(directory);
18333
18333
  const metalRequestFile = bootstrapAnswer("Owner-only metal remote request containing the reviewed genesis guests");
18334
- const metalRequest = readOperatorMetalBootstrapRequest(metalRequestFile);
18334
+ const metalRequest = readOperatorMetalBootstrapRequest(metalRequestFile, { validateMetalConfig: false });
18335
18335
  const guestHostKeysFile = bootstrapAnswer("Owner-only guest host-key evidence file");
18336
18336
  const guestHostKeys = readOperatorGuestHostKeyEvidence(guestHostKeysFile, metalRequest);
18337
18337
  const fleet = metalRequest.genesis.nodes;
18338
- const metalHostname = readMetalBootstrapConfig(metalRequest.metalConfigFile).metalHostname;
18338
+ const metalHostname = readMetalBootstrapConfig(metalRequest.metalConfigFile, {
18339
+ allowHistoricalRelease: true
18340
+ }).metalHostname;
18339
18341
  const checkpointPath = join12(output, "cloudflare-handoff.json");
18340
18342
  const template = interactiveBootstrap("platform", fleet, checkpointPath);
18341
18343
  const region = {
@@ -18443,7 +18445,7 @@ function interactiveBootstrap(kind, genesisGuests, genesisCloudflareCheckpoint)
18443
18445
  const backupBucket = backupEndpoint ? bootstrapAnswer("Backup S3 bucket") : undefined;
18444
18446
  const backupAccessKeyId = backupEndpoint ? bootstrapAnswer("Backup S3 access-key id") : undefined;
18445
18447
  const cloudflareHandoffFile = genesis ? cloudflareHostHandoffPath(genesisCloudflareCheckpoint, computeReference) : bootstrapAnswer("Node-specific Cloudflare host handoff (blank for no public edge)", "");
18446
- const cloudflareNodeName = cloudflareHandoffFile ? bootstrapAnswer("Cloudflare handoff node name", computeReference) : undefined;
18448
+ const cloudflareNodeName = cloudflareHandoffFile ? genesis ? computeReference : bootstrapAnswer("Cloudflare handoff node name", computeReference) : undefined;
18447
18449
  const databaseNetworkMode = "private-lan";
18448
18450
  const enrolmentSource = genesis ? "genesis-derived" : bootstrapAnswer("Enrolment source (genesis-derived/api-token)", "genesis-derived");
18449
18451
  return {
@@ -44,10 +44,17 @@ export interface MetalBootstrapApplyOptions {
44
44
  export declare class MetalBootstrapError extends Error {
45
45
  }
46
46
  export declare function normalizeMetalPublicIdentity(value: string): string;
47
- export declare function validateMetalBootstrapConfig(config: MetalBootstrapConfig): MetalBootstrapConfig;
47
+ export interface MetalBootstrapValidationOptions {
48
+ /**
49
+ * Read identity/topology from a config that was already applied by an older
50
+ * Agent release. New installs and repairs must never set this flag.
51
+ */
52
+ allowHistoricalRelease?: boolean;
53
+ }
54
+ export declare function validateMetalBootstrapConfig(config: MetalBootstrapConfig, options?: MetalBootstrapValidationOptions): MetalBootstrapConfig;
48
55
  /** Reject symlinks and group/world access before parsing coordinates or entropy. */
49
56
  export declare function validateOwnerOnlyPath(path: string, requireRootOwner: boolean): void;
50
- export declare function readMetalBootstrapConfig(path: string): MetalBootstrapConfig;
57
+ export declare function readMetalBootstrapConfig(path: string, options?: MetalBootstrapValidationOptions): MetalBootstrapConfig;
51
58
  export declare function planMetalBootstrap(config: MetalBootstrapConfig): MetalBootstrapPlan;
52
59
  export declare function renderMetalUnits(config: MetalBootstrapConfig): Record<string, string>;
53
60
  export declare function applyMetalBootstrap(config: MetalBootstrapConfig, options: MetalBootstrapApplyOptions): Promise<MetalBootstrapResult>;
@@ -354,7 +354,7 @@ function systemdAgentEgressDirectives(loopbackTcpPorts = []) {
354
354
  }
355
355
 
356
356
  // src/version.ts
357
- var VERSION = "0.1.71";
357
+ var VERSION = "0.1.72";
358
358
 
359
359
  // src/otel-collector.ts
360
360
  var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
@@ -579,7 +579,7 @@ var validUnit = (unit) => {
579
579
  throw new MetalBootstrapError("the OTLP collector must be independently supervised");
580
580
  }
581
581
  };
582
- function validateMetalBootstrapConfig(config) {
582
+ function validateMetalBootstrapConfig(config, options = {}) {
583
583
  if (!config || typeof config !== "object")
584
584
  throw new MetalBootstrapError("metal bootstrap config must be an object");
585
585
  exactKeys(config, ["kind", "metalHostname", "profile", "hostTelemetryEndpoint", "hostTelemetryUnit", "agentSeedFile"], "metal bootstrap config");
@@ -623,7 +623,7 @@ function validateMetalBootstrapConfig(config) {
623
623
  for (const image of Object.values(config.profile.images))
624
624
  if (!image.path.startsWith("/var/lib/forgezero/images/") || resolve(image.path) !== image.path || /[\0\r\n]/.test(image.path))
625
625
  throw new MetalBootstrapError("every pinned guest image must use the fixed image directory");
626
- if (config.profile.bunVersion !== SUPPORTED_BUN_VERSION || config.profile.bunReleaseSha256 !== SUPPORTED_BUN_RELEASE_SHA256 || config.profile.agentVersion !== VERSION) {
626
+ if (!options.allowHistoricalRelease && (config.profile.bunVersion !== SUPPORTED_BUN_VERSION || config.profile.bunReleaseSha256 !== SUPPORTED_BUN_RELEASE_SHA256 || config.profile.agentVersion !== VERSION)) {
627
627
  throw new MetalBootstrapError("metal guest runtime must use the package-owned Bun and Agent release coordinates");
628
628
  }
629
629
  let api;
@@ -669,7 +669,7 @@ function validateOwnerOnlyPath(path, requireRootOwner) {
669
669
  throw new MetalBootstrapError(requireRootOwner ? "private bootstrap file must be root-owned" : "private bootstrap file has an unexpected owner");
670
670
  }
671
671
  }
672
- function readMetalBootstrapConfig(path) {
672
+ function readMetalBootstrapConfig(path, options = {}) {
673
673
  validateOwnerOnlyPath(path, false);
674
674
  const metadata = statSync(path);
675
675
  if (metadata.size < 2 || metadata.size > MAX_CONFIG_BYTES)
@@ -680,7 +680,7 @@ function readMetalBootstrapConfig(path) {
680
680
  } catch {
681
681
  throw new MetalBootstrapError("metal bootstrap config is not valid JSON");
682
682
  }
683
- return validateMetalBootstrapConfig(parsed);
683
+ return validateMetalBootstrapConfig(parsed, options);
684
684
  }
685
685
  function planMetalBootstrap(config) {
686
686
  validateMetalBootstrapConfig(config);
@@ -1416,7 +1416,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
1416
1416
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
1417
1417
 
1418
1418
  // src/version.ts
1419
- var VERSION = "0.1.71";
1419
+ var VERSION = "0.1.72";
1420
1420
 
1421
1421
  // src/software.ts
1422
1422
  var PINNED_BUN_VERSION = "1.3.14";
@@ -5233,7 +5233,7 @@ var validUnit = (unit) => {
5233
5233
  throw new MetalBootstrapError("the OTLP collector must be independently supervised");
5234
5234
  }
5235
5235
  };
5236
- function validateMetalBootstrapConfig(config) {
5236
+ function validateMetalBootstrapConfig(config, options = {}) {
5237
5237
  if (!config || typeof config !== "object")
5238
5238
  throw new MetalBootstrapError("metal bootstrap config must be an object");
5239
5239
  exactKeys2(config, ["kind", "metalHostname", "profile", "hostTelemetryEndpoint", "hostTelemetryUnit", "agentSeedFile"], "metal bootstrap config");
@@ -5277,7 +5277,7 @@ function validateMetalBootstrapConfig(config) {
5277
5277
  for (const image of Object.values(config.profile.images))
5278
5278
  if (!image.path.startsWith("/var/lib/forgezero/images/") || resolve5(image.path) !== image.path || /[\0\r\n]/.test(image.path))
5279
5279
  throw new MetalBootstrapError("every pinned guest image must use the fixed image directory");
5280
- if (config.profile.bunVersion !== SUPPORTED_BUN_VERSION || config.profile.bunReleaseSha256 !== SUPPORTED_BUN_RELEASE_SHA256 || config.profile.agentVersion !== VERSION) {
5280
+ if (!options.allowHistoricalRelease && (config.profile.bunVersion !== SUPPORTED_BUN_VERSION || config.profile.bunReleaseSha256 !== SUPPORTED_BUN_RELEASE_SHA256 || config.profile.agentVersion !== VERSION)) {
5281
5281
  throw new MetalBootstrapError("metal guest runtime must use the package-owned Bun and Agent release coordinates");
5282
5282
  }
5283
5283
  let api;
@@ -5323,7 +5323,7 @@ function validateOwnerOnlyPath(path, requireRootOwner) {
5323
5323
  throw new MetalBootstrapError(requireRootOwner ? "private bootstrap file must be root-owned" : "private bootstrap file has an unexpected owner");
5324
5324
  }
5325
5325
  }
5326
- function readMetalBootstrapConfig(path) {
5326
+ function readMetalBootstrapConfig(path, options = {}) {
5327
5327
  validateOwnerOnlyPath(path, false);
5328
5328
  const metadata = statSync(path);
5329
5329
  if (metadata.size < 2 || metadata.size > MAX_CONFIG_BYTES)
@@ -5334,7 +5334,7 @@ function readMetalBootstrapConfig(path) {
5334
5334
  } catch {
5335
5335
  throw new MetalBootstrapError("metal bootstrap config is not valid JSON");
5336
5336
  }
5337
- return validateMetalBootstrapConfig(parsed);
5337
+ return validateMetalBootstrapConfig(parsed, options);
5338
5338
  }
5339
5339
  function planMetalBootstrap(config) {
5340
5340
  validateMetalBootstrapConfig(config);
@@ -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.71";
2128
+ var VERSION3 = "0.1.72";
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.71";
2128
+ var VERSION3 = "0.1.72";
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.71";
2
+ export declare const VERSION = "0.1.72";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgezero/agent",
3
- "version": "0.1.71",
3
+ "version": "0.1.72",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "check": "tsc --noEmit",