@forgezero/agent 0.1.35 → 0.1.36
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 +29 -0
- package/dist/agent-heartbeat.js +1 -1
- package/dist/bootstrap.d.ts +5 -0
- package/dist/bootstrap.js +60 -5
- package/dist/cli/agent-install.d.ts +3 -0
- package/dist/definition.js +9 -2
- package/dist/deploy-file.js +9 -2
- package/dist/fz-agent.js +492 -150
- package/dist/fz.js +69 -8
- package/dist/index.d.ts +2 -0
- package/dist/metal-bootstrap.js +1 -1
- package/dist/provision.d.ts +4 -0
- package/dist/provision.js +33 -5
- package/dist/software-helper.js +9 -2
- package/dist/software.d.ts +3 -1
- package/dist/software.js +12 -3
- package/dist/ssh-bootstrap.d.ts +72 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/schema/deploy-v2.json +1 -1
package/dist/fz.js
CHANGED
|
@@ -4875,7 +4875,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
|
|
|
4875
4875
|
var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
|
|
4876
4876
|
|
|
4877
4877
|
// src/version.ts
|
|
4878
|
-
var VERSION2 = "0.1.
|
|
4878
|
+
var VERSION2 = "0.1.36";
|
|
4879
4879
|
|
|
4880
4880
|
// src/software.ts
|
|
4881
4881
|
var BUN_INSTALLER_SHA256 = "bab8acfb046aac8c72407bdcce903957665d655d7acaa3e11c7c4616beae68dd";
|
|
@@ -4889,7 +4889,8 @@ var SOFTWARE_CATALOG = [
|
|
|
4889
4889
|
{ id: "nginx", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4890
4890
|
{ id: "arangodb", version: "3.11.14", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4891
4891
|
{ id: "cloudflared", version: "2026.7.3", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4892
|
-
{ id: "ufw", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
|
|
4892
|
+
{ id: "ufw", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
4893
|
+
{ id: "openssh-client", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
|
|
4893
4894
|
];
|
|
4894
4895
|
var UBUNTU_2604_X64 = [
|
|
4895
4896
|
{
|
|
@@ -4916,6 +4917,11 @@ var UBUNTU_2604_X64 = [
|
|
|
4916
4917
|
requirement: { id: "ufw", version: "ubuntu-26.04" },
|
|
4917
4918
|
check: "command -v ufw >/dev/null",
|
|
4918
4919
|
install: "DEBIAN_FRONTEND=noninteractive apt-get update -qq && apt-get install -y ufw"
|
|
4920
|
+
},
|
|
4921
|
+
{
|
|
4922
|
+
requirement: { id: "openssh-client", version: "ubuntu-26.04" },
|
|
4923
|
+
check: "command -v ssh >/dev/null && command -v scp >/dev/null && command -v ssh-keyscan >/dev/null && command -v ssh-keygen >/dev/null",
|
|
4924
|
+
install: "DEBIAN_FRONTEND=noninteractive apt-get update -qq && apt-get install -y openssh-client"
|
|
4919
4925
|
}
|
|
4920
4926
|
];
|
|
4921
4927
|
function validateSoftwareRequirements(value, _options = {}) {
|
|
@@ -4929,7 +4935,7 @@ function validateSoftwareRequirements(value, _options = {}) {
|
|
|
4929
4935
|
if (Object.keys(row).some((key) => key !== "id" && key !== "version")) {
|
|
4930
4936
|
throw new Error("software requirement contains an unknown field");
|
|
4931
4937
|
}
|
|
4932
|
-
if (!["bun", "nginx", "arangodb", "cloudflared", "ufw"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
4938
|
+
if (!["bun", "nginx", "arangodb", "cloudflared", "ufw", "openssh-client"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
4933
4939
|
throw new Error("software requirement coordinate is invalid");
|
|
4934
4940
|
}
|
|
4935
4941
|
const requirement = { id: row.id, version: row.version };
|
|
@@ -5482,7 +5488,12 @@ function agentUnit(options) {
|
|
|
5482
5488
|
if (Boolean(options.pullMigrations) !== Boolean(options.lifecycleProfilePath)) {
|
|
5483
5489
|
throw new Error("migration pull and lifecycle profile must be supplied together");
|
|
5484
5490
|
}
|
|
5491
|
+
const bootstrapEnabled = Boolean(options.pullBootstrap && options.bootstrapSshCredentialPath && options.bootstrapTargetTelemetryEndpoint);
|
|
5492
|
+
if ([options.pullBootstrap, options.bootstrapSshCredentialPath, options.bootstrapTargetTelemetryEndpoint].some(Boolean) && !bootstrapEnabled) {
|
|
5493
|
+
throw new Error("bootstrap pull, SSH credential and target telemetry endpoint must be supplied together");
|
|
5494
|
+
}
|
|
5485
5495
|
const lifecycleHelperSocketPath = lifecycleEnabled ? systemdPath(options.lifecycleHelperSocketPath ?? LIFECYCLE_HELPER_SOCKET, "lifecycle helper socket") : undefined;
|
|
5496
|
+
const bootstrapSshCredentialPath = bootstrapEnabled ? systemdPath(options.bootstrapSshCredentialPath, "bootstrap SSH credential") : undefined;
|
|
5486
5497
|
const warpValues = [
|
|
5487
5498
|
options.warpOrganization,
|
|
5488
5499
|
options.warpClientIdCredentialPath,
|
|
@@ -5548,6 +5559,9 @@ function agentUnit(options) {
|
|
|
5548
5559
|
options.publicApiUrl ? `FZ_PUBLIC_API_URL=${options.publicApiUrl}` : null,
|
|
5549
5560
|
options.pullDeployments ? "FZ_DEPLOY_PULL=true" : null,
|
|
5550
5561
|
options.pullMigrations ? "FZ_MIGRATION_PULL=true" : null,
|
|
5562
|
+
options.pullBootstrap ? "FZ_BOOTSTRAP_PULL=true" : null,
|
|
5563
|
+
options.pullBootstrap ? "FZ_BOOTSTRAP_SSH_KEY_CREDENTIAL=bootstrap-ssh-key" : null,
|
|
5564
|
+
options.pullBootstrap ? `FZ_BOOTSTRAP_TARGET_OTLP_ENDPOINT=${options.bootstrapTargetTelemetryEndpoint}` : null,
|
|
5551
5565
|
`FZ_AGENT_UPDATE_SOCKET=${DEFAULT_AGENT_UPDATE_SOCKET}`,
|
|
5552
5566
|
options.pullMigrations ? `FZ_LIFECYCLE_HELPER_SOCKET=${lifecycleHelperSocketPath}` : null
|
|
5553
5567
|
].filter((line) => line !== null);
|
|
@@ -5555,6 +5569,8 @@ function agentUnit(options) {
|
|
|
5555
5569
|
environment.push(`HOME=${deployRoot}/agent-home`, `XDG_CACHE_HOME=${deployRoot}/cache`);
|
|
5556
5570
|
}
|
|
5557
5571
|
const gitCredential = options.gitCredentialPath ? `LoadCredentialEncrypted=git-deploy-key:${options.gitCredentialPath}
|
|
5572
|
+
` : "";
|
|
5573
|
+
const bootstrapCredential = bootstrapEnabled ? `LoadCredentialEncrypted=bootstrap-ssh-key:${bootstrapSshCredentialPath}
|
|
5558
5574
|
` : "";
|
|
5559
5575
|
const projectCredentials = Object.entries(deploymentCredentials).map(([name, path]) => `LoadCredentialEncrypted=${name}:${path}`).join(`
|
|
5560
5576
|
`);
|
|
@@ -5609,7 +5625,7 @@ User=${user}
|
|
|
5609
5625
|
Group=${VAULT_GROUP}
|
|
5610
5626
|
${deploymentGroup}
|
|
5611
5627
|
LoadCredentialEncrypted=agent-seed:${seedCredentialPath}
|
|
5612
|
-
${gitCredential}${projectCredentials}${projectCredentials ? `
|
|
5628
|
+
${gitCredential}${bootstrapCredential}${projectCredentials}${projectCredentials ? `
|
|
5613
5629
|
` : ""}${snpPrepare}ExecStart=${bin}
|
|
5614
5630
|
Restart=always
|
|
5615
5631
|
RestartSec=2
|
|
@@ -5664,6 +5680,10 @@ function planProvision(options) {
|
|
|
5664
5680
|
if (Boolean(options.pullMigrations) !== Boolean(options.lifecycleProfilePath)) {
|
|
5665
5681
|
throw new Error("migration pull and lifecycle profile must be supplied together");
|
|
5666
5682
|
}
|
|
5683
|
+
const bootstrapEnabled = Boolean(options.pullBootstrap && options.bootstrapSshCredentialPath && options.bootstrapTargetTelemetryEndpoint);
|
|
5684
|
+
if ([options.pullBootstrap, options.bootstrapSshCredentialPath, options.bootstrapTargetTelemetryEndpoint].some(Boolean) && !bootstrapEnabled) {
|
|
5685
|
+
throw new Error("bootstrap pull, SSH credential and target telemetry endpoint must be supplied together");
|
|
5686
|
+
}
|
|
5667
5687
|
const warpValues = [
|
|
5668
5688
|
options.warpOrganization,
|
|
5669
5689
|
options.warpClientIdCredentialPath,
|
|
@@ -5689,13 +5709,20 @@ function planProvision(options) {
|
|
|
5689
5709
|
const gitPublicKeyDir = gitPublicKeyPath?.replace(/\/[^/]+$/, "");
|
|
5690
5710
|
const lifecycleProfilePath = lifecycleEnabled ? systemdPath(options.lifecycleProfilePath, "lifecycle profile") : undefined;
|
|
5691
5711
|
const lifecycleHelperSocketPath = lifecycleEnabled ? systemdPath(options.lifecycleHelperSocketPath ?? LIFECYCLE_HELPER_SOCKET, "lifecycle helper socket") : undefined;
|
|
5712
|
+
const bootstrapSshCredentialPath = bootstrapEnabled ? systemdPath(options.bootstrapSshCredentialPath, "bootstrap SSH credential") : undefined;
|
|
5692
5713
|
const warpClientIdCredentialPath = warpEnabled ? systemdPath(options.warpClientIdCredentialPath, "WARP client-id credential") : undefined;
|
|
5693
5714
|
const warpClientSecretCredentialPath = warpEnabled ? systemdPath(options.warpClientSecretCredentialPath, "WARP client-secret credential") : undefined;
|
|
5694
5715
|
return {
|
|
5695
5716
|
mode,
|
|
5696
5717
|
reason: reasonFor(mode),
|
|
5697
5718
|
unitPath: UNIT_PATH,
|
|
5698
|
-
unit: agentUnit({
|
|
5719
|
+
unit: agentUnit({
|
|
5720
|
+
...options,
|
|
5721
|
+
mode,
|
|
5722
|
+
lifecycleProfilePath,
|
|
5723
|
+
lifecycleHelperSocketPath,
|
|
5724
|
+
bootstrapSshCredentialPath
|
|
5725
|
+
}),
|
|
5699
5726
|
auxiliaryUnits: [
|
|
5700
5727
|
{ path: AGENT_SOCKET_UNIT_PATH, unit: agentSocketUnit(options) },
|
|
5701
5728
|
{ path: AGENT_SOCKET_PROXY_UNIT_PATH, unit: agentSocketProxyUnit(options) },
|
|
@@ -11639,6 +11666,7 @@ var SEED_CREDENTIAL = `${CREDS}/seed-sync-root.cred`;
|
|
|
11639
11666
|
var BACKUP_RECOVERY_CREDENTIAL = `${CREDS}/backup-recovery-root.cred`;
|
|
11640
11667
|
var WARP_CLIENT_ID_CREDENTIAL = `${CREDS}/warp-auth-client-id.cred`;
|
|
11641
11668
|
var WARP_CLIENT_SECRET_CREDENTIAL = `${CREDS}/warp-auth-client-secret.cred`;
|
|
11669
|
+
var BOOTSTRAP_SSH_CREDENTIAL = `${CREDS}/bootstrap-ssh-key.cred`;
|
|
11642
11670
|
var PLATFORM_ENROL_SOURCE = "/run/forgezero-platform-enrol-token";
|
|
11643
11671
|
var DB_MODE_EVIDENCE = "/var/lib/forgezero-cluster/server-mode.json";
|
|
11644
11672
|
var LIFECYCLE_PROFILE = "/etc/forgezero/lifecycle.json";
|
|
@@ -11701,6 +11729,20 @@ function validateBootstrapConfig(value) {
|
|
|
11701
11729
|
}
|
|
11702
11730
|
if (!value.enrolTokenFile)
|
|
11703
11731
|
throw new Error("tenant bootstrap requires --enrol-token-file");
|
|
11732
|
+
if (value.bootstrapRunner) {
|
|
11733
|
+
if (!value.bootstrapRunner.sshPrivateKeyFile.startsWith("/") || /[\r\n]/.test(value.bootstrapRunner.sshPrivateKeyFile)) {
|
|
11734
|
+
throw new Error("bootstrap runner SSH private-key file must be absolute");
|
|
11735
|
+
}
|
|
11736
|
+
let targetTelemetry;
|
|
11737
|
+
try {
|
|
11738
|
+
targetTelemetry = new URL(value.bootstrapRunner.targetTelemetryEndpoint);
|
|
11739
|
+
} catch {
|
|
11740
|
+
throw new Error("bootstrap target telemetry endpoint is malformed");
|
|
11741
|
+
}
|
|
11742
|
+
if (targetTelemetry.protocol !== "https:" || targetTelemetry.username || targetTelemetry.password || targetTelemetry.search || targetTelemetry.hash || targetTelemetry.port && targetTelemetry.port !== "443") {
|
|
11743
|
+
throw new Error("bootstrap target telemetry must be public HTTPS on port 443");
|
|
11744
|
+
}
|
|
11745
|
+
}
|
|
11704
11746
|
return value;
|
|
11705
11747
|
}
|
|
11706
11748
|
if (!PLATFORM_BOOTSTRAP_PROFILES.includes(value.profile))
|
|
@@ -11762,7 +11804,11 @@ function validateBootstrapConfig(value) {
|
|
|
11762
11804
|
}
|
|
11763
11805
|
function planBootstrap(input, initialized = false) {
|
|
11764
11806
|
const config = validateBootstrapConfig(structuredClone(input));
|
|
11765
|
-
const software = config.kind === "tenant" ? [
|
|
11807
|
+
const software = config.kind === "tenant" ? [
|
|
11808
|
+
...config.software ?? [],
|
|
11809
|
+
...config.bootstrapRunner && !config.software?.some(({ id: id2 }) => id2 === "openssh-client") ? [{ id: "openssh-client", version: "ubuntu-26.04" }] : [],
|
|
11810
|
+
...config.installCloudflared ? [{ id: "cloudflared", version: "2026.7.3" }] : []
|
|
11811
|
+
] : [
|
|
11766
11812
|
...config.firewall.enabled ? [{ id: "ufw", version: "ubuntu-26.04" }] : [],
|
|
11767
11813
|
{ id: "bun", version: "1.3.14" },
|
|
11768
11814
|
{ id: "nginx", version: "ubuntu-26.04" },
|
|
@@ -11997,6 +12043,10 @@ async function applyBootstrap(input, host = localBootstrapHost()) {
|
|
|
11997
12043
|
const alreadyEnrolled = host.exists("/var/lib/forgezero/enrolment.json");
|
|
11998
12044
|
host.mkdir(CREDS, 448);
|
|
11999
12045
|
host.mkdir("/var/lib/forgezero", 448);
|
|
12046
|
+
if (config.kind === "tenant" && config.bootstrapRunner && !host.exists(BOOTSTRAP_SSH_CREDENTIAL)) {
|
|
12047
|
+
await seal(host, "bootstrap-ssh-key", BOOTSTRAP_SSH_CREDENTIAL, privateFile(host, config.bootstrapRunner.sshPrivateKeyFile, "bootstrap runner SSH private key"));
|
|
12048
|
+
host.remove(config.bootstrapRunner.sshPrivateKeyFile);
|
|
12049
|
+
}
|
|
12000
12050
|
if (cloudflare?.warp) {
|
|
12001
12051
|
await seal(host, "warp-auth-client-id", WARP_CLIENT_ID_CREDENTIAL, cloudflare.warp.clientId);
|
|
12002
12052
|
await seal(host, "warp-auth-client-secret", WARP_CLIENT_SECRET_CREDENTIAL, cloudflare.warp.clientSecret);
|
|
@@ -12196,7 +12246,8 @@ function strictBootstrapDocument(value) {
|
|
|
12196
12246
|
"cloudflareHandoff",
|
|
12197
12247
|
"realm",
|
|
12198
12248
|
"enrolTokenFile",
|
|
12199
|
-
"software"
|
|
12249
|
+
"software",
|
|
12250
|
+
"bootstrapRunner"
|
|
12200
12251
|
], "bootstrap config");
|
|
12201
12252
|
if (root.kind === "platform") {
|
|
12202
12253
|
exactKeys2(root.firewall, ["enabled", "sshPort", "privateCidrs"], "firewall config");
|
|
@@ -12261,6 +12312,8 @@ function strictBootstrapDocument(value) {
|
|
|
12261
12312
|
exactKeys2(environment.cloudflare.warp, ["organization", "virtualNetworkId", "deviceProfileId"], "Cloudflare WARP runtime config");
|
|
12262
12313
|
}
|
|
12263
12314
|
} else if (root.kind === "tenant") {
|
|
12315
|
+
if (root.bootstrapRunner !== undefined)
|
|
12316
|
+
exactKeys2(root.bootstrapRunner, ["sshPrivateKeyFile", "targetTelemetryEndpoint"], "bootstrap runner config");
|
|
12264
12317
|
for (const key of ["environment", "profile", "computeReference", "database", "platformEnrolTokenFile", "runtime", "cloudflareHandoff"]) {
|
|
12265
12318
|
if (root[key] !== undefined && key !== "profile")
|
|
12266
12319
|
throw new Error(`tenant bootstrap cannot contain ${key}`);
|
|
@@ -12355,6 +12408,9 @@ function localBootstrapHost() {
|
|
|
12355
12408
|
generateGitIdentity: true,
|
|
12356
12409
|
pullDeployments: true,
|
|
12357
12410
|
pullMigrations: config.kind === "platform",
|
|
12411
|
+
pullBootstrap: config.kind === "tenant" && Boolean(config.bootstrapRunner),
|
|
12412
|
+
bootstrapSshCredentialPath: config.kind === "tenant" && config.bootstrapRunner ? BOOTSTRAP_SSH_CREDENTIAL : undefined,
|
|
12413
|
+
bootstrapTargetTelemetryEndpoint: config.kind === "tenant" ? config.bootstrapRunner?.targetTelemetryEndpoint : undefined,
|
|
12358
12414
|
lifecycleProfilePath: config.kind === "platform" ? LIFECYCLE_PROFILE : undefined,
|
|
12359
12415
|
...config.kind === "platform" && config.runtime.environment.cloudflare?.warp ? {
|
|
12360
12416
|
warpOrganization: config.runtime.environment.cloudflare.warp.organization,
|
|
@@ -14140,6 +14196,7 @@ function interactiveBootstrap(kind) {
|
|
|
14140
14196
|
if (!process.stdin.isTTY)
|
|
14141
14197
|
throw new Error("non-interactive bootstrap requires --bootstrap-config <private-json-file>");
|
|
14142
14198
|
if (kind === "tenant") {
|
|
14199
|
+
const runnerKey = bootstrapAnswer("Bootstrap runner SSH private-key file (blank to disable)", "");
|
|
14143
14200
|
return {
|
|
14144
14201
|
kind,
|
|
14145
14202
|
apiUrl: bootstrapAnswer("Platform API URL"),
|
|
@@ -14147,7 +14204,11 @@ function interactiveBootstrap(kind) {
|
|
|
14147
14204
|
nodeHostname: bootstrapAnswer("Node hostname", hostname()),
|
|
14148
14205
|
telemetryEndpoint: bootstrapAnswer("Public HTTPS OTLP endpoint"),
|
|
14149
14206
|
enrolTokenFile: bootstrapAnswer("Root-only enrolment token file"),
|
|
14150
|
-
profile: bootstrapAnswer("Deploy profile", "app")
|
|
14207
|
+
profile: bootstrapAnswer("Deploy profile", "app"),
|
|
14208
|
+
...runnerKey ? { bootstrapRunner: {
|
|
14209
|
+
sshPrivateKeyFile: runnerKey,
|
|
14210
|
+
targetTelemetryEndpoint: bootstrapAnswer("Public HTTPS OTLP endpoint for bootstrapped targets")
|
|
14211
|
+
} } : {}
|
|
14151
14212
|
};
|
|
14152
14213
|
}
|
|
14153
14214
|
const environment = bootstrapAnswer("Environment (production/development)", "production");
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export type { DeploymentPullOptions, RemoteDeploymentClaim, PullResult } from '.
|
|
|
15
15
|
export { pullProvisioningOnce, startProvisioningPull } from './provisioning-pull';
|
|
16
16
|
export type { CreateRemoteProvisionClaim, ProvisioningPullOptions, RemoteProvisionClaim, GuestAccess, ProvisionPullResult, ProvisionRunner, ProvisionResult } from './provisioning-pull';
|
|
17
17
|
export { pullMigrationOnce, startMigrationPull } from './migration-pull';
|
|
18
|
+
export { executeSshBootstrap, pullSshBootstrapOnce, startSshBootstrapPull } from './ssh-bootstrap';
|
|
19
|
+
export type { RemoteSshBootstrapClaim, SshBootstrapPullOptions, SshBootstrapResult } from './ssh-bootstrap';
|
|
18
20
|
export type { MigrationAction, MigrationEvidence, MigrationNetwork, MigrationPullOptions, MigrationPullResult, RemoteMigrationClaim } from './migration-pull';
|
|
19
21
|
export { enrolGuestIdentity, loadGuestBinding } from './guest-enrolment';
|
|
20
22
|
export type { GuestBinding, GuestEnrolmentOptions } from './guest-enrolment';
|
package/dist/metal-bootstrap.js
CHANGED
package/dist/provision.d.ts
CHANGED
|
@@ -100,6 +100,10 @@ export interface UnitOptions {
|
|
|
100
100
|
runnerPublicTcpPorts?: readonly number[];
|
|
101
101
|
/** Enable PQ-authenticated lifecycle claims through a constrained root helper. */
|
|
102
102
|
pullMigrations?: boolean;
|
|
103
|
+
/** Claim API-owned SSH bootstrap jobs; the private key stays a systemd credential on this runner. */
|
|
104
|
+
pullBootstrap?: boolean;
|
|
105
|
+
bootstrapSshCredentialPath?: string;
|
|
106
|
+
bootstrapTargetTelemetryEndpoint?: string;
|
|
103
107
|
/** Root-owned declarative lifecycle profile; never supplied by a migration claim. */
|
|
104
108
|
lifecycleProfilePath?: string;
|
|
105
109
|
lifecycleHelperSocketPath?: string;
|
package/dist/provision.js
CHANGED
|
@@ -673,6 +673,7 @@ function requestAgentUpdate(request, socketPath = DEFAULT_AGENT_UPDATE_SOCKET, t
|
|
|
673
673
|
|
|
674
674
|
// src/software.ts
|
|
675
675
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
676
|
+
var PINNED_BUN_VERSION = "1.3.14";
|
|
676
677
|
var BUN_INSTALLER_SHA256 = "bab8acfb046aac8c72407bdcce903957665d655d7acaa3e11c7c4616beae68dd";
|
|
677
678
|
var ARANGO_SHA256 = "b5a9197b4343f2ed554e1ebc1ef8e6529c7c39cde0035cdc311a4747a3355066";
|
|
678
679
|
var CLOUDFLARED_SHA256 = "9d71c677db00134c1bd4144b7783486b654ad281b1ea62b4972098d19f770f17";
|
|
@@ -684,7 +685,8 @@ var SOFTWARE_CATALOG = [
|
|
|
684
685
|
{ id: "nginx", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
685
686
|
{ id: "arangodb", version: "3.11.14", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
686
687
|
{ id: "cloudflared", version: "2026.7.3", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
687
|
-
{ id: "ufw", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
|
|
688
|
+
{ id: "ufw", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
689
|
+
{ id: "openssh-client", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
|
|
688
690
|
];
|
|
689
691
|
var UBUNTU_2604_X64 = [
|
|
690
692
|
{
|
|
@@ -711,6 +713,11 @@ var UBUNTU_2604_X64 = [
|
|
|
711
713
|
requirement: { id: "ufw", version: "ubuntu-26.04" },
|
|
712
714
|
check: "command -v ufw >/dev/null",
|
|
713
715
|
install: "DEBIAN_FRONTEND=noninteractive apt-get update -qq && apt-get install -y ufw"
|
|
716
|
+
},
|
|
717
|
+
{
|
|
718
|
+
requirement: { id: "openssh-client", version: "ubuntu-26.04" },
|
|
719
|
+
check: "command -v ssh >/dev/null && command -v scp >/dev/null && command -v ssh-keyscan >/dev/null && command -v ssh-keygen >/dev/null",
|
|
720
|
+
install: "DEBIAN_FRONTEND=noninteractive apt-get update -qq && apt-get install -y openssh-client"
|
|
714
721
|
}
|
|
715
722
|
];
|
|
716
723
|
function observeSoftwareHost(osRelease = readFileSync3("/etc/os-release", "utf8"), architecture = process.arch) {
|
|
@@ -735,7 +742,7 @@ function validateSoftwareRequirements(value, _options = {}) {
|
|
|
735
742
|
if (Object.keys(row).some((key) => key !== "id" && key !== "version")) {
|
|
736
743
|
throw new Error("software requirement contains an unknown field");
|
|
737
744
|
}
|
|
738
|
-
if (!["bun", "nginx", "arangodb", "cloudflared", "ufw"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
745
|
+
if (!["bun", "nginx", "arangodb", "cloudflared", "ufw", "openssh-client"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
739
746
|
throw new Error("software requirement coordinate is invalid");
|
|
740
747
|
}
|
|
741
748
|
const requirement = { id: row.id, version: row.version };
|
|
@@ -884,7 +891,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
|
|
|
884
891
|
}
|
|
885
892
|
|
|
886
893
|
// src/version.ts
|
|
887
|
-
var VERSION3 = "0.1.
|
|
894
|
+
var VERSION3 = "0.1.36";
|
|
888
895
|
|
|
889
896
|
// src/egress-policy.ts
|
|
890
897
|
import { realpathSync } from "node:fs";
|
|
@@ -1419,7 +1426,12 @@ function agentUnit(options) {
|
|
|
1419
1426
|
if (Boolean(options.pullMigrations) !== Boolean(options.lifecycleProfilePath)) {
|
|
1420
1427
|
throw new Error("migration pull and lifecycle profile must be supplied together");
|
|
1421
1428
|
}
|
|
1429
|
+
const bootstrapEnabled = Boolean(options.pullBootstrap && options.bootstrapSshCredentialPath && options.bootstrapTargetTelemetryEndpoint);
|
|
1430
|
+
if ([options.pullBootstrap, options.bootstrapSshCredentialPath, options.bootstrapTargetTelemetryEndpoint].some(Boolean) && !bootstrapEnabled) {
|
|
1431
|
+
throw new Error("bootstrap pull, SSH credential and target telemetry endpoint must be supplied together");
|
|
1432
|
+
}
|
|
1422
1433
|
const lifecycleHelperSocketPath = lifecycleEnabled ? systemdPath(options.lifecycleHelperSocketPath ?? LIFECYCLE_HELPER_SOCKET, "lifecycle helper socket") : undefined;
|
|
1434
|
+
const bootstrapSshCredentialPath = bootstrapEnabled ? systemdPath(options.bootstrapSshCredentialPath, "bootstrap SSH credential") : undefined;
|
|
1423
1435
|
const warpValues = [
|
|
1424
1436
|
options.warpOrganization,
|
|
1425
1437
|
options.warpClientIdCredentialPath,
|
|
@@ -1485,6 +1497,9 @@ function agentUnit(options) {
|
|
|
1485
1497
|
options.publicApiUrl ? `FZ_PUBLIC_API_URL=${options.publicApiUrl}` : null,
|
|
1486
1498
|
options.pullDeployments ? "FZ_DEPLOY_PULL=true" : null,
|
|
1487
1499
|
options.pullMigrations ? "FZ_MIGRATION_PULL=true" : null,
|
|
1500
|
+
options.pullBootstrap ? "FZ_BOOTSTRAP_PULL=true" : null,
|
|
1501
|
+
options.pullBootstrap ? "FZ_BOOTSTRAP_SSH_KEY_CREDENTIAL=bootstrap-ssh-key" : null,
|
|
1502
|
+
options.pullBootstrap ? `FZ_BOOTSTRAP_TARGET_OTLP_ENDPOINT=${options.bootstrapTargetTelemetryEndpoint}` : null,
|
|
1488
1503
|
`FZ_AGENT_UPDATE_SOCKET=${DEFAULT_AGENT_UPDATE_SOCKET}`,
|
|
1489
1504
|
options.pullMigrations ? `FZ_LIFECYCLE_HELPER_SOCKET=${lifecycleHelperSocketPath}` : null
|
|
1490
1505
|
].filter((line) => line !== null);
|
|
@@ -1492,6 +1507,8 @@ function agentUnit(options) {
|
|
|
1492
1507
|
environment.push(`HOME=${deployRoot}/agent-home`, `XDG_CACHE_HOME=${deployRoot}/cache`);
|
|
1493
1508
|
}
|
|
1494
1509
|
const gitCredential = options.gitCredentialPath ? `LoadCredentialEncrypted=git-deploy-key:${options.gitCredentialPath}
|
|
1510
|
+
` : "";
|
|
1511
|
+
const bootstrapCredential = bootstrapEnabled ? `LoadCredentialEncrypted=bootstrap-ssh-key:${bootstrapSshCredentialPath}
|
|
1495
1512
|
` : "";
|
|
1496
1513
|
const projectCredentials = Object.entries(deploymentCredentials).map(([name, path]) => `LoadCredentialEncrypted=${name}:${path}`).join(`
|
|
1497
1514
|
`);
|
|
@@ -1546,7 +1563,7 @@ User=${user}
|
|
|
1546
1563
|
Group=${VAULT_GROUP}
|
|
1547
1564
|
${deploymentGroup}
|
|
1548
1565
|
LoadCredentialEncrypted=agent-seed:${seedCredentialPath}
|
|
1549
|
-
${gitCredential}${projectCredentials}${projectCredentials ? `
|
|
1566
|
+
${gitCredential}${bootstrapCredential}${projectCredentials}${projectCredentials ? `
|
|
1550
1567
|
` : ""}${snpPrepare}ExecStart=${bin}
|
|
1551
1568
|
Restart=always
|
|
1552
1569
|
RestartSec=2
|
|
@@ -1601,6 +1618,10 @@ function planProvision(options) {
|
|
|
1601
1618
|
if (Boolean(options.pullMigrations) !== Boolean(options.lifecycleProfilePath)) {
|
|
1602
1619
|
throw new Error("migration pull and lifecycle profile must be supplied together");
|
|
1603
1620
|
}
|
|
1621
|
+
const bootstrapEnabled = Boolean(options.pullBootstrap && options.bootstrapSshCredentialPath && options.bootstrapTargetTelemetryEndpoint);
|
|
1622
|
+
if ([options.pullBootstrap, options.bootstrapSshCredentialPath, options.bootstrapTargetTelemetryEndpoint].some(Boolean) && !bootstrapEnabled) {
|
|
1623
|
+
throw new Error("bootstrap pull, SSH credential and target telemetry endpoint must be supplied together");
|
|
1624
|
+
}
|
|
1604
1625
|
const warpValues = [
|
|
1605
1626
|
options.warpOrganization,
|
|
1606
1627
|
options.warpClientIdCredentialPath,
|
|
@@ -1626,13 +1647,20 @@ function planProvision(options) {
|
|
|
1626
1647
|
const gitPublicKeyDir = gitPublicKeyPath?.replace(/\/[^/]+$/, "");
|
|
1627
1648
|
const lifecycleProfilePath = lifecycleEnabled ? systemdPath(options.lifecycleProfilePath, "lifecycle profile") : undefined;
|
|
1628
1649
|
const lifecycleHelperSocketPath = lifecycleEnabled ? systemdPath(options.lifecycleHelperSocketPath ?? LIFECYCLE_HELPER_SOCKET, "lifecycle helper socket") : undefined;
|
|
1650
|
+
const bootstrapSshCredentialPath = bootstrapEnabled ? systemdPath(options.bootstrapSshCredentialPath, "bootstrap SSH credential") : undefined;
|
|
1629
1651
|
const warpClientIdCredentialPath = warpEnabled ? systemdPath(options.warpClientIdCredentialPath, "WARP client-id credential") : undefined;
|
|
1630
1652
|
const warpClientSecretCredentialPath = warpEnabled ? systemdPath(options.warpClientSecretCredentialPath, "WARP client-secret credential") : undefined;
|
|
1631
1653
|
return {
|
|
1632
1654
|
mode,
|
|
1633
1655
|
reason: reasonFor(mode),
|
|
1634
1656
|
unitPath: UNIT_PATH,
|
|
1635
|
-
unit: agentUnit({
|
|
1657
|
+
unit: agentUnit({
|
|
1658
|
+
...options,
|
|
1659
|
+
mode,
|
|
1660
|
+
lifecycleProfilePath,
|
|
1661
|
+
lifecycleHelperSocketPath,
|
|
1662
|
+
bootstrapSshCredentialPath
|
|
1663
|
+
}),
|
|
1636
1664
|
auxiliaryUnits: [
|
|
1637
1665
|
{ path: AGENT_SOCKET_UNIT_PATH, unit: agentSocketUnit(options) },
|
|
1638
1666
|
{ path: AGENT_SOCKET_PROXY_UNIT_PATH, unit: agentSocketProxyUnit(options) },
|
package/dist/software-helper.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/software.ts
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
+
var PINNED_BUN_VERSION = "1.3.14";
|
|
3
4
|
var BUN_INSTALLER_SHA256 = "bab8acfb046aac8c72407bdcce903957665d655d7acaa3e11c7c4616beae68dd";
|
|
4
5
|
var ARANGO_SHA256 = "b5a9197b4343f2ed554e1ebc1ef8e6529c7c39cde0035cdc311a4747a3355066";
|
|
5
6
|
var CLOUDFLARED_SHA256 = "9d71c677db00134c1bd4144b7783486b654ad281b1ea62b4972098d19f770f17";
|
|
@@ -11,7 +12,8 @@ var SOFTWARE_CATALOG = [
|
|
|
11
12
|
{ id: "nginx", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
12
13
|
{ id: "arangodb", version: "3.11.14", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
13
14
|
{ id: "cloudflared", version: "2026.7.3", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
14
|
-
{ id: "ufw", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
|
|
15
|
+
{ id: "ufw", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
16
|
+
{ id: "openssh-client", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
|
|
15
17
|
];
|
|
16
18
|
var UBUNTU_2604_X64 = [
|
|
17
19
|
{
|
|
@@ -38,6 +40,11 @@ var UBUNTU_2604_X64 = [
|
|
|
38
40
|
requirement: { id: "ufw", version: "ubuntu-26.04" },
|
|
39
41
|
check: "command -v ufw >/dev/null",
|
|
40
42
|
install: "DEBIAN_FRONTEND=noninteractive apt-get update -qq && apt-get install -y ufw"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
requirement: { id: "openssh-client", version: "ubuntu-26.04" },
|
|
46
|
+
check: "command -v ssh >/dev/null && command -v scp >/dev/null && command -v ssh-keyscan >/dev/null && command -v ssh-keygen >/dev/null",
|
|
47
|
+
install: "DEBIAN_FRONTEND=noninteractive apt-get update -qq && apt-get install -y openssh-client"
|
|
41
48
|
}
|
|
42
49
|
];
|
|
43
50
|
function observeSoftwareHost(osRelease = readFileSync("/etc/os-release", "utf8"), architecture = process.arch) {
|
|
@@ -62,7 +69,7 @@ function validateSoftwareRequirements(value, _options = {}) {
|
|
|
62
69
|
if (Object.keys(row).some((key) => key !== "id" && key !== "version")) {
|
|
63
70
|
throw new Error("software requirement contains an unknown field");
|
|
64
71
|
}
|
|
65
|
-
if (!["bun", "nginx", "arangodb", "cloudflared", "ufw"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
72
|
+
if (!["bun", "nginx", "arangodb", "cloudflared", "ufw", "openssh-client"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
66
73
|
throw new Error("software requirement coordinate is invalid");
|
|
67
74
|
}
|
|
68
75
|
const requirement = { id: row.id, version: row.version };
|
package/dist/software.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type CatalogStatus = 'testing' | 'active' | 'retired';
|
|
2
2
|
export type DeploymentChannel = 'development' | 'production';
|
|
3
|
-
export type SoftwareId = 'bun' | 'nginx' | 'arangodb' | 'cloudflared' | 'ufw';
|
|
3
|
+
export type SoftwareId = 'bun' | 'nginx' | 'arangodb' | 'cloudflared' | 'ufw' | 'openssh-client';
|
|
4
4
|
/** Repository input is a catalogue coordinate, never a root command. */
|
|
5
5
|
export interface SoftwareRequirement {
|
|
6
6
|
id: SoftwareId;
|
|
@@ -32,6 +32,8 @@ export interface SoftwareCommandResult {
|
|
|
32
32
|
output: string;
|
|
33
33
|
}
|
|
34
34
|
export type SoftwareExec = (command: string) => Promise<SoftwareCommandResult>;
|
|
35
|
+
export declare const PINNED_BUN_VERSION = "1.3.14";
|
|
36
|
+
export declare const BUN_INSTALLER_SHA256 = "bab8acfb046aac8c72407bdcce903957665d655d7acaa3e11c7c4616beae68dd";
|
|
35
37
|
/** Public, command-free catalog. Root strategies remain private below. */
|
|
36
38
|
export declare const OS_CATALOG: readonly OsCatalogEntry[];
|
|
37
39
|
export declare const SOFTWARE_CATALOG: readonly SoftwareCatalogEntry[];
|
package/dist/software.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/software.ts
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
+
var PINNED_BUN_VERSION = "1.3.14";
|
|
3
4
|
var BUN_INSTALLER_SHA256 = "bab8acfb046aac8c72407bdcce903957665d655d7acaa3e11c7c4616beae68dd";
|
|
4
5
|
var ARANGO_SHA256 = "b5a9197b4343f2ed554e1ebc1ef8e6529c7c39cde0035cdc311a4747a3355066";
|
|
5
6
|
var CLOUDFLARED_SHA256 = "9d71c677db00134c1bd4144b7783486b654ad281b1ea62b4972098d19f770f17";
|
|
@@ -11,7 +12,8 @@ var SOFTWARE_CATALOG = [
|
|
|
11
12
|
{ id: "nginx", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
12
13
|
{ id: "arangodb", version: "3.11.14", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
13
14
|
{ id: "cloudflared", version: "2026.7.3", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
14
|
-
{ id: "ufw", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
|
|
15
|
+
{ id: "ufw", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
|
|
16
|
+
{ id: "openssh-client", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
|
|
15
17
|
];
|
|
16
18
|
var UBUNTU_2604_X64 = [
|
|
17
19
|
{
|
|
@@ -38,6 +40,11 @@ var UBUNTU_2604_X64 = [
|
|
|
38
40
|
requirement: { id: "ufw", version: "ubuntu-26.04" },
|
|
39
41
|
check: "command -v ufw >/dev/null",
|
|
40
42
|
install: "DEBIAN_FRONTEND=noninteractive apt-get update -qq && apt-get install -y ufw"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
requirement: { id: "openssh-client", version: "ubuntu-26.04" },
|
|
46
|
+
check: "command -v ssh >/dev/null && command -v scp >/dev/null && command -v ssh-keyscan >/dev/null && command -v ssh-keygen >/dev/null",
|
|
47
|
+
install: "DEBIAN_FRONTEND=noninteractive apt-get update -qq && apt-get install -y openssh-client"
|
|
41
48
|
}
|
|
42
49
|
];
|
|
43
50
|
function observeSoftwareHost(osRelease = readFileSync("/etc/os-release", "utf8"), architecture = process.arch) {
|
|
@@ -62,7 +69,7 @@ function validateSoftwareRequirements(value, _options = {}) {
|
|
|
62
69
|
if (Object.keys(row).some((key) => key !== "id" && key !== "version")) {
|
|
63
70
|
throw new Error("software requirement contains an unknown field");
|
|
64
71
|
}
|
|
65
|
-
if (!["bun", "nginx", "arangodb", "cloudflared", "ufw"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
72
|
+
if (!["bun", "nginx", "arangodb", "cloudflared", "ufw", "openssh-client"].includes(String(row.id)) || typeof row.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$/.test(row.version)) {
|
|
66
73
|
throw new Error("software requirement coordinate is invalid");
|
|
67
74
|
}
|
|
68
75
|
const requirement = { id: row.id, version: row.version };
|
|
@@ -108,5 +115,7 @@ export {
|
|
|
108
115
|
observeSoftwareHost,
|
|
109
116
|
ensureSoftwareRequirements,
|
|
110
117
|
SOFTWARE_CATALOG,
|
|
111
|
-
|
|
118
|
+
PINNED_BUN_VERSION,
|
|
119
|
+
OS_CATALOG,
|
|
120
|
+
BUN_INSTALLER_SHA256
|
|
112
121
|
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { NodeKeyPair } from '@forgezero/runtime/identity';
|
|
2
|
+
import type { AgentOperationTelemetry } from './telemetry-runtime';
|
|
3
|
+
import { type GitHostResolver } from './git-egress';
|
|
4
|
+
export interface RemoteSshBootstrapClaim {
|
|
5
|
+
computeKey: string;
|
|
6
|
+
computeReference: string;
|
|
7
|
+
claimToken: string;
|
|
8
|
+
claimExpiresAtTs: number;
|
|
9
|
+
attempt: number;
|
|
10
|
+
realm: string;
|
|
11
|
+
projectKey: string;
|
|
12
|
+
environmentKey: string;
|
|
13
|
+
target: {
|
|
14
|
+
host: string;
|
|
15
|
+
port: number;
|
|
16
|
+
user: string;
|
|
17
|
+
hostKeySha256: string;
|
|
18
|
+
nodeHostname: string;
|
|
19
|
+
};
|
|
20
|
+
enrolmentToken: string;
|
|
21
|
+
}
|
|
22
|
+
export interface BootstrapCommandResult {
|
|
23
|
+
exitCode: number;
|
|
24
|
+
output: string;
|
|
25
|
+
}
|
|
26
|
+
export type BootstrapCommand = (argv: readonly string[], options?: {
|
|
27
|
+
stdin?: string;
|
|
28
|
+
secret?: boolean;
|
|
29
|
+
}) => Promise<BootstrapCommandResult>;
|
|
30
|
+
export interface SshBootstrapPullOptions {
|
|
31
|
+
apiUrl: string;
|
|
32
|
+
platformApiUrl: string;
|
|
33
|
+
nodeKey: string;
|
|
34
|
+
keys: NodeKeyPair;
|
|
35
|
+
sshKeyPath: string;
|
|
36
|
+
targetTelemetryEndpoint: string;
|
|
37
|
+
fzCliPath?: string;
|
|
38
|
+
fzAgentPath?: string;
|
|
39
|
+
exec?: BootstrapCommand;
|
|
40
|
+
fetch?: (input: URL, init: RequestInit) => Promise<Response>;
|
|
41
|
+
intervalMs?: number;
|
|
42
|
+
requestTimeoutMs?: number;
|
|
43
|
+
now?: () => number;
|
|
44
|
+
setTimer?: (callback: () => void, ms: number) => unknown;
|
|
45
|
+
clearTimer?: (handle: unknown) => void;
|
|
46
|
+
onEvent?: (event: string, detail?: unknown) => void;
|
|
47
|
+
telemetry?: AgentOperationTelemetry;
|
|
48
|
+
resolveHost?: GitHostResolver;
|
|
49
|
+
}
|
|
50
|
+
export type SshBootstrapResult = {
|
|
51
|
+
status: 'idle';
|
|
52
|
+
} | {
|
|
53
|
+
status: 'completed';
|
|
54
|
+
computeKey: string;
|
|
55
|
+
attempt: number;
|
|
56
|
+
} | {
|
|
57
|
+
status: 'failed';
|
|
58
|
+
computeKey: string;
|
|
59
|
+
attempt: number;
|
|
60
|
+
failureCode: string;
|
|
61
|
+
};
|
|
62
|
+
export declare class SshBootstrapError extends Error {
|
|
63
|
+
readonly code: string;
|
|
64
|
+
constructor(code: string, message?: string);
|
|
65
|
+
}
|
|
66
|
+
/** Execute one job without ever putting the enrolment token or SSH key in argv. */
|
|
67
|
+
export declare function executeSshBootstrap(claim: RemoteSshBootstrapClaim, options: Pick<SshBootstrapPullOptions, 'platformApiUrl' | 'sshKeyPath' | 'targetTelemetryEndpoint' | 'fzCliPath' | 'fzAgentPath' | 'exec' | 'resolveHost'>): Promise<void>;
|
|
68
|
+
export declare function pullSshBootstrapOnce(options: SshBootstrapPullOptions): Promise<SshBootstrapResult>;
|
|
69
|
+
export declare function startSshBootstrapPull(options: SshBootstrapPullOptions): {
|
|
70
|
+
stop(): Promise<void>;
|
|
71
|
+
readonly active: boolean;
|
|
72
|
+
};
|
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.
|
|
2
|
+
export declare const VERSION = "0.1.36";
|
package/package.json
CHANGED
package/schema/deploy-v2.json
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"additionalProperties": false,
|
|
29
29
|
"required": ["id", "version"],
|
|
30
30
|
"properties": {
|
|
31
|
-
"id": { "enum": ["bun", "nginx", "arangodb", "cloudflared", "ufw"] },
|
|
31
|
+
"id": { "enum": ["bun", "nginx", "arangodb", "cloudflared", "ufw", "openssh-client"] },
|
|
32
32
|
"version": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9.-]{0,31}$" }
|
|
33
33
|
}
|
|
34
34
|
}
|