@forgezero/agent 0.1.74 → 0.1.76
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 +126 -17
- package/dist/agent-heartbeat.d.ts +25 -1
- package/dist/agent-heartbeat.js +45 -5
- package/dist/bootstrap.js +10 -7
- package/dist/community-rehearsal-host.js +218 -13
- package/dist/credential-schema.d.ts +1 -1
- package/dist/credential-schema.js +1 -1
- package/dist/definition.js +206 -7
- package/dist/deploy-actions.d.ts +7 -0
- package/dist/deploy-compiler.js +191 -10
- package/dist/deploy-file.js +206 -7
- package/dist/deploy-plan-runner.d.ts +3 -0
- package/dist/deploy-plan-runner.js +190 -9
- package/dist/deploy-plan.js +187 -8
- package/dist/deploy-providers.d.ts +19 -0
- package/dist/deploy.d.ts +89 -3
- package/dist/deploy.js +49 -2
- package/dist/deployment-connectivity.d.ts +63 -0
- package/dist/deployment-connectivity.js +155 -0
- package/dist/deployment-pull.d.ts +2 -0
- package/dist/deployment-targets.d.ts +9 -0
- package/dist/deployment-targets.js +141 -0
- package/dist/deployment.d.ts +69 -0
- package/dist/fz-agent.js +1122 -313
- package/dist/fz.js +234 -26
- package/dist/index.d.ts +1 -0
- package/dist/metal-bootstrap.js +1 -1
- package/dist/metal-helper-socket.js +210 -11
- package/dist/metal-provision.js +210 -11
- package/dist/operator-bootstrap.js +11 -9
- package/dist/platform-bootstrap-runtime.js +209 -10
- package/dist/platform-fleet-verification.js +525 -155
- package/dist/platform-genesis.js +206 -7
- package/dist/process-input.d.ts +11 -0
- package/dist/provision.js +472 -99
- package/dist/service-supervisor.d.ts +6 -0
- package/dist/software-helper.d.ts +3 -0
- package/dist/software-helper.js +472 -98
- package/dist/software.d.ts +4 -1
- package/dist/software.js +210 -8
- package/dist/ubuntu.js +206 -7
- package/dist/version.d.ts +1 -1
- package/package.json +12 -4
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.
|
|
4637
|
+
}, VERSION = "0.1.15";
|
|
4638
4638
|
var init_dist = __esm(() => {
|
|
4639
4639
|
init_identity();
|
|
4640
4640
|
VaultError = class VaultError extends Error {
|
|
@@ -4810,9 +4810,17 @@ async function spawnWith(command, env, report = () => {}, options = {}) {
|
|
|
4810
4810
|
}
|
|
4811
4811
|
|
|
4812
4812
|
// src/cli/index.ts
|
|
4813
|
-
init_dist();
|
|
4814
4813
|
import { existsSync as existsSync12, lstatSync as lstatSync10, mkdirSync as mkdirSync13, readFileSync as readFileSync15, writeFileSync as writeFileSync13 } from "fs";
|
|
4815
4814
|
import { basename as basename3, dirname as dirname14, isAbsolute as isAbsolute7, join as join12, resolve as resolve11 } from "path";
|
|
4815
|
+
|
|
4816
|
+
// src/process-input.ts
|
|
4817
|
+
async function writeAndCloseProcessInput(input, value) {
|
|
4818
|
+
input.write(value);
|
|
4819
|
+
await input.end();
|
|
4820
|
+
}
|
|
4821
|
+
|
|
4822
|
+
// src/cli/index.ts
|
|
4823
|
+
init_dist();
|
|
4816
4824
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4817
4825
|
import { hostname } from "os";
|
|
4818
4826
|
|
|
@@ -4829,7 +4837,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
|
|
|
4829
4837
|
var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
|
|
4830
4838
|
|
|
4831
4839
|
// src/version.ts
|
|
4832
|
-
var VERSION2 = "0.1.
|
|
4840
|
+
var VERSION2 = "0.1.76";
|
|
4833
4841
|
|
|
4834
4842
|
// src/software.ts
|
|
4835
4843
|
var PINNED_BUN_VERSION = "1.3.14";
|
|
@@ -4863,6 +4871,8 @@ var OS_CATALOG = [
|
|
|
4863
4871
|
var SOFTWARE_CATALOG = [
|
|
4864
4872
|
{ id: "bun", version: "1.3.14", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4865
4873
|
{ id: "docker", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4874
|
+
{ id: "containerd", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4875
|
+
{ id: "kata-containers", version: "4.0.0", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4866
4876
|
{ id: "nginx", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4867
4877
|
{ id: "arangodb", version: "3.11.14", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4868
4878
|
{ id: "cloudflared", version: "2026.7.3", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
@@ -4871,6 +4881,7 @@ var SOFTWARE_CATALOG = [
|
|
|
4871
4881
|
{ id: "openssh-client", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4872
4882
|
{ id: "git", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4873
4883
|
{ id: "docker", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4884
|
+
{ id: "containerd", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4874
4885
|
{ id: "nginx", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4875
4886
|
{ id: "ufw", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4876
4887
|
{ id: "openssh-client", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
@@ -4895,7 +4906,7 @@ function validateSoftwareRequirements(value, _options = {}) {
|
|
|
4895
4906
|
if (Object.keys(row).some((key) => key !== "id" && key !== "version")) {
|
|
4896
4907
|
throw new Error("software requirement contains an unknown field");
|
|
4897
4908
|
}
|
|
4898
|
-
if (!["bun", "docker", "nginx", "arangodb", "cloudflared", "cloudflare-warp", "ufw", "openssh-client", "git"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
4909
|
+
if (!["bun", "docker", "containerd", "kata-containers", "nginx", "arangodb", "cloudflared", "cloudflare-warp", "ufw", "openssh-client", "git"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
4899
4910
|
throw new Error("software requirement coordinate is invalid");
|
|
4900
4911
|
}
|
|
4901
4912
|
const requirement = { id: row.id, version: row.version };
|
|
@@ -6383,10 +6394,8 @@ var fixed = async (argv2, stdin) => {
|
|
|
6383
6394
|
stderr: "pipe",
|
|
6384
6395
|
env: { PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", LANG: "C", LC_ALL: "C", DEBIAN_FRONTEND: "noninteractive" }
|
|
6385
6396
|
});
|
|
6386
|
-
if (stdin !== undefined && child.stdin && typeof child.stdin !== "number")
|
|
6387
|
-
child.stdin
|
|
6388
|
-
child.stdin.end();
|
|
6389
|
-
}
|
|
6397
|
+
if (stdin !== undefined && child.stdin && typeof child.stdin !== "number")
|
|
6398
|
+
await writeAndCloseProcessInput(child.stdin, stdin);
|
|
6390
6399
|
const [stdout, stderr, exitCode] = await Promise.all([
|
|
6391
6400
|
new Response(child.stdout).text(),
|
|
6392
6401
|
new Response(child.stderr).text(),
|
|
@@ -10399,6 +10408,13 @@ function validateBuiltInAction(definition, context, where) {
|
|
|
10399
10408
|
throw new Error(`${where}.with.requirements must name existing requirements`);
|
|
10400
10409
|
return;
|
|
10401
10410
|
}
|
|
10411
|
+
if (definition.uses === "forgezero.network/ensure@1") {
|
|
10412
|
+
exact(withValue, ["target"], `${where}.with`);
|
|
10413
|
+
if (typeof withValue.target !== "string" || !Object.values(context.components).some((entry) => entry.target === withValue.target)) {
|
|
10414
|
+
throw new Error(`${where}.with.target must name a target used by a component`);
|
|
10415
|
+
}
|
|
10416
|
+
return;
|
|
10417
|
+
}
|
|
10402
10418
|
if (definition.uses === "forgezero.exec/argv@1") {
|
|
10403
10419
|
const allowed = ["component", "argv", "credentials"];
|
|
10404
10420
|
const unknown = Object.keys(withValue).filter((key) => !allowed.includes(key));
|
|
@@ -10454,6 +10470,8 @@ function validateBuiltInProvider(requirement2, where) {
|
|
|
10454
10470
|
const expected = {
|
|
10455
10471
|
"forgezero.bun": { capability: "runtime.javascript", versions: ["1.3.14"], keys: ["installScope"] },
|
|
10456
10472
|
"forgezero.docker": { capability: "runtime.container", versions: ["ubuntu-24.04", "ubuntu-26.04"], keys: ["installScope", "storageDriver", "dataRoot", "liveRestore", "logDriver", "defaultNetwork", "rootless"] },
|
|
10473
|
+
"forgezero.containerd": { capability: "runtime.container", versions: ["ubuntu-24.04", "ubuntu-26.04"], keys: ["installScope", "runtimeClass", "namespace", "snapshotter"] },
|
|
10474
|
+
"forgezero.kata": { capability: "runtime.container", versions: ["4.0.0"], keys: ["installScope", "runtimeClass", "namespace", "hypervisor", "confidentialGuest"] },
|
|
10457
10475
|
"forgezero.nginx": { capability: "proxy.http", versions: ["ubuntu-24.04", "ubuntu-26.04"], keys: ["installScope", "websocket", "maximumBodyMiB", "workerProcesses", "workerConnections"] },
|
|
10458
10476
|
"forgezero.arangodb": { capability: "database.arangodb", versions: ["3.11.14"], keys: ["installScope", "runtime", "dataPath", "bind"] },
|
|
10459
10477
|
"forgezero.cloudflared": { capability: "network.public-tunnel", versions: ["2026.7.3"], keys: ["installScope", "mode"] },
|
|
@@ -10474,6 +10492,10 @@ function validateBuiltInProvider(requirement2, where) {
|
|
|
10474
10492
|
if (row2.storageDriver !== "overlay2" || row2.dataRoot !== "/var/lib/docker" || row2.liveRestore !== true || row2.logDriver !== "local" || row2.defaultNetwork !== "bridge" || row2.rootless !== false)
|
|
10475
10493
|
throw new Error(`${where} Docker config is unsupported by the fixed host strategy`);
|
|
10476
10494
|
}
|
|
10495
|
+
if (requirement2.provider === "forgezero.containerd" && (row2.runtimeClass !== "runc" || row2.namespace !== "forgezero" || row2.snapshotter !== "overlayfs"))
|
|
10496
|
+
throw new Error(`${where} containerd config is unsupported by the fixed host strategy`);
|
|
10497
|
+
if (requirement2.provider === "forgezero.kata" && (row2.runtimeClass !== "kata-qemu-snp" || row2.namespace !== "forgezero" || row2.hypervisor !== "qemu" || row2.confidentialGuest !== "sev-snp"))
|
|
10498
|
+
throw new Error(`${where} Kata config is unsupported by the fixed host strategy`);
|
|
10477
10499
|
if (requirement2.provider === "forgezero.nginx" && (typeof row2.websocket !== "boolean" || !Number.isInteger(row2.maximumBodyMiB) || Number(row2.maximumBodyMiB) < 1 || Number(row2.maximumBodyMiB) > 1024 || !(row2.workerProcesses === "auto" || Number.isInteger(row2.workerProcesses)) || !Number.isInteger(row2.workerConnections)))
|
|
10478
10500
|
throw new Error(`${where} Nginx config is invalid`);
|
|
10479
10501
|
if (requirement2.provider === "forgezero.arangodb" && (row2.runtime !== "native" || !absolute(row2.dataPath) || row2.bind !== "private"))
|
|
@@ -10551,7 +10573,7 @@ function reference(value, where) {
|
|
|
10551
10573
|
const row2 = object(value, where);
|
|
10552
10574
|
exact3(row2, ["$ref"], where);
|
|
10553
10575
|
const coordinate = boundedString(row2.$ref, `${where}.$ref`, 256);
|
|
10554
|
-
if (!/^(inputs\.[a-z][A-Za-z0-9-]{0,62}|steps\.[a-z][A-Za-z0-9-]{0,62}\.(status|outputs\.[a-z][A-Za-z0-9-]{0,62})|components\.[a-z][A-Za-z0-9-]{0,62}\.[a-z][A-Za-z0-9-]{0,62}|targets\.[a-z][A-Za-z0-9-]{0,62}\.[a-z][A-Za-z0-9-]{0,62}|deployment\.[a-z][A-Za-z0-9-]{0,62})$/.test(coordinate)) {
|
|
10576
|
+
if (!/^(inputs\.[a-z][A-Za-z0-9-]{0,62}|steps\.[a-z][A-Za-z0-9-]{0,62}\.(status|outputs\.[a-z][A-Za-z0-9-]{0,62})|components\.[a-z][A-Za-z0-9-]{0,62}\.[a-z][A-Za-z0-9-]{0,62}|targets\.[a-z][A-Za-z0-9-]{0,62}\.[a-z][A-Za-z0-9-]{0,62}|deployment\.[a-z][A-Za-z0-9-]{0,62}|execution\.(targetName|slot|releaseExecutor|runtime|cpuCores|memoryMiB|storageGiB))$/.test(coordinate)) {
|
|
10555
10577
|
fail2(where, "contains an unsupported reference.");
|
|
10556
10578
|
}
|
|
10557
10579
|
return { $ref: coordinate };
|
|
@@ -10791,10 +10813,9 @@ function validateNetwork(value, where) {
|
|
|
10791
10813
|
named(container.network, `${where}.container.network`);
|
|
10792
10814
|
}
|
|
10793
10815
|
}
|
|
10794
|
-
function validateComponent(value, where,
|
|
10816
|
+
function validateComponent(value, where, targets, requirements) {
|
|
10795
10817
|
const row2 = object(value, where);
|
|
10796
|
-
|
|
10797
|
-
fail2(`${where}.target`, "must name an existing target.");
|
|
10818
|
+
const selectedTarget = targets.get(String(row2.target)) ?? fail2(`${where}.target`, "must name an existing target.");
|
|
10798
10819
|
if (row2.kind === "application") {
|
|
10799
10820
|
exact3(row2, ["kind", "target", "runtime", "service", "resources", "storage", "network", "rollout"], where);
|
|
10800
10821
|
const runtime = object(row2.runtime, `${where}.runtime`);
|
|
@@ -10805,7 +10826,9 @@ function validateComponent(value, where, targetNames, requirements) {
|
|
|
10805
10826
|
exact3(runtime, ["kind", "provider", "requirement", "argv"], `${where}.runtime`);
|
|
10806
10827
|
validateArgv(runtime.argv, `${where}.runtime.argv`);
|
|
10807
10828
|
} else if (runtime.kind === "container") {
|
|
10808
|
-
exact3(runtime, ["kind", "provider", "requirement", "image", "entrypoint", "security"], `${where}.runtime`);
|
|
10829
|
+
exact3(runtime, ["kind", "provider", "requirement", "runtimeClass", "image", "entrypoint", "security"], `${where}.runtime`);
|
|
10830
|
+
if (runtime.runtimeClass !== undefined && !["runc", "kata-qemu-snp"].includes(String(runtime.runtimeClass)))
|
|
10831
|
+
fail2(`${where}.runtime.runtimeClass`, "is unsupported.");
|
|
10809
10832
|
const image = object(runtime.image, `${where}.runtime.image`);
|
|
10810
10833
|
exact3(image, ["source"], `${where}.runtime.image`);
|
|
10811
10834
|
const source = object(image.source, `${where}.runtime.image.source`);
|
|
@@ -10839,6 +10862,23 @@ function validateComponent(value, where, targetNames, requirements) {
|
|
|
10839
10862
|
fail2(`${where}.runtime.requirement`, "must provide runtime.container.");
|
|
10840
10863
|
if (runtimeRequirement && runtime.kind === "native" && !runtimeRequirement.capability.startsWith("runtime."))
|
|
10841
10864
|
fail2(`${where}.runtime.requirement`, "must provide a runtime capability.");
|
|
10865
|
+
const execution = selectedTarget.allocation.execution;
|
|
10866
|
+
if (execution === "native" && runtime.kind !== "native")
|
|
10867
|
+
fail2(`${where}.runtime.kind`, "must be native for the selected target.");
|
|
10868
|
+
if (execution !== "native" && runtime.kind !== "container")
|
|
10869
|
+
fail2(`${where}.runtime.kind`, "must be container for the selected target.");
|
|
10870
|
+
if (runtime.kind === "container" && execution === "oci-runc") {
|
|
10871
|
+
if (!["forgezero.containerd", "forgezero.docker"].includes(String(runtime.provider)))
|
|
10872
|
+
fail2(`${where}.runtime.provider`, "must be forgezero.containerd for an OCI runc target.");
|
|
10873
|
+
if (runtime.runtimeClass !== undefined && runtime.runtimeClass !== "runc")
|
|
10874
|
+
fail2(`${where}.runtime.runtimeClass`, "must be runc for the selected target.");
|
|
10875
|
+
}
|
|
10876
|
+
if (runtime.kind === "container" && execution === "oci-kata-qemu-snp") {
|
|
10877
|
+
if (runtime.provider !== "forgezero.kata")
|
|
10878
|
+
fail2(`${where}.runtime.provider`, "must be forgezero.kata for a Kata QEMU SNP target.");
|
|
10879
|
+
if (runtime.runtimeClass !== "kata-qemu-snp")
|
|
10880
|
+
fail2(`${where}.runtime.runtimeClass`, "must be kata-qemu-snp for the selected target.");
|
|
10881
|
+
}
|
|
10842
10882
|
const service = object(row2.service, `${where}.service`);
|
|
10843
10883
|
exact3(service, ["protocol", "port", "health", "websocket", "maximumConnections"], `${where}.service`);
|
|
10844
10884
|
if (service.protocol !== "http")
|
|
@@ -10870,6 +10910,18 @@ function validateComponent(value, where, targetNames, requirements) {
|
|
|
10870
10910
|
const network = object(row2.network, `${where}.network`);
|
|
10871
10911
|
if (network.container === undefined)
|
|
10872
10912
|
fail2(`${where}.network.container`, "must select bridge or reviewed host networking.");
|
|
10913
|
+
if (selectedTarget.allocation.sharing === "shared") {
|
|
10914
|
+
if (object(runtime.security, `${where}.runtime.security`).root !== "read-only")
|
|
10915
|
+
fail2(`${where}.runtime.security.root`, "must be read-only on a shared compute.");
|
|
10916
|
+
if (network.container.mode !== "bridge")
|
|
10917
|
+
fail2(`${where}.network.container.mode`, "must be bridge on a shared compute.");
|
|
10918
|
+
if (Array.isArray(row2.storage) && row2.storage.some((mount) => mount.class !== "ephemeral")) {
|
|
10919
|
+
fail2(`${where}.storage`, "may contain only size-bounded tmpfs mounts on a shared compute.");
|
|
10920
|
+
}
|
|
10921
|
+
}
|
|
10922
|
+
}
|
|
10923
|
+
if (runtime.kind === "native" && selectedTarget.allocation.sharing !== "exclusive") {
|
|
10924
|
+
fail2(`${where}.target`, "native applications require an exclusive compute.");
|
|
10873
10925
|
}
|
|
10874
10926
|
if (row2.storage !== undefined) {
|
|
10875
10927
|
if (!Array.isArray(row2.storage) || row2.storage.length > 32)
|
|
@@ -10906,6 +10958,8 @@ function validateComponent(value, where, targetNames, requirements) {
|
|
|
10906
10958
|
fail2(`${where}.runtime.mode`, "must match the provider runtime mode.");
|
|
10907
10959
|
if (runtime.mode !== "native")
|
|
10908
10960
|
fail2(`${where}.runtime.mode`, "must be native in deployment plan v1.");
|
|
10961
|
+
if (selectedTarget.allocation.execution !== "native")
|
|
10962
|
+
fail2(`${where}.target`, "must select a native execution target for database components.");
|
|
10909
10963
|
const topology = object(row2.topology, `${where}.topology`);
|
|
10910
10964
|
if (topology.mode === "standalone")
|
|
10911
10965
|
exact3(topology, ["mode"], `${where}.topology`);
|
|
@@ -11102,15 +11156,20 @@ function compileDeployment(sourceValue) {
|
|
|
11102
11156
|
if (targetEntries.length < 1 || targetEntries.length > 64)
|
|
11103
11157
|
fail2("deployment.spec.targets", "must contain 1 to 64 targets.");
|
|
11104
11158
|
const targetNames = new Set(targetEntries.map(([targetName]) => named(targetName, "deployment.spec.targets key")));
|
|
11159
|
+
const targetDefinitions = new Map;
|
|
11105
11160
|
for (const [targetName, value] of targetEntries) {
|
|
11106
11161
|
const target = object(value, `deployment.spec.targets.${targetName}`);
|
|
11107
|
-
exact3(target, ["kind", "selector", "cardinality", "placement"], `deployment.spec.targets.${targetName}`);
|
|
11162
|
+
exact3(target, ["kind", "selector", "cardinality", "allocation", "provisioning", "connectivity", "placement"], `deployment.spec.targets.${targetName}`);
|
|
11108
11163
|
if (target.kind !== "compute")
|
|
11109
11164
|
fail2(`deployment.spec.targets.${targetName}.kind`, "must be compute.");
|
|
11110
11165
|
const selector = object(target.selector, `deployment.spec.targets.${targetName}.selector`);
|
|
11111
|
-
exact3(selector, ["profiles", "confidentialCompute", "labels"], `deployment.spec.targets.${targetName}.selector`);
|
|
11166
|
+
exact3(selector, ["profiles", "operatingSystem", "confidentialCompute", "labels"], `deployment.spec.targets.${targetName}.selector`);
|
|
11112
11167
|
if (!Array.isArray(selector.profiles) || selector.profiles.length < 1 || selector.profiles.length > 32 || selector.profiles.some((profile) => typeof profile !== "string" || !NAME3.test(profile)) || new Set(selector.profiles).size !== selector.profiles.length)
|
|
11113
11168
|
fail2(`deployment.spec.targets.${targetName}.selector.profiles`, "is invalid.");
|
|
11169
|
+
const operatingSystem = object(selector.operatingSystem, `deployment.spec.targets.${targetName}.selector.operatingSystem`);
|
|
11170
|
+
exact3(operatingSystem, ["id", "version", "architecture"], `deployment.spec.targets.${targetName}.selector.operatingSystem`);
|
|
11171
|
+
if (operatingSystem.id !== "ubuntu" || !["24.04", "26.04"].includes(String(operatingSystem.version)) || operatingSystem.architecture !== "x64")
|
|
11172
|
+
fail2(`deployment.spec.targets.${targetName}.selector.operatingSystem`, "is unsupported.");
|
|
11114
11173
|
if (selector.confidentialCompute !== undefined && !["required", "preferred", "disabled"].includes(String(selector.confidentialCompute)))
|
|
11115
11174
|
fail2(`deployment.spec.targets.${targetName}.selector.confidentialCompute`, "is unsupported.");
|
|
11116
11175
|
if (selector.labels !== undefined)
|
|
@@ -11123,8 +11182,108 @@ function compileDeployment(sourceValue) {
|
|
|
11123
11182
|
integer(cardinality.desired, `deployment.spec.targets.${targetName}.cardinality.desired`, minimum, maximum);
|
|
11124
11183
|
else
|
|
11125
11184
|
reference(cardinality.desired, `deployment.spec.targets.${targetName}.cardinality.desired`);
|
|
11185
|
+
const allocation = object(target.allocation, `deployment.spec.targets.${targetName}.allocation`);
|
|
11186
|
+
exact3(allocation, ["execution", "sharing", "resources", "existing"], `deployment.spec.targets.${targetName}.allocation`);
|
|
11187
|
+
if (!["native", "oci-runc", "oci-kata-qemu-snp"].includes(String(allocation.execution)))
|
|
11188
|
+
fail2(`deployment.spec.targets.${targetName}.allocation.execution`, "is unsupported.");
|
|
11189
|
+
if (!["exclusive", "shared"].includes(String(allocation.sharing)))
|
|
11190
|
+
fail2(`deployment.spec.targets.${targetName}.allocation.sharing`, "is unsupported.");
|
|
11191
|
+
if (!["prefer", "require"].includes(String(allocation.existing)))
|
|
11192
|
+
fail2(`deployment.spec.targets.${targetName}.allocation.existing`, "is unsupported.");
|
|
11193
|
+
const capacity = object(allocation.resources, `deployment.spec.targets.${targetName}.allocation.resources`);
|
|
11194
|
+
exact3(capacity, ["cpuCores", "memoryMiB", "storageGiB"], `deployment.spec.targets.${targetName}.allocation.resources`);
|
|
11195
|
+
const capacityValue = (value2, where, minimumValue, maximumValue) => {
|
|
11196
|
+
if (typeof value2 === "number")
|
|
11197
|
+
integer(value2, where, minimumValue, maximumValue);
|
|
11198
|
+
else
|
|
11199
|
+
reference(value2, where);
|
|
11200
|
+
};
|
|
11201
|
+
capacityValue(capacity.cpuCores, `deployment.spec.targets.${targetName}.allocation.resources.cpuCores`, 1, 1024);
|
|
11202
|
+
capacityValue(capacity.memoryMiB, `deployment.spec.targets.${targetName}.allocation.resources.memoryMiB`, 128, 4194304);
|
|
11203
|
+
capacityValue(capacity.storageGiB, `deployment.spec.targets.${targetName}.allocation.resources.storageGiB`, 1, 1048576);
|
|
11204
|
+
if (allocation.execution === "oci-kata-qemu-snp" && selector.confidentialCompute !== "required")
|
|
11205
|
+
fail2(`deployment.spec.targets.${targetName}.selector.confidentialCompute`, "must be required for Kata QEMU SNP.");
|
|
11206
|
+
if ((allocation.execution === "oci-kata-qemu-snp" || selector.confidentialCompute === "required") && operatingSystem.version !== "26.04")
|
|
11207
|
+
fail2(`deployment.spec.targets.${targetName}.selector.operatingSystem.version`, "must be Ubuntu 26.04 for SEV-SNP.");
|
|
11208
|
+
if (allocation.execution !== "oci-kata-qemu-snp" && selector.confidentialCompute === "required" && allocation.execution !== "native")
|
|
11209
|
+
fail2(`deployment.spec.targets.${targetName}.allocation.execution`, "cannot satisfy required confidential compute.");
|
|
11210
|
+
if (target.provisioning !== undefined) {
|
|
11211
|
+
const provisioning = object(target.provisioning, `deployment.spec.targets.${targetName}.provisioning`);
|
|
11212
|
+
exact3(provisioning, ["planKey", "regionKey", "imageKey", "environmentKey", "ownership", "metalHostname", "maxMonthlySpendMinor"], `deployment.spec.targets.${targetName}.provisioning`);
|
|
11213
|
+
for (const key of ["planKey", "regionKey", "imageKey", "environmentKey"])
|
|
11214
|
+
named(provisioning[key], `deployment.spec.targets.${targetName}.provisioning.${key}`);
|
|
11215
|
+
if (!["platform", "tenant-metal"].includes(String(provisioning.ownership)) || provisioning.ownership === "tenant-metal" !== Boolean(provisioning.metalHostname))
|
|
11216
|
+
fail2(`deployment.spec.targets.${targetName}.provisioning.ownership`, "must bind platform capacity or one tenant metal hostname.");
|
|
11217
|
+
if (provisioning.metalHostname !== undefined && !/^(?=.{1,253}$)[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?$/.test(String(provisioning.metalHostname)))
|
|
11218
|
+
fail2(`deployment.spec.targets.${targetName}.provisioning.metalHostname`, "is invalid.");
|
|
11219
|
+
if (typeof provisioning.maxMonthlySpendMinor !== "string" || !/^\d{1,18}$/.test(provisioning.maxMonthlySpendMinor))
|
|
11220
|
+
fail2(`deployment.spec.targets.${targetName}.provisioning.maxMonthlySpendMinor`, "must be a bounded decimal minor-unit amount.");
|
|
11221
|
+
}
|
|
11222
|
+
if (allocation.existing === "prefer" && target.provisioning === undefined)
|
|
11223
|
+
fail2(`deployment.spec.targets.${targetName}.provisioning`, "is required when placement may provision after reuse.");
|
|
11224
|
+
if (allocation.existing === "require" && target.provisioning !== undefined)
|
|
11225
|
+
fail2(`deployment.spec.targets.${targetName}.provisioning`, "must be omitted for reuse-only placement.");
|
|
11226
|
+
if (target.connectivity !== undefined) {
|
|
11227
|
+
const connectivity = object(target.connectivity, `deployment.spec.targets.${targetName}.connectivity`);
|
|
11228
|
+
exact3(connectivity, ["private", "public"], `deployment.spec.targets.${targetName}.connectivity`);
|
|
11229
|
+
const declaredPrivate = connectivity.private === undefined ? undefined : object(connectivity.private, `deployment.spec.targets.${targetName}.connectivity.private`);
|
|
11230
|
+
if (declaredPrivate?.mode === "cloudflare-warp" && allocation.sharing !== "exclusive")
|
|
11231
|
+
fail2(`deployment.spec.targets.${targetName}.allocation.sharing`, "must be exclusive for a Cloudflare WARP connector.");
|
|
11232
|
+
if (connectivity.private !== undefined) {
|
|
11233
|
+
const privateNetwork = declaredPrivate;
|
|
11234
|
+
if (privateNetwork.mode === "cloudflare-warp") {
|
|
11235
|
+
exact3(privateNetwork, ["mode", "credential", "network"], `deployment.spec.targets.${targetName}.connectivity.private`);
|
|
11236
|
+
if (!credentials[named(privateNetwork.credential, `deployment.spec.targets.${targetName}.connectivity.private.credential`)])
|
|
11237
|
+
fail2(`deployment.spec.targets.${targetName}.connectivity.private.credential`, "must name a declared credential.");
|
|
11238
|
+
if (typeof privateNetwork.network === "string")
|
|
11239
|
+
named(privateNetwork.network, `deployment.spec.targets.${targetName}.connectivity.private.network`);
|
|
11240
|
+
else
|
|
11241
|
+
reference(privateNetwork.network, `deployment.spec.targets.${targetName}.connectivity.private.network`);
|
|
11242
|
+
} else {
|
|
11243
|
+
exact3(privateNetwork, ["mode"], `deployment.spec.targets.${targetName}.connectivity.private`);
|
|
11244
|
+
if (!["disabled", "private-lan"].includes(String(privateNetwork.mode)))
|
|
11245
|
+
fail2(`deployment.spec.targets.${targetName}.connectivity.private.mode`, "is unsupported.");
|
|
11246
|
+
}
|
|
11247
|
+
}
|
|
11248
|
+
if (connectivity.public !== undefined) {
|
|
11249
|
+
const publicNetwork = object(connectivity.public, `deployment.spec.targets.${targetName}.connectivity.public`);
|
|
11250
|
+
if (publicNetwork.mode === "cloudflare-tunnel") {
|
|
11251
|
+
exact3(publicNetwork, ["mode", "credential", "zone", "hostname"], `deployment.spec.targets.${targetName}.connectivity.public`);
|
|
11252
|
+
if (!credentials[named(publicNetwork.credential, `deployment.spec.targets.${targetName}.connectivity.public.credential`)])
|
|
11253
|
+
fail2(`deployment.spec.targets.${targetName}.connectivity.public.credential`, "must name a declared credential.");
|
|
11254
|
+
if (typeof publicNetwork.zone === "string") {
|
|
11255
|
+
if (!/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(publicNetwork.zone))
|
|
11256
|
+
fail2(`deployment.spec.targets.${targetName}.connectivity.public.zone`, "is invalid.");
|
|
11257
|
+
} else
|
|
11258
|
+
reference(publicNetwork.zone, `deployment.spec.targets.${targetName}.connectivity.public.zone`);
|
|
11259
|
+
const hostname = object(publicNetwork.hostname, `deployment.spec.targets.${targetName}.connectivity.public.hostname`);
|
|
11260
|
+
const value2 = (coordinate, where, pattern) => {
|
|
11261
|
+
if (typeof coordinate === "string") {
|
|
11262
|
+
if (!pattern.test(coordinate))
|
|
11263
|
+
fail2(where, "is invalid.");
|
|
11264
|
+
} else
|
|
11265
|
+
reference(coordinate, where);
|
|
11266
|
+
};
|
|
11267
|
+
if (hostname.mode === "static") {
|
|
11268
|
+
exact3(hostname, ["mode", "label"], `deployment.spec.targets.${targetName}.connectivity.public.hostname`);
|
|
11269
|
+
value2(hostname.label, `deployment.spec.targets.${targetName}.connectivity.public.hostname.label`, /^[a-z0-9](?:[a-z0-9-]{0,48}[a-z0-9])?$/);
|
|
11270
|
+
} else if (hostname.mode === "indexed") {
|
|
11271
|
+
exact3(hostname, ["mode", "prefix", "startAt"], `deployment.spec.targets.${targetName}.connectivity.public.hostname`);
|
|
11272
|
+
value2(hostname.prefix, `deployment.spec.targets.${targetName}.connectivity.public.hostname.prefix`, /^[a-z0-9](?:[a-z0-9-]{0,48}[a-z0-9])?$/);
|
|
11273
|
+
if (hostname.startAt !== undefined)
|
|
11274
|
+
integer(hostname.startAt, `deployment.spec.targets.${targetName}.connectivity.public.hostname.startAt`, 0, 1e6);
|
|
11275
|
+
} else
|
|
11276
|
+
fail2(`deployment.spec.targets.${targetName}.connectivity.public.hostname.mode`, "is unsupported.");
|
|
11277
|
+
} else {
|
|
11278
|
+
exact3(publicNetwork, ["mode"], `deployment.spec.targets.${targetName}.connectivity.public`);
|
|
11279
|
+
if (publicNetwork.mode !== "disabled")
|
|
11280
|
+
fail2(`deployment.spec.targets.${targetName}.connectivity.public.mode`, "is unsupported.");
|
|
11281
|
+
}
|
|
11282
|
+
}
|
|
11283
|
+
}
|
|
11126
11284
|
if (target.placement !== undefined)
|
|
11127
11285
|
jsonValue(target.placement, `deployment.spec.targets.${targetName}.placement`);
|
|
11286
|
+
targetDefinitions.set(targetName, target);
|
|
11128
11287
|
}
|
|
11129
11288
|
const requirements = object(spec.requirements ?? {}, "deployment.spec.requirements");
|
|
11130
11289
|
if (Object.keys(requirements).length > 64)
|
|
@@ -11138,13 +11297,34 @@ function compileDeployment(sourceValue) {
|
|
|
11138
11297
|
const key = `${requirementValue.provider}@${requirementValue.contract}:${requirementValue.capability}`;
|
|
11139
11298
|
requiredProviders.set(key, { provider: requirementValue.provider, contract: requirementValue.contract, capability: requirementValue.capability });
|
|
11140
11299
|
}
|
|
11300
|
+
for (const [targetName, target] of targetDefinitions) {
|
|
11301
|
+
if (target.connectivity?.public?.mode === "cloudflare-tunnel" && ![...requirementDefinitions.values()].some(({ capability }) => capability === "network.public-tunnel")) {
|
|
11302
|
+
fail2(`deployment.spec.targets.${targetName}.connectivity.public`, "requires one network.public-tunnel provider requirement.");
|
|
11303
|
+
}
|
|
11304
|
+
if (target.connectivity?.private?.mode === "cloudflare-warp" && ![...requirementDefinitions.values()].some(({ capability }) => capability === "network.private")) {
|
|
11305
|
+
fail2(`deployment.spec.targets.${targetName}.connectivity.private`, "requires one network.private provider requirement.");
|
|
11306
|
+
}
|
|
11307
|
+
}
|
|
11141
11308
|
const components = object(spec.components, "deployment.spec.components");
|
|
11142
11309
|
const componentEntries = Object.entries(components);
|
|
11143
11310
|
if (componentEntries.length < 1 || componentEntries.length > 128)
|
|
11144
11311
|
fail2("deployment.spec.components", "must contain 1 to 128 components.");
|
|
11145
11312
|
for (const [componentName, value] of componentEntries) {
|
|
11146
11313
|
named(componentName, "deployment.spec.components key");
|
|
11147
|
-
validateComponent(value, `deployment.spec.components.${componentName}`,
|
|
11314
|
+
validateComponent(value, `deployment.spec.components.${componentName}`, targetDefinitions, requirementDefinitions);
|
|
11315
|
+
}
|
|
11316
|
+
for (const [targetName, target] of targetDefinitions) {
|
|
11317
|
+
if (target.connectivity?.public?.mode !== "cloudflare-tunnel")
|
|
11318
|
+
continue;
|
|
11319
|
+
const publicApplications = componentEntries.filter(([, component2]) => {
|
|
11320
|
+
const candidate = component2;
|
|
11321
|
+
return candidate.kind === "application" && candidate.target === targetName && candidate.network?.public?.mode === "cloudflare-tunnel";
|
|
11322
|
+
});
|
|
11323
|
+
if (publicApplications.length !== 1)
|
|
11324
|
+
fail2(`deployment.spec.targets.${targetName}.connectivity.public`, "requires exactly one application on the target with network.public cloudflare-tunnel.");
|
|
11325
|
+
const application = publicApplications[0][1];
|
|
11326
|
+
if (application.kind !== "application" || !application.network?.ingress?.stablePort)
|
|
11327
|
+
fail2(`deployment.spec.components.${publicApplications[0][0]}.network.ingress`, "requires one stablePort for Tunnel ingress.");
|
|
11148
11328
|
}
|
|
11149
11329
|
const actionContext = {
|
|
11150
11330
|
components,
|
|
@@ -11186,6 +11366,14 @@ function compileDeployment(sourceValue) {
|
|
|
11186
11366
|
});
|
|
11187
11367
|
plannedWorkflows.push({ id: workflowName, ...workflowValue.concurrency ? { concurrency: workflowValue.concurrency } : {}, stages: plannedStages });
|
|
11188
11368
|
}
|
|
11369
|
+
const deployWorkflow = plannedWorkflows.find(({ id: id2 }) => id2 === "deploy");
|
|
11370
|
+
for (const [targetName, target] of targetDefinitions) {
|
|
11371
|
+
if (!target.connectivity || target.connectivity.public?.mode !== "cloudflare-tunnel" && target.connectivity.private?.mode !== "cloudflare-warp")
|
|
11372
|
+
continue;
|
|
11373
|
+
const ensures = deployWorkflow?.stages.flatMap(({ steps }) => steps).filter((step3) => step3.uses === "forgezero.network/ensure@1" && step3.with.target === targetName && (step3.scope.kind === "each-target" || step3.scope.kind === "target-batches") && step3.scope.target === targetName) ?? [];
|
|
11374
|
+
if (ensures.length !== 1)
|
|
11375
|
+
fail2(`deployment.spec.workflows.deploy`, `must contain exactly one network.ensure step scoped to connected target ${targetName}.`);
|
|
11376
|
+
}
|
|
11189
11377
|
const typedSource = source;
|
|
11190
11378
|
return {
|
|
11191
11379
|
format: DEPLOY_PLAN_FORMAT,
|
|
@@ -11294,8 +11482,10 @@ export default defineDeployment({
|
|
|
11294
11482
|
inputs: { replicas: input.integer({ minimum: 1, maximum: 32, default: 1 }) },
|
|
11295
11483
|
targets: {
|
|
11296
11484
|
app: target.compute({
|
|
11297
|
-
|
|
11298
|
-
|
|
11485
|
+
profiles: ['app'],
|
|
11486
|
+
replicas: { minimum: 1, desired: input.ref('replicas'), maximum: 32 },
|
|
11487
|
+
resources: { cpuCores: 1, memoryMiB: 512, storageGiB: 8 },
|
|
11488
|
+
os: 'ubuntu-24.04', runtime: 'native', isolation: 'standard', reuse: 'require'
|
|
11299
11489
|
})
|
|
11300
11490
|
},
|
|
11301
11491
|
requirements: { bun: providers.bun.require() },
|
|
@@ -14893,8 +15083,7 @@ function localBootstrapHost() {
|
|
|
14893
15083
|
const execute = async (argv2, options = {}) => {
|
|
14894
15084
|
const child = Bun.spawn([...argv2], { stdin: options.stdin === undefined ? "ignore" : "pipe", stdout: "pipe", stderr: "pipe" });
|
|
14895
15085
|
if (options.stdin !== undefined && child.stdin && typeof child.stdin !== "number") {
|
|
14896
|
-
child.stdin
|
|
14897
|
-
child.stdin.end();
|
|
15086
|
+
await writeAndCloseProcessInput(child.stdin, options.stdin);
|
|
14898
15087
|
}
|
|
14899
15088
|
const [stdout, stderr, exitCode] = await Promise.all([
|
|
14900
15089
|
new Response(child.stdout).text(),
|
|
@@ -16634,8 +16823,7 @@ var defaultExec3 = async (argv2, options = {}) => {
|
|
|
16634
16823
|
}
|
|
16635
16824
|
});
|
|
16636
16825
|
if (options.stdin !== undefined && child.stdin && typeof child.stdin !== "number") {
|
|
16637
|
-
child.stdin
|
|
16638
|
-
child.stdin.end();
|
|
16826
|
+
await writeAndCloseProcessInput(child.stdin, options.stdin);
|
|
16639
16827
|
}
|
|
16640
16828
|
const [stdout, stderr, exitCode] = await Promise.all([
|
|
16641
16829
|
new Response(child.stdout).text(),
|
|
@@ -18099,9 +18287,8 @@ async function cmdAgent(options, args) {
|
|
|
18099
18287
|
mkdirSync13(dirname14(enrolTokenCredentialPath), { recursive: true, mode: 448 });
|
|
18100
18288
|
const sealing = Bun.spawn(["systemd-creds", "encrypt", "--name=enrol-token", "-", enrolTokenCredentialPath], { stdin: "pipe", stdout: "ignore", stderr: "pipe" });
|
|
18101
18289
|
if (sealing.stdin && typeof sealing.stdin !== "number") {
|
|
18102
|
-
sealing.stdin
|
|
18290
|
+
await writeAndCloseProcessInput(sealing.stdin, `${token}
|
|
18103
18291
|
`);
|
|
18104
|
-
sealing.stdin.end();
|
|
18105
18292
|
}
|
|
18106
18293
|
const error = await new Response(sealing.stderr).text();
|
|
18107
18294
|
if (await sealing.exited !== 0)
|
|
@@ -19277,6 +19464,24 @@ async function cmdDeploy(options, args) {
|
|
|
19277
19464
|
return 0;
|
|
19278
19465
|
}
|
|
19279
19466
|
const pipelineKey = required(options.pipelineKey, "--pipeline");
|
|
19467
|
+
if (operation === "plan") {
|
|
19468
|
+
const revision = required(options.revision, "--revision").toLowerCase();
|
|
19469
|
+
if (!/^[a-f0-9]{40}$/.test(revision))
|
|
19470
|
+
throw new Error("--revision must be a full 40-character Git commit.");
|
|
19471
|
+
const compiled = inspectCompiledDeployment(options.projectRoot);
|
|
19472
|
+
let inputs;
|
|
19473
|
+
if (options.data !== undefined) {
|
|
19474
|
+
const parsed = JSON.parse(options.data === "-" ? await Bun.stdin.text() : options.data);
|
|
19475
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
19476
|
+
throw new Error("--data must be one JSON object of typed deployment inputs.");
|
|
19477
|
+
inputs = parsed;
|
|
19478
|
+
}
|
|
19479
|
+
out.line(JSON.stringify(await deploymentRequest(options, "/plan", {
|
|
19480
|
+
method: "POST",
|
|
19481
|
+
body: { pipelineKey, revision, plan: compiled.plan, ...inputs ? { inputs } : {} }
|
|
19482
|
+
}), null, 2));
|
|
19483
|
+
return 0;
|
|
19484
|
+
}
|
|
19280
19485
|
if (operation === "attach") {
|
|
19281
19486
|
if (options.targets.length === 0)
|
|
19282
19487
|
throw new Error("At least one --target <compute>@<profile> is required.");
|
|
@@ -19322,7 +19527,7 @@ async function cmdDeploy(options, args) {
|
|
|
19322
19527
|
out.line(JSON.stringify(await deploymentRequest(options, "/rotate", { method: "POST", body: { pipelineKey } }), null, 2));
|
|
19323
19528
|
return 0;
|
|
19324
19529
|
}
|
|
19325
|
-
out.fail("Usage: fz deploy init|compile|check|sync|catalog|list|connect|attach|runs|release|enable|disable|target-enable|target-disable|rotate");
|
|
19530
|
+
out.fail("Usage: fz deploy init|compile|check|sync|catalog|list|connect|plan|attach|runs|release|enable|disable|target-enable|target-disable|rotate");
|
|
19326
19531
|
return 2;
|
|
19327
19532
|
} catch (cause) {
|
|
19328
19533
|
out.fail(cause instanceof Error ? cause.message : String(cause));
|
|
@@ -19399,7 +19604,10 @@ function usage() {
|
|
|
19399
19604
|
fz deploy sync Prove readiness and print the Git synchronization rule
|
|
19400
19605
|
fz deploy catalog List selectable tested OS/software coordinates
|
|
19401
19606
|
fz deploy list List pipelines for .fz/config.json's project
|
|
19402
|
-
fz deploy connect Create a repository pipeline
|
|
19607
|
+
fz deploy connect Create a repository pipeline; optional --target values
|
|
19608
|
+
are manual anchors, not required for automatic placement
|
|
19609
|
+
fz deploy plan Approve the compiled plan at --revision and let the API
|
|
19610
|
+
reuse idle compute before bounded provisioning
|
|
19403
19611
|
fz deploy attach Attach --target <compute>@<profile> to a pipeline
|
|
19404
19612
|
fz deploy runs Show pipeline deployment runs
|
|
19405
19613
|
fz deploy release Queue one exact --revision; --wait for completion
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { AGENT_CREDENTIAL_LOCATIONS, AGENT_CREDENTIAL_POLICY, METAL_SYSTEMD_CRED
|
|
|
13
13
|
export type { AgentCredentialLocation, DeploymentCredentialBinding, DeploymentCredentialSchema } from './credential-schema';
|
|
14
14
|
export { createDeploymentManager, DeploymentError } from './deployment';
|
|
15
15
|
export type { DeploymentManager, DeploymentOptions, DeploymentRequest, DeploymentResult } from './deployment';
|
|
16
|
+
export { DeploymentInputError, resolveDeploymentInputs, resolveDeploymentTargets } from './deployment-targets';
|
|
16
17
|
export { DEFAULT_CONTROL_SOCKET, requestControl, startControlServer } from './control';
|
|
17
18
|
export { pullDeploymentOnce, startDeploymentPull } from './deployment-pull';
|
|
18
19
|
export type { DeploymentPullOptions, RemoteDeploymentClaim, PullResult } from './deployment-pull';
|
package/dist/metal-bootstrap.js
CHANGED
|
@@ -354,7 +354,7 @@ function systemdAgentEgressDirectives(loopbackTcpPorts = []) {
|
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
// src/version.ts
|
|
357
|
-
var VERSION = "0.1.
|
|
357
|
+
var VERSION = "0.1.76";
|
|
358
358
|
|
|
359
359
|
// src/otel-collector.ts
|
|
360
360
|
var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
|