@forgezero/agent 0.1.82 → 0.1.83

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
@@ -85,6 +85,8 @@ Every row links to the detailed explanation and named-import/example area below.
85
85
 
86
86
  bun add -g @forgezero/agent — Install the version-matched fz operator CLI and fz-agent daemon.
87
87
  fz deploy init — Create a typed forgezero.deploy.ts and its canonical inert execution plan.
88
+ fz deploy init --runtime containerd --os ubuntu-24.04 --replicas 1 --cpu-cores 2 --memory-mib 2048 --storage-gib 20 --reuse require — Create one ordinary containerd/runc compute definition with exact reserved resources; existing eligible project capacity is required.
89
+ fz deploy init --runtime kata-snp --os ubuntu-26.04 --replicas 1 --cpu-cores 2 --memory-mib 4096 --storage-gib 40 --reuse prefer — Create one Kata QEMU SEV-SNP definition; reuse eligible capacity first, then provisioning still requires an explicit approved plan and spend ceiling.
88
90
  fz deploy compile — Compile and validate TypeScript deployment intent into .fz/deploy.plan.json.
89
91
  fz deploy check — Refuse stale plans, unsafe provider/action coordinates and unresolved deployment blockers.
90
92
  fz bootstrap platform bundle --root /absolute/api --branch dev --output /secure/forgezero/development/api.bundle — Build one verified release-generation-one source bundle without a Git credential.
@@ -97,6 +99,8 @@ fz status — Read installed service and bootstrap evidence.
97
99
  ```text
98
100
  bun add -g @forgezero/agent
99
101
  fz deploy init
102
+ fz deploy init --runtime containerd --os ubuntu-24.04 --replicas 1 --cpu-cores 2 --memory-mib 2048 --storage-gib 20 --reuse require
103
+ fz deploy init --runtime kata-snp --os ubuntu-26.04 --replicas 1 --cpu-cores 2 --memory-mib 4096 --storage-gib 40 --reuse prefer
100
104
  fz deploy compile
101
105
  fz deploy check
102
106
  fz bootstrap platform bundle --root /absolute/api --branch dev --output /secure/forgezero/development/api.bundle
@@ -1402,7 +1406,7 @@ await runDeploymentPlan({
1402
1406
  <a id="forgezero-agent-deploy-compiler"></a>
1403
1407
  ## @forgezero/agent/deploy-compiler
1404
1408
 
1405
- Explicit developer/CI compiler from forgezero.deploy.ts to canonical .fz/deploy.plan.json; never used to execute project TypeScript in production. This entry exposes 7 named value exports and 1 named type export. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
1409
+ Explicit developer/CI compiler from forgezero.deploy.ts to canonical .fz/deploy.plan.json; never used to execute project TypeScript in production. This entry exposes 7 named value exports and 3 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
1406
1410
 
1407
1411
  ```text
1408
1412
  import {
@@ -1417,6 +1421,8 @@ import {
1417
1421
 
1418
1422
  import type {
1419
1423
  DeploymentCompilation,
1424
+ DeploymentInitOptions,
1425
+ DeploymentInitRuntime,
1420
1426
  } from '@forgezero/agent/deploy-compiler';
1421
1427
  ```
1422
1428
 
@@ -750,7 +750,7 @@ async function postSignedNode(options, path, body) {
750
750
  }
751
751
 
752
752
  // src/version.ts
753
- var VERSION3 = "0.1.82";
753
+ var VERSION3 = "0.1.83";
754
754
 
755
755
  // src/agent-heartbeat.ts
756
756
  function readAgentHostMetrics() {
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.82";
1419
+ var VERSION = "0.1.83";
1420
1420
 
1421
1421
  // src/software.ts
1422
1422
  var PINNED_BUN_VERSION = "1.3.14";
@@ -8,11 +8,24 @@ export interface DeploymentCompilation {
8
8
  digest: `sha256:${string}`;
9
9
  changed: boolean;
10
10
  }
11
- export declare function defaultTypeScriptDeployment(name: string): string;
11
+ export type DeploymentInitRuntime = 'native' | 'containerd' | 'kata-snp';
12
+ export interface DeploymentInitOptions {
13
+ runtime?: DeploymentInitRuntime;
14
+ operatingSystem?: 'ubuntu-24.04' | 'ubuntu-26.04';
15
+ isolation?: 'standard' | 'sev-snp';
16
+ replicas?: number;
17
+ cpuCores?: number;
18
+ memoryMiB?: number;
19
+ storageGiB?: number;
20
+ sharing?: 'exclusive' | 'shared';
21
+ reuse?: 'require' | 'prefer';
22
+ profile?: string;
23
+ }
24
+ export declare function defaultTypeScriptDeployment(name: string, options?: DeploymentInitOptions): string;
12
25
  export declare function initializeTypeScriptDeployment(rootValue: string, options: {
13
26
  name: string;
14
27
  force?: boolean;
15
- }): string;
28
+ } & DeploymentInitOptions): string;
16
29
  export declare function loadDeploymentSource(root: string, sourceFile?: string): Promise<unknown>;
17
30
  export declare function compileDeploymentProject(rootValue: string, options?: {
18
31
  sourceFile?: string;
@@ -1142,46 +1142,82 @@ function parseDeploymentPlan(value) {
1142
1142
  }
1143
1143
 
1144
1144
  // src/deploy-compiler.ts
1145
- import { existsSync, lstatSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
1146
- import { dirname, isAbsolute, relative, resolve, sep } from "path";
1147
- import { pathToFileURL } from "url";
1145
+ import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
1146
+ import { tmpdir } from "os";
1147
+ import { dirname, isAbsolute, join, relative, resolve, sep } from "path";
1148
+ import { fileURLToPath, pathToFileURL } from "url";
1148
1149
  var DEPLOY_SOURCE_FILE = "forgezero.deploy.ts";
1149
1150
  var DEPLOY_PLAN_FILE = ".fz/deploy.plan.json";
1150
1151
  function safeName(value) {
1151
1152
  const result = value.toLowerCase().replace(/^@[^/]+\//, "").replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63);
1152
1153
  return /^[a-z]/.test(result) ? result : `app-${result || "service"}`;
1153
1154
  }
1154
- function defaultTypeScriptDeployment(name) {
1155
- return `import { actions, application, defineDeployment, input, providers, stage, target, workflow } from '@forgezero/agent/deploy';
1156
-
1157
- export default defineDeployment({
1158
- apiVersion: 'deploy.forgezero.net/v1',
1159
- kind: 'Deployment',
1160
- metadata: { name: '${safeName(name)}' },
1161
- spec: {
1162
- security: { attestation: 'preferred' },
1163
- inputs: { replicas: input.integer({ minimum: 1, maximum: 32, default: 1 }) },
1164
- targets: {
1165
- app: target.compute({
1166
- profiles: ['app'],
1167
- replicas: { minimum: 1, desired: input.ref('replicas'), maximum: 32 },
1168
- resources: { cpuCores: 1, memoryMiB: 512, storageGiB: 8 },
1169
- os: 'ubuntu-24.04', runtime: 'native', isolation: 'standard', reuse: 'require'
1170
- })
1171
- },
1172
- requirements: { bun: providers.bun.require() },
1173
- components: {
1155
+ function initCoordinates(options) {
1156
+ const runtime = options.runtime ?? "native";
1157
+ const isolation = options.isolation ?? (runtime === "kata-snp" ? "sev-snp" : "standard");
1158
+ const operatingSystem = options.operatingSystem ?? (isolation === "sev-snp" ? "ubuntu-26.04" : "ubuntu-24.04");
1159
+ const result = {
1160
+ runtime,
1161
+ isolation,
1162
+ operatingSystem,
1163
+ replicas: options.replicas ?? 1,
1164
+ cpuCores: options.cpuCores ?? 1,
1165
+ memoryMiB: options.memoryMiB ?? 512,
1166
+ storageGiB: options.storageGiB ?? 8,
1167
+ sharing: options.sharing ?? "exclusive",
1168
+ reuse: options.reuse ?? "require",
1169
+ profile: options.profile ?? "app"
1170
+ };
1171
+ if (!/^[a-z][a-z0-9-]{0,62}$/.test(result.profile))
1172
+ throw new Error("deployment profile must be a lowercase typed name");
1173
+ if (!Number.isSafeInteger(result.replicas) || result.replicas < 1 || result.replicas > 1024)
1174
+ throw new Error("deployment replicas must be an integer from 1 to 1024");
1175
+ if (!Number.isSafeInteger(result.cpuCores) || result.cpuCores < 1 || result.cpuCores > 1024)
1176
+ throw new Error("deployment CPU cores must be an integer from 1 to 1024");
1177
+ if (!Number.isSafeInteger(result.memoryMiB) || result.memoryMiB < 128 || result.memoryMiB > 4194304)
1178
+ throw new Error("deployment memory must be an integer from 128 to 4194304 MiB");
1179
+ if (!Number.isSafeInteger(result.storageGiB) || result.storageGiB < 1 || result.storageGiB > 1048576)
1180
+ throw new Error("deployment storage must be an integer from 1 to 1048576 GiB");
1181
+ if (runtime === "kata-snp" && isolation !== "sev-snp")
1182
+ throw new Error("kata-snp requires sev-snp isolation");
1183
+ if (runtime === "containerd" && isolation === "sev-snp")
1184
+ throw new Error("containerd runc cannot provide sev-snp; use kata-snp");
1185
+ if (isolation === "sev-snp" && operatingSystem !== "ubuntu-26.04")
1186
+ throw new Error("sev-snp requires ubuntu-26.04");
1187
+ if (runtime === "native" && result.sharing !== "exclusive")
1188
+ throw new Error("native deployments require exclusive compute");
1189
+ return result;
1190
+ }
1191
+ function defaultTypeScriptDeployment(name, options = {}) {
1192
+ const selected = initCoordinates(options);
1193
+ const execution = selected.runtime === "native" ? "native" : selected.runtime === "containerd" ? "oci-runc" : "oci-kata-qemu-snp";
1194
+ const hostPackageVersion = selected.operatingSystem === "ubuntu-24.04" ? "ubuntu-24.04" : "ubuntu-26.04";
1195
+ const requirementBlock = selected.runtime === "native" ? `bun: providers.bun.require()` : selected.runtime === "containerd" ? `containerd: providers.containerd.require({ version: '${hostPackageVersion}' }),
1196
+ nginx: providers.nginx.require({ version: '${hostPackageVersion}' })` : `containerd: providers.containerd.require(),
1197
+ kata: providers.kata.require(),
1198
+ nginx: providers.nginx.require()`;
1199
+ const componentBlock = selected.runtime === "native" ? `
1174
1200
  app: application({
1175
1201
  target: 'app',
1176
1202
  runtime: { kind: 'native', provider: 'forgezero.bun', requirement: 'bun', argv: ['/usr/local/bin/bun', 'run', 'start'] },
1177
1203
  service: { protocol: 'http', port: 3000, health: { protocol: 'http', method: 'GET', path: '/health', expectedStatus: [200], timeoutMs: 5_000 } },
1178
1204
  resources: {},
1179
1205
  rollout: { strategy: 'direct' }
1180
- })
1181
- },
1182
- workflows: {
1183
- deploy: workflow({
1184
- stages: {
1206
+ })` : `
1207
+ app: application({
1208
+ target: 'app',
1209
+ runtime: {
1210
+ kind: 'container', provider: '${selected.runtime === "containerd" ? "forgezero.containerd" : "forgezero.kata"}', requirement: '${selected.runtime === "containerd" ? "containerd" : "kata"}', runtimeClass: '${selected.runtime === "containerd" ? "runc" : "kata-qemu-snp"}',
1211
+ image: { source: { kind: 'build', context: '.', dockerfile: 'Dockerfile' } },
1212
+ security: { privileged: false, noNewPrivileges: true, root: 'read-only', dropCapabilities: ['ALL'] }
1213
+ },
1214
+ service: { protocol: 'http', port: 3000, health: { protocol: 'http', method: 'GET', path: '/health', expectedStatus: [200], timeoutMs: 5_000 } },
1215
+ resources: { cpu: { limit: ${selected.cpuCores} }, memory: { limitMiB: ${selected.memoryMiB}, swap: 'disabled' }, pids: { limit: 256 } },
1216
+ storage: [{ class: 'ephemeral', path: '/tmp', type: 'tmpfs', sizeMiB: ${Math.min(128, Math.max(16, Math.floor(selected.memoryMiB / 4)))} }],
1217
+ network: { ingress: { exposure: 'loopback', stablePort: 3000 }, container: { mode: 'bridge', network: 'app' } },
1218
+ rollout: { strategy: 'blue-green', proxy: 'nginx', drainMs: 30_000, automaticRollback: true }
1219
+ })`;
1220
+ const workflowBlock = selected.runtime === "native" ? `
1185
1221
  build: stage({ strategy: { mode: 'sequential' }, steps: {
1186
1222
  build: actions.exec.argv(
1187
1223
  { component: 'app', argv: ['/usr/local/bin/fz-agent', 'pipeline-todo', 'replace with the project build argv'] },
@@ -1196,7 +1232,42 @@ export default defineDeployment({
1196
1232
  } }),
1197
1233
  verify: stage({ dependsOn: ['release'], strategy: { mode: 'parallel' }, steps: {
1198
1234
  health: actions.service.health({ component: 'app' }, { scope: { kind: 'each-target', target: 'app' }, timeoutMs: 30_000 })
1199
- } })
1235
+ } })` : `
1236
+ prepare: stage({ strategy: { mode: 'sequential' }, steps: {
1237
+ software: actions.software.ensure({ requirements: [${selected.runtime === "containerd" ? "'containerd', 'nginx'" : "'containerd', 'kata', 'nginx'"}] }, { scope: { kind: 'each-target', target: 'app' }, timeoutMs: 900_000 }),
1238
+ review: actions.exec.argv({ component: 'app', argv: ['/usr/local/bin/fz-agent', 'pipeline-todo', 'review the Dockerfile and container entrypoint'] }, { scope: { kind: 'release-executor' } })
1239
+ } }),
1240
+ build: stage({ dependsOn: ['prepare'], strategy: { mode: 'sequential' }, steps: {
1241
+ image: actions.container.build({ component: 'app' }, { scope: { kind: 'release-executor' }, timeoutMs: 900_000 })
1242
+ } }),
1243
+ release: stage({ dependsOn: ['build'], strategy: { mode: 'blue-green', maximumConcurrency: 1, minimumHealthy: 1 }, steps: {
1244
+ promote: actions.service.promote({ component: 'app', imageDigest: { $ref: 'steps.image.outputs.digest' } }, { scope: { kind: 'each-target', target: 'app' }, timeoutMs: 180_000 })
1245
+ } }),
1246
+ verify: stage({ dependsOn: ['release'], strategy: { mode: 'parallel' }, steps: {
1247
+ health: actions.service.health({ component: 'app' }, { scope: { kind: 'each-target', target: 'app' }, timeoutMs: 30_000 })
1248
+ } })`;
1249
+ return `import { actions, application, defineDeployment, providers, stage, target, workflow } from '@forgezero/agent/deploy';
1250
+
1251
+ export default defineDeployment({
1252
+ apiVersion: 'deploy.forgezero.net/v1',
1253
+ kind: 'Deployment',
1254
+ metadata: { name: '${safeName(name)}' },
1255
+ spec: {
1256
+ security: { attestation: '${selected.isolation === "sev-snp" ? "required" : "preferred"}' },
1257
+ targets: {
1258
+ app: target.compute({
1259
+ profiles: ['${selected.profile}'], replicas: ${selected.replicas},
1260
+ resources: { cpuCores: ${selected.cpuCores}, memoryMiB: ${selected.memoryMiB}, storageGiB: ${selected.storageGiB} },
1261
+ os: '${selected.operatingSystem}', runtime: '${execution}', isolation: '${selected.isolation}',
1262
+ sharing: '${selected.sharing}', reuse: '${selected.reuse}'
1263
+ })
1264
+ },
1265
+ requirements: { ${requirementBlock} },
1266
+ components: {${componentBlock}
1267
+ },
1268
+ workflows: {
1269
+ deploy: workflow({
1270
+ stages: {${workflowBlock}
1200
1271
  }
1201
1272
  })
1202
1273
  }
@@ -1208,7 +1279,7 @@ function initializeTypeScriptDeployment(rootValue, options) {
1208
1279
  const path = localPath(rootValue, DEPLOY_SOURCE_FILE, "deployment source");
1209
1280
  if (existsSync(path) && !options.force)
1210
1281
  throw new Error(`${DEPLOY_SOURCE_FILE} already exists; use --force only when replacing it deliberately`);
1211
- writeFileSync(path, defaultTypeScriptDeployment(options.name), { mode: 420, flag: options.force ? "w" : "wx" });
1282
+ writeFileSync(path, defaultTypeScriptDeployment(options.name, options), { mode: 420, flag: options.force ? "w" : "wx" });
1212
1283
  return path;
1213
1284
  }
1214
1285
  function inside(root, path) {
@@ -1229,10 +1300,35 @@ async function loadDeploymentSource(root, sourceFile = DEPLOY_SOURCE_FILE) {
1229
1300
  const status = lstatSync(source);
1230
1301
  if (!status.isFile() || status.isSymbolicLink() || status.size > 2 * 1024 * 1024)
1231
1302
  throw new Error("deployment source must be one bounded regular file");
1232
- const module = await import(`${pathToFileURL(source).href}?forgezero=${status.mtimeMs}`);
1233
- if (module.default === undefined)
1234
- throw new Error(`${sourceFile} must export one default deployment definition`);
1235
- return module.default;
1303
+ const builtDeploy = new URL("./deploy.js", import.meta.url);
1304
+ const sourceDeploy = new URL("./deploy.ts", import.meta.url);
1305
+ const deployModule = existsSync(fileURLToPath(builtDeploy)) ? builtDeploy.href : sourceDeploy.href;
1306
+ const result = await Bun.build({
1307
+ entrypoints: [source],
1308
+ target: "bun",
1309
+ format: "esm",
1310
+ minify: false,
1311
+ plugins: [{
1312
+ name: "forgezero-deploy-authoring",
1313
+ setup(builder) {
1314
+ builder.onResolve({ filter: /^@forgezero\/agent\/deploy$/ }, () => ({ path: fileURLToPath(deployModule) }));
1315
+ }
1316
+ }]
1317
+ });
1318
+ if (!result.success || result.outputs.length !== 1) {
1319
+ throw new Error(`deployment source compilation failed: ${result.logs.map((entry) => entry.message).join("; ")}`);
1320
+ }
1321
+ const directory = mkdtempSync(join(tmpdir(), "forgezero-deploy-compile-"));
1322
+ const compiled = join(directory, "deployment.mjs");
1323
+ try {
1324
+ writeFileSync(compiled, Buffer.from(await result.outputs[0].arrayBuffer()), { mode: 384, flag: "wx" });
1325
+ const module = await import(`${pathToFileURL(compiled).href}?forgezero=${status.mtimeMs}`);
1326
+ if (module.default === undefined)
1327
+ throw new Error(`${sourceFile} must export one default deployment definition`);
1328
+ return module.default;
1329
+ } finally {
1330
+ rmSync(directory, { recursive: true, force: true });
1331
+ }
1236
1332
  }
1237
1333
  async function compileDeploymentProject(rootValue, options = {}) {
1238
1334
  const root = resolve(rootValue);
package/dist/fz-agent.js CHANGED
@@ -9331,7 +9331,7 @@ async function writeAndCloseProcessInput(input, value) {
9331
9331
  }
9332
9332
 
9333
9333
  // src/version.ts
9334
- var VERSION2 = "0.1.82";
9334
+ var VERSION2 = "0.1.83";
9335
9335
 
9336
9336
  // src/ssh-bootstrap.ts
9337
9337
  class SshBootstrapError extends Error {
package/dist/fz.js CHANGED
@@ -4634,7 +4634,7 @@ var VaultError, runtimeEnvironment = () => typeof process !== "undefined" && pro
4634
4634
  } catch {
4635
4635
  return;
4636
4636
  }
4637
- }, VERSION = "0.1.15";
4637
+ }, VERSION = "0.1.16";
4638
4638
  var init_dist = __esm(() => {
4639
4639
  init_identity();
4640
4640
  VaultError = class VaultError extends Error {
@@ -4811,7 +4811,7 @@ async function spawnWith(command, env, report = () => {}, options = {}) {
4811
4811
 
4812
4812
  // src/cli/index.ts
4813
4813
  import { existsSync as existsSync12, lstatSync as lstatSync10, mkdirSync as mkdirSync13, readFileSync as readFileSync16, writeFileSync as writeFileSync13 } from "fs";
4814
- import { basename as basename3, dirname as dirname14, isAbsolute as isAbsolute7, join as join12, resolve as resolve12 } from "path";
4814
+ import { basename as basename3, dirname as dirname14, isAbsolute as isAbsolute7, join as join13, resolve as resolve12 } from "path";
4815
4815
 
4816
4816
  // src/process-input.ts
4817
4817
  async function writeAndCloseProcessInput(input, value) {
@@ -4821,7 +4821,7 @@ async function writeAndCloseProcessInput(input, value) {
4821
4821
 
4822
4822
  // src/cli/index.ts
4823
4823
  init_dist();
4824
- import { fileURLToPath as fileURLToPath3 } from "url";
4824
+ import { fileURLToPath as fileURLToPath4 } from "url";
4825
4825
  import { hostname } from "os";
4826
4826
 
4827
4827
  // src/agent-update.ts
@@ -4837,7 +4837,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
4837
4837
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
4838
4838
 
4839
4839
  // src/version.ts
4840
- var VERSION2 = "0.1.82";
4840
+ var VERSION2 = "0.1.83";
4841
4841
 
4842
4842
  // src/software.ts
4843
4843
  var PINNED_BUN_VERSION = "1.3.14";
@@ -10365,9 +10365,10 @@ function initializeDeployFile(root, options = {}) {
10365
10365
  }
10366
10366
 
10367
10367
  // src/deploy-compiler.ts
10368
- import { existsSync as existsSync6, lstatSync as lstatSync2, mkdirSync as mkdirSync6, readFileSync as readFileSync6, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
10369
- import { dirname as dirname5, isAbsolute, relative, resolve as resolve4, sep as sep3 } from "path";
10370
- import { pathToFileURL } from "url";
10368
+ import { existsSync as existsSync6, lstatSync as lstatSync2, mkdirSync as mkdirSync6, mkdtempSync, readFileSync as readFileSync6, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
10369
+ import { tmpdir } from "os";
10370
+ import { dirname as dirname5, isAbsolute, join as join5, relative, resolve as resolve4, sep as sep3 } from "path";
10371
+ import { fileURLToPath, pathToFileURL } from "url";
10371
10372
 
10372
10373
  // src/deploy-plan.ts
10373
10374
  import { createHash as createHash2 } from "crypto";
@@ -11518,37 +11519,72 @@ function safeName2(value) {
11518
11519
  const result = value.toLowerCase().replace(/^@[^/]+\//, "").replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63);
11519
11520
  return /^[a-z]/.test(result) ? result : `app-${result || "service"}`;
11520
11521
  }
11521
- function defaultTypeScriptDeployment(name) {
11522
- return `import { actions, application, defineDeployment, input, providers, stage, target, workflow } from '@forgezero/agent/deploy';
11523
-
11524
- export default defineDeployment({
11525
- apiVersion: 'deploy.forgezero.net/v1',
11526
- kind: 'Deployment',
11527
- metadata: { name: '${safeName2(name)}' },
11528
- spec: {
11529
- security: { attestation: 'preferred' },
11530
- inputs: { replicas: input.integer({ minimum: 1, maximum: 32, default: 1 }) },
11531
- targets: {
11532
- app: target.compute({
11533
- profiles: ['app'],
11534
- replicas: { minimum: 1, desired: input.ref('replicas'), maximum: 32 },
11535
- resources: { cpuCores: 1, memoryMiB: 512, storageGiB: 8 },
11536
- os: 'ubuntu-24.04', runtime: 'native', isolation: 'standard', reuse: 'require'
11537
- })
11538
- },
11539
- requirements: { bun: providers.bun.require() },
11540
- components: {
11522
+ function initCoordinates(options) {
11523
+ const runtime = options.runtime ?? "native";
11524
+ const isolation = options.isolation ?? (runtime === "kata-snp" ? "sev-snp" : "standard");
11525
+ const operatingSystem = options.operatingSystem ?? (isolation === "sev-snp" ? "ubuntu-26.04" : "ubuntu-24.04");
11526
+ const result = {
11527
+ runtime,
11528
+ isolation,
11529
+ operatingSystem,
11530
+ replicas: options.replicas ?? 1,
11531
+ cpuCores: options.cpuCores ?? 1,
11532
+ memoryMiB: options.memoryMiB ?? 512,
11533
+ storageGiB: options.storageGiB ?? 8,
11534
+ sharing: options.sharing ?? "exclusive",
11535
+ reuse: options.reuse ?? "require",
11536
+ profile: options.profile ?? "app"
11537
+ };
11538
+ if (!/^[a-z][a-z0-9-]{0,62}$/.test(result.profile))
11539
+ throw new Error("deployment profile must be a lowercase typed name");
11540
+ if (!Number.isSafeInteger(result.replicas) || result.replicas < 1 || result.replicas > 1024)
11541
+ throw new Error("deployment replicas must be an integer from 1 to 1024");
11542
+ if (!Number.isSafeInteger(result.cpuCores) || result.cpuCores < 1 || result.cpuCores > 1024)
11543
+ throw new Error("deployment CPU cores must be an integer from 1 to 1024");
11544
+ if (!Number.isSafeInteger(result.memoryMiB) || result.memoryMiB < 128 || result.memoryMiB > 4194304)
11545
+ throw new Error("deployment memory must be an integer from 128 to 4194304 MiB");
11546
+ if (!Number.isSafeInteger(result.storageGiB) || result.storageGiB < 1 || result.storageGiB > 1048576)
11547
+ throw new Error("deployment storage must be an integer from 1 to 1048576 GiB");
11548
+ if (runtime === "kata-snp" && isolation !== "sev-snp")
11549
+ throw new Error("kata-snp requires sev-snp isolation");
11550
+ if (runtime === "containerd" && isolation === "sev-snp")
11551
+ throw new Error("containerd runc cannot provide sev-snp; use kata-snp");
11552
+ if (isolation === "sev-snp" && operatingSystem !== "ubuntu-26.04")
11553
+ throw new Error("sev-snp requires ubuntu-26.04");
11554
+ if (runtime === "native" && result.sharing !== "exclusive")
11555
+ throw new Error("native deployments require exclusive compute");
11556
+ return result;
11557
+ }
11558
+ function defaultTypeScriptDeployment(name, options = {}) {
11559
+ const selected = initCoordinates(options);
11560
+ const execution = selected.runtime === "native" ? "native" : selected.runtime === "containerd" ? "oci-runc" : "oci-kata-qemu-snp";
11561
+ const hostPackageVersion = selected.operatingSystem === "ubuntu-24.04" ? "ubuntu-24.04" : "ubuntu-26.04";
11562
+ const requirementBlock = selected.runtime === "native" ? `bun: providers.bun.require()` : selected.runtime === "containerd" ? `containerd: providers.containerd.require({ version: '${hostPackageVersion}' }),
11563
+ nginx: providers.nginx.require({ version: '${hostPackageVersion}' })` : `containerd: providers.containerd.require(),
11564
+ kata: providers.kata.require(),
11565
+ nginx: providers.nginx.require()`;
11566
+ const componentBlock = selected.runtime === "native" ? `
11541
11567
  app: application({
11542
11568
  target: 'app',
11543
11569
  runtime: { kind: 'native', provider: 'forgezero.bun', requirement: 'bun', argv: ['/usr/local/bin/bun', 'run', 'start'] },
11544
11570
  service: { protocol: 'http', port: 3000, health: { protocol: 'http', method: 'GET', path: '/health', expectedStatus: [200], timeoutMs: 5_000 } },
11545
11571
  resources: {},
11546
11572
  rollout: { strategy: 'direct' }
11547
- })
11548
- },
11549
- workflows: {
11550
- deploy: workflow({
11551
- stages: {
11573
+ })` : `
11574
+ app: application({
11575
+ target: 'app',
11576
+ runtime: {
11577
+ kind: 'container', provider: '${selected.runtime === "containerd" ? "forgezero.containerd" : "forgezero.kata"}', requirement: '${selected.runtime === "containerd" ? "containerd" : "kata"}', runtimeClass: '${selected.runtime === "containerd" ? "runc" : "kata-qemu-snp"}',
11578
+ image: { source: { kind: 'build', context: '.', dockerfile: 'Dockerfile' } },
11579
+ security: { privileged: false, noNewPrivileges: true, root: 'read-only', dropCapabilities: ['ALL'] }
11580
+ },
11581
+ service: { protocol: 'http', port: 3000, health: { protocol: 'http', method: 'GET', path: '/health', expectedStatus: [200], timeoutMs: 5_000 } },
11582
+ resources: { cpu: { limit: ${selected.cpuCores} }, memory: { limitMiB: ${selected.memoryMiB}, swap: 'disabled' }, pids: { limit: 256 } },
11583
+ storage: [{ class: 'ephemeral', path: '/tmp', type: 'tmpfs', sizeMiB: ${Math.min(128, Math.max(16, Math.floor(selected.memoryMiB / 4)))} }],
11584
+ network: { ingress: { exposure: 'loopback', stablePort: 3000 }, container: { mode: 'bridge', network: 'app' } },
11585
+ rollout: { strategy: 'blue-green', proxy: 'nginx', drainMs: 30_000, automaticRollback: true }
11586
+ })`;
11587
+ const workflowBlock = selected.runtime === "native" ? `
11552
11588
  build: stage({ strategy: { mode: 'sequential' }, steps: {
11553
11589
  build: actions.exec.argv(
11554
11590
  { component: 'app', argv: ['/usr/local/bin/fz-agent', 'pipeline-todo', 'replace with the project build argv'] },
@@ -11563,7 +11599,42 @@ export default defineDeployment({
11563
11599
  } }),
11564
11600
  verify: stage({ dependsOn: ['release'], strategy: { mode: 'parallel' }, steps: {
11565
11601
  health: actions.service.health({ component: 'app' }, { scope: { kind: 'each-target', target: 'app' }, timeoutMs: 30_000 })
11566
- } })
11602
+ } })` : `
11603
+ prepare: stage({ strategy: { mode: 'sequential' }, steps: {
11604
+ software: actions.software.ensure({ requirements: [${selected.runtime === "containerd" ? "'containerd', 'nginx'" : "'containerd', 'kata', 'nginx'"}] }, { scope: { kind: 'each-target', target: 'app' }, timeoutMs: 900_000 }),
11605
+ review: actions.exec.argv({ component: 'app', argv: ['/usr/local/bin/fz-agent', 'pipeline-todo', 'review the Dockerfile and container entrypoint'] }, { scope: { kind: 'release-executor' } })
11606
+ } }),
11607
+ build: stage({ dependsOn: ['prepare'], strategy: { mode: 'sequential' }, steps: {
11608
+ image: actions.container.build({ component: 'app' }, { scope: { kind: 'release-executor' }, timeoutMs: 900_000 })
11609
+ } }),
11610
+ release: stage({ dependsOn: ['build'], strategy: { mode: 'blue-green', maximumConcurrency: 1, minimumHealthy: 1 }, steps: {
11611
+ promote: actions.service.promote({ component: 'app', imageDigest: { $ref: 'steps.image.outputs.digest' } }, { scope: { kind: 'each-target', target: 'app' }, timeoutMs: 180_000 })
11612
+ } }),
11613
+ verify: stage({ dependsOn: ['release'], strategy: { mode: 'parallel' }, steps: {
11614
+ health: actions.service.health({ component: 'app' }, { scope: { kind: 'each-target', target: 'app' }, timeoutMs: 30_000 })
11615
+ } })`;
11616
+ return `import { actions, application, defineDeployment, providers, stage, target, workflow } from '@forgezero/agent/deploy';
11617
+
11618
+ export default defineDeployment({
11619
+ apiVersion: 'deploy.forgezero.net/v1',
11620
+ kind: 'Deployment',
11621
+ metadata: { name: '${safeName2(name)}' },
11622
+ spec: {
11623
+ security: { attestation: '${selected.isolation === "sev-snp" ? "required" : "preferred"}' },
11624
+ targets: {
11625
+ app: target.compute({
11626
+ profiles: ['${selected.profile}'], replicas: ${selected.replicas},
11627
+ resources: { cpuCores: ${selected.cpuCores}, memoryMiB: ${selected.memoryMiB}, storageGiB: ${selected.storageGiB} },
11628
+ os: '${selected.operatingSystem}', runtime: '${execution}', isolation: '${selected.isolation}',
11629
+ sharing: '${selected.sharing}', reuse: '${selected.reuse}'
11630
+ })
11631
+ },
11632
+ requirements: { ${requirementBlock} },
11633
+ components: {${componentBlock}
11634
+ },
11635
+ workflows: {
11636
+ deploy: workflow({
11637
+ stages: {${workflowBlock}
11567
11638
  }
11568
11639
  })
11569
11640
  }
@@ -11575,7 +11646,7 @@ function initializeTypeScriptDeployment(rootValue, options) {
11575
11646
  const path = localPath(rootValue, DEPLOY_SOURCE_FILE, "deployment source");
11576
11647
  if (existsSync6(path) && !options.force)
11577
11648
  throw new Error(`${DEPLOY_SOURCE_FILE} already exists; use --force only when replacing it deliberately`);
11578
- writeFileSync6(path, defaultTypeScriptDeployment(options.name), { mode: 420, flag: options.force ? "w" : "wx" });
11649
+ writeFileSync6(path, defaultTypeScriptDeployment(options.name, options), { mode: 420, flag: options.force ? "w" : "wx" });
11579
11650
  return path;
11580
11651
  }
11581
11652
  function inside(root, path) {
@@ -11596,10 +11667,35 @@ async function loadDeploymentSource(root, sourceFile = DEPLOY_SOURCE_FILE) {
11596
11667
  const status = lstatSync2(source);
11597
11668
  if (!status.isFile() || status.isSymbolicLink() || status.size > 2 * 1024 * 1024)
11598
11669
  throw new Error("deployment source must be one bounded regular file");
11599
- const module = await import(`${pathToFileURL(source).href}?forgezero=${status.mtimeMs}`);
11600
- if (module.default === undefined)
11601
- throw new Error(`${sourceFile} must export one default deployment definition`);
11602
- return module.default;
11670
+ const builtDeploy = new URL("./deploy.js", import.meta.url);
11671
+ const sourceDeploy = new URL("./deploy.ts", import.meta.url);
11672
+ const deployModule = existsSync6(fileURLToPath(builtDeploy)) ? builtDeploy.href : sourceDeploy.href;
11673
+ const result = await Bun.build({
11674
+ entrypoints: [source],
11675
+ target: "bun",
11676
+ format: "esm",
11677
+ minify: false,
11678
+ plugins: [{
11679
+ name: "forgezero-deploy-authoring",
11680
+ setup(builder) {
11681
+ builder.onResolve({ filter: /^@forgezero\/agent\/deploy$/ }, () => ({ path: fileURLToPath(deployModule) }));
11682
+ }
11683
+ }]
11684
+ });
11685
+ if (!result.success || result.outputs.length !== 1) {
11686
+ throw new Error(`deployment source compilation failed: ${result.logs.map((entry) => entry.message).join("; ")}`);
11687
+ }
11688
+ const directory = mkdtempSync(join5(tmpdir(), "forgezero-deploy-compile-"));
11689
+ const compiled = join5(directory, "deployment.mjs");
11690
+ try {
11691
+ writeFileSync6(compiled, Buffer.from(await result.outputs[0].arrayBuffer()), { mode: 384, flag: "wx" });
11692
+ const module = await import(`${pathToFileURL(compiled).href}?forgezero=${status.mtimeMs}`);
11693
+ if (module.default === undefined)
11694
+ throw new Error(`${sourceFile} must export one default deployment definition`);
11695
+ return module.default;
11696
+ } finally {
11697
+ rmSync4(directory, { recursive: true, force: true });
11698
+ }
11603
11699
  }
11604
11700
  async function compileDeploymentProject(rootValue, options = {}) {
11605
11701
  const root = resolve4(rootValue);
@@ -11733,7 +11829,7 @@ import {
11733
11829
  unlinkSync,
11734
11830
  writeFileSync as writeFileSync7
11735
11831
  } from "fs";
11736
- import { dirname as dirname6, join as join5 } from "path";
11832
+ import { dirname as dirname6, join as join6 } from "path";
11737
11833
  import { homedir } from "os";
11738
11834
  var EMPTY2 = () => ({ version: 1, sessions: {} });
11739
11835
  function canonicalApi(value) {
@@ -11751,8 +11847,8 @@ ${realm.trim() || "platform"}`).toString("base64url");
11751
11847
  function defaultSessionPath(env = process.env) {
11752
11848
  if (env.FZ_SESSION_FILE?.trim())
11753
11849
  return env.FZ_SESSION_FILE.trim();
11754
- const state = env.XDG_STATE_HOME?.trim() || join5(homedir(), ".local", "state");
11755
- return join5(state, "forgezero", "sessions.json");
11850
+ const state = env.XDG_STATE_HOME?.trim() || join6(homedir(), ".local", "state");
11851
+ return join6(state, "forgezero", "sessions.json");
11756
11852
  }
11757
11853
  function assertPrivate(path, kind) {
11758
11854
  if (!existsSync7(path))
@@ -11851,7 +11947,7 @@ import {
11851
11947
  writeFileSync as writeFileSync9
11852
11948
  } from "fs";
11853
11949
  import { dirname as dirname9 } from "path";
11854
- import { fileURLToPath } from "url";
11950
+ import { fileURLToPath as fileURLToPath2 } from "url";
11855
11951
 
11856
11952
  // src/ubuntu.ts
11857
11953
  var current = OS_CATALOG[0];
@@ -12427,7 +12523,7 @@ function planLocalOtlpProof(endpoint, collectorUnit) {
12427
12523
  import { constants } from "fs";
12428
12524
  import { createHmac, randomUUID } from "crypto";
12429
12525
  import { chmod, lstat, mkdir, open, readdir, rename, rmdir, stat, unlink } from "fs/promises";
12430
- import { dirname as dirname7, join as join6, resolve as resolve5 } from "path";
12526
+ import { dirname as dirname7, join as join7, resolve as resolve5 } from "path";
12431
12527
  import { isIP as isIP3 } from "net";
12432
12528
 
12433
12529
  // src/cloudflare-edge.ts
@@ -13099,7 +13195,7 @@ function cloudflareHostHandoffPath(checkpointPath, nodeName) {
13099
13195
  const normalized = nodeName.trim().toLowerCase();
13100
13196
  if (!/^[a-z0-9][a-z0-9-]{0,62}$/.test(normalized))
13101
13197
  throw new Error("Cloudflare host handoff node name is invalid");
13102
- return join6(`${resolve5(checkpointPath)}.hosts`, `${normalized}.json`);
13198
+ return join7(`${resolve5(checkpointPath)}.hosts`, `${normalized}.json`);
13103
13199
  }
13104
13200
  async function readCloudflareHostHandoff(handoffPath, nodeName) {
13105
13201
  let parsed;
@@ -13481,7 +13577,7 @@ async function removeCloudflareBootstrapSecrets(checkpointPath, output) {
13481
13577
  throw new Error("Cloudflare host handoff directory contains unexpected files; refusing secret cleanup");
13482
13578
  }
13483
13579
  for (const name of expected)
13484
- await unlink(join6(directory, name));
13580
+ await unlink(join7(directory, name));
13485
13581
  await rmdir(directory);
13486
13582
  }
13487
13583
  await unlink(resolve5(checkpointPath));
@@ -13923,7 +14019,7 @@ var LIFECYCLE_PROFILE = "/etc/forgezero/lifecycle.json";
13923
14019
  var CONTROL_SOCKET = "/run/forgezero/control.sock";
13924
14020
  var CLOUDFLARED_METRICS_ADDRESS = "127.0.0.1:20241";
13925
14021
  var CLOUDFLARED_DIAGNOSTICS_URL = `http://${CLOUDFLARED_METRICS_ADDRESS}/diag/tunnel`;
13926
- var PACKAGED_AGENT_BIN = fileURLToPath(new URL("./fz-agent.js", import.meta.url));
14022
+ var PACKAGED_AGENT_BIN = fileURLToPath2(new URL("./fz-agent.js", import.meta.url));
13927
14023
  var privateOrigin = (value) => {
13928
14024
  let url;
13929
14025
  try {
@@ -14150,7 +14246,7 @@ var unitEscape = (value) => {
14150
14246
  };
14151
14247
  function databaseUnit(config) {
14152
14248
  const db = config.database;
14153
- const join7 = db.role === "joiner" ? ` --starter.join=${unitEscape(db.master)}` : "";
14249
+ const join8 = db.role === "joiner" ? ` --starter.join=${unitEscape(db.master)}` : "";
14154
14250
  const agency = db.agency === "none" ? " --cluster.start-agent=false --cluster.start-coordinator=true --cluster.start-dbserver=true" : "";
14155
14251
  return `[Unit]
14156
14252
  Description=ForgeZero ArangoDB Community 3.11.14 cluster (${db.role}; agency=${db.agency})
@@ -14162,7 +14258,7 @@ Type=simple
14162
14258
  User=arangodb
14163
14259
  Group=arangodb
14164
14260
  LoadCredentialEncrypted=arangodb-jwt:${JWT_CREDENTIAL}
14165
- ExecStart=/usr/bin/arangodb --starter.mode=cluster --starter.address=${unitEscape(db.address)} --starter.host=${unitEscape(db.address)} --starter.data-dir=/var/lib/forgezero-cluster --auth.jwt-secret=%d/arangodb-jwt${join7}${agency}
14261
+ ExecStart=/usr/bin/arangodb --starter.mode=cluster --starter.address=${unitEscape(db.address)} --starter.host=${unitEscape(db.address)} --starter.data-dir=/var/lib/forgezero-cluster --auth.jwt-secret=%d/arangodb-jwt${join8}${agency}
14166
14262
  Restart=always
14167
14263
  RestartSec=5
14168
14264
  UMask=0077
@@ -15489,11 +15585,11 @@ async function runCloudflareBootstrapFinalizeCommand(configPath, dependencies =
15489
15585
 
15490
15586
  // src/operator-bootstrap.ts
15491
15587
  import { createHash as createHash6, randomBytes as randomBytes9 } from "crypto";
15492
- import { chmodSync as chmodSync6, lstatSync as lstatSync7, mkdirSync as mkdirSync12, mkdtempSync, readFileSync as readFileSync12, rmSync as rmSync7, writeFileSync as writeFileSync12 } from "fs";
15588
+ import { chmodSync as chmodSync6, lstatSync as lstatSync7, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync2, readFileSync as readFileSync12, rmSync as rmSync7, writeFileSync as writeFileSync12 } from "fs";
15493
15589
  import { isIP as isIP6 } from "net";
15494
- import { tmpdir } from "os";
15495
- import { basename as basename2, dirname as dirname13, isAbsolute as isAbsolute5, join as join10, resolve as resolve9 } from "path";
15496
- import { fileURLToPath as fileURLToPath2 } from "url";
15590
+ import { tmpdir as tmpdir2 } from "os";
15591
+ import { basename as basename2, dirname as dirname13, isAbsolute as isAbsolute5, join as join11, resolve as resolve9 } from "path";
15592
+ import { fileURLToPath as fileURLToPath3 } from "url";
15497
15593
 
15498
15594
  // src/metal-bootstrap.ts
15499
15595
  import { createHash as createHash5, randomBytes as randomBytes8 } from "crypto";
@@ -15512,15 +15608,15 @@ import {
15512
15608
  unlinkSync as unlinkSync2,
15513
15609
  writeFileSync as writeFileSync11
15514
15610
  } from "fs";
15515
- import { dirname as dirname12, isAbsolute as isAbsolute4, join as join9, resolve as resolve8 } from "path";
15611
+ import { dirname as dirname12, isAbsolute as isAbsolute4, join as join10, resolve as resolve8 } from "path";
15516
15612
  import { isIP as isIP5 } from "net";
15517
15613
 
15518
15614
  // src/metal-isolation.ts
15519
15615
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
15520
- import { join as join8 } from "path";
15616
+ import { join as join9 } from "path";
15521
15617
 
15522
15618
  // src/metal-provision.ts
15523
- import { dirname as dirname11, isAbsolute as isAbsolute3, join as join7 } from "path";
15619
+ import { dirname as dirname11, isAbsolute as isAbsolute3, join as join8 } from "path";
15524
15620
  import { isIP as isIP4 } from "net";
15525
15621
  var SAFE_NAME2 = /^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,63}$/;
15526
15622
  var DEVICE = /^[a-zA-Z][a-zA-Z0-9_.-]{0,14}$/;
@@ -15716,15 +15812,15 @@ async function applyMetalIsolation(profile, exec = defaultExec) {
15716
15812
  await requireGuestsInSlice(exec);
15717
15813
  const unitDir = profile.unitDir;
15718
15814
  mkdirSync10(unitDir, { recursive: true });
15719
- writeFileSync10(join8(unitDir, "forgezero-guests.slice"), metalGuestSliceUnit(profile), { mode: 420 });
15815
+ writeFileSync10(join9(unitDir, "forgezero-guests.slice"), metalGuestSliceUnit(profile), { mode: 420 });
15720
15816
  for (const unit of ["system.slice", "user.slice"]) {
15721
- const directory = join8(unitDir, `${unit}.d`);
15817
+ const directory = join9(unitDir, `${unit}.d`);
15722
15818
  mkdirSync10(directory, { recursive: true });
15723
- writeFileSync10(join8(directory, "50-forgezero-housekeeping.conf"), metalHousekeepingDropIn(profile, "slice"), { mode: 420 });
15819
+ writeFileSync10(join9(directory, "50-forgezero-housekeeping.conf"), metalHousekeepingDropIn(profile, "slice"), { mode: 420 });
15724
15820
  }
15725
- const initDirectory = join8(unitDir, "init.scope.d");
15821
+ const initDirectory = join9(unitDir, "init.scope.d");
15726
15822
  mkdirSync10(initDirectory, { recursive: true });
15727
- writeFileSync10(join8(initDirectory, "50-forgezero-housekeeping.conf"), metalHousekeepingDropIn(profile, "scope"), { mode: 420 });
15823
+ writeFileSync10(join9(initDirectory, "50-forgezero-housekeeping.conf"), metalHousekeepingDropIn(profile, "scope"), { mode: 420 });
15728
15824
  await checked4(exec, ["systemctl", "daemon-reload"]);
15729
15825
  await requireGuestsInSlice(exec);
15730
15826
  const properties = [`AllowedCPUs=${profile.housekeepingCpus}`];
@@ -16104,9 +16200,9 @@ var installAgentBinary = (source, version) => {
16104
16200
  validateAgentSourcePath(source);
16105
16201
  const release = `/opt/forgezero/agent/versions/${version}/dist`;
16106
16202
  mkdirSync11(release, { recursive: true, mode: 493 });
16107
- copyFileSync2(source, join9(release, "fz-agent.js"));
16108
- chmodSync5(join9(release, "fz-agent.js"), 493);
16109
- chownSync(join9(release, "fz-agent.js"), 0, 0);
16203
+ copyFileSync2(source, join10(release, "fz-agent.js"));
16204
+ chmodSync5(join10(release, "fz-agent.js"), 493);
16205
+ chownSync(join10(release, "fz-agent.js"), 0, 0);
16110
16206
  mkdirSync11("/opt/forgezero/agent", { recursive: true, mode: 493 });
16111
16207
  for (const [link, target] of [
16112
16208
  ["/opt/forgezero/agent/current.next", `versions/${version}`],
@@ -16256,7 +16352,7 @@ async function applyMetalBootstrap(config, options) {
16256
16352
  }
16257
16353
  await applyMetalIsolation(config.profile, (argv2) => exec(argv2));
16258
16354
  for (const [unit, body] of Object.entries(renderMetalUnits(config)))
16259
- atomicWrite2(join9(UNIT_DIRECTORY, unit), body, 420);
16355
+ atomicWrite2(join10(UNIT_DIRECTORY, unit), body, 420);
16260
16356
  await runChecked(exec, ["/usr/bin/systemctl", "daemon-reload"]);
16261
16357
  await runChecked(exec, [
16262
16358
  "/usr/bin/systemctl",
@@ -16390,7 +16486,7 @@ async function metalBootstrapStatus(exec = defaultExec2) {
16390
16486
  "forgezero-metal-agent-egress.service",
16391
16487
  "forgezero-metal-agent.service"
16392
16488
  ]) {
16393
- if (!existsSync10(join9(UNIT_DIRECTORY, unit)))
16489
+ if (!existsSync10(join10(UNIT_DIRECTORY, unit)))
16394
16490
  units[unit] = "missing";
16395
16491
  else
16396
16492
  units[unit] = (await exec(["/usr/bin/systemctl", "is-active", "--quiet", unit])).exitCode === 0 ? "active" : "inactive";
@@ -16919,7 +17015,7 @@ function writeKnownHosts(request, directory) {
16919
17015
  const lines = [`fz-operator-target ${request.target.hostKey}`];
16920
17016
  if (request.target.jump)
16921
17017
  lines.push(`${hostLabel(request.target.jump.address, request.target.jump.port)} ${request.target.jump.hostKey}`);
16922
- const path = join10(directory, "known_hosts");
17018
+ const path = join11(directory, "known_hosts");
16923
17019
  writeFileSync12(path, `${lines.join(`
16924
17020
  `)}
16925
17021
  `, { mode: 384, flag: "wx" });
@@ -17009,7 +17105,7 @@ async function collectOperatorGuestHostKeys(request, options = {}, includeRehear
17009
17105
  publicIdentity(request.target.identityPublicKeyFile);
17010
17106
  socketPath(request.target.agentSocket);
17011
17107
  const exec = options.exec ?? defaultExec3;
17012
- const directory = mkdtempSync(join10(tmpdir(), "forgezero-operator-host-keys-"));
17108
+ const directory = mkdtempSync2(join11(tmpdir2(), "forgezero-operator-host-keys-"));
17013
17109
  try {
17014
17110
  const knownHosts = writeKnownHosts(request, directory);
17015
17111
  const nodes = [];
@@ -17045,7 +17141,7 @@ async function stageConfig(config, directory) {
17045
17141
  const staged = [];
17046
17142
  for (const [name, source] of secretSources(config)) {
17047
17143
  const bytes = ownerFile(source, SECRET_LIMIT, name);
17048
- const local = join10(directory, name);
17144
+ const local = join11(directory, name);
17049
17145
  writeFileSync12(local, bytes, { mode: 384, flag: "wx" });
17050
17146
  staged.push(name);
17051
17147
  const remotePath = `${REMOTE_STAGE}/${name}`;
@@ -17065,7 +17161,7 @@ async function stageConfig(config, directory) {
17065
17161
  manifestFile: `${REMOTE_STAGE}/bootstrap-api.bundle.json`,
17066
17162
  branch: bundle.manifest.branch
17067
17163
  };
17068
- const path = join10(directory, "platform-config.json");
17164
+ const path = join11(directory, "platform-config.json");
17069
17165
  writeFileSync12(path, `${JSON.stringify(rewritten, null, 2)}
17070
17166
  `, { mode: 384, flag: "wx" });
17071
17167
  return { path, files: staged, bundleFiles };
@@ -17075,14 +17171,14 @@ function stageMetalConfig(config, directory) {
17075
17171
  const files = [];
17076
17172
  if (config.agentSeedFile) {
17077
17173
  const name = "metal-agent-seed";
17078
- writeFileSync12(join10(directory, name), ownerFile(config.agentSeedFile, SECRET_LIMIT, name), {
17174
+ writeFileSync12(join11(directory, name), ownerFile(config.agentSeedFile, SECRET_LIMIT, name), {
17079
17175
  mode: 384,
17080
17176
  flag: "wx"
17081
17177
  });
17082
17178
  rewritten.agentSeedFile = `${REMOTE_STAGE}/${name}`;
17083
17179
  files.push(name);
17084
17180
  }
17085
- const path = join10(directory, "metal-config.json");
17181
+ const path = join11(directory, "metal-config.json");
17086
17182
  writeFileSync12(path, `${JSON.stringify(rewritten, null, 2)}
17087
17183
  `, { mode: 384, flag: "wx" });
17088
17184
  return { path, files };
@@ -17094,15 +17190,15 @@ async function verifiedBunArchive(directory, fetcher) {
17094
17190
  const bytes = new Uint8Array(await response.arrayBuffer());
17095
17191
  if (createHash6("sha256").update(bytes).digest("hex") !== BUN_RELEASE_SHA256)
17096
17192
  throw new Error("pinned Bun checksum mismatch");
17097
- const path = join10(directory, "bun.zip");
17193
+ const path = join11(directory, "bun.zip");
17098
17194
  writeFileSync12(path, bytes, { mode: 384, flag: "wx" });
17099
17195
  return path;
17100
17196
  }
17101
17197
  async function installPackagedAgent(request, knownHosts, exec, directory, remoteTemp, options) {
17102
17198
  const artifacts = [
17103
- [options.fzCliPath ?? fileURLToPath2(new URL("./fz.js", import.meta.url)), "fz.js"],
17104
- [options.fzAgentPath ?? fileURLToPath2(new URL("./fz-agent.js", import.meta.url)), "fz-agent.js"],
17105
- [options.fzGitSshPath ?? fileURLToPath2(new URL("./fz-git-ssh.js", import.meta.url)), "fz-git-ssh.js"]
17199
+ [options.fzCliPath ?? fileURLToPath3(new URL("./fz.js", import.meta.url)), "fz.js"],
17200
+ [options.fzAgentPath ?? fileURLToPath3(new URL("./fz-agent.js", import.meta.url)), "fz-agent.js"],
17201
+ [options.fzGitSshPath ?? fileURLToPath3(new URL("./fz-git-ssh.js", import.meta.url)), "fz-git-ssh.js"]
17106
17202
  ];
17107
17203
  for (const [artifact] of artifacts) {
17108
17204
  if (!readFileSync12(artifact).length)
@@ -17145,7 +17241,7 @@ async function applyOperatorPlatformBootstrap(request, mode, options = {}) {
17145
17241
  publicIdentity(request.target.identityPublicKeyFile);
17146
17242
  socketPath(request.target.agentSocket);
17147
17243
  const exec = options.exec ?? defaultExec3;
17148
- const directory = mkdtempSync(join10(tmpdir(), "forgezero-operator-bootstrap-"));
17244
+ const directory = mkdtempSync2(join11(tmpdir2(), "forgezero-operator-bootstrap-"));
17149
17245
  const remoteTemp = `/tmp/forgezero-operator-${randomBytes9(12).toString("hex")}`;
17150
17246
  let knownHosts = "";
17151
17247
  try {
@@ -17162,7 +17258,7 @@ async function applyOperatorPlatformBootstrap(request, mode, options = {}) {
17162
17258
  await installPackagedAgent(request, knownHosts, exec, directory, remoteTemp, options);
17163
17259
  await copy(exec, request, knownHosts, staged.path, `${remoteTemp}/platform-config.json`, true);
17164
17260
  for (const name of staged.files)
17165
- await copy(exec, request, knownHosts, join10(directory, name), `${remoteTemp}/${name}`, true);
17261
+ await copy(exec, request, knownHosts, join11(directory, name), `${remoteTemp}/${name}`, true);
17166
17262
  for (const bundle of staged.bundleFiles)
17167
17263
  await copy(exec, request, knownHosts, bundle.source, `${remoteTemp}/${bundle.name}`, true);
17168
17264
  for (const name of ["platform-config.json", ...staged.files, ...staged.bundleFiles.map(({ name: name2 }) => name2)])
@@ -17210,7 +17306,7 @@ async function applyOperatorMetalBootstrap(request, mode, options = {}) {
17210
17306
  publicIdentity(request.target.identityPublicKeyFile);
17211
17307
  socketPath(request.target.agentSocket);
17212
17308
  const exec = options.exec ?? defaultExec3;
17213
- const directory = mkdtempSync(join10(tmpdir(), "forgezero-operator-metal-"));
17309
+ const directory = mkdtempSync2(join11(tmpdir2(), "forgezero-operator-metal-"));
17214
17310
  const remoteTemp = `/tmp/forgezero-operator-${randomBytes9(12).toString("hex")}`;
17215
17311
  let knownHosts = "";
17216
17312
  try {
@@ -17243,7 +17339,7 @@ async function applyOperatorMetalBootstrap(request, mode, options = {}) {
17243
17339
  await installPackagedAgent(request, knownHosts, exec, directory, remoteTemp, options);
17244
17340
  await copy(exec, request, knownHosts, staged.path, `${remoteTemp}/metal-config.json`, true);
17245
17341
  for (const name of staged.files)
17246
- await copy(exec, request, knownHosts, join10(directory, name), `${remoteTemp}/${name}`, true);
17342
+ await copy(exec, request, knownHosts, join11(directory, name), `${remoteTemp}/${name}`, true);
17247
17343
  for (const name of ["metal-config.json", ...staged.files])
17248
17344
  await remote(exec, request, knownHosts, ["/usr/bin/sudo", "-n", "/usr/bin/install", "-m", "0600", `${remoteTemp}/${name}`, `${REMOTE_STAGE}/${name}`], "remote metal handoff", true);
17249
17345
  const initialized = await remoteRegularFileExists(exec, request, knownHosts, "/etc/forgezero/metal.initialized.json");
@@ -17512,7 +17608,7 @@ async function applyHostMaintenance(request, runtime = localRuntime()) {
17512
17608
 
17513
17609
  // src/cli/maintenance.ts
17514
17610
  import { existsSync as existsSync11, lstatSync as lstatSync9, readFileSync as readFileSync14, realpathSync as realpathSync5 } from "fs";
17515
- import { isAbsolute as isAbsolute6, join as join11, relative as relative2, resolve as resolve10 } from "path";
17611
+ import { isAbsolute as isAbsolute6, join as join12, relative as relative2, resolve as resolve10 } from "path";
17516
17612
  var API_OPERATION_ENTRYPOINTS = {
17517
17613
  "dev-reset": ["src", "server", "maintenance", "dev-reset.ts"],
17518
17614
  "db-backup": ["src", "server", "maintenance", "snapshot-backup.ts"],
@@ -17581,7 +17677,7 @@ function unsupportedRepositoryCliOption(argv2) {
17581
17677
  return;
17582
17678
  }
17583
17679
  function manifestName(root) {
17584
- const manifestPath = join11(root, "package.json");
17680
+ const manifestPath = join12(root, "package.json");
17585
17681
  if (!existsSync11(manifestPath)) {
17586
17682
  throw new Error(`No package.json exists at repository root ${root}.`);
17587
17683
  }
@@ -17597,7 +17693,7 @@ function manifestName(root) {
17597
17693
  return name;
17598
17694
  }
17599
17695
  function checkedEntrypoint(root, parts) {
17600
- const candidate = join11(root, ...parts);
17696
+ const candidate = join12(root, ...parts);
17601
17697
  if (!existsSync11(candidate) || !lstatSync9(candidate).isFile()) {
17602
17698
  throw new Error(`The reviewed operation entrypoint is missing: ${candidate}`);
17603
17699
  }
@@ -17625,7 +17721,7 @@ function resolveRepositoryOperation(operation, requestedRoot) {
17625
17721
  };
17626
17722
  }
17627
17723
  if (name === "forgezero") {
17628
- const apiRoot = realpathSync5(join11(root, "api"));
17724
+ const apiRoot = realpathSync5(join12(root, "api"));
17629
17725
  if (manifestName(apiRoot) !== "@forgezero/api") {
17630
17726
  throw new Error(`${apiRoot} is not the ForgeZero API package.`);
17631
17727
  }
@@ -17667,7 +17763,7 @@ function resolveRepositoryOperation(operation, requestedRoot) {
17667
17763
  ])
17668
17764
  };
17669
17765
  }
17670
- const rehearsalRoot = join11(root, "tests", "rehearsals", "community-cluster-api");
17766
+ const rehearsalRoot = join12(root, "tests", "rehearsals", "community-cluster-api");
17671
17767
  return {
17672
17768
  operation,
17673
17769
  root,
@@ -17721,7 +17817,7 @@ function planAppBuild(input) {
17721
17817
 
17722
17818
  // src/cli/index.ts
17723
17819
  var DEFAULT_MODE = (THRESHOLD_MODES.find((mode) => mode.threshold === 1 && mode.total === 1) ?? THRESHOLD_MODES[0]).id;
17724
- var PACKAGED_AGENT_BIN2 = fileURLToPath3(new URL("./fz-agent.js", import.meta.url));
17820
+ var PACKAGED_AGENT_BIN2 = fileURLToPath4(new URL("./fz-agent.js", import.meta.url));
17725
17821
  function parseOptions(argv2) {
17726
17822
  const options = {
17727
17823
  api: process.env.FZ_API ?? "http://localhost:8787",
@@ -17744,6 +17840,14 @@ function parseOptions(argv2) {
17744
17840
  deploySoftware: [],
17745
17841
  deployChannel: "production",
17746
17842
  requireAttestation: false,
17843
+ deployInitCustomized: false,
17844
+ deployRuntime: "native",
17845
+ deployReplicas: 1,
17846
+ deployCpuCores: 1,
17847
+ deployMemoryMiB: 512,
17848
+ deployStorageGiB: 8,
17849
+ deploySharing: "exclusive",
17850
+ deployReuse: "require",
17747
17851
  force: false,
17748
17852
  noBrowser: false,
17749
17853
  provider: "github",
@@ -17795,7 +17899,55 @@ function parseOptions(argv2) {
17795
17899
  options.optionError = "--channel must be production or development.";
17796
17900
  } else if (token === "--attestation")
17797
17901
  options.requireAttestation = true;
17798
- else if (token === "--force")
17902
+ else if (token === "--runtime") {
17903
+ const value = argv2[++index];
17904
+ options.deployInitCustomized = true;
17905
+ if (value === "native" || value === "containerd" || value === "kata-snp")
17906
+ options.deployRuntime = value;
17907
+ else
17908
+ options.optionError = "--runtime must be native, containerd, or kata-snp.";
17909
+ } else if (token === "--os") {
17910
+ const value = argv2[++index];
17911
+ options.deployInitCustomized = true;
17912
+ if (value === "ubuntu-24.04" || value === "ubuntu-26.04")
17913
+ options.deployOperatingSystem = value;
17914
+ else
17915
+ options.optionError = "--os must be ubuntu-24.04 or ubuntu-26.04.";
17916
+ } else if (token === "--isolation") {
17917
+ const value = argv2[++index];
17918
+ options.deployInitCustomized = true;
17919
+ if (value === "standard" || value === "sev-snp")
17920
+ options.deployIsolation = value;
17921
+ else
17922
+ options.optionError = "--isolation must be standard or sev-snp.";
17923
+ } else if (["--replicas", "--cpu-cores", "--memory-mib", "--storage-gib"].includes(token)) {
17924
+ const value = Number(argv2[++index] ?? "");
17925
+ options.deployInitCustomized = true;
17926
+ if (!Number.isSafeInteger(value) || value < 1)
17927
+ options.optionError = `${token} must be a positive integer.`;
17928
+ else if (token === "--replicas")
17929
+ options.deployReplicas = value;
17930
+ else if (token === "--cpu-cores")
17931
+ options.deployCpuCores = value;
17932
+ else if (token === "--memory-mib")
17933
+ options.deployMemoryMiB = value;
17934
+ else
17935
+ options.deployStorageGiB = value;
17936
+ } else if (token === "--sharing") {
17937
+ const value = argv2[++index];
17938
+ options.deployInitCustomized = true;
17939
+ if (value === "exclusive" || value === "shared")
17940
+ options.deploySharing = value;
17941
+ else
17942
+ options.optionError = "--sharing must be exclusive or shared.";
17943
+ } else if (token === "--reuse") {
17944
+ const value = argv2[++index];
17945
+ options.deployInitCustomized = true;
17946
+ if (value === "require" || value === "prefer")
17947
+ options.deployReuse = value;
17948
+ else
17949
+ options.optionError = "--reuse must be require or prefer.";
17950
+ } else if (token === "--force")
17799
17951
  options.force = true;
17800
17952
  else if (token === "--browser")
17801
17953
  options.noBrowser = false;
@@ -18631,10 +18783,10 @@ function interactiveGenesisGuests() {
18631
18783
  function writeMetalOperatorFiles(directory) {
18632
18784
  const output = genesisOutputDirectory(directory);
18633
18785
  const config = interactiveMetalBootstrap();
18634
- const metalConfig = writeBootstrapConfig(join12(output, "metal.json"), config);
18786
+ const metalConfig = writeBootstrapConfig(join13(output, "metal.json"), config);
18635
18787
  const identity = operatorIdentityCoordinates();
18636
18788
  const target = interactiveOperatorHop("Metal", { user: "root" });
18637
- const remoteRequest = writeOperatorMetalBootstrapRequest(join12(output, "metal-remote.json"), {
18789
+ const remoteRequest = writeOperatorMetalBootstrapRequest(join13(output, "metal-remote.json"), {
18638
18790
  kind: "metal-remote",
18639
18791
  metalConfigFile: metalConfig,
18640
18792
  target: { ...target, ...identity },
@@ -18652,7 +18804,7 @@ function writePlatformGenesisFleet(directory) {
18652
18804
  const metalHostname = readMetalBootstrapConfig(metalRequest.metalConfigFile, {
18653
18805
  allowHistoricalRelease: true
18654
18806
  }).metalHostname;
18655
- const checkpointPath = join12(output, "cloudflare-handoff.json");
18807
+ const checkpointPath = join13(output, "cloudflare-handoff.json");
18656
18808
  const template = interactiveBootstrap("platform", fleet, checkpointPath);
18657
18809
  const region = {
18658
18810
  label: bootstrapAnswer(`Region ${template.runtime.environment.nodeRegion} display label`),
@@ -18667,7 +18819,7 @@ function writePlatformGenesisFleet(directory) {
18667
18819
  cloudflareHandoffFile: cloudflareHostHandoffPath(checkpointPath, guest.name)
18668
18820
  });
18669
18821
  const realtimeEnabled = bootstrapBoolean("Configure existing Worker realtime fan-out?", "yes");
18670
- const cloudflareConfig = writeBootstrapConfig(join12(output, "cloudflare.json"), createCloudflareBootstrapDiscoveryCommandConfig({
18822
+ const cloudflareConfig = writeBootstrapConfig(join13(output, "cloudflare.json"), createCloudflareBootstrapDiscoveryCommandConfig({
18671
18823
  checkpointPath,
18672
18824
  discovery: {
18673
18825
  zoneName: bootstrapAnswer("Cloudflare DNS zone name", "forgezero.net"),
@@ -18685,7 +18837,7 @@ function writePlatformGenesisFleet(directory) {
18685
18837
  tunnelName: bootstrapAnswer(`${guest.name} Tunnel name`, guest.name)
18686
18838
  }))
18687
18839
  }));
18688
- const cloudflareAcceptance = join12(output, "cloudflare-acceptance.json");
18840
+ const cloudflareAcceptance = join13(output, "cloudflare-acceptance.json");
18689
18841
  const configs = platformGenesisBootstrapConfigs(template, fleet, nodes, metalHostname, region).map((config) => {
18690
18842
  const path = `${output}/${config.computeReference}-platform.json`;
18691
18843
  writeBootstrapConfig(path, config);
@@ -18694,7 +18846,7 @@ function writePlatformGenesisFleet(directory) {
18694
18846
  const requests = configs.map((platformConfigFile, index) => {
18695
18847
  const guest = fleet[index];
18696
18848
  const host = guestHostKeys.nodes.find(({ name }) => name === guest.name);
18697
- return writeOperatorPlatformBootstrapRequest(join12(output, `${guest.name}-remote.json`), {
18849
+ return writeOperatorPlatformBootstrapRequest(join13(output, `${guest.name}-remote.json`), {
18698
18850
  kind: "platform-remote",
18699
18851
  platformConfigFile,
18700
18852
  target: {
@@ -18715,7 +18867,7 @@ function writePlatformGenesisFleet(directory) {
18715
18867
  }
18716
18868
  });
18717
18869
  });
18718
- const fleetRequest = writeOperatorPlatformBootstrapFleetRequest(join12(output, "platform-fleet-remote.json"), requests, { configFile: cloudflareConfig, acceptanceFile: cloudflareAcceptance });
18870
+ const fleetRequest = writeOperatorPlatformBootstrapFleetRequest(join13(output, "platform-fleet-remote.json"), requests, { configFile: cloudflareConfig, acceptanceFile: cloudflareAcceptance });
18719
18871
  return { configs, requests, fleetRequest, cloudflareConfig, cloudflareAcceptance };
18720
18872
  }
18721
18873
  function interactiveBootstrap(kind, genesisGuests, genesisCloudflareCheckpoint) {
@@ -19454,7 +19606,7 @@ async function cmdDeploy(options, args) {
19454
19606
  if (options.optionError)
19455
19607
  throw new Error(options.optionError);
19456
19608
  if (operation === "init") {
19457
- if (options.deploySoftware.length > 0 || options.deployProfile !== "app" || options.requireAttestation) {
19609
+ if (!options.deployInitCustomized && (options.deploySoftware.length > 0 || options.deployProfile !== "app" || options.requireAttestation)) {
19458
19610
  const created = initializeDeployFile(options.projectRoot, {
19459
19611
  name: options.projectName,
19460
19612
  profile: options.deployProfile,
@@ -19469,7 +19621,23 @@ async function cmdDeploy(options, args) {
19469
19621
  out.ok(`Initialized legacy .fz/deploy.json (${created.summary.digest}).`);
19470
19622
  return 0;
19471
19623
  }
19472
- initializeTypeScriptDeployment(options.projectRoot, { name: options.projectName ?? basename3(resolve12(options.projectRoot)), force: options.force });
19624
+ if (options.deployInitCustomized && (options.deploySoftware.length > 0 || options.requireAttestation)) {
19625
+ throw new Error("typed runtime initialization selects its tested software and attestation from --runtime/--isolation; do not combine --software or --attestation");
19626
+ }
19627
+ initializeTypeScriptDeployment(options.projectRoot, {
19628
+ name: options.projectName ?? basename3(resolve12(options.projectRoot)),
19629
+ force: options.force,
19630
+ runtime: options.deployRuntime,
19631
+ operatingSystem: options.deployOperatingSystem,
19632
+ isolation: options.deployIsolation,
19633
+ replicas: options.deployReplicas,
19634
+ cpuCores: options.deployCpuCores,
19635
+ memoryMiB: options.deployMemoryMiB,
19636
+ storageGiB: options.deployStorageGiB,
19637
+ sharing: options.deploySharing,
19638
+ reuse: options.deployReuse,
19639
+ profile: options.deployProfile
19640
+ });
19473
19641
  const compiled = await compileDeploymentProject(options.projectRoot);
19474
19642
  if (options.json)
19475
19643
  out.line(JSON.stringify({ source: compiled.source, output: compiled.output, digest: compiled.digest }, null, 2));
@@ -19721,7 +19889,9 @@ function usage() {
19721
19889
  fz project check Fail when truth sources or generated adapters drift
19722
19890
  fz app build Build the static App for a numbered local/development/
19723
19891
  production choice, --profile, or an explicit --api origin
19724
- fz deploy init Create forgezero.deploy.ts and its fail-safe canonical plan
19892
+ fz deploy init Create forgezero.deploy.ts and its fail-safe canonical plan;
19893
+ select native, containerd runc, or Kata QEMU SNP and
19894
+ explicit per-compute resources with the options below
19725
19895
  fz deploy compile Compile TypeScript into .fz/deploy.plan.json
19726
19896
  fz deploy check Validate source, plan, actions, providers and topology
19727
19897
  fz deploy sync Prove readiness and print the Git synchronization rule
@@ -19792,6 +19962,15 @@ function usage() {
19792
19962
  --software <key@ver> Initial tested software coordinate; repeatable
19793
19963
  --channel <name> Catalog view: production or development (shows testing)
19794
19964
  --attestation Require hardware attestation for every deploy step
19965
+ --runtime <mode> native, containerd, or kata-snp
19966
+ --os <image> ubuntu-24.04 or ubuntu-26.04 (SNP requires 26.04)
19967
+ --isolation <mode> standard or sev-snp
19968
+ --replicas <n> Exact initial compute cardinality (default 1)
19969
+ --cpu-cores <n> Reserved CPU cores per compute
19970
+ --memory-mib <n> Reserved memory MiB per compute
19971
+ --storage-gib <n> Reserved storage GiB per compute
19972
+ --sharing <mode> exclusive or shared (native requires exclusive)
19973
+ --reuse <mode> require existing capacity or prefer reuse then approved provisioning
19795
19974
  --force Init may replace an existing generated target
19796
19975
 
19797
19976
  REMOTE DEPLOY OPTIONS
@@ -366,7 +366,7 @@ function systemdAgentEgressDirectives(loopbackTcpPorts = []) {
366
366
  }
367
367
 
368
368
  // src/version.ts
369
- var VERSION = "0.1.82";
369
+ var VERSION = "0.1.83";
370
370
 
371
371
  // src/otel-collector.ts
372
372
  var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
@@ -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.82";
1419
+ var VERSION = "0.1.83";
1420
1420
 
1421
1421
  // src/software.ts
1422
1422
  var PINNED_BUN_VERSION = "1.3.14";
@@ -2647,7 +2647,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
2647
2647
  }
2648
2648
 
2649
2649
  // src/version.ts
2650
- var VERSION3 = "0.1.82";
2650
+ var VERSION3 = "0.1.83";
2651
2651
 
2652
2652
  // src/egress-policy.ts
2653
2653
  import { realpathSync as realpathSync3 } from "node:fs";
package/dist/provision.js CHANGED
@@ -2647,7 +2647,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
2647
2647
  }
2648
2648
 
2649
2649
  // src/version.ts
2650
- var VERSION3 = "0.1.82";
2650
+ var VERSION3 = "0.1.83";
2651
2651
 
2652
2652
  // src/egress-policy.ts
2653
2653
  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.82";
2
+ export declare const VERSION = "0.1.83";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgezero/agent",
3
- "version": "0.1.82",
3
+ "version": "0.1.83",
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.11",
20
- "@forgezero/vault": "0.1.15",
19
+ "@forgezero/runtime": "0.1.12",
20
+ "@forgezero/vault": "0.1.16",
21
21
  "@noble/curves": "2.2.0",
22
22
  "@noble/hashes": "2.2.0",
23
23
  "@noble/post-quantum": "0.6.1",