[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,692 @@
import test from "node:test";
import assert from "node:assert/strict";
import {
buildSftpHostCredentials,
} from "./useSftpHostCredentials.ts";
import type { Host, Identity, KnownHost, SSHKey } from "../../../domain/models.ts";
const host = (overrides: Partial<Host> = {}): Host => ({
id: "host-1",
label: "Host",
hostname: "example.com",
username: "root",
tags: [],
os: "linux",
...overrides,
});
test("buildSftpHostCredentials forwards system agent settings for target and jump hosts", () => {
const jump = host({
id: "jump-1",
hostname: "jump.example.com",
useSshAgent: true,
identityFilePaths: ["~/.ssh/jump"],
identitiesOnly: true,
});
const credentials = buildSftpHostCredentials({
host: host({
hostChain: { hostIds: ["jump-1"] },
useSshAgent: true,
identityAgent: "$SSH_AUTH_SOCK",
identityFilePaths: ["~/.ssh/aws_root"],
identitiesOnly: true,
addKeysToAgent: "yes",
useKeychain: true,
}),
hosts: [jump],
keys: [],
identities: [],
});
assert.deepEqual(
{
useSshAgent: credentials.useSshAgent,
identityAgent: credentials.identityAgent,
identityFilePaths: credentials.identityFilePaths,
identitiesOnly: credentials.identitiesOnly,
addKeysToAgent: credentials.addKeysToAgent,
useKeychain: credentials.useKeychain,
},
{
useSshAgent: true,
identityAgent: "$SSH_AUTH_SOCK",
identityFilePaths: ["~/.ssh/aws_root"],
identitiesOnly: true,
addKeysToAgent: "yes",
useKeychain: true,
},
);
assert.equal(credentials.jumpHosts?.[0]?.useSshAgent, true);
assert.deepEqual(credentials.jumpHosts?.[0]?.identityFilePaths, ["~/.ssh/jump"]);
assert.equal(credentials.jumpHosts?.[0]?.identitiesOnly, true);
});
test("buildSftpHostCredentials forwards target and jump-host timeouts", () => {
const jumpHost = host({
id: "jump-1",
sshTcpConnectTimeoutSeconds: 75,
sshAuthReadyTimeoutSeconds: 360,
});
const credentials = buildSftpHostCredentials({
host: host({
hostChain: { hostIds: ["jump-1"] },
sshTcpConnectTimeoutSeconds: 45,
sshAuthReadyTimeoutSeconds: 300,
}),
hosts: [jumpHost],
keys: [],
identities: [],
});
assert.equal(credentials.sshTcpConnectTimeoutMs, 45_000);
assert.equal(credentials.sshAuthReadyTimeoutMs, 300_000);
assert.equal(credentials.jumpHosts?.[0]?.sshTcpConnectTimeoutMs, 75_000);
assert.equal(credentials.jumpHosts?.[0]?.sshAuthReadyTimeoutMs, 360_000);
});
test("buildSftpHostCredentials keeps automatic auth per target and jump host", () => {
const jumpHost = host({ id: "jump-1", authMethod: "auto", password: "jump-secret", requiresMfa: true });
const credentials = buildSftpHostCredentials({
host: host({
authMethod: "auto",
password: "target-secret",
requiresMfa: true,
hostChain: { hostIds: ["jump-1"] },
}),
hosts: [jumpHost],
keys: [],
identities: [],
});
assert.equal(credentials.authMethod, "auto");
assert.equal(credentials.requiresMfa, true);
assert.equal(credentials.jumpHosts?.[0]?.authMethod, "auto");
assert.equal(credentials.jumpHosts?.[0]?.requiresMfa, true);
});
test("buildSftpHostCredentials drops stale identity paths for password-only hosts", () => {
const jumpHost = host({
id: "jump-1",
authMethod: "password",
password: "jump-secret",
useSshAgent: true,
identityFilePaths: ["~/.ssh/stale-jump"],
});
const credentials = buildSftpHostCredentials({
host: host({
authMethod: "password",
password: "target-secret",
useSshAgent: true,
identityFilePaths: ["~/.ssh/stale-target"],
hostChain: { hostIds: ["jump-1"] },
}),
hosts: [jumpHost],
keys: [],
identities: [],
});
assert.equal(credentials.identityFilePaths, undefined);
assert.equal(credentials.useSshAgent, false);
assert.equal(credentials.jumpHosts?.[0]?.identityFilePaths, undefined);
assert.equal(credentials.jumpHosts?.[0]?.useSshAgent, false);
});
test("buildSftpHostCredentials rejects missing jump hosts", () => {
assert.throws(
() => buildSftpHostCredentials({
host: host({ hostChain: { hostIds: ["missing-jump"] } }),
hosts: [],
keys: [],
identities: [],
}),
/Jump host "missing-jump" is missing/,
);
});
test("buildSftpHostCredentials rejects missing saved proxy profiles", () => {
assert.throws(
() => buildSftpHostCredentials({
host: host({ proxyProfileId: "missing-proxy" }),
hosts: [],
keys: [],
identities: [],
}),
/Saved proxy for host "Host" is missing/,
);
});
test("buildSftpHostCredentials rejects missing saved proxy profiles on jump hosts", () => {
const jumpHost = host({ id: "jump-1", label: "Jump", proxyProfileId: "missing-proxy" });
assert.throws(
() => buildSftpHostCredentials({
host: host({ hostChain: { hostIds: ["jump-1"] } }),
hosts: [jumpHost],
keys: [],
identities: [],
}),
/Saved proxy for jump host "Jump" is missing/,
);
});
test("buildSftpHostCredentials rejects missing proxy identities", () => {
assert.throws(
() => buildSftpHostCredentials({
host: host({
proxyConfig: {
type: "http",
host: "proxy.example.com",
port: 3128,
identityId: "missing-identity",
},
}),
hosts: [],
keys: [],
identities: [],
}),
/Proxy identity for "Host" is missing/,
);
});
test("buildSftpHostCredentials rejects incomplete proxy identities", () => {
assert.throws(
() => buildSftpHostCredentials({
host: host({
proxyConfig: {
type: "http",
host: "proxy.example.com",
port: 3128,
identityId: "identity-1",
},
}),
hosts: [],
keys: [],
identities: [{
id: "identity-1",
label: "Proxy login",
username: "proxy-user",
authMethod: "password",
created: 1,
}],
}),
/Proxy identity for "Host" is incomplete/,
);
});
test("buildSftpHostCredentials rejects proxy identities with blank usernames even when passwords are encrypted", () => {
assert.throws(
() => buildSftpHostCredentials({
host: host({
proxyConfig: {
type: "http",
host: "proxy.example.com",
port: 3128,
identityId: "identity-1",
},
}),
hosts: [],
keys: [],
identities: [{
id: "identity-1",
label: "Proxy login",
username: " ",
authMethod: "password",
password: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
created: 1,
}],
}),
/Proxy identity for "Host" is incomplete/,
);
});
test("buildSftpHostCredentials rejects missing proxy identities on jump hosts", () => {
const jumpHost = host({
id: "jump-1",
label: "Jump",
proxyConfig: {
type: "http",
host: "proxy.example.com",
port: 3128,
identityId: "missing-identity",
},
});
assert.throws(
() => buildSftpHostCredentials({
host: host({ hostChain: { hostIds: ["jump-1"] } }),
hosts: [jumpHost],
keys: [],
identities: [],
}),
/Proxy identity for "Jump" is missing/,
);
});
test("buildSftpHostCredentials rejects incomplete proxy identities on jump hosts", () => {
const jumpHost = host({
id: "jump-1",
label: "Jump",
proxyConfig: {
type: "http",
host: "proxy.example.com",
port: 3128,
identityId: "identity-1",
},
});
assert.throws(
() => buildSftpHostCredentials({
host: host({ hostChain: { hostIds: ["jump-1"] } }),
hosts: [jumpHost],
keys: [],
identities: [{
id: "identity-1",
label: "Proxy login",
username: "",
authMethod: "password",
password: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
created: 1,
}],
}),
/Proxy identity for "Jump" is incomplete/,
);
});
test("buildSftpHostCredentials forwards custom ProxyCommand settings", () => {
const credentials = buildSftpHostCredentials({
host: host({
proxyConfig: {
type: "command",
host: "",
port: 0,
command: "cloudflared access ssh --hostname %h",
},
}),
hosts: [],
keys: [],
identities: [],
});
assert.deepEqual(credentials.proxy, {
type: "command",
host: "",
port: 0,
command: "cloudflared access ssh --hostname %h",
username: undefined,
password: undefined,
});
});
test("buildSftpHostCredentials resolves proxy credentials from a selected identity", () => {
const identity: Identity = {
id: "identity-1",
label: "Proxy login",
username: "proxy-user",
authMethod: "password",
password: "proxy-secret",
created: 1,
};
const credentials = buildSftpHostCredentials({
host: host({
proxyConfig: {
type: "socks5",
host: "proxy.example.com",
port: 1080,
identityId: identity.id,
},
}),
hosts: [],
keys: [],
identities: [identity],
});
assert.deepEqual(credentials.proxy, {
type: "socks5",
host: "proxy.example.com",
port: 1080,
username: "proxy-user",
password: "proxy-secret",
});
});
test("buildSftpHostCredentials rejects undecryptable proxy identity passwords", () => {
assert.throws(
() => buildSftpHostCredentials({
host: host({
proxyConfig: {
type: "http",
host: "proxy.example.com",
port: 3128,
identityId: "identity-1",
},
}),
hosts: [],
keys: [],
identities: [{
id: "identity-1",
label: "Proxy login",
username: "proxy-user",
authMethod: "password",
password: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
created: 1,
}],
}),
/Proxy credentials cannot be decrypted/,
);
});
test("buildSftpHostCredentials resolves jump host proxy credentials from a selected identity", () => {
const identity: Identity = {
id: "identity-1",
label: "Proxy login",
username: "proxy-user",
authMethod: "password",
password: "proxy-secret",
created: 1,
};
const jumpHost = host({
id: "jump-1",
label: "Jump",
proxyConfig: {
type: "socks5",
host: "jump-proxy.example.com",
port: 1080,
identityId: identity.id,
},
});
const credentials = buildSftpHostCredentials({
host: host({ hostChain: { hostIds: ["jump-1"] } }),
hosts: [jumpHost],
keys: [],
identities: [identity],
});
assert.deepEqual(credentials.jumpHosts?.[0]?.proxy, {
type: "socks5",
host: "jump-proxy.example.com",
port: 1080,
username: "proxy-user",
password: "proxy-secret",
});
});
test("buildSftpHostCredentials rejects undecryptable jump host proxy identity passwords", () => {
const jumpHost = host({
id: "jump-1",
label: "Jump",
proxyConfig: {
type: "http",
host: "proxy.example.com",
port: 3128,
identityId: "identity-1",
},
});
assert.throws(
() => buildSftpHostCredentials({
host: host({ hostChain: { hostIds: ["jump-1"] } }),
hosts: [jumpHost],
keys: [],
identities: [{
id: "identity-1",
label: "Proxy login",
username: "proxy-user",
authMethod: "password",
password: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
created: 1,
}],
}),
/Proxy credentials for jump host "Jump" cannot be decrypted/,
);
});
test("buildSftpHostCredentials passes reference keys as identity file paths", () => {
const key: SSHKey = {
id: "key-1",
label: "Reference key",
type: "ED25519",
privateKey: "",
source: "reference",
category: "key",
created: 1,
filePath: "/Users/alice/.ssh/id_ed25519",
passphrase: "saved-passphrase",
};
const credentials = buildSftpHostCredentials({
host: host({ authMethod: "key", identityFileId: "key-1" }),
hosts: [],
keys: [key],
identities: [],
});
assert.equal(credentials.privateKey, undefined);
assert.deepEqual(credentials.identityFilePaths, ["/Users/alice/.ssh/id_ed25519"]);
assert.equal(credentials.passphrase, "saved-passphrase");
});
test("buildSftpHostCredentials forwards known hosts for SFTP host-key checks", () => {
const knownHosts: KnownHost[] = [{
id: "kh-1",
hostname: "example.com",
port: 22,
keyType: "ssh-ed25519",
publicKey: "SHA256:abc",
fingerprint: "abc",
discoveredAt: 1,
}];
const credentials = buildSftpHostCredentials({
host: host(),
hosts: [],
keys: [],
identities: [],
knownHosts,
});
assert.equal(credentials.knownHosts, knownHosts);
});
test("buildSftpHostCredentials forwards the host-key verification setting", () => {
const credentials = buildSftpHostCredentials({
host: host(),
hosts: [],
keys: [],
identities: [],
terminalSettings: {
verifyHostKeys: false,
keepaliveInterval: 30,
keepaliveCountMax: 10,
},
});
assert.equal(credentials.verifyHostKeys, false);
});
test("buildSftpHostCredentials passes jump host reference keys as identity file paths", () => {
const key: SSHKey = {
id: "jump-key",
label: "Jump key",
type: "ED25519",
privateKey: "",
source: "reference",
category: "key",
created: 1,
filePath: "/Users/alice/.ssh/jump_ed25519",
};
const jumpHost = host({
id: "jump-1",
label: "Jump",
authMethod: "key",
identityFileId: "jump-key",
});
const credentials = buildSftpHostCredentials({
host: host({ hostChain: { hostIds: ["jump-1"] } }),
hosts: [jumpHost],
keys: [key],
identities: [],
});
assert.equal(credentials.jumpHosts?.[0]?.privateKey, undefined);
assert.deepEqual(credentials.jumpHosts?.[0]?.identityFilePaths, ["/Users/alice/.ssh/jump_ed25519"]);
});
test("buildSftpHostCredentials rejects undecryptable saved password credentials", () => {
assert.throws(
() => buildSftpHostCredentials({
host: host({
authMethod: "password",
password: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
}),
hosts: [],
keys: [],
identities: [],
}),
/Saved credentials cannot be decrypted/,
);
});
test("buildSftpHostCredentials keeps automatic target discovery available with an unreadable saved password", () => {
const credentials = buildSftpHostCredentials({
host: host({
authMethod: "auto",
password: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
}),
hosts: [],
keys: [],
identities: [],
});
assert.equal(credentials.authMethod, "auto");
assert.equal(credentials.password, undefined);
});
test("buildSftpHostCredentials keeps automatic jump discovery available with an unreadable saved password", () => {
const jumpHost = host({
id: "jump-1",
label: "Jump",
authMethod: "auto",
password: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
});
const credentials = buildSftpHostCredentials({
host: host({ hostChain: { hostIds: ["jump-1"] } }),
hosts: [jumpHost],
keys: [],
identities: [],
});
assert.equal(credentials.jumpHosts?.[0]?.authMethod, "auto");
assert.equal(credentials.jumpHosts?.[0]?.password, undefined);
});
test("buildSftpHostCredentials omits local key file paths for password auth", () => {
const credentials = buildSftpHostCredentials({
host: host({
authMethod: "password",
password: "secret",
identityFilePaths: ["/Users/alice/.ssh/id_ed25519"],
}),
hosts: [],
keys: [],
identities: [],
});
assert.equal(credentials.password, "secret");
assert.equal(credentials.privateKey, undefined);
assert.equal(credentials.identityFilePaths, undefined);
});
test("buildSftpHostCredentials rejects undecryptable saved key material without fallback credentials", () => {
const key: SSHKey = {
id: "key-1",
label: "Imported key",
type: "ED25519",
privateKey: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
source: "imported",
category: "key",
created: 1,
};
assert.throws(
() => buildSftpHostCredentials({
host: host({ authMethod: "key", identityFileId: "key-1" }),
hosts: [],
keys: [key],
identities: [],
}),
/Saved credentials cannot be decrypted/,
);
});
test("buildSftpHostCredentials does not use stale local key paths when a selected key is unavailable", () => {
const key: SSHKey = {
id: "key-1",
label: "Imported key",
type: "ED25519",
privateKey: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
source: "imported",
category: "key",
created: 1,
};
assert.throws(
() => buildSftpHostCredentials({
host: host({
authMethod: "key",
identityFileId: "key-1",
identityFilePaths: ["/Users/alice/.ssh/stale_ed25519"],
}),
hosts: [],
keys: [key],
identities: [],
}),
/Saved credentials cannot be decrypted/,
);
});
test("buildSftpHostCredentials uses the system agent when a synced key cannot be decrypted", () => {
const key: SSHKey = {
id: "key-1",
label: "Synced key",
type: "ED25519",
publicKey: "ssh-ed25519 AAAASELECTED",
privateKey: "enc:v1:djEwdGVzdAAAAAAAAAAAAAAAAA==",
source: "imported",
category: "key",
created: 1,
};
const credentials = buildSftpHostCredentials({
host: host({
authMethod: "key",
identityFileId: "key-1",
useSshAgent: true,
}),
hosts: [],
keys: [key],
identities: [],
});
assert.equal(credentials.useSshAgent, true);
assert.deepEqual(credentials.agentPublicKeys, ["ssh-ed25519 AAAASELECTED"]);
assert.equal(credentials.privateKey, undefined);
});
test("imported IdentityFile paths remain usable when agent login is disabled", () => {
const credentials = buildSftpHostCredentials({
host: host({
identityFilePaths: ["~/.ssh/id_work"],
useSshAgent: false,
identityAgent: "none",
}),
hosts: [],
keys: [],
identities: [],
});
assert.equal(credentials.useSshAgent, false);
assert.deepEqual(credentials.identityFilePaths, ["~/.ssh/id_work"]);
});