Skip to content

Clavyn v0.1.2-alpha.6

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 16 Sep 05:36

What's Changed

This alpha is a performance and hardening release. Terminals now render on the GPU, the app boots in 3 IPC round-trips instead of 12, terminal output travels as coalesced binary batches instead of one JSON event per packet, and the vault file authenticates its own header. It also closes a remote process-crash vector in the SSH stack and a webview route to downgrade-installed updates.

Highlights

  • GPU-accelerated terminal rendering. Panes render through the xterm WebGL addon — a render-bound stream measured 5.9x faster per frame (4.5 ms → 0.73 ms at 120x40), up to 10.7 MiB/s. A least-recently-used budget of eight panes keeps the app under the browser's 16-context WebGL cap; evicted panes and lost contexts fall back to the DOM renderer with the transcript intact. The addon loads on demand in its own chunk. (#63)
  • Startup boots in 3 IPC round-trips instead of 12. The independent boot queries run in parallel and the update check no longer blocks first paint — it fires in the background and still opens the modal when a release is found. Host/group loads are de-duplicated and versioned, so an in-flight read can no longer overwrite a newer change. (#55)
  • Terminal output is coalesced off the JSON event path. Output batches at 64 KiB or a 6 ms window and travels as binary over a per-session channel. Bulk output drops from 128 to 16 IPC messages per MiB; a byte-at-a-time writer drops from 19,519 messages to 30; a 32 KiB chunk no longer becomes ~114 KiB of evaluated JavaScript. Keystroke echo still goes out immediately. (#49)
  • Changed host keys are reported with both fingerprints instead of a bare "Unknown server key". The presented key is held under Known Hosts pending fingerprint confirmation; removing a host tombstones its entry so it cannot silently fall back to trust-on-first-use; "Forget permanently" and key replacement confirm through a native OS dialog showing the real stored fingerprint. (#38)
  • The vault file authenticates its own header. Key metadata, salt, version and epoch are bound to the ciphertext as AES-GCM associated data, so a tampered vault.json (e.g. a swapped-in public key under your label) fails the tag check. Decrypted payload memory is zeroized, and legacy vault migration rebuilds metadata from the private keys rather than trusting the old header. (#49)
  • russh is built without zlib, closing an unbounded decompression loop a hostile server could drive into a panic that took the whole process down. Clavyn never negotiates compression, so nothing is lost. (#29)
  • SSH connects no longer freeze the vault. Connects held the vault mutex across the network exchange — one silent host blocked unlock, reset and every key operation until restart. The lock is now held only for key auth, connects are time-bounded with keepalives, and the Argon2id KDF runs on a blocking thread with the master key cached per session. (#52)

Fixed

  • A live session id can no longer be hijacked by a second terminal; concurrent local terminals are capped and the slot is reserved before the blocking PTY spawn. (#31, #49)
  • A session's final output is never lost to the close notification — cat bigfile; exit previously dropped the last batch. A detached PTY reader can no longer emit stale output into a reused session id. (#49)
  • A second instance can no longer clobber shared app data (it focuses the running window), and workspace layouts are validated on write so a corrupt split ratio can't brick startup. (#40)
  • Key import no longer leaves private key material in the dialog after Cancel, a failed import, or a vault auto-lock; a failed import keeps your label and Import tab. (#58)
  • Out-of-range terminal dimensions are rejected instead of wrapping to a zero-column PTY or going out on the wire over SSH. (#49, #61)
  • The frontend entry chunk is 25% smaller — navigable views and the search addon load on first render, tailwind-merge is dropped, and the build targets es2022 with Vue production flags. (#37)
  • The update check runs once per launch instead of twice. (#66)

Security hardening

  • Vault reset now tears down live SSH sessions, SFTP channels and local PTYs under the same destructive boundary it describes. (#58)
  • Disabling biometric unlock now requires an unlocked vault; the webview's unused updater/process capability — which permitted downgrades and an unconditional app-kill — is removed. (#33)
  • The webview CSP now declares every directive that does not inherit from default-src, drops the unused GitHub connect-src origins, and scopes shell open to the two URLs the UI uses. (#47)
  • Windows state files get an explicit owner-only DACL instead of inheriting the profile's, and the temp file is CREATE_NEW so a planted file can't be written through and renamed into place. (#46)
  • The release pipeline is hardened: CI actions pinned to commit SHAs, npm ci without install scripts, per-job release permissions, fork PRs kept off self-hosted runners, and semver-validated dispatch inputs. (#42)
  • Two unregistered SFTP commands — an unbounded remote read and an unconstrained remote write — are deleted. (#61)

Dependencies

  • Rust: russh-sftp 3.0, russh-keys 0.49.2, russh-cryptovec 0.62, argon2 0.6, rand 0.10, base64 0.23, uuid. (#80, #82, #83, #84, #85, #88, #89)
  • Frontend: Vite 8, TypeScript 7, @xterm/addon-fit 0.11, @xterm/addon-webgl 0.19; Playwright 1.63 for e2e. (#75, #78, #79, #90)
  • CI: actions/checkout 7, actions/setup-node 7, actions/upload-artifact 7, tauri-action 1.0. (#72, #73, #74, #76)

See CHANGELOG.md for the full history.

Full Changelog: v0.1.2-alpha.5...v0.1.2-alpha.6