diff --git a/.github/workflows/ssh-relay-runtime-artifacts.yml b/.github/workflows/ssh-relay-runtime-artifacts.yml index 6287cd1da6c..4e4aecb241a 100644 --- a/.github/workflows/ssh-relay-runtime-artifacts.yml +++ b/.github/workflows/ssh-relay-runtime-artifacts.yml @@ -573,6 +573,10 @@ jobs: cp "$fixture/client-key.pub" "$HOME/.ssh/authorized_keys" chmod 600 "$HOME/.ssh/authorized_keys" "$fixture/client-key" "$fixture/host-key" sudo chown root:root "$fixture/host-key" + # Why: hosted runner accounts are shadow-locked, which sshd rejects before public-key auth. + random_password=$(openssl rand -hex 32) + sudo usermod --password "$(openssl passwd -6 "$random_password")" "$USER" + unset random_password port=22222 server_version=$(/usr/sbin/sshd -V 2>&1 | head -1) config="$fixture/sshd_config" @@ -599,7 +603,7 @@ jobs: break fi if test "$attempt" = 20; then - cat "$fixture/sshd.log" + sudo tail -200 "$fixture/sshd.log" exit 1 fi sleep 0.25 diff --git a/config/scripts/ssh-relay-runtime-workflow.test.mjs b/config/scripts/ssh-relay-runtime-workflow.test.mjs index 97bf9a9a7aa..427b5e93b42 100644 --- a/config/scripts/ssh-relay-runtime-workflow.test.mjs +++ b/config/scripts/ssh-relay-runtime-workflow.test.mjs @@ -95,6 +95,8 @@ describe('SSH relay runtime artifact workflow', () => { expect(start.if).toBe("runner.os == 'Linux'") expect(start.run).toContain('ListenAddress 127.0.0.1') expect(start.run).toContain('Subsystem sftp internal-sftp') + expect(start.run).toContain('sudo usermod --password') + expect(start.run).toContain('PasswordAuthentication no') expect(start.run).toContain('timeout --signal=TERM --kill-after=15s 180s sudo apt-get') expect(measure.if).toBe("runner.os == 'Linux'") expect(measure.run).toContain('ssh-relay-runtime-sftp-openssh-full-size.test.ts') diff --git a/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist-summary.md b/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist-summary.md index 1f38d7ffc10..f8475922b92 100644 --- a/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist-summary.md +++ b/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist-summary.md @@ -10,7 +10,12 @@ A checked box means the work has evidence in the detailed ledger. Design approva complete a box. Active checkpoint: **Milestone 6 / Work Package 5 bounded runtime transfer — disconnected live -OpenSSH SFTP composition is in progress, 2026-07-15, Codex implementation owner.** +OpenSSH SFTP runner fixture auth correction is in progress, 2026-07-15, Codex implementation owner.** +`E-M6-SFTP-LIVE-COMPOSITION-CI-RED-001` records both target-native Linux jobs passing build, +contracts, and existing full-size measurement before stock sshd rejected GitHub's shadow-locked +`runner` account ahead of public-key validation. No SFTP bytes were sent and no live cell is credited. +The narrow rerun keeps password authentication disabled and gives only the ephemeral account a fresh +random password hash so public-key authentication can proceed. `E-M6-SFTP-LIVE-COMPOSITION-AUDIT-001` limits this package to one authenticated built-in `SshConnection`, one raw SFTP channel, the existing one-to-four file transfer, captured-transport- only force close with awaited teardown, and exact full-size Linux x64/arm64 runtime transfer against diff --git a/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist.md b/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist.md index 8df452fb05e..0228bafd963 100644 --- a/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist.md +++ b/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist.md @@ -9,7 +9,7 @@ work; keep exact commands, runner identities, hashes, metrics, and residual gaps Date created: 2026-07-14
Last updated: 2026-07-15
Current phase: Milestone 6 / Work Package 5 bounded runtime transfer — **In progress — 2026-07-15, Codex implementation owner: disconnected authenticated-connection/SFTP-tree composition and live OpenSSH proof**. 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.
-Session checkpoint: **LIVE SFTP COMPOSITION LOCALLY GREEN / EXACT-HEAD RUNNER PROOF NEXT — 2026-07-15, Codex implementation owner** — `E-M6-SFTP-LIVE-COMPOSITION-LOCAL-001` proves the disconnected authenticated-connection owner, captured-client force close, cancellation cleanup/breaker ordering, workflow oracle, focused/broad/release suites, typecheck, full lint, formatting, max-lines, diff, protected-resolver, and no-product-import gates locally. The purpose suite is 15/15; the live full-size suite is deliberately skipped locally because no runner OpenSSH/runtime inputs are present and therefore earns no live cell. Push this isolated package and require exact-head Linux x64/arm64 stock-OpenSSH full-size metrics before crediting live SFTP. Do not credit Windows/POSIX system SSH, high-RTT, `MaxSessions=1`, product/settings/fallback wiring, tuple enablement, publication, or default behavior. Merging to `main` remains prohibited, SignPath is deferred, and legacy remains the production default.
+Session checkpoint: **LIVE SFTP RUNNER FIXTURE RED / NARROW AUTH-FIX IN PROGRESS — 2026-07-15, Codex implementation owner** — `E-M6-SFTP-LIVE-COMPOSITION-CI-RED-001` proves both target-native Linux builds and all pre-live contracts passed, then the loopback stock-OpenSSH fixture rejected GitHub's shadow-locked `runner` account before public-key validation. No SFTP bytes were sent and no live cell is credited. Keep password authentication disabled; assign only a fresh random ephemeral password hash so stock sshd accepts the runner account for public-key authentication, fix failure-log readability, rerun exact head, and require full metrics. Do not credit Windows/POSIX system SSH, high-RTT, `MaxSessions=1`, product/settings/fallback wiring, tuple enablement, publication, or default behavior. Merging to `main` remains prohibited, SignPath is deferred, and legacy remains the production default.
Primary design: [SSH relay GitHub Release plan](./2026-07-14-ssh-relay-github-release-plan.html)
Motivating issues: [#8450](https://github.com/stablyai/orca/issues/8450), [#1693](https://github.com/stablyai/orca/issues/1693) @@ -17323,6 +17323,32 @@ src/main/ssh/ssh-relay-runtime-sftp-tree-transfer.test.ts` — PASS, 15/15 in 1. settings/fallback wiring, tuple enablement, publication, or default behavior is proved. Legacy remains the sole production/default path and SignPath remains deferred. +### E-M6-SFTP-LIVE-COMPOSITION-CI-RED-001 — stock sshd rejects the hosted runner's locked account + +- Date/owner/head/run: 2026-07-15, Codex implementation owner; exact implementation commit + `32f78d720febdb5581282cfbc64b6aae374930f4`, SSH Relay Runtime Artifacts run + [29513130758](https://github.com/stablyai/orca/actions/runs/29513130758). +- Passing boundary before RED: Linux x64 job + [87671358587](https://github.com/stablyai/orca/actions/runs/29513130758/job/87671358587) and Linux + arm64 job [87671358592](https://github.com/stablyai/orca/actions/runs/29513130758/job/87671358592) + both pass checkout, exact Node 24.18.0 setup, native identity, prerequisites, the complete runtime + contract suite including all five new connection-owner cases, exact Node input download, target- + native build/reproducibility/read-back/smoke, and full-size extraction/cache/scan/stream measurement. +- Expected evidence failure: both jobs then fail `Start loopback OpenSSH SFTP fixture`; the live + transfer step is skipped and sends zero SFTP bytes. The server binds only `127.0.0.1:22222`, but + every key-auth probe is rejected with `User runner not allowed because account is locked` before + public-key validation. The arm64 cleanup log confirms stock sshd accepted the config/listener and + rejected only the shadow account state. The x64 runner is Ubuntu 24.04.4 image + `20260714.240.1`, X64, kernel `6.17.0-1020-azure`; arm64 is the target-native hosted counterpart. +- Narrow correction: retain `PasswordAuthentication no`, `KbdInteractiveAuthentication no`, + loopback-only listen, one ephemeral Ed25519 client key, and strict modes. Generate a fresh random + 32-byte password, store only its SHA-512 shadow hash on the ephemeral runner account, immediately + unset the plaintext shell variable, and continue to authenticate only with the generated public + key. Also read root-owned sshd logs through `sudo` on failure. This changes only CI fixture account + eligibility; no product authentication, connection, transfer, or fallback code changes. +- Residual: no live SFTP transfer/filesystem/mode/RSS/cancellation evidence is credited from this + run. Exact-head Linux x64/arm64 rerun plus all-six/adjacent regression proof remains mandatory. + ## Accepted Gaps No product gap is accepted merely because it appears in this list. Each entry requires explicit