mirror of
https://github.com/stablyai/orca.git
synced 2026-10-25 16:03:53 +00:00
test(ssh): pin Windows fixture host trust
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
+23
-3
@@ -9,9 +9,13 @@ keeps commands, hashes, runner identities, timings, and failure details.
|
||||
A checked box means the work has evidence in the detailed ledger. Design approval alone does not
|
||||
complete a box.
|
||||
|
||||
Active checkpoint: **Milestone 6 / Work Package 5 bounded runtime transfer — bounded verbose
|
||||
Win32-OpenSSH lifecycle capture locally green; exact-head native proof required, 2026-07-16, Codex
|
||||
implementation owner.**
|
||||
Active checkpoint: **Milestone 6 / Work Package 5 bounded runtime transfer — explicit fixture
|
||||
host-key trust correction in progress, 2026-07-16, Codex implementation owner.** Exact head
|
||||
`b24dda744892c2ee43a3fb345d889ba97adb4239`, run `29554073553`, and Windows x64/ARM64 jobs
|
||||
`87802525440`/`87802525442` prove the bounded verbose diagnostic and show both clients stop before
|
||||
authentication while looking for the runner account's missing default `known_hosts`. The next
|
||||
single-variable correction passes the fixture's exact pinned file with strict checking; production
|
||||
SSH arguments and every product/default path remain unchanged.
|
||||
`E-M6-WINDOWS-SYSTEM-SSH-TREE-LIVE-PORTABLE-FIXTURE-LOCAL-001` records the portable-fixture
|
||||
correction locally green: the no-Orca-publication workflow oracle permits the one exact pinned
|
||||
Microsoft fixture release URL while Orca release URLs, `gh release`, and `contents: write` remain
|
||||
@@ -225,6 +229,22 @@ output replay; the live suite uses 6 seconds, `-vvv`, outer 8/10-second safety c
|
||||
trace tail. Focused 119/119, all 285 release contracts, typecheck, full lint/reliability/max-lines,
|
||||
formatting, diff, and protected-resolver isolation pass with honest native skips. Commit/push only
|
||||
this artifact and require x64/ARM64 phase classification before selecting ConPTY or another client.
|
||||
Exact head `b24dda744892c2ee43a3fb345d889ba97adb4239`, run `29554073553`, and Windows x64/ARM64
|
||||
jobs `87802525440`/`87802525442` prove 101 files/863 cases with 19 skips plus the internal timeout,
|
||||
replay, and job-termination contracts. Both 6111.6731/6395.98-millisecond traces stop before
|
||||
authentication at `hostkeys_find_by_key_hostfile`: Win32-OpenSSH looks under the runner account
|
||||
instead of the isolated fixture client home. `E-M6-WINDOWS-VERBOSE-LIFECYCLE-CAPTURE-CI-RED-001`
|
||||
therefore replaces the prior session-close hypothesis with one narrower correction: pass only the
|
||||
fixture's exact pinned `known_hosts` with strict checking. Both profile teardowns still catch locked
|
||||
`UsrClass.dat`; all four non-Windows jobs and both Linux supplements pass.
|
||||
`E-M6-WINDOWS-DIAGNOSTIC-HOST-TRUST-CORRECTION-LOCAL-001` records that correction locally green:
|
||||
the purpose contract proves `-vvv`, `StrictHostKeyChecking=yes`, and the exact fixture
|
||||
`UserKnownHostsFile` occur before `--`, rejects `StrictHostKeyChecking=no`, and compares against an
|
||||
unchanged production argument vector. Focused 120/120, all 285 release contracts, typecheck, full
|
||||
lint/reliability/max-lines, formatting, diff, and protected-resolver isolation pass with honest
|
||||
native/live skips. Commit/push only this runner diagnostic and require fresh x64/ARM64 strict-trust,
|
||||
authentication, natural settlement, full-size transfer, and exact teardown proof. Production,
|
||||
Beta, fallback, tuple, publication, default, and signing paths remain untouched.
|
||||
`E-M6-WINDOWS-SYSTEM-SSH-TREE-LIVE-AUDIT-001` fixes the loopback-only official Microsoft
|
||||
server, fixture-owned non-admin account/ACL, exact host-key trust, Windows PowerShell 5.1,
|
||||
serial/default and four-channel metrics, cancellation/collision/cleanup, and deterministic teardown
|
||||
|
||||
+88
-20
@@ -8,8 +8,8 @@ work; keep exact commands, runner identities, hashes, metrics, and residual gaps
|
||||
|
||||
Date created: 2026-07-14<br>
|
||||
Last updated: 2026-07-16<br>
|
||||
Current phase: Milestone 6 / Work Package 5 bounded runtime transfer — **Locally green / bounded verbose client-lifecycle native proof required — 2026-07-16, Codex implementation owner**. `E-M6-WINDOWS-VERBOSE-LIFECYCLE-CAPTURE-LOCAL-001` records the runner-temp internal deadline, job settlement, bounded replay, and verbose trace-tail contracts locally green. Commit/push only this diagnostic and require both native architectures to identify the last completed client phase before selecting ConPTY or another client. Every production/default SSH path remains disconnected. Real Apple/SignPath rehearsals remain deferred.<br>
|
||||
Session checkpoint: **PRIVATE CONSOLE EOF PROVEN / PRIVATE OUTPUT PIPES FALSIFIED / BOUNDED REGULAR OUTPUT ACTIVE — 2026-07-16, Codex implementation owner** — exact head `5841b12bc94ecd1027e507e4b741e09fcb0a093d`, run `29552101635`, and x64/ARM64 jobs `87796673326`/`87796673353` both pass 101 files/860 cases with 19 skips, legacy compilation, real-console qualification/EOF, argv/binary/exit/handle-exclusion/cancellation, unchanged full-runtime reproducibility, and full-size cache gates. Live diagnostics still time out after 8025.1553/8034.6943 milliseconds with ended stdout, closed channel, no sentinel/process exit, and zero stderr; both exact teardowns catch locked `UsrClass.dat`. All four non-Windows primary jobs and both Linux supplements pass. No product caller, full-size Windows transfer claim, upload, default/fallback, Beta, tuple publication, or signing behavior changed.<br>
|
||||
Current phase: Milestone 6 / Work Package 5 bounded runtime transfer — **In progress — explicit fixture host-key trust correction, 2026-07-16, Codex implementation owner**. Exact head `b24dda744892c2ee43a3fb345d889ba97adb4239`, run `29554073553`, and x64/ARM64 jobs `87802525440`/`87802525442` prove the internal deadline, job settlement, bounded replay, and verbose trace capture. Both clients stop before authentication while resolving the runner account's missing default `known_hosts`; Win32-OpenSSH ignored the workflow's overridden profile variables. Pass only the fixture's exact pinned `known_hosts` path with strict checking, keep production arguments unchanged, and require fresh native proof before selecting ConPTY or another client. Every production/default SSH path remains disconnected. Real Apple/SignPath rehearsals remain deferred.<br>
|
||||
Session checkpoint: **VERBOSE TRACE CLASSIFIED / FIXTURE TRUST PATH ACTIVE — 2026-07-16, Codex implementation owner** — x64/ARM64 pass 101 files/863 cases with 19 skips, legacy compilation, launcher internal-timeout/replay/job-termination, unchanged runtime reproducibility, and full-size cache gates. Their 6111.6731/6395.98-millisecond traces both show `C:\\Users\\runneradmin\\.ssh\\known_hosts` lookup and stop at `hostkeys_find_by_key_hostfile` before authentication; lifecycle is `sentinel=false`, `stdoutEnded=true`, `processExit=1`, `channelClosed=true`, `closeCode=1`, and `stderrBytes=7923`. Both exact teardowns still catch locked `UsrClass.dat`. All four non-Windows primary jobs and both Linux supplements pass. No product caller, full-size Windows transfer claim, upload, default/fallback, Beta, tuple publication, or signing behavior changed.<br>
|
||||
Primary design: [SSH relay GitHub Release plan](./2026-07-14-ssh-relay-github-release-plan.html)<br>
|
||||
Motivating issues: [#8450](https://github.com/stablyai/orca/issues/8450), [#1693](https://github.com/stablyai/orca/issues/1693)
|
||||
|
||||
@@ -19867,15 +19867,15 @@ config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 119 runnable cases wi
|
||||
- Syntax/focused evidence: `node --check config/scripts/build-windows-ssh-no-input-launcher.mjs`
|
||||
and `node --check config/scripts/ssh-relay-runtime-windows-no-input-launcher.test.mjs` pass.
|
||||
`/usr/bin/time -l pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1
|
||||
src/main/ssh/ssh-connection.test.ts src/main/ssh/ssh-system-fallback.test.ts
|
||||
src/main/ssh/ssh-system-no-input-windows-openssh.test.ts
|
||||
src/main/ssh/ssh-relay-runtime-windows-system-ssh-openssh-full-size.test.ts
|
||||
config/scripts/ssh-relay-runtime-windows-no-input-launcher.test.mjs
|
||||
config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 119 runnable cases with nine declared
|
||||
src/main/ssh/ssh-connection.test.ts src/main/ssh/ssh-system-fallback.test.ts
|
||||
src/main/ssh/ssh-system-no-input-windows-openssh.test.ts
|
||||
src/main/ssh/ssh-relay-runtime-windows-system-ssh-openssh-full-size.test.ts
|
||||
config/scripts/ssh-relay-runtime-windows-no-input-launcher.test.mjs
|
||||
config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 119 runnable cases with nine declared
|
||||
native/live skips in 2.59 seconds real; maximum RSS is 171,491,328 bytes and peak footprint is
|
||||
97,064,696 bytes.
|
||||
- Release contracts: `pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1
|
||||
--reporter=dot config/scripts/ssh-relay-runtime-*.test.mjs` passes 51 files and 285 runnable cases
|
||||
--reporter=dot config/scripts/ssh-relay-runtime-*.test.mjs` passes 51 files and 285 runnable cases
|
||||
with seven declared Windows skips in 13.29 seconds.
|
||||
- Static gates: `/usr/bin/time -l pnpm typecheck` passes in 2.86 seconds real with
|
||||
1,247,576,064-byte maximum RSS and 97,343,320-byte peak footprint. `/usr/bin/time -l pnpm lint`
|
||||
@@ -19883,7 +19883,7 @@ config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 119 runnable cases wi
|
||||
355-entry max-lines ratchet; maximum RSS is 2,044,805,120 bytes and peak footprint is 97,163,000
|
||||
bytes. Purpose-file formatting and `git diff --check` pass;
|
||||
`git diff --exit-code HEAD -- src/main/ssh/ssh-remote-node-resolution.ts
|
||||
src/main/ssh/ssh-remote-node-resolution.test.ts` is empty.
|
||||
src/main/ssh/ssh-remote-node-resolution.test.ts` is empty.
|
||||
- Residual boundary: local source contracts do not prove legacy .NET Framework compilation,
|
||||
delete-on-close behavior, overflow settlement, binary replay, job cancellation, live OpenSSH, or
|
||||
exact fixture teardown on Windows. Commit and push only this disconnected package, then require
|
||||
@@ -19942,11 +19942,11 @@ config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 119 runnable cases wi
|
||||
and external-cancellation cases remain. The new native case is honestly skipped locally.
|
||||
- Syntax/focused evidence: both launcher scripts pass `node --check`.
|
||||
`/usr/bin/time -l pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1
|
||||
src/main/ssh/ssh-connection.test.ts src/main/ssh/ssh-system-fallback.test.ts
|
||||
src/main/ssh/ssh-system-no-input-windows-openssh.test.ts
|
||||
src/main/ssh/ssh-relay-runtime-windows-system-ssh-openssh-full-size.test.ts
|
||||
config/scripts/ssh-relay-runtime-windows-no-input-launcher.test.mjs
|
||||
config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 119 runnable cases with ten declared
|
||||
src/main/ssh/ssh-connection.test.ts src/main/ssh/ssh-system-fallback.test.ts
|
||||
src/main/ssh/ssh-system-no-input-windows-openssh.test.ts
|
||||
src/main/ssh/ssh-relay-runtime-windows-system-ssh-openssh-full-size.test.ts
|
||||
config/scripts/ssh-relay-runtime-windows-no-input-launcher.test.mjs
|
||||
config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 119 runnable cases with ten declared
|
||||
native/live skips in 2.69 seconds real; maximum RSS is 171,212,800 bytes and peak footprint is
|
||||
97,179,456 bytes.
|
||||
- Release/static evidence: the unquoted release-contract command passes 51 files and 285 runnable
|
||||
@@ -19960,6 +19960,74 @@ config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 119 runnable cases wi
|
||||
package and require exact-head x64/ARM64 evidence. Do not select ConPTY, another client, a product
|
||||
caller, Beta, fallback, tuple, publication, default, signing, or SignPath behavior from local proof.
|
||||
|
||||
### E-M6-WINDOWS-VERBOSE-LIFECYCLE-CAPTURE-CI-RED-001 — native trace exposes missing fixture host-key path
|
||||
|
||||
- Date/owner/source/run: 2026-07-16, Codex implementation owner; exact head
|
||||
`b24dda744892c2ee43a3fb345d889ba97adb4239`, artifact run
|
||||
[29554073553](https://github.com/stablyai/orca/actions/runs/29554073553), Windows x64 job
|
||||
[87802525440](https://github.com/stablyai/orca/actions/runs/29554073553/job/87802525440) on
|
||||
`windows-2022`, and native ARM64 job
|
||||
[87802525442](https://github.com/stablyai/orca/actions/runs/29554073553/job/87802525442) on
|
||||
`windows-11-arm64`; both use Node 24.18.0.
|
||||
- Preserved gates: both Windows jobs pass legacy .NET launcher compilation and 101 files/863
|
||||
runnable cases with 19 declared skips, including internal diagnostic timeout, exact replay,
|
||||
job-owned termination, console EOF, argv/binary/exit, output overflow/cleanup, unrelated-handle
|
||||
exclusion, external cancellation, clean-build identity, runtime smoke, and both full-size cache
|
||||
gates. Linux x64/ARM64 jobs `87802525448`/`87802525441`, Darwin x64/ARM64 jobs
|
||||
`87802525450`/`87802525446`, and Linux oldest-userland supplements
|
||||
`87803014758`/`87803014770` pass at the same exact head.
|
||||
- Native lifecycle evidence: x64 exits after 6111.6731 ms and ARM64 after 6395.98 ms. Both report
|
||||
`timedOut=false`, `sentinel=false`, `stdoutEnded=true`, `processExit=1`, `channelClosed=true`,
|
||||
`closeCode=1`, and `stderrBytes=7923`. The false outer-timeout field is expected: the new internal
|
||||
6,000 ms launcher deadline terminates and settles the owned job, replays the bounded trace, and
|
||||
returns exit 1 before the 8,000/10,000 ms external safety ceilings.
|
||||
- Trace classification: both stock Win32-OpenSSH 9.5 clients establish TCP, complete key exchange,
|
||||
receive the fixture's Ed25519 host key, and then try
|
||||
`C:\Users\runneradmin\.ssh\known_hosts`. They stop at `hostkeys_find_by_key_hostfile` because that
|
||||
default file is absent. The workflow-created pinned file is instead under the isolated
|
||||
`ORCA_SSH_RELAY_LIVE_WINDOWS_SYSTEM_SSH_CLIENT_HOME`. Win32-OpenSSH therefore ignored the step's
|
||||
overridden `HOME`/`USERPROFILE` for host-key discovery. Earlier server authentication/session
|
||||
log lines came from the fixture readiness probe and do not prove this diagnostic authenticated.
|
||||
- Teardown/residual: both jobs still fail visibly on the owned fixture profile's locked
|
||||
`UsrClass.dat`; the full-size Windows transfer correctly remains unexecuted after the diagnostic.
|
||||
This result does not justify ConPTY or an alternate client. The next single-variable correction
|
||||
must pass only the fixture's exact pinned `known_hosts` path with `StrictHostKeyChecking=yes`,
|
||||
never weaken trust, and keep production SSH argument construction unchanged.
|
||||
|
||||
### E-M6-WINDOWS-DIAGNOSTIC-HOST-TRUST-CORRECTION-LOCAL-001 — exact pinned trust path is locally green
|
||||
|
||||
- Date/owner/base/runner: 2026-07-16, Codex implementation owner; uncommitted runner-only test
|
||||
correction atop exact verbose-trace head `b24dda744892c2ee43a3fb345d889ba97adb4239` on Apple arm64,
|
||||
macOS 26.2 build 25C56, Node 26.5.0, and pnpm 10.24.0.
|
||||
- Boundary: the live diagnostic now requires
|
||||
`ORCA_SSH_RELAY_LIVE_WINDOWS_SYSTEM_SSH_CLIENT_HOME`, builds its exact fixture file with
|
||||
`path.join(clientHome, '.ssh', 'known_hosts')`, and inserts `-vvv`,
|
||||
`StrictHostKeyChecking=yes`, and `UserKnownHostsFile=<exact fixture path>` before OpenSSH's `--`
|
||||
separator. The purpose contract compares the complete diagnostic vector with an independently
|
||||
built production vector, rejects `StrictHostKeyChecking=no`, and proves connection reuse and all
|
||||
production arguments are unchanged.
|
||||
- Syntax/focused evidence: both launcher scripts pass `node --check`.
|
||||
`/usr/bin/time -l pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1
|
||||
src/main/ssh/ssh-connection.test.ts src/main/ssh/ssh-system-fallback.test.ts
|
||||
src/main/ssh/ssh-system-no-input-windows-openssh.test.ts
|
||||
src/main/ssh/ssh-relay-runtime-windows-system-ssh-openssh-full-size.test.ts
|
||||
config/scripts/ssh-relay-runtime-windows-no-input-launcher.test.mjs
|
||||
config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 120 runnable cases with ten declared
|
||||
native/live skips in 3.13 seconds real; maximum RSS is 174,571,520 bytes and peak footprint is
|
||||
97,113,848 bytes.
|
||||
- Release/static evidence: the unquoted release-contract command passes 51 files and 285 runnable
|
||||
cases with eight declared Windows skips in 16.23 seconds; maximum RSS is 196,100,096 bytes and
|
||||
peak footprint is 97,179,360 bytes. `/usr/bin/time -l pnpm typecheck` passes in 3.38 seconds real
|
||||
with 1,208,680,448-byte maximum RSS and 97,031,952-byte peak footprint. `/usr/bin/time -l pnpm
|
||||
lint` passes in 18.59 seconds real with the 26 existing warnings, all 41 reliability gates, and
|
||||
the 355-entry max-lines ratchet; maximum RSS is 2,027,831,296 bytes and peak footprint is
|
||||
97,392,520 bytes.
|
||||
- Residual boundary: local execution does not prove the fixture path is accepted by Win32-OpenSSH,
|
||||
authentication completes, the launcher exits naturally, full-size transfer runs, or the fixture
|
||||
profile tears down. Commit/push only this correction and require exact-head x64/ARM64 evidence.
|
||||
No production caller, Beta, fallback, tuple, publication, default, signing, or SignPath behavior
|
||||
is authorized by this local proof.
|
||||
|
||||
## Accepted Gaps
|
||||
|
||||
No product gap is accepted merely because it appears in this list. Each entry requires explicit
|
||||
@@ -20018,12 +20086,12 @@ The project is not complete until every applicable item below is checked with ev
|
||||
|
||||
## Next Required Action
|
||||
|
||||
Commit and push only the bounded internal-timeout and verbose-output capture recorded by
|
||||
`E-M6-WINDOWS-VERBOSE-LIFECYCLE-CAPTURE-LOCAL-001`, then require exact-head Windows x64 and
|
||||
ARM64 legacy-compiler, launcher-timeout settlement, verbose-client phase classification, and exact
|
||||
profile/directory teardown evidence. Do not
|
||||
change the production Windows handle or check the broad Milestone 6 Windows system-SSH item until
|
||||
both architectures select the same console-independent strategy. Do not add an
|
||||
Commit and push only the explicit diagnostic fixture-trust correction recorded by
|
||||
`E-M6-WINDOWS-DIAGNOSTIC-HOST-TRUST-CORRECTION-LOCAL-001`, then require exact-head Windows x64 and
|
||||
ARM64 legacy-compiler, launcher, strict host-key authentication, natural client settlement,
|
||||
full-size transfer, and exact profile/directory teardown evidence. Do not change the production
|
||||
Windows handle or check the broad Milestone 6 Windows system-SSH item until both architectures pass
|
||||
the same console-independent strategy. Do not add an
|
||||
Electron/startup/product importer, per-target mode wiring, fallback, tuple
|
||||
enablement, release publication, or default behavior.
|
||||
Keep Node upstream `.tar.xz` inputs, Windows ZIP, `ORCA_RELAY_PATH`, existing desktop required-assets
|
||||
|
||||
@@ -1669,19 +1669,23 @@
|
||||
queued console EOF before child creation, and shared that console with the SSH
|
||||
child while retaining private output pipes, exact handle inheritance, job
|
||||
ownership, and bounded cancellation. Native x64/arm64 prove the console handle
|
||||
and zero-byte cooked EOF but the live client still hangs, falsifying stdin alone.
|
||||
The next one-variable diagnostic retained that console stdin and replaced only
|
||||
child stdout/stderr pipes with unique delete-on-close regular files under an
|
||||
explicit per-stream byte ceiling, bounded polling/cancellation, incremental
|
||||
and zero-byte cooked EOF but the live client still hangs, falsifying stdin
|
||||
alone. The next one-variable diagnostic retained that console stdin and replaced
|
||||
only child stdout/stderr pipes with unique delete-on-close regular files under
|
||||
an explicit per-stream byte ceiling, bounded polling/cancellation, incremental
|
||||
post-exit replay, and exact cleanup. Native x64/arm64 prove those contracts, but
|
||||
the live client still hangs with the same lifecycle tuple, falsifying redirected
|
||||
output pipes as the remaining cause. Before selecting ConPTY or another SSH
|
||||
client, the runner-only launcher must boundedly terminate its own diagnostic
|
||||
child and replay an exact verbose OpenSSH trace to classify the stuck client
|
||||
phase. Do not package, sign, or add a product caller. POSIX retains ignored
|
||||
stdin plus <code>-n</code>; fixture-owned Windows session processes settle
|
||||
before profile hives are boundedly unloaded and native profile deletion begins;
|
||||
<code>MaxSessions=1</code>; interrupted upload; stale lock
|
||||
output pipes as the remaining cause. The bounded verbose trace on native
|
||||
x64/arm64 then shows that Win32-OpenSSH ignores the workflow's overridden
|
||||
profile variables for host-key discovery and stops before authentication while
|
||||
looking for the runner account's missing default <code>known_hosts</code>.
|
||||
Before selecting ConPTY or another SSH client, pass only the fixture's exact
|
||||
pinned <code>known_hosts</code> path with strict host-key checking and require
|
||||
both architectures to pass. Do not weaken trust, package, sign, or add a product
|
||||
caller. POSIX retains ignored stdin plus <code>-n</code>; fixture-owned Windows
|
||||
session processes settle before profile hives are boundedly unloaded and native
|
||||
profile deletion begins; <code>MaxSessions=1</code>; interrupted upload; stale
|
||||
lock
|
||||
</td>
|
||||
<td>
|
||||
Bundled Node hashes the full staged tree before sentinel write;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import { join } from 'node:path'
|
||||
import { performance } from 'node:perf_hooks'
|
||||
|
||||
import { describe, expect, it } from 'vitest'
|
||||
@@ -26,9 +27,12 @@ type DiagnosticResult = {
|
||||
const host = process.env.ORCA_SSH_RELAY_LIVE_WINDOWS_SYSTEM_SSH_HOST
|
||||
const user = process.env.ORCA_SSH_RELAY_LIVE_WINDOWS_SYSTEM_SSH_USER
|
||||
const identityFile = process.env.ORCA_SSH_RELAY_LIVE_WINDOWS_SYSTEM_SSH_IDENTITY
|
||||
const clientHome = process.env.ORCA_SSH_RELAY_LIVE_WINDOWS_SYSTEM_SSH_CLIENT_HOME
|
||||
const launcherPath = process.env.ORCA_SSH_WINDOWS_NO_INPUT_LAUNCHER
|
||||
const port = Number.parseInt(process.env.ORCA_SSH_RELAY_LIVE_WINDOWS_SYSTEM_SSH_PORT ?? '', 10)
|
||||
const hasLiveInput = Boolean(host && user && identityFile && launcherPath && Number.isInteger(port))
|
||||
const hasLiveInput = Boolean(
|
||||
host && user && identityFile && clientHome && launcherPath && Number.isInteger(port)
|
||||
)
|
||||
|
||||
function createTarget(): SshTarget {
|
||||
return {
|
||||
@@ -44,6 +48,25 @@ function createTarget(): SshTarget {
|
||||
}
|
||||
}
|
||||
|
||||
function buildDiagnosticSshArgs(target: SshTarget, knownHostsPath: string): string[] {
|
||||
const sshArgs = buildSshArgs(target)
|
||||
const destinationSeparator = sshArgs.indexOf('--')
|
||||
if (destinationSeparator < 0) {
|
||||
throw new Error('Windows OpenSSH diagnostic arguments lost the destination separator')
|
||||
}
|
||||
// Why: Win32-OpenSSH ignores overridden profile variables; use only the fixture's pinned trust.
|
||||
sshArgs.splice(
|
||||
destinationSeparator,
|
||||
0,
|
||||
'-vvv',
|
||||
'-o',
|
||||
'StrictHostKeyChecking=yes',
|
||||
'-o',
|
||||
`UserKnownHostsFile=${knownHostsPath}`
|
||||
)
|
||||
return sshArgs
|
||||
}
|
||||
|
||||
async function runDiagnostic(): Promise<DiagnosticResult> {
|
||||
const sshPath = findSystemSsh()
|
||||
if (!sshPath) {
|
||||
@@ -51,14 +74,10 @@ async function runDiagnostic(): Promise<DiagnosticResult> {
|
||||
}
|
||||
const mode: DiagnosticMode = 'private-console-regular-output-verbose-timeout'
|
||||
const startedAt = performance.now()
|
||||
// Why: Win32-OpenSSH still hangs with proven console EOF plus piped output, so this diagnostic
|
||||
// isolates stdout/stderr as bounded regular files without changing production transport.
|
||||
const sshArgs = buildSshArgs(createTarget())
|
||||
const destinationSeparator = sshArgs.indexOf('--')
|
||||
if (destinationSeparator < 0) {
|
||||
throw new Error('Windows OpenSSH diagnostic arguments lost the destination separator')
|
||||
}
|
||||
sshArgs.splice(destinationSeparator, 0, '-vvv')
|
||||
const sshArgs = buildDiagnosticSshArgs(
|
||||
createTarget(),
|
||||
join(clientHome as string, '.ssh', 'known_hosts')
|
||||
)
|
||||
const child = spawn(
|
||||
launcherPath as string,
|
||||
['--diagnostic-timeout-ms', '6000', sshPath, ...sshArgs, 'echo ORCA-SYSTEM-SSH-OK'],
|
||||
@@ -147,6 +166,42 @@ async function runDiagnostic(): Promise<DiagnosticResult> {
|
||||
})
|
||||
}
|
||||
|
||||
describe('Windows OpenSSH no-input diagnostic trust arguments', () => {
|
||||
it('adds only strict fixture trust and verbosity before the destination separator', () => {
|
||||
const target: SshTarget = {
|
||||
id: 'windows-no-input-contract',
|
||||
label: 'windows-no-input-contract',
|
||||
host: '127.0.0.1',
|
||||
port: 22224,
|
||||
username: 'fixture-user',
|
||||
identityFile: 'C:\\fixture\\client-key',
|
||||
identitiesOnly: true,
|
||||
systemSshConnectionReuse: true,
|
||||
source: 'manual'
|
||||
}
|
||||
const knownHostsPath = 'C:\\fixture\\client-home\\.ssh\\known_hosts'
|
||||
const productionArgs = buildSshArgs(target)
|
||||
const diagnosticArgs = buildDiagnosticSshArgs(target, knownHostsPath)
|
||||
const destinationSeparator = productionArgs.indexOf('--')
|
||||
const diagnosticOnlyArgs = [
|
||||
'-vvv',
|
||||
'-o',
|
||||
'StrictHostKeyChecking=yes',
|
||||
'-o',
|
||||
`UserKnownHostsFile=${knownHostsPath}`
|
||||
]
|
||||
|
||||
expect(diagnosticArgs).toEqual([
|
||||
...productionArgs.slice(0, destinationSeparator),
|
||||
...diagnosticOnlyArgs,
|
||||
...productionArgs.slice(destinationSeparator)
|
||||
])
|
||||
expect(diagnosticArgs.indexOf('-vvv')).toBeLessThan(diagnosticArgs.indexOf('--'))
|
||||
expect(diagnosticArgs).not.toContain('StrictHostKeyChecking=no')
|
||||
expect(buildSshArgs(target)).toEqual(productionArgs)
|
||||
})
|
||||
})
|
||||
|
||||
describe.skipIf(!hasLiveInput)('Windows OpenSSH no-input child-handle diagnostic', () => {
|
||||
it(
|
||||
'captures the verbose client phase after a bounded private-console diagnostic timeout',
|
||||
|
||||
Reference in New Issue
Block a user