fix(ssh): detach Windows no-input probe

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinwoo-H
2026-07-16 19:54:23 -04:00
co-authored by Orca
parent b652c1ebcc
commit 8ae6dcf645
10 changed files with 269 additions and 87 deletions
@@ -1697,9 +1697,40 @@ jobs:
if (Test-Path -LiteralPath $log) { Get-Content -LiteralPath $log -Tail 200 }
try {
if ($ownsAccount -and $userSid) {
function Dismount-FixtureRegistryHive([string]$hiveName) {
$registryPath = "Registry::HKEY_USERS\$hiveName"
if (-not (Test-Path -LiteralPath $registryPath)) { return }
$regPath = Join-Path $env:SystemRoot 'System32/reg.exe'
$process = Start-Process -FilePath $regPath `
-ArgumentList @('unload', "HKU\$hiveName") -PassThru -WindowStyle Hidden
try {
if (-not $process.WaitForExit(2000)) {
$process.Kill()
if (-not $process.WaitForExit(2000)) {
throw "Fixture registry hive unload did not stop: $hiveName"
}
throw "Fixture registry hive unload timed out: $hiveName"
}
if ($process.ExitCode -ne 0) {
throw "Fixture registry hive unload failed ($($process.ExitCode)): $hiveName"
}
} finally {
$process.Dispose()
}
}
$escapedSid = $userSid.Replace("'", "''")
$profileFailure = $null
for ($attempt = 1; $attempt -le 20; $attempt += 1) {
try {
# Why: the fixture's UsrClass hive can outlive sshd; unload only
# this owned SID before asking Windows to delete its profile.
Dismount-FixtureRegistryHive "${userSid}_Classes"
Dismount-FixtureRegistryHive $userSid
} catch {
$profileFailure = $_.Exception.Message
Start-Sleep -Milliseconds 500
continue
}
$profile = Get-CimInstance Win32_UserProfile -Filter "SID='$escapedSid'" `
-ErrorAction SilentlyContinue
if (-not $profile) { break }
@@ -0,0 +1,93 @@
export function assertWindowsOpenSshWorkflow(workflow, expect) {
const steps = workflow.jobs['build-windows-runtime'].steps
const start = steps.find(
(step) => step.name === 'Start loopback Windows OpenSSH system-SSH fixture'
)
const measure = steps.find(
(step) => step.name === 'Measure exact full-size runtime over Windows system SSH'
)
const stop = steps.find(
(step) => step.name === 'Stop loopback Windows OpenSSH system-SSH fixture'
)
expect(start).toBeDefined()
expect(measure).toBeDefined()
expect(stop).toBeDefined()
expect(start.shell).toBe('pwsh')
expect(start.run).toContain('10.0.0.0p2-Preview')
expect(start.run).toContain('23f50f3458c4c5d0b12217c6a5ddfde0137210a30fa870e98b29827f7b43aba5')
expect(start.run).toContain('698c6aec31c1dd0fb996206e8741f4531a97355686b5431ef347d531b07fcd42')
expect(start.run).toContain('4652e861c0335ee80a51306ceab75aa35c8865b235f97ce7dd5a0fd9dab44b5d')
expect(start.run).toContain('7ad2b7721893c54ad6e4fec1a3477701fb48975323c2c4ac6cd0b8c972ab242a')
expect(start.run).toContain('--connect-timeout 20 --max-time 300 --retry 2')
expect(start.run).toContain('Get-AuthenticodeSignature')
expect(start.run).toContain('$actualNativeNames -join "`n"')
expect(start.run).toContain('$expectedNativeNames -join "`n"')
expect(start.run).toContain("'ssh-sk-helper.exe'")
expect(start.run).toContain("'sshd-session.exe'")
expect(start.run).toContain('$libcryptoFiles.Count -ne 1')
expect(start.run).toContain("$libcryptoSignature.Status -ne 'Valid'")
expect(start.run).toContain('587116075365AA15BCD8E4FA9CB31BE372B5DE51')
expect(start.run).toContain('CN=Microsoft 3rd Party Application Component')
expect(start.run).toContain('F5877012FBD62FABCBDC8D8CEE9C9585BA30DF79')
expect(start.run).toContain('3F56A45111684D454E231CFDC4DA5C8D370F9816')
expect(start.run).toContain('$expectedExecutableSignerThumbprints -notcontains $thumbprint')
expect(start.run).not.toContain("'NotSigned'")
expect(start.run).toContain("if ($nativeFile.Name -eq 'libcrypto.dll') { continue }")
expect(start.run).toContain("$signature.Status -ne 'Valid'")
expect(start.run).toContain('CN=Microsoft Corporation')
expect(start.run).toContain('[Security.AccessControl.DirectorySecurity]::new()')
expect(start.run).toContain('[Security.AccessControl.FileSecurity]::new()')
expect(start.run).toContain('$security.SetAccessRuleProtection($true, $false)')
expect(start.run).toContain('[void]$security.AddAccessRule($accessRule)')
expect(start.run).toContain('$acl.AreAccessRulesProtected')
expect(start.run).toContain('Fixture ACL trustee closure changed')
expect(start.run).toContain('@($systemSid, $administratorsSid)')
expect(start.run).not.toContain('Add-WindowsCapability')
expect(start.run).toContain('New-LocalUser')
expect(start.run.indexOf("Join-Path $fixture 'account-owned'")).toBeLessThan(
start.run.indexOf('New-LocalUser')
)
expect(start.run).toContain('ListenAddress 127.0.0.1')
expect(start.run).toContain('PasswordAuthentication no')
expect(start.run).toContain('StrictModes yes')
expect(start.run).toContain('StrictHostKeyChecking=yes')
expect(start.run).toContain('powershell.exe')
expect(start.run).toContain('([Version]$remotePowerShellVersion).Major -ne 5')
expect(start.run).toContain('/setowner')
expect(start.run).toContain("Set-FixtureOwner $hostKey 'S-1-5-18'")
expect(start.run).toContain('Set-FixtureOwner $authorizedKeys $userSid')
expect(start.run).not.toContain('administrators_authorized_keys')
expect(start.run).toContain('New-Service')
expect(start.run.indexOf("Join-Path $fixture 'service-owned'")).toBeLessThan(
start.run.indexOf('New-Service')
)
expect(measure.shell).toBe('pwsh')
expect(measure.run).toContain("$env:ORCA_SSH_FORCE_SYSTEM_TRANSPORT = '1'")
expect(measure.run).toContain('ssh-relay-runtime-windows-system-ssh-openssh-full-size.test.ts')
expect(measure.run).toContain("Join-Path $firstOutput 'runtime'")
expect(stop.if).toBe("always() && runner.os == 'Windows'")
expect(stop.shell).toBe('pwsh')
expect(stop.run).toContain('fixture-owned')
expect(stop.run).toContain('service-owned')
expect(stop.run).toContain('account-owned')
expect(stop.run).not.toContain('service-backup.json')
expect(stop.run).not.toContain('sc.exe config')
expect(stop.run).toContain('sc.exe delete')
expect(stop.run).toContain('Dismount-FixtureRegistryHive "${userSid}_Classes"')
expect(stop.run).toContain('Dismount-FixtureRegistryHive $userSid')
expect(stop.run).toContain("Join-Path $env:SystemRoot 'System32/reg.exe'")
expect(stop.run).toContain('@(\'unload\', "HKU\\$hiveName")')
expect(stop.run).toContain('$process.WaitForExit(2000)')
expect(stop.run).toContain('$process.Kill()')
expect(stop.run.indexOf('Dismount-FixtureRegistryHive "${userSid}_Classes"')).toBeLessThan(
stop.run.indexOf('Dismount-FixtureRegistryHive $userSid')
)
expect(stop.run.indexOf('Dismount-FixtureRegistryHive $userSid')).toBeLessThan(
stop.run.indexOf('Remove-CimInstance -InputObject $profile')
)
expect(stop.run).toContain('Remove-CimInstance -InputObject $profile')
expect(stop.run).toContain('Fixture profile did not settle within 10 seconds')
expect(stop.run).toContain('fixture profile directory remains')
expect(stop.run).toContain('Remove-LocalUser')
}
@@ -2,6 +2,7 @@ import { readFile } from 'node:fs/promises'
import { parse } from 'yaml'
import { describe, expect, it } from 'vitest'
import { assertWindowsOpenSshWorkflow } from './ssh-relay-runtime-windows-openssh-workflow-contract.mjs'
const workflowUrl = new URL(
'../../.github/workflows/ssh-relay-runtime-artifacts.yml',
@@ -142,85 +143,7 @@ describe('SSH relay runtime artifact workflow', () => {
it('runs full-size Windows system SSH against loopback native OpenSSH', async () => {
const workflow = parse(await readFile(workflowUrl, 'utf8'))
const steps = workflow.jobs['build-windows-runtime'].steps
const start = steps.find(
(step) => step.name === 'Start loopback Windows OpenSSH system-SSH fixture'
)
const measure = steps.find(
(step) => step.name === 'Measure exact full-size runtime over Windows system SSH'
)
const stop = steps.find(
(step) => step.name === 'Stop loopback Windows OpenSSH system-SSH fixture'
)
expect(start).toBeDefined()
expect(measure).toBeDefined()
expect(stop).toBeDefined()
expect(start.shell).toBe('pwsh')
expect(start.run).toContain('10.0.0.0p2-Preview')
expect(start.run).toContain('23f50f3458c4c5d0b12217c6a5ddfde0137210a30fa870e98b29827f7b43aba5')
expect(start.run).toContain('698c6aec31c1dd0fb996206e8741f4531a97355686b5431ef347d531b07fcd42')
expect(start.run).toContain('4652e861c0335ee80a51306ceab75aa35c8865b235f97ce7dd5a0fd9dab44b5d')
expect(start.run).toContain('7ad2b7721893c54ad6e4fec1a3477701fb48975323c2c4ac6cd0b8c972ab242a')
expect(start.run).toContain('--connect-timeout 20 --max-time 300 --retry 2')
expect(start.run).toContain('Get-AuthenticodeSignature')
expect(start.run).toContain('$actualNativeNames -join "`n"')
expect(start.run).toContain('$expectedNativeNames -join "`n"')
expect(start.run).toContain("'ssh-sk-helper.exe'")
expect(start.run).toContain("'sshd-session.exe'")
expect(start.run).toContain('$libcryptoFiles.Count -ne 1')
expect(start.run).toContain("$libcryptoSignature.Status -ne 'Valid'")
expect(start.run).toContain('587116075365AA15BCD8E4FA9CB31BE372B5DE51')
expect(start.run).toContain('CN=Microsoft 3rd Party Application Component')
expect(start.run).toContain('F5877012FBD62FABCBDC8D8CEE9C9585BA30DF79')
expect(start.run).toContain('3F56A45111684D454E231CFDC4DA5C8D370F9816')
expect(start.run).toContain('$expectedExecutableSignerThumbprints -notcontains $thumbprint')
expect(start.run).not.toContain("'NotSigned'")
expect(start.run).toContain("if ($nativeFile.Name -eq 'libcrypto.dll') { continue }")
expect(start.run).toContain("$signature.Status -ne 'Valid'")
expect(start.run).toContain('CN=Microsoft Corporation')
expect(start.run).toContain('[Security.AccessControl.DirectorySecurity]::new()')
expect(start.run).toContain('[Security.AccessControl.FileSecurity]::new()')
expect(start.run).toContain('$security.SetAccessRuleProtection($true, $false)')
expect(start.run).toContain('[void]$security.AddAccessRule($accessRule)')
expect(start.run).toContain('$acl.AreAccessRulesProtected')
expect(start.run).toContain('Fixture ACL trustee closure changed')
expect(start.run).toContain('@($systemSid, $administratorsSid)')
expect(start.run).not.toContain('Add-WindowsCapability')
expect(start.run).toContain('New-LocalUser')
expect(start.run.indexOf("Join-Path $fixture 'account-owned'")).toBeLessThan(
start.run.indexOf('New-LocalUser')
)
expect(start.run).toContain('ListenAddress 127.0.0.1')
expect(start.run).toContain('PasswordAuthentication no')
expect(start.run).toContain('StrictModes yes')
expect(start.run).toContain('StrictHostKeyChecking=yes')
expect(start.run).toContain('powershell.exe')
expect(start.run).toContain('([Version]$remotePowerShellVersion).Major -ne 5')
expect(start.run).toContain('/setowner')
expect(start.run).toContain("Set-FixtureOwner $hostKey 'S-1-5-18'")
expect(start.run).toContain('Set-FixtureOwner $authorizedKeys $userSid')
expect(start.run).not.toContain('administrators_authorized_keys')
expect(start.run).toContain('New-Service')
expect(start.run.indexOf("Join-Path $fixture 'service-owned'")).toBeLessThan(
start.run.indexOf('New-Service')
)
expect(measure.shell).toBe('pwsh')
expect(measure.run).toContain("$env:ORCA_SSH_FORCE_SYSTEM_TRANSPORT = '1'")
expect(measure.run).toContain('ssh-relay-runtime-windows-system-ssh-openssh-full-size.test.ts')
expect(measure.run).toContain("Join-Path $firstOutput 'runtime'")
expect(stop.if).toBe("always() && runner.os == 'Windows'")
expect(stop.shell).toBe('pwsh')
expect(stop.run).toContain('fixture-owned')
expect(stop.run).toContain('service-owned')
expect(stop.run).toContain('account-owned')
expect(stop.run).not.toContain('service-backup.json')
expect(stop.run).not.toContain('sc.exe config')
expect(stop.run).toContain('sc.exe delete')
expect(stop.run).toContain('Remove-CimInstance -InputObject $profile')
expect(stop.run).toContain('Fixture profile did not settle within 10 seconds')
expect(stop.run).toContain('fixture profile directory remains')
expect(stop.run).toContain('Remove-LocalUser')
assertWindowsOpenSshWorkflow(workflow, expect)
})
it('uploads only the first output after two clean builds verify and compare', async () => {
@@ -66,8 +66,28 @@ are atomically replaced with exact protected allow-only rules independent of dri
owned `Win32_UserProfile` is deleted through a bounded native lifecycle before account/filesystem
teardown. Focused tests pass 71 cases with one declared live skip, all three PowerShell blocks parse,
all 283 artifact contracts pass, typecheck and full lint/reliability/max-lines pass, formatting/diff
are clean, and the protected resolver files remain unchanged. Commit/push this isolated package and
require fresh x64/arm64 live proof before advancing.
are clean, and the protected resolver files remain unchanged. Exact head
`b652c1ebcce3803443d84c89811146366cdbdd5b` is pushed. Artifact run `29542292712` preserves all
non-Windows gates and independently reaches the Windows fixture on x64, but job `87766845800` is
RED: exact ACL replacement, official OpenSSH setup, authentication, and PowerShell 5.1 pass before
the production probe times out after 32.064 seconds. Closing the Node stdin pipe is insufficient;
the no-input probe needs native OpenSSH `-n` without disabling connection reuse. Teardown also
finds the owned fixture SID's `UsrClass.dat` hive still loaded after the bounded profile-removal
loop. Add probe-only `-n`, boundedly unload only that SID's `_Classes` and primary hives before
retrying `Win32_UserProfile` removal, and require fresh x64/arm64 live proof before advancing.
ARM64 job `87766845741` independently reaches the same boundary: official OpenSSH setup passes,
the production probe times out after 34.01 seconds, and teardown catches the same owned
`UsrClass.dat` lock after the bounded profile loop. This is a shared native OpenSSH/profile
lifecycle correction, not an x64-only exception.
`E-M6-WINDOWS-SYSTEM-SSH-TREE-LIVE-NOINPUT-PROFILE-CORRECTION-LOCAL-001` records the narrow
correction locally green: only the no-input connection probe emits OpenSSH `-n` before `--`, reuse
flags remain enabled, ordinary commands exclude `-n`, and teardown boundedly unloads only the
fixture SID's `_Classes` and primary hives before retrying native profile deletion. The Windows
workflow oracle is split by concrete domain responsibility without a max-lines bypass. Focused
tests pass 115 cases with one declared native skip, all three PowerShell blocks parse, 283/283
artifact contracts pass, typecheck and full lint/reliability/max-lines pass, formatting/diff are
clean, and the protected resolver files remain unchanged. Commit/push this isolated package and
require fresh native x64/arm64 proof before advancing.
`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
@@ -9,7 +9,7 @@ work; keep exact commands, runner identities, hashes, metrics, and residual gaps
Date created: 2026-07-14<br>
Last updated: 2026-07-15<br>
Current phase: Milestone 6 / Work Package 5 bounded runtime transfer — **In progress — 2026-07-15, Codex implementation owner: exact-head Windows OpenSSH live-proof diagnosis and fixture correction**. Keep every capability disconnected from every production/default SSH path. Real Apple/SignPath rehearsals remain an explicit late gate and are not on this package's critical path.<br>
Session checkpoint: **WINDOWS ACL/PROBE/PROFILE CORRECTION LOCALLY GREEN / EXACT-HEAD PROOF NEXT — 2026-07-15, Codex implementation owner** — exact pushed head `d28552f0d953e40d96a4c24cdcdb5ba7d85b7c9f`, artifact run `29541119819`, and x64/arm64 jobs `87763404467`/`87763404492` independently pass checkout/toolchain, 283 contracts, clean-build equality/smoke, full-size cache, both pinned archive/library hashes, exact 15-file closure, and every audited signer check before exposing three narrower gaps. ARM64's C: fixture root retains explicit Authenticated Users and Users ACEs; x64's no-input production `ssh.exe` probe leaves piped stdin open and waits 30 seconds after the remote command closes; x64 teardown finds the owned profile's loaded `UsrClass.dat`. `E-M6-WINDOWS-SYSTEM-SSH-TREE-LIVE-EXACT-HEAD-CORRECTION-LOCAL-001` atomically replaces each fixture DACL with exact protected allow-only rules, closes stdin for the no-input production probe without disabling connection reuse, and deletes the owned `Win32_UserProfile` through a bounded native lifecycle before account/filesystem cleanup. Focused, PowerShell syntax, 283-contract, typecheck, full lint/reliability/max-lines, formatting, diff, and protected-resolver isolation gates pass locally. Commit/push and require fresh x64/arm64 live proof. Production runtime bytes still cross authenticated SSH and no product remote downloads anything. Do not connect a product caller, change legacy upload/fallback/default behavior, enable a tuple, publish an artifact, or perform SignPath work. Merging to `main` remains prohibited, SignPath is deferred, and legacy remains the production default.<br>
Session checkpoint: **WINDOWS NATIVE NO-INPUT/PROFILE-HIVE CORRECTION LOCALLY GREEN / EXACT-HEAD PROOF NEXT — 2026-07-15, Codex implementation owner** — exact head `b652c1ebcce3803443d84c89811146366cdbdd5b`, artifact run `29542292712`, x64 job `87766845800`, and ARM64 job `87766845741` preserve all prior artifact/build/cache/hash/closure/signer gates and independently expose the same native probe/profile gaps. `E-M6-WINDOWS-SYSTEM-SSH-TREE-LIVE-NOINPUT-PROFILE-CORRECTION-LOCAL-001` adds probe-only OpenSSH `-n` before `--` while retaining connection reuse and excluding `-n` from ordinary commands; boundedly unloads only the fixture-owned SID's `_Classes` and primary hives before retrying native profile deletion; retains exact teardown assertions; and splits the Windows workflow oracle by concrete domain responsibility without a max-lines bypass. Focused tests, all three PowerShell parses, 283 artifact contracts, typecheck, full lint/reliability/max-lines, formatting, diff, and protected-resolver isolation pass locally. Commit/push this isolated package and require fresh x64/arm64 proof. Production runtime bytes still cross authenticated SSH and no product remote downloads anything. Do not connect a product caller, change legacy upload/fallback/default behavior, enable a tuple, publish an artifact, or perform SignPath work. Merging to `main` remains prohibited, SignPath is deferred, and legacy remains the production default.<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)
@@ -19092,6 +19092,85 @@ config/scripts/ssh-relay-runtime-*.test.mjs` passes 50 files and 283/283 cases i
exact-head x64/arm64 proof before closing the live Windows gate. Legacy remains the sole
production/default path; product/Beta/settings/fallback/tuple/publication/signing remain absent.
### E-M6-WINDOWS-SYSTEM-SSH-TREE-LIVE-NOINPUT-PROFILE-RED-001 — exact head proves ACL and exposes native no-input/profile-hive gaps
- Date/owner/head/run: 2026-07-15, Codex implementation owner; exact pushed head
`b652c1ebcce3803443d84c89811146366cdbdd5b`, artifact run `29542292712`, native x64 job
`87766845800` (`windows-2022`, Windows Server 2022) and native ARM64 job `87766845741`
(`windows-11-arm`).
- Preserved evidence: all four non-Windows primary jobs and both Linux supplement jobs pass. The
x64 job passes exact checkout/toolchain, 283 runtime artifact contracts, clean-build identity and
smoke, full-size cache, both pinned archive/library hashes, exact 15-file closure, all audited
signer checks, exact fixture DACL replacement, official OpenSSH service/authentication, and
PowerShell 5.1 before the live transfer suite.
- X64 RED: the production no-input connection probe times out after 32.064 seconds with
`System SSH connection timed out`. Closing the spawned process's Node stdin pipe does not make
native Windows OpenSSH detach its stdin worker. Preserve `systemSshConnectionReuse`; add
OpenSSH `-n` only to the no-input probe argv before `--`, and prove argv order plus connection
behavior.
- Teardown RED: the bounded ten-second `Remove-CimInstance Win32_UserProfile` loop cannot settle
while the owned fixture profile's `UsrClass.dat` remains loaded; profile and fixture directory
deletion then fail and exact absence assertions catch both. For the fixture-owned SID only,
boundedly unload `HKU\\&lt;SID&gt;_Classes` and then `HKU\\&lt;SID&gt;` with `reg.exe unload`, retry
native profile deletion, and retain exact account/profile/directory absence assertions.
- ARM64 independent RED: official OpenSSH fixture startup passes, then the same production probe
fails with `System SSH connection timed out` after 34.01 seconds. The teardown reports
`Fixture profile did not settle within 10 seconds`, then exact filesystem deletion identifies
`C:\Users\orca_ssh_fixture\AppData\Local\Microsoft\Windows\UsrClass.dat` as used by another
process and reports that the fixture profile directory remains. The same correction is therefore
required on both native Windows architectures.
- Promotion condition: update the workflow oracle, parse every PowerShell block, pass the focused,
283-contract, typecheck, full-lint/reliability/max-lines, formatting, diff, and protected-resolver
isolation gates, then require fresh exact-head x64/arm64 live proof. Legacy remains the sole
production/default path and SignPath remains deferred.
### E-M6-WINDOWS-SYSTEM-SSH-TREE-LIVE-NOINPUT-PROFILE-CORRECTION-LOCAL-001 — probe-only native no-input and owned-hive teardown are locally green
- Date/owner/base/runner: 2026-07-15, Codex implementation owner; uncommitted correction atop exact
RED head `b652c1ebcce3803443d84c89811146366cdbdd5b` on Apple arm64, macOS 26.2 build 25C56,
Node 26.5.0, pnpm 10.24.0. Native Windows execution remains required.
- Probe correction: `SystemSshBuildArgsOptions.noInput` emits OpenSSH `-n` before the `--`
destination terminator. Only the raw cross-shell connection probe requests it; ordinary
system-SSH commands are asserted to omit it. The probe still requests Orca ControlMaster,
`ControlPersist=300`, and keepalives, so this does not evade the required connection-reuse path.
The existing explicit stdin close remains as deterministic local pipe ownership.
- Teardown correction: for the fixture-created account SID only, the workflow checks and unloads
`HKU\\&lt;SID&gt;_Classes` before `HKU\\&lt;SID&gt;` through `%SystemRoot%\\System32\\reg.exe`.
Every process wait is bounded to two seconds, a stuck process is killed and boundedly awaited,
and failure is retried inside the existing ten-second profile lifecycle. Native
`Remove-CimInstance Win32_UserProfile`, account deletion, directory deletion, and all exact
absence assertions remain mandatory.
- Structure/oracle correction: Windows OpenSSH workflow assertions moved into the concrete
`config/scripts/ssh-relay-runtime-windows-openssh-workflow-contract.mjs` responsibility while
`ssh-relay-runtime-workflow.test.mjs` remains the caller used by every historical command. The
files are 93 and 551 lines respectively; no max-lines disable or budget bump was added.
- Focused command: `/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-relay-runtime-windows-system-ssh-openssh-full-size.test.ts
config/scripts/ssh-relay-runtime-workflow.test.mjs` passes 3 files plus one declared native live
skip, 115 passed tests plus one skip, in 4.24 seconds real; maximum RSS is 158,269,440 bytes and
peak footprint is 97,392,376 bytes. Independent YAML extraction plus PowerShell
`[scriptblock]::Create()` parses all three start/measure/stop blocks.
- Release-contract command: `/usr/bin/time -l pnpm exec vitest run --config
config/vitest.config.ts --maxWorkers=1 --reporter=dot
config/scripts/ssh-relay-runtime-*.test.mjs` passes 50 files and 283/283 cases in 21.65 seconds
real; maximum RSS is 195,526,656 bytes and peak footprint is 98,375,440 bytes.
- Static commands: `/usr/bin/time -l pnpm typecheck` passes in 6.75 seconds real with maximum RSS
1,826,357,248 bytes and peak footprint 98,015,040 bytes. `/usr/bin/time -l pnpm lint` passes in
22.61 seconds real with only the 26 pre-existing warnings, all 41 reliability gates, the
355-entry max-lines ratchet, bundled guides, and localization checks; maximum RSS is
2,036,318,208 bytes and peak footprint is 97,425,240 bytes.
- Isolation evidence: targeted `oxfmt --check` passes all ten changed code/workflow/plan files;
`git diff --check`, an independent no-index whitespace check for the new contract module, and
exact working-tree equality to `HEAD` for `ssh-remote-node-resolution.ts` and its test pass. Only
the artifact workflow, concrete workflow oracle split, no-input argv/probe implementation and
tests, and three planning artifacts are touched.
- Residual boundary: local macOS proof cannot execute native Windows `ssh.exe -n`, registry hive
unload, profile removal, service/auth, full-size transfer, cancellation, collision, or teardown.
Commit/push this isolated correction and require fresh exact-head x64/arm64 proof before closing
the live Windows gate. Legacy remains the sole production/default path; SignPath and product
caller/Beta/settings/fallback/tuple/publication work remain deferred.
## Accepted Gaps
No product gap is accepted merely because it appears in this list. Each entry requires explicit
@@ -1642,7 +1642,10 @@
<td>
Full-size runtime over SFTP and POSIX/Windows system SSH; tar/no-tar; no remote
hash tools; corrupted upload; bundled-Node corruption/failure; bounded memory
and concurrency; no-input system-SSH probe stdin/child settlement;
and concurrency; no-input system-SSH probe uses native OpenSSH <code>-n</code>
before the destination terminator and proves child settlement without disabling
connection reuse; fixture-owned Windows profile hives are boundedly unloaded
before native profile deletion;
<code>MaxSessions=1</code>; interrupted upload; stale lock
</td>
<td>
+5 -2
View File
@@ -949,6 +949,7 @@ describe('SshConnection', () => {
'echo ORCA-SYSTEM-SSH-OK',
{
wrapCommand: false,
noInput: true,
resolvedConfig: expect.objectContaining({ proxyUseFdpass: true })
}
)
@@ -1002,6 +1003,7 @@ describe('SshConnection', () => {
'echo ORCA-SYSTEM-SSH-OK',
expect.objectContaining({
wrapCommand: false,
noInput: true,
resolvedConfig: expect.objectContaining({ proxyUseFdpass: true })
})
)
@@ -1012,6 +1014,7 @@ describe('SshConnection', () => {
expect.objectContaining({
disableControlMaster: true,
wrapCommand: false,
noInput: true,
resolvedConfig: expect.objectContaining({ proxyUseFdpass: true })
})
)
@@ -1050,7 +1053,7 @@ describe('SshConnection', () => {
expect(spawnSystemSshCommandMock).toHaveBeenCalledWith(
expect.objectContaining({ proxyCommand: 'ssh -W %h:%p bastion.example.com' }),
'echo ORCA-SYSTEM-SSH-OK',
{ wrapCommand: false }
{ wrapCommand: false, noInput: true }
)
})
@@ -1071,7 +1074,7 @@ describe('SshConnection', () => {
expect(spawnSystemSshCommandMock).toHaveBeenCalledWith(
expect.objectContaining({ host: '192.168.0.210' }),
'echo ORCA-SYSTEM-SSH-OK',
{ wrapCommand: false }
{ wrapCommand: false, noInput: true }
)
})
+6 -2
View File
@@ -694,7 +694,8 @@ export class SshConnection {
// Why: this probe runs before remote platform detection. A raw echo works
// under POSIX shells, cmd.exe, and PowerShell; `/bin/sh` wrapping does not.
const channel = this.spawnTrackedSystemSshCommand('echo ORCA-SYSTEM-SSH-OK', {
wrapCommand: false
wrapCommand: false,
noInput: true
})
try {
await new Promise<void>((resolve, reject) => {
@@ -908,7 +909,10 @@ export class SshConnection {
return new Error('SSH connection attempt was cancelled')
}
private spawnTrackedSystemSshCommand(command: string, options?: SshExecOptions): ClientChannel {
private spawnTrackedSystemSshCommand(
command: string,
options?: SshExecOptions & Pick<SystemSshBuildArgsOptions, 'noInput'>
): ClientChannel {
if (options?.signal?.aborted) {
throw createSshOperationAbortError()
}
+17
View File
@@ -391,9 +391,26 @@ describe('spawnSystemSsh', () => {
expect(args).toContain('ServerAliveCountMax=3')
})
it('places no-input mode before the destination without disabling connection reuse', () => {
const args = buildSshArgs(createTarget(), {
noInput: true,
resolvedConfig: createResolvedConfig()
})
const noInputIdx = args.indexOf('-n')
const terminatorIdx = args.indexOf('--')
expect(noInputIdx).toBeGreaterThan(-1)
expect(noInputIdx).toBeLessThan(terminatorIdx)
expect(args).toContain('ControlMaster=auto')
expect(args).toContain('ControlPersist=300')
expect(args).not.toContain('-S')
})
it('spawns a remote command through the system ssh target', () => {
spawnSystemSshCommand(createTarget({ configHost: 'fdpass-host' }), 'echo hello')
const args = spawnMock.mock.calls[0][1] as string[]
expect(args).not.toContain('-n')
expect(spawnMock).toHaveBeenCalledWith(
SYSTEM_SSH_PATH,
expect.arrayContaining(['--', 'deploy@fdpass-host', "exec /bin/sh -c 'echo hello'"]),
+9
View File
@@ -5,6 +5,7 @@ export type SystemSshBuildArgsOptions = {
resolvedConfig?: SystemSshResolvedConfig | null
disableControlMaster?: boolean
suppressOrcaControlMaster?: boolean
noInput?: boolean
}
export function buildSshArgs(target: SshTarget, options?: SystemSshBuildArgsOptions): string[] {
@@ -13,6 +14,11 @@ export function buildSshArgs(target: SshTarget, options?: SystemSshBuildArgsOpti
args.push('-o', 'BatchMode=no')
// Forward stdin/stdout for relay communication
args.push('-T')
if (options?.noInput === true) {
// Why: closing a parent pipe does not reliably detach native Windows
// OpenSSH's input worker for commands that can never consume stdin.
args.push('-n')
}
// Why: ControlMaster multiplexes all SSH exec commands over a single connection,
// eliminating the ~9s handshake overhead per command. Without this, each
@@ -91,6 +97,9 @@ export function getSystemSshBuildArgsFromOperationOptions(
if (options?.suppressOrcaControlMaster === true) {
buildArgsOptions.suppressOrcaControlMaster = true
}
if (options?.noInput === true) {
buildArgsOptions.noInput = true
}
return Object.keys(buildArgsOptions).length === 0 ? undefined : buildArgsOptions
}