Skip to content

Draft: desktop SSH tmux selection, identity recovery and transport retry - #1

Draft
Mafei wants to merge 13 commits into
masterfrom
feature/ssh-tmux-recovery
Draft

Mafei wants to merge 13 commits into
masterfrom
feature/ssh-tmux-recovery

Conversation

@Mafei

@Mafei Mafei commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

Adds authenticated tmux discovery and selection per SSH tab, atomic explicit creation, saved identity restoration, duplicate-tab reservation, shared/read-only/explicit takeover, bounded exec and cancellable transport retry. Existing host-key and authentication flows are retained; restored tmux channels bypass login scripts and cwd injection.

Cancelling an unanswered keyboard-interactive prompt previously left the old connection flight waiting. Destruction now rejects embedded prompts, clears tab state and releases the native client handle. Shell and exec acquisition/startup have cancellation/deadline boundaries with late-channel cleanup. Jump transport loss explicitly reaches dependent targets, including targets still authenticating.

Jump direct-tcpip acquisition now registers target cancellation before jump lookup/authentication and has a 10-second deadline. Rejection, timeout and target startup failure release references/subscriptions and discard unconsumed forwards. The installed russh native client holds its client mutex during channel-open waits; an abandoned request temporarily excludes that transport from new acquisitions. Reconnect authenticates a fresh transport while existing tabs keep their old shell. Late native forwards are closed without starting an old-generation target handshake.

The macOS artifact build previously edited Electron fuses/bundles and skipped final signing, producing invalid signatures on Apple Silicon. Artifact-only packaging now ad-hoc signs native sources before ASAR creation, completes all directory/fuse edits, then signs frameworks, helpers and the main app from inside out. DMG/ZIP are created from that prepackaged signed directory. Bundle executables are verified in their original Info.plist/resource context. Existing safety fuses remain unchanged (000000011); hardened runtime remains enabled. The old macOS artifact at b71e08025a6e522c69a4ec292535f8acf93a46fd is superseded and has confirmed invalid signatures.

Validation for head fb869900e1ac6da0ff577a53ab7084778d6389bc: CI run 37585234706 completed success, all four jobs succeeded. SSH/tmux 29 pass, SSH integration 31 pass, unit 11 pass, signing discovery/order 2 pass — 73 total, 0 fail, 0 skip. build:typings, lint and complete build passed. Windows x64 and Linux x64 package jobs succeeded; Windows UAC/VC runtime preparation and portable ZIP augmentation passed.

macOS ARM validation logs: both actual DMG/ZIP apps passed archive integrity, ASAR native byte integrity, arm64 loader-path checks, unchanged fuse checks and codesign --verify --deep --strict --all-architectures. All 48 on-disk native/bundle components have valid ad-hoc signatures, including the app, all four Helpers, Electron/Mantle/ReactiveObjC/Squirrel frameworks, native addons and spawn helpers. The two archives contain identical verified binary/signature records. A deliberately changed fuse in a disposable extracted copy was rejected, then the exact original bytes were restored and validated again.

Both delivered archive apps also passed actual startup smoke tests on the standard macos-15 ARM runner: isolated temporary profiles, Angular renderer bootstrap without safe-mode fallback, seven native modules loaded (russh, node-pty, keytar, fontmanager-redux, native-process-working-directory, macos-native-processlist, serialport bindings), and a disposable PTY printed TABBY_CI_PTY_READY. No stored passwords or SSH credentials were accessed. Screenshots and startup logs are included. These are startup/native-loading checks, not full desktop/SSH GUI interaction coverage.

Gatekeeper trust remains separate: spctl --assess --type execute returned rejected, exit 3 for both archive apps on the runner. This artifact has valid ad-hoc integrity signatures, no Developer ID signing identity and no Apple notarization; it is not claimed to pass the user's normal downloaded-app security assessment. No user Mac security setting or quarantine metadata was changed, and no user Mac startup test was performed for this repair.

Integration tests load the actual SSHSession, SSHShellSession, SSHTabComponent, connectable lifecycle and terminal middleware. Loopback-only SSH2 fixtures exercise the real russh client and Python PTYs with real tmux. Covered: unanswered KI cancel→reconnect, stale responses/generations, every acquisition stage's cancellation/rejection/timeout, shared jump TCP loss, pending native direct-tcpip cancellation while another real tab remains open, reference balance/late cleanup, authentication-stage jump loss, shared/read-only/takeover, identity recovery/rename, occupied automatic restore pause, escaped Unicode/quoted names, atomic duplicate creation and same-name replacement without implicit recreation.

Version 1.0.239-nightly.0, all artifacts from the head above:

Platform Contents Download
macOS ARM64, ad-hoc tabby-1.0.239-nightly.0-macos-arm64.dmg, tabby-1.0.239-nightly.0-macos-arm64.zip, macos-arm64-verification.json, two startup screenshots and two logs tabby-macos-arm64-adhoc
Windows x64, unsigned installer EXE, portable ZIP with VC runtime tabby-windows-x64-unsigned
Linux x64, unsigned tar.gz tabby-linux-x64-unsigned

Artifact metadata head, byte sizes and SHA-256 digests match successful upload logs. The JSON report additionally records individual DMG/ZIP and binary hashes, signature status, source SHA, unchanged fuses, startup results and separate Gatekeeper assessments.

Artifact Bytes SHA-256 Expires
tabby-linux-x64-unsigned 158964521 960a1926a3a4ead8d5cb3669d68510769c68342372df4a69741b6b7e38ca308c 2026-10-21 07:16:07 UTC
tabby-windows-x64-unsigned 355465204 145068a5b274d5f52c23afa7b6ae46bcf8ba6801e31a181fd68e838f72867ed1 2026-10-21 07:21:46 UTC
tabby-macos-arm64-adhoc 318005247 037c354ead5d0d2d1a9a5abfe680c2d1fa25603589a5f66c97c7e6c0acde6b9c 2026-10-21 07:18:58 UTC

Remains draft. Workflow permissions remain contents:read, release/signing credentials empty, publish:never and strict upstream repository guards. No Developer ID/notarization credentials, account, secret, permission expansion, merge, release or deployment. Production OpenSSH/PAM/private-key/agent/X11 and full desktop interactions remain outside coverage. PID/start-time identity cannot survive server replacement across reboot or provide hard fencing; takeover does not permanently revoke an old client.

Design and validation boundaries: docs/design/ssh-tmux-recovery.md.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant