/** * SSH Tunnel (OpenSSH ControlMaster multiplexer) * * A single TCP connection + SSH handshake per stage, reused by every * scanfix that needs remote state. Without this, N scanfixes × ~500ms * of handshake overhead dominates the run. * * Lifecycle: * - `openTunnel(stage, envConfig, keyPath)` starts `ssh -M -S -fN` * and returns a handle. Subsequent `tunnelExec(handle, cmd)` calls add * channels on the existing connection (no re-handshake). * - `closeTunnel(handle)` issues `ssh -O exit` and removes the socket. * - Tunnels auto-close on process exit via a best-effort `exit` handler. * * Windows: ControlMaster works on Windows 10+ with OpenSSH (built in). * Older Windows falls back to per-command SSH — callers must tolerate it. * * Note: this module is a pure primitive. Nothing in scan/fix/deploy calls * it yet. The DAG runner plus migrated scanfixes are the consumers. */ import type { EnvironmentConfig } from '../types/index.js'; export interface TunnelHandle { socket: string; host: string; user: string; keyPath: string | null; stage: string; } /** * Open a multiplexed SSH master to the stage's server. Idempotent: returns * the same handle if already open for this stage in this process. */ export declare function openTunnel(stage: string, envConfig: EnvironmentConfig, keyPath: string | null): TunnelHandle; /** * Look up the tunnel already opened for a stage (returns null if nothing * opened one yet). Scanfixes call this to acquire the shared handle rather * than opening their own connection; `runStageChain` opens the tunnel before * the fix DAG runs and closes it after. */ export declare function getTunnel(stage: string): TunnelHandle | null; /** * Run a command through an open tunnel. Reuses the multiplexed connection * — no new handshake. Returns trimmed stdout; throws on non-zero exit. */ export declare function tunnelExec(handle: TunnelHandle, command: string): string; /** * Close the multiplexed master. Safe to call multiple times. */ export declare function closeTunnel(handle: TunnelHandle): void; /** * Introspection: is the tunnel socket live? */ export declare function isTunnelAlive(handle: TunnelHandle): boolean; //# sourceMappingURL=ssh-tunnel.d.ts.map