2.0 KiB
SFTP restart recovery must not guess another server
Audit baseline: 7b964ead21c1e176999557147914f4975a63f5c8.
Confirmed defect
resolveHostForTransferEndpoint used a display-name/hostname search when a
recorded host id no longer existed, and returned the first match when multiple
hosts shared a name. Dedicated resume used those credentials to open the target
and start uploading. A saved task for a deleted server could therefore send
its source file to an unrelated same-named server. Both endpoint directions and
folder recovery use this resolver.
Two regressions invoke resumeTransferWithDedicatedSession, with the real
resolver, scheduler, credential construction, and resume path but instrumented
bridge I/O. Before the fix, both selected an unrelated endpoint and called
startStreamTransfer: a deleted recorded id with one same-named replacement,
and a legacy task without an id with two same-named hosts. Both now stop before
opening or uploading.
Fix contract
- A recorded host id is authoritative; absence must not fall back to a name.
- Legacy tasks without an id may resolve a name only if exactly one host matches.
- Preserve exact-id recovery, unique-name legacy recovery, and a still-live original session when vault credentials are absent.
- Never select an arbitrary member of an ambiguous name match.
This does not freeze future edits to the connection options of an existing host id; a persisted immutable endpoint snapshot would be a separate schema and migration change. It also does not claim to explain all historical restart failures from issue #3213 or #2638.
Verification
node --test --import tsx application/state/sftp/dedicatedTransferResume.test.ts:
39 passed, including both regressions and existing single-file/folder restart,
remote-to-remote, source-validation, and live-session fallback tests.
Broader SFTP audit remains in progress in the sibling codex/sftp-transfer-audit
worktree; its first control-ordering fix is PR #3284.