2836dcd016
Lands the building blocks the SSH specs will compose on top of. Every piece talks to a real sshd container — no mocks at any layer. - fixtures/ssh-image.ts: builds kandev-sshd:e2e once per machine (Alpine + openssh-server + openssh-sftp-server + git + bash + sudo + iproute2 + iptables, pre-bakes mock-agent at /usr/local/bin/mock-agent, generates a fresh host key on entrypoint, reads the worker public key out of a bind-mounted /authorized_keys). The agentctl binary is deliberately NOT pre-baked so tests exercise the SFTP upload + sha256 cache path the production code uses. - helpers/ssh.ts: per-worker sshd lifecycle (startSSHServer / stopSSHServer), keypair generation, host-key fingerprint scanning, fault injection (regenerateHostKey for host-key-rotation specs, dropTrafficToPort22 / restoreTraffic for connection-drop tests, killRemotePid for "agentctl died" recovery), and remote inspection helpers (readRemoteFile / remotePathExists / listRemoteDir / countSshdConnections). - helpers/ssh-bastion.ts: two-container ProxyJump setup. Bastion is on a private Docker network and has a published port; target is on the same network with NO host port — any successful connection MUST have traversed the bastion, which makes the proxy-jump assertion honest. - fixtures/ssh-test-base.ts: worker-scoped fixture mirroring docker-test-base. Skips when Docker isn't reachable. Spins up the sshd container, generates keys, scans the fingerprint, then seeds a workspace + workflow + bare repo + mock-agent profile + an SSH executor with the fingerprint already trusted. Specs that need to exercise the test-then-trust UI gate create their own executor on top of the same target. - pages/SSHSettingsPage.ts: Page Object covering the connection form, test/save buttons, trust checkbox, observed/pinned fingerprint, per step badges, and the sessions table. - helpers/api-client.ts: new createSSHExecutor / updateExecutor / getExecutor / testSSHConnection / listSSHSessions methods plus matching DTO types.