@forgezero/agent 0.1.134 → 0.1.136

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/fz-agent.js CHANGED
@@ -2,8 +2,8 @@
2
2
  // @bun
3
3
 
4
4
  // src/index.ts
5
- import { randomBytes as randomBytes7 } from "crypto";
6
- import { readFileSync as readFileSync20, writeFileSync as writeFileSync18, existsSync as existsSync23, mkdirSync as mkdirSync18, chmodSync as chmodSync19, lstatSync as lstatSync10, statfsSync as statfsSync3 } from "fs";
5
+ import { randomBytes as randomBytes8 } from "crypto";
6
+ import { readFileSync as readFileSync20, writeFileSync as writeFileSync18, existsSync as existsSync23, mkdirSync as mkdirSync18, chmodSync as chmodSync20, lstatSync as lstatSync10, statfsSync as statfsSync3 } from "fs";
7
7
  import { cpus as cpus3, totalmem as totalmem3 } from "os";
8
8
  import { dirname as dirname16, join as join12 } from "path";
9
9
 
@@ -6462,7 +6462,7 @@ function validateBuiltInProvider(requirement2, where) {
6462
6462
 
6463
6463
  // src/deploy-plan.ts
6464
6464
  var DEPLOY_PLAN_FORMAT = "forgezero-deployment-plan";
6465
- var DEPLOY_PLAN_VERSION = 1;
6465
+ var DEPLOY_PLAN_VERSION = 2;
6466
6466
 
6467
6467
  class DeploymentPlanError extends Error {
6468
6468
  constructor(message) {
@@ -6476,6 +6476,13 @@ var ACTION = /^[a-z][a-z0-9.-]{0,127}\/[a-z][a-z0-9.-]{0,127}@[1-9][0-9]{0,5}$/;
6476
6476
  var VERSION = /^[A-Za-z0-9][A-Za-z0-9.+_-]{0,63}$/;
6477
6477
  var ABSOLUTE_PATH = /^\/(?:[A-Za-z0-9._-]+\/?)*$/;
6478
6478
  var HEALTH_PATH = /^\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]{0,255}$/;
6479
+ function deploymentBranch(value, where = "deployment.spec.source.branch") {
6480
+ const branch = boundedString(value, where, 255);
6481
+ if (branch === "@" || branch.startsWith("/") || branch.endsWith("/") || branch.startsWith(".") || branch.endsWith(".") || branch.endsWith(".lock") || branch.includes("..") || branch.includes("//") || branch.includes("@{") || /[\x00-\x20~^:?*\[\\]/.test(branch)) {
6482
+ fail(where, "must be one exact valid Git branch name.");
6483
+ }
6484
+ return branch;
6485
+ }
6479
6486
  var fail = (where, message) => {
6480
6487
  throw new DeploymentPlanError(`${where} ${message}`);
6481
6488
  };
@@ -7111,7 +7118,10 @@ function compileDeployment(sourceValue) {
7111
7118
  if (metadata.description !== undefined)
7112
7119
  boundedString(metadata.description, "deployment.metadata.description", 1024);
7113
7120
  const spec = object(source.spec, "deployment.spec");
7114
- exact3(spec, ["security", "inputs", "credentials", "targets", "requirements", "components", "workflows"], "deployment.spec");
7121
+ exact3(spec, ["source", "security", "inputs", "credentials", "targets", "requirements", "components", "workflows"], "deployment.spec");
7122
+ const sourceSelector = object(spec.source, "deployment.spec.source");
7123
+ exact3(sourceSelector, ["branch"], "deployment.spec.source");
7124
+ deploymentBranch(sourceSelector.branch);
7115
7125
  if (spec.security !== undefined) {
7116
7126
  const security = object(spec.security, "deployment.spec.security");
7117
7127
  exact3(security, ["attestation"], "deployment.spec.security");
@@ -7208,11 +7218,13 @@ function compileDeployment(sourceValue) {
7208
7218
  if (provisioning.metalHostname !== undefined && !/^(?=.{1,253}$)[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?$/.test(String(provisioning.metalHostname)))
7209
7219
  fail(`deployment.spec.targets.${targetName}.provisioning.metalHostname`, "is invalid.");
7210
7220
  const provisionedResources = object(provisioning.resources, `deployment.spec.targets.${targetName}.provisioning.resources`);
7211
- exact3(provisionedResources, ["physicalCores", "vcpu", "memoryGib", "diskGib", "egressGuaranteedMbps", "egressBurstMbps", "confidential"], `deployment.spec.targets.${targetName}.provisioning.resources`);
7221
+ exact3(provisionedResources, ["physicalCores", "vcpu", "memoryGib", "diskGib", "diskEncryption", "egressGuaranteedMbps", "egressBurstMbps", "confidential"], `deployment.spec.targets.${targetName}.provisioning.resources`);
7212
7222
  integer(provisionedResources.physicalCores, `deployment.spec.targets.${targetName}.provisioning.resources.physicalCores`, 1, 1024);
7213
7223
  integer(provisionedResources.vcpu, `deployment.spec.targets.${targetName}.provisioning.resources.vcpu`, 1, 4096);
7214
7224
  integer(provisionedResources.memoryGib, `deployment.spec.targets.${targetName}.provisioning.resources.memoryGib`, 1, 4194304);
7215
7225
  integer(provisionedResources.diskGib, `deployment.spec.targets.${targetName}.provisioning.resources.diskGib`, 1, 1048576);
7226
+ if (provisionedResources.diskEncryption !== undefined && !["none", "luks2"].includes(String(provisionedResources.diskEncryption)))
7227
+ fail(`deployment.spec.targets.${targetName}.provisioning.resources.diskEncryption`, "must be none or luks2.");
7216
7228
  integer(provisionedResources.egressGuaranteedMbps, `deployment.spec.targets.${targetName}.provisioning.resources.egressGuaranteedMbps`, 0, 1e7);
7217
7229
  integer(provisionedResources.egressBurstMbps, `deployment.spec.targets.${targetName}.provisioning.resources.egressBurstMbps`, Number(provisionedResources.egressGuaranteedMbps), 1e7);
7218
7230
  if (typeof provisionedResources.confidential !== "boolean")
@@ -7442,6 +7454,7 @@ function compileDeployment(sourceValue) {
7442
7454
  ...metadata.description ? { description: metadata.description } : {},
7443
7455
  requiredProviders: [...requiredProviders.values()].sort((left, right) => `${left.provider}:${left.contract}:${left.capability}`.localeCompare(`${right.provider}:${right.contract}:${right.capability}`)),
7444
7456
  spec: {
7457
+ source: sourceSelector,
7445
7458
  ...spec.security ? { security: spec.security } : {},
7446
7459
  inputs,
7447
7460
  credentials,
@@ -8568,7 +8581,7 @@ function createDeploymentManager(options) {
8568
8581
  const credential = plan.spec.credentials?.[credentialName];
8569
8582
  if (!credential || !options.cache)
8570
8583
  throw new DeploymentActionError("refused", `credential ${credentialName} is unavailable`);
8571
- environment[environmentName] = await options.cache.get(credential.source.name);
8584
+ environment[environmentName] = await options.cache.get(request.credentialBindings?.[credentialName] ?? credential.source.name);
8572
8585
  credentialValues.push(environment[environmentName]);
8573
8586
  }
8574
8587
  }
@@ -9118,7 +9131,8 @@ async function deployClaim(options, claim) {
9118
9131
  revision: claim.revision,
9119
9132
  releaseExecutor: claim.releaseExecutor,
9120
9133
  ...claim.assignment ? { assignment: claim.assignment } : {},
9121
- ...claim.connectivityCapabilities ? { connectivityCapabilities: claim.connectivityCapabilities } : {}
9134
+ ...claim.connectivityCapabilities ? { connectivityCapabilities: claim.connectivityCapabilities } : {},
9135
+ ...claim.credentialBindings ? { credentialBindings: claim.credentialBindings } : {}
9122
9136
  }).result;
9123
9137
  result = options.telemetry ? await options.telemetry.observe("deployment.run", run2) : await run2();
9124
9138
  } finally {
@@ -9669,7 +9683,7 @@ async function writeAndCloseProcessInput(input, value) {
9669
9683
  }
9670
9684
 
9671
9685
  // src/version.ts
9672
- var VERSION2 = "0.1.134";
9686
+ var VERSION2 = "0.1.136";
9673
9687
 
9674
9688
  // src/ssh-bootstrap.ts
9675
9689
  function deriveMetalAdmissionProvisioning(lscpu) {
@@ -10479,12 +10493,13 @@ function startMetalAdmissionPull(options) {
10479
10493
  }
10480
10494
 
10481
10495
  // src/metal-helper-socket.ts
10482
- import { chmodSync as chmodSync8, existsSync as existsSync8, unlinkSync as unlinkSync6 } from "fs";
10496
+ import { chmodSync as chmodSync9, existsSync as existsSync8, unlinkSync as unlinkSync6 } from "fs";
10483
10497
  import { connect as connect2, createServer as createServer3 } from "net";
10484
10498
 
10485
10499
  // src/metal-provision.ts
10486
- import { createHash as createHash7 } from "crypto";
10500
+ import { createHash as createHash7, randomBytes as randomBytes6 } from "crypto";
10487
10501
  import {
10502
+ chmodSync as chmodSync8,
10488
10503
  existsSync as existsSync7,
10489
10504
  mkdirSync as mkdirSync5,
10490
10505
  readFileSync as readFileSync6,
@@ -10548,6 +10563,10 @@ function guestUnit(spec) {
10548
10563
  `ExecStopPost=-/usr/sbin/ip link del ${spec.tap}`
10549
10564
  ].join(`
10550
10565
  `) : "";
10566
+ const encryptedDisk = spec.diskEncryption ? `LoadCredentialEncrypted=${spec.diskEncryption.credentialName}:${spec.diskEncryption.credentialPath}
10567
+ ExecStartPre=/usr/sbin/cryptsetup open --type luks2 --key-file %d/${spec.diskEncryption.credentialName} ${spec.diskEncryption.source} ${spec.diskEncryption.mapper}
10568
+ ExecStopPost=-/usr/sbin/cryptsetup close ${spec.diskEncryption.mapper}
10569
+ ` : "";
10551
10570
  return `[Unit]
10552
10571
  Description=ForgeZero guest ${spec.name}
10553
10572
  Documentation=https://www.forgezero.net
@@ -10557,7 +10576,7 @@ Wants=network-online.target
10557
10576
  [Service]
10558
10577
  Type=simple
10559
10578
  Slice=forgezero-guests.slice
10560
- ${tapSetup}
10579
+ ${encryptedDisk}${tapSetup}
10561
10580
  ExecStart=${argv2}
10562
10581
  Restart=always
10563
10582
  RestartSec=5
@@ -10848,6 +10867,8 @@ function guestBootstrapOperations(profile, attested = Boolean(profile.confidenti
10848
10867
  validateMetalProfile(profile);
10849
10868
  const agentBun = "/usr/local/lib/forgezero/bun";
10850
10869
  return [
10870
+ ["/usr/sbin/swapoff", "--all"],
10871
+ ["/usr/bin/systemctl", "mask", "--now", "swap.target"],
10851
10872
  ...attested ? [
10852
10873
  ["/usr/sbin/modprobe", "sev-guest"],
10853
10874
  ["/usr/bin/test", "-c", "/dev/sev-guest"]
@@ -10924,6 +10945,7 @@ ${access.sshPublicKeys.map((key) => ` - ${JSON.stringify(key)}`).join(`
10924
10945
  return {
10925
10946
  userData: `#cloud-config
10926
10947
  package_update: true
10948
+ swap: { size: 0 }
10927
10949
  ${users}disable_root: true
10928
10950
  # Git is part of the deployment transport, not a tenant-selected prerequisite:
10929
10951
  # every dynamically claimed repository must be cloneable on a clean image.
@@ -10956,7 +10978,8 @@ var checked2 = async (exec, argv2) => {
10956
10978
  async function provisionMetalGuest(profile, claim, exec) {
10957
10979
  validateMetalProfile(profile);
10958
10980
  assertSupportedGuestImage(claim.spec.imageKey, claim.spec.confidential);
10959
- if (!claim.computeKey || !claim.spec.reference || !SAFE_NAME.test(claim.spec.imageKey) || claim.spec.guestName !== undefined && !SAFE_NAME.test(claim.spec.guestName) || claim.spec.cpuPoolKey !== undefined && !SAFE_NAME.test(claim.spec.cpuPoolKey) || !Number.isInteger(claim.spec.physicalCores) || claim.spec.physicalCores < 1 || claim.spec.physicalCores > 256 || !Number.isInteger(claim.spec.vcpu) || claim.spec.vcpu < 1 || claim.spec.vcpu > 512 || !Number.isInteger(claim.spec.memoryGib) || claim.spec.memoryGib < 1 || claim.spec.memoryGib > 8192 || !Number.isInteger(claim.spec.diskGib) || claim.spec.diskGib < 8 || claim.spec.diskGib > 65536 || !Number.isInteger(claim.spec.egressGuaranteedMbps) || claim.spec.egressGuaranteedMbps < 0 || !Number.isInteger(claim.spec.egressBurstMbps) || claim.spec.egressBurstMbps < claim.spec.egressGuaranteedMbps)
10981
+ const diskEncryption = claim.spec.diskEncryption ?? "none";
10982
+ if (!claim.computeKey || !claim.spec.reference || !SAFE_NAME.test(claim.spec.imageKey) || claim.spec.guestName !== undefined && !SAFE_NAME.test(claim.spec.guestName) || claim.spec.cpuPoolKey !== undefined && !SAFE_NAME.test(claim.spec.cpuPoolKey) || !Number.isInteger(claim.spec.physicalCores) || claim.spec.physicalCores < 1 || claim.spec.physicalCores > 256 || !Number.isInteger(claim.spec.vcpu) || claim.spec.vcpu < 1 || claim.spec.vcpu > 512 || !Number.isInteger(claim.spec.memoryGib) || claim.spec.memoryGib < 1 || claim.spec.memoryGib > 8192 || !Number.isInteger(claim.spec.diskGib) || claim.spec.diskGib < 8 || claim.spec.diskGib > 65536 || !["none", "luks2"].includes(diskEncryption) || !Number.isInteger(claim.spec.egressGuaranteedMbps) || claim.spec.egressGuaranteedMbps < 0 || !Number.isInteger(claim.spec.egressBurstMbps) || claim.spec.egressBurstMbps < claim.spec.egressGuaranteedMbps)
10960
10983
  throw new MetalProvisionError("invalid compute claim");
10961
10984
  const image = profile.images[claim.spec.imageKey];
10962
10985
  if (!image || !isAbsolute3(image.path) || !SHA256.test(image.sha256)) {
@@ -10985,6 +11008,9 @@ async function provisionMetalGuest(profile, claim, exec) {
10985
11008
  const prior = manifests.find((row2) => row2.computeKey === claim.computeKey);
10986
11009
  if (prior && prior.reference !== claim.spec.reference)
10987
11010
  throw new MetalProvisionError("compute identity conflicts with host inventory");
11011
+ if (prior && (prior.diskEncryption ?? "none") !== diskEncryption) {
11012
+ throw new MetalProvisionError("an allocated guest disk encryption mode is immutable");
11013
+ }
10988
11014
  const address = requestedAddress(profile, claim, manifests);
10989
11015
  const cpuPool = allocateCpuPool(profile, claim, manifests);
10990
11016
  const manifest = prior ?? {
@@ -10996,6 +11022,7 @@ async function provisionMetalGuest(profile, claim, exec) {
10996
11022
  cpuPoolKey: cpuPool.key,
10997
11023
  allowedCpus: cpuPool.cpus,
10998
11024
  allowedMemoryNodes: cpuPool.memoryNodes,
11025
+ diskEncryption,
10999
11026
  phase: "allocating"
11000
11027
  };
11001
11028
  const save = () => writeFileSync6(manifestPath, `${JSON.stringify(manifest, null, 2)}
@@ -11005,8 +11032,70 @@ async function provisionMetalGuest(profile, claim, exec) {
11005
11032
  const exists = (await exec(["lvs", "--noheadings", lv])).exitCode === 0;
11006
11033
  if (!exists)
11007
11034
  await checked2(exec, ["lvcreate", "-y", "-n", name, "-L", `${claim.spec.diskGib}G`, profile.volumeGroup]);
11035
+ const encrypted = diskEncryption === "luks2";
11036
+ const mapper = `fz-${createHash7("sha256").update(claim.computeKey).digest("hex").slice(0, 20)}`;
11037
+ const mappedDisk = `/dev/mapper/${mapper}`;
11038
+ const credentialName = `guest-disk-${createHash7("sha256").update(claim.computeKey).digest("hex").slice(0, 20)}`;
11039
+ const credentialPath = `/etc/forgezero/creds/${credentialName}.cred`;
11040
+ const keyPath = `/run/forgezero/${credentialName}.key`;
11041
+ let imageTarget = lv;
11042
+ if (encrypted) {
11043
+ mkdirSync5(dirname5(credentialPath), { recursive: true, mode: 448 });
11044
+ mkdirSync5(dirname5(keyPath), { recursive: true, mode: 448 });
11045
+ if (existsSync7(keyPath))
11046
+ unlinkSync5(keyPath);
11047
+ if (!existsSync7(credentialPath)) {
11048
+ if (exists && (await exec(["cryptsetup", "isLuks", lv])).exitCode === 0) {
11049
+ throw new MetalProvisionError("encrypted guest disk exists without its sealed unlock credential");
11050
+ }
11051
+ writeFileSync6(keyPath, randomBytes6(64), { mode: 384, flag: "wx" });
11052
+ try {
11053
+ await checked2(exec, ["systemd-creds", "encrypt", `--name=${credentialName}`, keyPath, credentialPath]);
11054
+ chmodSync8(credentialPath, 384);
11055
+ } catch (cause) {
11056
+ if (existsSync7(credentialPath))
11057
+ unlinkSync5(credentialPath);
11058
+ throw cause;
11059
+ }
11060
+ } else {
11061
+ await checked2(exec, ["systemd-creds", "decrypt", `--name=${credentialName}`, credentialPath, keyPath]);
11062
+ }
11063
+ try {
11064
+ if ((await exec(["cryptsetup", "isLuks", lv])).exitCode !== 0) {
11065
+ await checked2(exec, [
11066
+ "cryptsetup",
11067
+ "luksFormat",
11068
+ "--batch-mode",
11069
+ "--type",
11070
+ "luks2",
11071
+ "--cipher",
11072
+ "aes-xts-plain64",
11073
+ "--key-size",
11074
+ "512",
11075
+ "--key-file",
11076
+ keyPath,
11077
+ lv
11078
+ ]);
11079
+ }
11080
+ if ((await exec(["cryptsetup", "status", mapper])).exitCode !== 0) {
11081
+ await checked2(exec, ["cryptsetup", "open", "--type", "luks2", "--key-file", keyPath, lv, mapper]);
11082
+ }
11083
+ imageTarget = mappedDisk;
11084
+ if (manifest.phase === "allocating") {
11085
+ await checked2(exec, ["qemu-img", "convert", "-O", "raw", image.path, imageTarget]);
11086
+ manifest.phase = "image-ready";
11087
+ save();
11088
+ }
11089
+ } finally {
11090
+ if (existsSync7(keyPath))
11091
+ unlinkSync5(keyPath);
11092
+ if ((await exec(["cryptsetup", "status", mapper])).exitCode === 0) {
11093
+ await checked2(exec, ["cryptsetup", "close", mapper]);
11094
+ }
11095
+ }
11096
+ }
11008
11097
  if (manifest.phase === "allocating") {
11009
- await checked2(exec, ["qemu-img", "convert", "-O", "raw", image.path, lv]);
11098
+ await checked2(exec, ["qemu-img", "convert", "-O", "raw", image.path, imageTarget]);
11010
11099
  manifest.phase = "image-ready";
11011
11100
  save();
11012
11101
  }
@@ -11030,7 +11119,8 @@ async function provisionMetalGuest(profile, claim, exec) {
11030
11119
  memoryGib: claim.spec.memoryGib,
11031
11120
  allowedCpus: manifest.allowedCpus,
11032
11121
  allowedMemoryNodes: manifest.allowedMemoryNodes,
11033
- disk: lv,
11122
+ disk: encrypted ? mappedDisk : lv,
11123
+ ...encrypted ? { diskEncryption: { source: lv, mapper, credentialName, credentialPath } } : {},
11034
11124
  seed,
11035
11125
  bridge: profile.bridge,
11036
11126
  mac: manifest.mac,
@@ -11088,6 +11178,7 @@ function legacyPlatformManifest(profile, claim, name) {
11088
11178
  cpuPoolKey: claim.spec.cpuPoolKey ?? "",
11089
11179
  allowedCpus: values.get("CPUSET") ?? "",
11090
11180
  allowedMemoryNodes: values.get("NUMA"),
11181
+ diskEncryption: "none",
11091
11182
  phase: "running",
11092
11183
  disk,
11093
11184
  unit: `forgezero-guest@${name}.service`
@@ -11102,6 +11193,9 @@ async function removeMetalGuest(profile, claim, exec) {
11102
11193
  const service = `forgezero-guest@${name}.service`;
11103
11194
  const unitPath = join4(profile.unitDir, service);
11104
11195
  const lv = `/dev/${profile.volumeGroup}/${name}`;
11196
+ const mapper = `fz-${createHash7("sha256").update(claim.computeKey).digest("hex").slice(0, 20)}`;
11197
+ const credentialName = `guest-disk-${createHash7("sha256").update(claim.computeKey).digest("hex").slice(0, 20)}`;
11198
+ const credentialPath = `/etc/forgezero/creds/${credentialName}.cred`;
11105
11199
  const manifest = existsSync7(manifestPath) ? JSON.parse(readFileSync6(manifestPath, "utf8")) : legacyPlatformManifest(profile, claim, name);
11106
11200
  if (!manifest) {
11107
11201
  const seedBase = join4(profile.seedDir, name);
@@ -11136,9 +11230,14 @@ async function removeMetalGuest(profile, claim, exec) {
11136
11230
  else if ((await exec(["systemctl", "is-active", service])).exitCode === 0) {
11137
11231
  throw new MetalProvisionError("guest unit is active but its owned unit file is missing");
11138
11232
  }
11233
+ const encrypted = (manifest.diskEncryption ?? "none") === "luks2";
11234
+ if (encrypted && (await exec(["cryptsetup", "status", mapper])).exitCode === 0) {
11235
+ throw new MetalProvisionError("guest disk mapping remained active after the guest stopped");
11236
+ }
11139
11237
  if ((await exec(["lvs", "--noheadings", lv])).exitCode === 0)
11140
11238
  await checked2(exec, ["lvremove", "-fy", lv]);
11141
11239
  for (const path2 of [
11240
+ ...encrypted ? [credentialPath] : [],
11142
11241
  unitPath,
11143
11242
  join4(profile.seedDir, `${name}-seed.iso`),
11144
11243
  join4(profile.seedDir, `${name}-user-data`),
@@ -11239,7 +11338,7 @@ function startMetalHelper(options) {
11239
11338
  });
11240
11339
  socket.on("error", () => socket.destroy());
11241
11340
  });
11242
- server.listen(socketPath, () => chmodSync8(socketPath, 432));
11341
+ server.listen(socketPath, () => chmodSync9(socketPath, 432));
11243
11342
  return {
11244
11343
  server,
11245
11344
  async stop() {
@@ -11279,7 +11378,7 @@ function requestMetalProvision(claim, socketPath = DEFAULT_METAL_HELPER_SOCKET)
11279
11378
  }
11280
11379
 
11281
11380
  // src/deployment-runner.ts
11282
- import { chmodSync as chmodSync9, existsSync as existsSync9, realpathSync, unlinkSync as unlinkSync7 } from "fs";
11381
+ import { chmodSync as chmodSync10, existsSync as existsSync9, realpathSync, unlinkSync as unlinkSync7 } from "fs";
11283
11382
  import { isAbsolute as isAbsolute4, resolve, sep } from "path";
11284
11383
  import { connect as connect3, createServer as createServer4 } from "net";
11285
11384
  var DEFAULT_DEPLOYMENT_RUNNER_SOCKET = "/run/forgezero-deploy/runner.sock";
@@ -11441,7 +11540,7 @@ function startDeploymentRunner(options) {
11441
11540
  const ready = new Promise((resolveReady, rejectReady) => {
11442
11541
  server.once("error", rejectReady);
11443
11542
  server.listen(socketPath, () => {
11444
- chmodSync9(socketPath, options.socketMode ?? 432);
11543
+ chmodSync10(socketPath, options.socketMode ?? 432);
11445
11544
  server.off("error", rejectReady);
11446
11545
  resolveReady();
11447
11546
  });
@@ -11793,7 +11892,7 @@ async function closeServerWithin(server, timeoutMs) {
11793
11892
  }
11794
11893
 
11795
11894
  // src/lifecycle-helper.ts
11796
- import { chmodSync as chmodSync10, existsSync as existsSync11, readFileSync as readFileSync7, unlinkSync as unlinkSync8 } from "fs";
11895
+ import { chmodSync as chmodSync11, existsSync as existsSync11, readFileSync as readFileSync7, unlinkSync as unlinkSync8 } from "fs";
11797
11896
  import { connect as connect4, createConnection, createServer as createServer5, isIP as isIP3 } from "net";
11798
11897
  var DEFAULT_LIFECYCLE_HELPER_SOCKET = "/run/forgezero-lifecycle/helper.sock";
11799
11898
  var MAX_REQUEST_BYTES4 = 16 * 1024;
@@ -11975,7 +12074,7 @@ function startLifecycleHelper(options) {
11975
12074
  });
11976
12075
  socket.on("error", () => socket.destroy());
11977
12076
  });
11978
- server.listen(socketPath, () => chmodSync10(socketPath, 432));
12077
+ server.listen(socketPath, () => chmodSync11(socketPath, 432));
11979
12078
  return {
11980
12079
  server,
11981
12080
  async stop() {
@@ -12015,7 +12114,7 @@ function requestLifecycleAction(claim, socketPath = DEFAULT_LIFECYCLE_HELPER_SOC
12015
12114
  }
12016
12115
 
12017
12116
  // src/warp-config.ts
12018
- import { chmodSync as chmodSync11, mkdirSync as mkdirSync7, renameSync as renameSync6, symlinkSync as symlinkSync3, unlinkSync as unlinkSync9, writeFileSync as writeFileSync8 } from "fs";
12117
+ import { chmodSync as chmodSync12, mkdirSync as mkdirSync7, renameSync as renameSync6, symlinkSync as symlinkSync3, unlinkSync as unlinkSync9, writeFileSync as writeFileSync8 } from "fs";
12019
12118
  var xml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
12020
12119
  function renderWarpMdm(options) {
12021
12120
  if (!/^[a-z0-9][a-z0-9-]{0,62}$/i.test(options.organization))
@@ -12040,7 +12139,7 @@ function materializeWarpMdm(options) {
12040
12139
  mkdirSync7(servicePath.replace(/\/[^/]+$/, ""), { recursive: true, mode: 448 });
12041
12140
  const next = `${runtimePath}.next`;
12042
12141
  writeFileSync8(next, renderWarpMdm(options), { mode: 384 });
12043
- chmodSync11(next, 384);
12142
+ chmodSync12(next, 384);
12044
12143
  renameSync6(next, runtimePath);
12045
12144
  try {
12046
12145
  unlinkSync9(servicePath);
@@ -12098,7 +12197,7 @@ async function configureMeshConnector(input) {
12098
12197
  // src/agent-update.ts
12099
12198
  import { createHash as createHash8, timingSafeEqual, randomUUID as randomUUID2 } from "crypto";
12100
12199
  import {
12101
- chmodSync as chmodSync12,
12200
+ chmodSync as chmodSync13,
12102
12201
  closeSync as closeSync2,
12103
12202
  existsSync as existsSync12,
12104
12203
  fsyncSync,
@@ -12192,8 +12291,8 @@ var checked4 = async (run2, input, label) => {
12192
12291
  return result;
12193
12292
  };
12194
12293
  async function validateReleaseDirectory(directory, release, run2) {
12195
- chmodSync12(directory, 493);
12196
- chmodSync12(join7(directory, "dist"), 493);
12294
+ chmodSync13(directory, 493);
12295
+ chmodSync13(join7(directory, "dist"), 493);
12197
12296
  const manifest = JSON.parse(readFileSync9(join7(directory, "package.json"), "utf8"));
12198
12297
  if (manifest.name !== release.package || manifest.version !== release.version) {
12199
12298
  throw new Error("agent update manifest does not match the selected release");
@@ -12206,7 +12305,7 @@ async function validateReleaseDirectory(directory, release, run2) {
12206
12305
  `)) {
12207
12306
  throw new Error("agent update artifact is not a self-contained Bun executable");
12208
12307
  }
12209
- chmodSync12(binary, 493);
12308
+ chmodSync13(binary, 493);
12210
12309
  }
12211
12310
  const version = (await checked4(run2, { command: agent, args: ["--version"] }, "agent update smoke test")).output.trim();
12212
12311
  if (version !== release.version)
@@ -12325,7 +12424,7 @@ function clearAgentCandidate(root = DEFAULT_AGENT_RELEASE_ROOT) {
12325
12424
  // src/agent-update-helper.ts
12326
12425
  import { randomUUID as randomUUID4 } from "crypto";
12327
12426
  import {
12328
- chmodSync as chmodSync14,
12427
+ chmodSync as chmodSync15,
12329
12428
  closeSync as closeSync3,
12330
12429
  existsSync as existsSync14,
12331
12430
  fsyncSync as fsyncSync2,
@@ -12342,7 +12441,7 @@ import { dirname as dirname8, join as join8, resolve as resolve3 } from "path";
12342
12441
 
12343
12442
  // src/agent-handover.ts
12344
12443
  import { randomUUID as randomUUID3 } from "crypto";
12345
- import { chmodSync as chmodSync13, existsSync as existsSync13, renameSync as renameSync8, rmSync as rmSync6, symlinkSync as symlinkSync5, unlinkSync as unlinkSync10 } from "fs";
12444
+ import { chmodSync as chmodSync14, existsSync as existsSync13, renameSync as renameSync8, rmSync as rmSync6, symlinkSync as symlinkSync5, unlinkSync as unlinkSync10 } from "fs";
12346
12445
  import { basename as basename2, dirname as dirname7 } from "path";
12347
12446
  import { connect as connect5, createServer as createServer6 } from "net";
12348
12447
  var DEFAULT_AGENT_CANDIDATE_READY_SOCKET = "/run/forgezero/candidate-ready.sock";
@@ -12363,7 +12462,7 @@ function startAgentCandidateReady(ready, socketPath = DEFAULT_AGENT_CANDIDATE_RE
12363
12462
  unlinkSync10(socketPath);
12364
12463
  const server = createServer6((socket) => socket.end(`${JSON.stringify(ready)}
12365
12464
  `));
12366
- server.listen(socketPath, () => chmodSync13(socketPath, 432));
12465
+ server.listen(socketPath, () => chmodSync14(socketPath, 432));
12367
12466
  return server;
12368
12467
  }
12369
12468
  function probeAgentCandidate(expected, socketPath = DEFAULT_AGENT_CANDIDATE_READY_SOCKET, timeoutMs = 5000) {
@@ -12916,7 +13015,7 @@ function startAgentUpdateHelper(options = {}) {
12916
13015
  });
12917
13016
  socket.on("error", () => socket.destroy());
12918
13017
  });
12919
- server.listen(socketPath, () => chmodSync14(socketPath, 432));
13018
+ server.listen(socketPath, () => chmodSync15(socketPath, 432));
12920
13019
  return server;
12921
13020
  }
12922
13021
  function requestAgentUpdate(request, socketPath = DEFAULT_AGENT_UPDATE_SOCKET, timeoutMs = 90000) {
@@ -13133,7 +13232,7 @@ function startAgentHeartbeat(options) {
13133
13232
  }
13134
13233
 
13135
13234
  // src/software-helper.ts
13136
- import { chmodSync as chmodSync15, existsSync as existsSync18, mkdirSync as mkdirSync13, unlinkSync as unlinkSync12 } from "fs";
13235
+ import { chmodSync as chmodSync16, existsSync as existsSync18, mkdirSync as mkdirSync13, unlinkSync as unlinkSync12 } from "fs";
13137
13236
  import { connect as connect7, createServer as createServer8 } from "net";
13138
13237
  import { dirname as dirname12 } from "path";
13139
13238
 
@@ -14121,7 +14220,7 @@ function startSoftwareHelper(options = {}) {
14121
14220
  });
14122
14221
  socket.on("error", () => socket.destroy());
14123
14222
  });
14124
- server.listen(socketPath, () => chmodSync15(socketPath, 432));
14223
+ server.listen(socketPath, () => chmodSync16(socketPath, 432));
14125
14224
  return server;
14126
14225
  }
14127
14226
  function requestContainer(op, request, socketPath, timeoutMs) {
@@ -15206,7 +15305,7 @@ var METAL_SYSTEMD_CREDENTIALS = {
15206
15305
 
15207
15306
  // src/platform-bootstrap-runtime.ts
15208
15307
  import {
15209
- chmodSync as chmodSync16,
15308
+ chmodSync as chmodSync17,
15210
15309
  chownSync,
15211
15310
  copyFileSync as copyFileSync2,
15212
15311
  existsSync as existsSync19,
@@ -15305,7 +15404,7 @@ var secureRelease = (path2, uid, gid) => {
15305
15404
  if (metadata.isSymbolicLink())
15306
15405
  return;
15307
15406
  chownSync(current2, uid, gid);
15308
- chmodSync16(current2, metadata.isDirectory() ? 365 : 292);
15407
+ chmodSync17(current2, metadata.isDirectory() ? 365 : 292);
15309
15408
  if (metadata.isDirectory())
15310
15409
  for (const name of readdirSync4(current2))
15311
15410
  visit(join10(current2, name));
@@ -15546,7 +15645,7 @@ import { lstatSync as lstatSync7 } from "fs";
15546
15645
 
15547
15646
  // src/bootstrap.ts
15548
15647
  import {
15549
- chmodSync as chmodSync18,
15648
+ chmodSync as chmodSync19,
15550
15649
  existsSync as existsSync22,
15551
15650
  lstatSync as lstatSync6,
15552
15651
  mkdirSync as mkdirSync16,
@@ -16547,9 +16646,9 @@ function planProvision(options) {
16547
16646
  }
16548
16647
 
16549
16648
  // src/cli/agent-install.ts
16550
- import { randomBytes as randomBytes6 } from "crypto";
16649
+ import { randomBytes as randomBytes7 } from "crypto";
16551
16650
  import {
16552
- chmodSync as chmodSync17,
16651
+ chmodSync as chmodSync18,
16553
16652
  copyFileSync as copyFileSync3,
16554
16653
  existsSync as existsSync21,
16555
16654
  lstatSync as lstatSync5,
@@ -16640,12 +16739,12 @@ var runProvisionOperation = async (operation) => {
16640
16739
  mkdirSync15(`${release}/dist`, { recursive: true, mode: 493 });
16641
16740
  mkdirSync15(dirname13(operation.binary), { recursive: true, mode: 493 });
16642
16741
  copyFileSync3(operation.source, `${release}/dist/fz-agent.js`);
16643
- chmodSync17(`${release}/dist/fz-agent.js`, 493);
16742
+ chmodSync18(`${release}/dist/fz-agent.js`, 493);
16644
16743
  const gitSshSource = `${dirname13(operation.source)}/fz-git-ssh.js`;
16645
16744
  if (!existsSync21(gitSshSource))
16646
16745
  return { stdout: "packaged fz-git-ssh.js is missing", exitCode: 1 };
16647
16746
  copyFileSync3(gitSshSource, `${release}/dist/fz-git-ssh.js`);
16648
- chmodSync17(`${release}/dist/fz-git-ssh.js`, 493);
16747
+ chmodSync18(`${release}/dist/fz-git-ssh.js`, 493);
16649
16748
  const pending = "/opt/forgezero/agent/current.next";
16650
16749
  rmSync11(pending, { force: true });
16651
16750
  symlinkSync7(`versions/${operation.version}`, pending);
@@ -16660,10 +16759,10 @@ var runProvisionOperation = async (operation) => {
16660
16759
  if (operation.kind === "ensure-seed") {
16661
16760
  if (existsSync21(operation.credential) && lstatSync5(operation.credential).size > 0)
16662
16761
  return { stdout: "", exitCode: 0 };
16663
- const seed = randomBytes6(32).toString("base64url");
16762
+ const seed = randomBytes7(32).toString("base64url");
16664
16763
  const result = await fixed(["/usr/bin/systemd-creds", "encrypt", "--name=agent-seed", "-", operation.credential], seed);
16665
16764
  if (result.exitCode === 0)
16666
- chmodSync17(operation.credential, 256);
16765
+ chmodSync18(operation.credential, 256);
16667
16766
  return result;
16668
16767
  }
16669
16768
  if (operation.kind === "ensure-git-identity") {
@@ -16679,7 +16778,7 @@ var runProvisionOperation = async (operation) => {
16679
16778
  result = await fixed(["/usr/bin/systemd-creds", "encrypt", "--name=git-deploy-key", key, operation.credential]);
16680
16779
  if (result.exitCode !== 0)
16681
16780
  return result;
16682
- chmodSync17(operation.credential, 256);
16781
+ chmodSync18(operation.credential, 256);
16683
16782
  }
16684
16783
  if (!existsSync21(operation.publicKey) || lstatSync5(operation.publicKey).size < 1) {
16685
16784
  if (!existsSync21(key)) {
@@ -16713,7 +16812,7 @@ var runProvisionOperation = async (operation) => {
16713
16812
  return { stdout: "bootstrap SSH private-key source is missing or unsafe", exitCode: 1 };
16714
16813
  }
16715
16814
  copyFileSync3(operation.source, key);
16716
- chmodSync17(key, 384);
16815
+ chmodSync18(key, 384);
16717
16816
  } else {
16718
16817
  result = await fixed(["/usr/bin/ssh-keygen", "-q", "-t", "ed25519", "-N", "", "-C", "forgezero-bootstrap-runner", "-f", key]);
16719
16818
  if (result.exitCode !== 0)
@@ -16726,14 +16825,14 @@ var runProvisionOperation = async (operation) => {
16726
16825
  result = await fixed(["/usr/bin/systemd-creds", "encrypt", "--name=bootstrap-ssh-key", key, operation.credential]);
16727
16826
  if (result.exitCode !== 0)
16728
16827
  return result;
16729
- chmodSync17(operation.credential, 256);
16828
+ chmodSync18(operation.credential, 256);
16730
16829
  }
16731
16830
  if (!existsSync21(operation.publicKey) || lstatSync5(operation.publicKey).size < 1) {
16732
16831
  if (!existsSync21(key)) {
16733
16832
  const decrypted = await fixed(["/usr/bin/systemd-creds", "decrypt", "--name=bootstrap-ssh-key", operation.credential, key]);
16734
16833
  if (decrypted.exitCode !== 0)
16735
16834
  return decrypted;
16736
- chmodSync17(key, 384);
16835
+ chmodSync18(key, 384);
16737
16836
  }
16738
16837
  const derived = await fixed(["/usr/bin/ssh-keygen", "-y", "-f", key]);
16739
16838
  const publicKey = normalizeEd25519PublicKey(derived.stdout);
@@ -16743,7 +16842,7 @@ var runProvisionOperation = async (operation) => {
16743
16842
  mkdirSync15(dirname13(operation.publicKey), { recursive: true, mode: 493 });
16744
16843
  writeFileSync15(operation.publicKey, `${publicKey} forgezero-bootstrap-runner
16745
16844
  `, { mode: 292 });
16746
- chmodSync17(operation.publicKey, 292);
16845
+ chmodSync18(operation.publicKey, 292);
16747
16846
  }
16748
16847
  if (operation.source)
16749
16848
  rmSync11(operation.source, { force: true });
@@ -16760,7 +16859,7 @@ var runProvisionOperation = async (operation) => {
16760
16859
  return { stdout: "enrolment source is missing", exitCode: 1 };
16761
16860
  const result = await fixed(["/usr/bin/systemd-creds", "encrypt", "--name=enrol-token", operation.source, operation.credential]);
16762
16861
  if (result.exitCode === 0) {
16763
- chmodSync17(operation.credential, 256);
16862
+ chmodSync18(operation.credential, 256);
16764
16863
  rmSync11(operation.source, { force: true });
16765
16864
  }
16766
16865
  return result;
@@ -17146,7 +17245,7 @@ function localBootstrapHost() {
17146
17245
  mkdirSync16(dirname14(path2), { recursive: true, mode: 493 });
17147
17246
  const temporary = `${path2}.next.${process.pid}`;
17148
17247
  writeFileSync16(temporary, content, { mode });
17149
- chmodSync18(temporary, mode);
17248
+ chmodSync19(temporary, mode);
17150
17249
  renameSync15(temporary, path2);
17151
17250
  },
17152
17251
  mkdir: (path2, mode) => mkdirSync16(path2, { recursive: true, mode }),
@@ -18022,9 +18121,9 @@ function loadOrCreateSeed(path2) {
18022
18121
  return seed2;
18023
18122
  }
18024
18123
  mkdirSync18(dirname16(path2), { recursive: true });
18025
- const seed = new Uint8Array(randomBytes7(32));
18124
+ const seed = new Uint8Array(randomBytes8(32));
18026
18125
  writeFileSync18(path2, Buffer.from(seed).toString("base64url"), { mode: 384 });
18027
- chmodSync19(path2, 384);
18126
+ chmodSync20(path2, 384);
18028
18127
  return seed;
18029
18128
  }
18030
18129
  var DEFAULT_SOCKET_PATH = DEFAULT_SOCKET;