Commit Graph

30 Commits

Author SHA1 Message Date
Vantz Stockwell
512347af5f feat: Local PTY Copilot Panel — replace Gemini stub with real terminal
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 3m6s
Ripped out the Gemini API stub (ai/mod.rs, ai_commands.rs, GeminiPanel.vue)
and replaced it with a local PTY terminal in the sidebar panel. Users select
a shell (bash/zsh/sh on Unix, PowerShell/CMD/Git Bash on Windows), launch it,
and run claude/gemini/codex or any CLI tool directly.

Backend:
- New PtyService module using portable-pty (cross-platform PTY)
- DashMap session registry (same pattern as SshService)
- spawn_blocking output loop (portable-pty reader is synchronous)
- 5 Tauri commands: list_available_shells, spawn_local_shell, pty_write,
  pty_resize, disconnect_pty

Frontend:
- Parameterized useTerminal composable: backend='ssh'|'pty'
- convertEol=false for PTY (PTY driver handles LF→CRLF)
- CopilotPanel.vue with shell selector, launch/kill, session ended prompt
- Ctrl+Shift+G toggle preserved

Tests: 87 total (5 new PTY tests), zero warnings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:43:18 -04:00
Vantz Stockwell
eda36c937b fix: pure Rust EC key decryption — no openssl dependency
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 3m3s
Replaced the openssl CLI fallback with pure Rust crypto for EC private
keys in SEC1 format (-----BEGIN EC PRIVATE KEY-----). Handles PKCS#5
encrypted keys (AES-128-CBC + MD5 EVP_BytesToKey KDF) and converts to
PKCS#8 PEM that russh can parse natively.

All crypto crates (md5, aes, cbc, sec1, pkcs8) were already in the dep
tree via russh — just promoted to direct dependencies. Zero new binary
dependencies, works on Windows without openssl installed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:08:55 -04:00
Vantz Stockwell
74b9be3046 fix: remove desktop shortcut from NSIS installer by default
Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Has been cancelled
Tauri's NSIS bundler creates a desktop shortcut unconditionally. Added
a POSTINSTALL hook that deletes it immediately after creation. Start
menu shortcut remains. Users who want a desktop shortcut can create
one manually.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:04:06 -04:00
Vantz Stockwell
4a0c2c9790 fix: SSH key auth — handle EC/DSA keys via openssl pkey fallback
Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Has been cancelled
russh only parses 4 PEM headers: OPENSSH, RSA, PKCS8, ENCRYPTED PKCS8.
EC keys (-----BEGIN EC PRIVATE KEY-----) with PKCS5 encryption silently
failed with "Could not read key".

Fix adds two fallbacks:
1. If russh can't parse the key, convert to PKCS8 via `openssl pkey`
   which handles EC, DSA, and all other OpenSSL-supported formats
2. If the input doesn't start with -----BEGIN, try reading it as a
   file path (supports ~ expansion) for keys stored on disk

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:18:01 -04:00
Vantz Stockwell
633087633e test: full test coverage — 82 tests across all modules, zero warnings
Added tests for 3 uncovered modules:
- db: open, migrate, idempotent migration, FK/WAL pragmas, clone shares conn
- theme: seed_builtins (7 themes), idempotent seed, get_by_name, hex color
  validation, sort ordering, case sensitivity
- rdp/input: scancode lookup, extended key detection, value extraction,
  mouse flag composition, map coverage assertion

Existing test count: 52 (vault, connections, credentials, settings, host_keys)
New tests added: 30
Total: 82 tests, all passing, zero compiler warnings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:33:36 -04:00
Vantz Stockwell
8c431d3d12 fix: SSH input deadlock — output loop held channel mutex across await
Root cause: The output reader loop held Arc<TokioMutex<Channel>> while
calling ch.wait().await. After the initial prompt rendered and the server
went idle, wait() blocked indefinitely holding the lock. ssh_write()
could never acquire the mutex to send keystrokes. Permanent deadlock.

Fix: Separated read/write paths. The output loop now owns the Channel
exclusively via tokio::select!, receiving resize/shutdown commands through
an mpsc channel. Writes go through Handle::data(channel_id, data) which
bypasses the Channel entirely — no shared mutex, no deadlock.

Also killed all compiler warnings (unused imports in rdp module).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:28:09 -04:00
Vantz Stockwell
99ecbe739e feat: RDP clipboard paste, keyboard grab default ON, frame dirty flag
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 2m49s
1. Clipboard paste (rdp_send_clipboard): simulates typing each character
   via scancode key press/release events. Full ASCII coverage including
   all symbols, numbers, and shifted characters. Handles 32-char
   generated passwords without manual typing.

2. Keyboard grab defaults to ON so RDP sessions accept keyboard input
   immediately without requiring the user to click the toolbar toggle.

3. Frame dirty flag: GraphicsUpdate sets an AtomicBool, get_frame only
   encodes + returns base64 when dirty (returns empty string otherwise).
   Eliminates ~8MB/frame base64 encoding on unchanged frames at 30fps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:57:16 -04:00
Vantz Stockwell
ffe79e9a54 fix: add Tauri v2 capabilities — unblock event:listen for SSH terminal
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 2m50s
The app had no capabilities file, so Tauri v2's ACL blocked all
frontend listen() calls. SSH connections succeeded on the Rust side
but the terminal never received data events, appearing as "nothing
happened." Grants core:default, core:event:default, core🪟default,
and shell:allow-open.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:00:54 -04:00
Vantz Stockwell
6e33bbdcf1 fix: serialize tags as array (not JSON string), DevTools debug-only
- ConnectionRecord.tags changed from String to Vec<String> so the
  frontend receives a proper array instead of a raw JSON string.
  The old behavior caused v-for to iterate characters, corrupting
  the connection display in the sidebar.
- DevTools now only auto-opens in debug builds (cfg(debug_assertions)),
  not in production.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:58:58 -04:00
Vantz Stockwell
e28d0f65cd feat: integrate Gemini AI XO copilot + backend cleanup + connection timeouts
Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Failing after 9s
Backend cleanup (Gemini):
- Strip verbose doc comments across SSH, RDP, and command modules
- Add 10s timeout on SSH connect/auth, 15s on RDP connection
- Fix macOS data directory to ~/Library/Application Support/Wraith
- Add generic disconnect_session command
- Simplify SFTP setup and error handling
- Inline AppState field construction

Gemini AI XO integration:
- Add GeminiService (src-tauri/src/ai/) with API Key, Service Account,
  and Google Account (OAuth2) authentication methods
- Add ai_commands (set_gemini_auth, gemini_chat, is_gemini_authenticated)
- Add GeminiPanel.vue — collapsible chat sidebar with multi-auth UI
- Wire Ctrl+Shift+G toggle and status bar AI button in MainLayout
- Add reqwest + anyhow dependencies

Bugfix:
- Fix dropped modulo operator in Ctrl+Tab/Ctrl+Shift+Tab handlers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:38:52 -04:00
Vantz Stockwell
8e335f92b5 refactor: clean up backend — strip verbose docs, add connection timeouts, fix macOS data dir
- Remove redundant doc comments and section headers across SSH, RDP, and command modules
- Add 10s timeout on SSH connect/auth, 15s timeout on RDP connection
- Fix macOS data directory to use ~/Library/Application Support/Wraith
- Add generic disconnect_session command alongside disconnect_ssh
- Simplify SFTP setup and RDP error handling
- Add explicit label/url to main window config

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:30:02 -04:00
Vantz Stockwell
429f41d853 fix: auto-patch tauri.conf.json version from git tag in CI
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 2m48s
Never manually sync version again. CI reads the tag, patches
the config before building. Also bumped to 1.1.5.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 03:37:30 -04:00
Vantz Stockwell
0cdc865483 debug: enable DevTools in release builds
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 2m44s
Added devtools Cargo feature, auto-open DevTools on startup
so we can see frontend console errors on Windows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 03:23:59 -04:00
Vantz Stockwell
6c7b277494 fix: SSH auth — decrypt credentials from vault before connecting
Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Failing after 6s
Added decrypt_password and decrypt_ssh_key Tauri commands.
Connect flow now resolves credentialId → decrypted credentials
from the vault. Falls back to window.prompt on auth failure.
Fixed case-sensitive error string matching.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 03:04:47 -04:00
Vantz Stockwell
9cf64f99c7 fix: remove updater plugin — missing pubkey crashes on startup
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 2m41s
Will re-enable after generating Tauri signing keypair.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:40:55 -04:00
Vantz Stockwell
8602f1779b debug: add file-based startup log to diagnose silent crash
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 2m47s
Writes to %APPDATA%\Wraith\wraith-startup.log since release
builds suppress all console output via windows_subsystem.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:35:08 -04:00
Vantz Stockwell
db1bd39030 fix: bump version in tauri.conf.json to 1.1.0
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 2m49s
Tauri uses this for the installer filename, not the git tag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:29:02 -04:00
Vantz Stockwell
4eb304222d fix: use Tauri bundler for NSIS — runner now under ActRunner account
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 5m30s
Re-enable Tauri NSIS bundler (embeds frontend in exe). Runner
runs as ActRunner service account with proper user profile,
so Tauri's downloaded NSIS/tools should work. Removed manual
NSIS step and template file from workflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:17:28 -04:00
Vantz Stockwell
15ee82ef53 fix: move NSIS script to template file — avoid YAML !include parse error
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 2m43s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:01:42 -04:00
Vantz Stockwell
5910e7a849 fix: skip Tauri bundler, build NSIS installer manually
Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Failing after 2m34s
Tauri's bundled makensis can't run under SYSTEM account.
Use --no-bundle, then build installer with system NSIS
directly — same pattern as the old Go pipeline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:47:16 -04:00
Vantz Stockwell
84a2fc8618 fix: bundle target NSIS only — skip WiX/MSI
Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Failing after 2m34s
WiX candle.exe fails under SYSTEM account. NSIS is all we need.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:18:53 -04:00
Vantz Stockwell
08ebf35c66 fix: NSIS installMode perMachine — install to Program Files
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 1m39s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:43:01 -04:00
Vantz Stockwell
47fb066f1d docs: Phase 7 complete — CLAUDE.md + Go migration checklist
Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Has been cancelled
CLAUDE.md for future XOs: tech stack, architecture, commands,
key design decisions, lineage from Go version.

GO_MIGRATION.md: step-by-step checklist for deploying v2,
archiving Go repo, configuring CI secrets, first release.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:48:36 -04:00
Vantz Stockwell
bb5b9469d1 feat: Phase 6 complete — CI/CD pipeline + auto-updater
Gitea Actions workflow: Tauri build on Windows, Azure Key Vault
EV code signing via jsign, NSIS installer, Gitea package upload,
release creation with v-prefixed tag. Tauri updater plugin wired
with Gitea releases endpoint. Shell plugin configured for open().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:39:42 -04:00
Vantz Stockwell
0cd4cc0f64 feat: Phase 5 complete — themes, editor, shortcuts, workspace, settings
Theme service: 7 built-in themes seeded from Rust, ThemePicker
loads from backend. Workspace service: save/load snapshots, crash
recovery detection. SettingsModal: full port with Tauri invoke.
CommandPalette, HostKeyDialog, ConnectionEditDialog all ported.

CodeMirror editor: inline above terminal, reads/writes via SFTP.
Full keyboard shortcuts: Ctrl+K/W/Tab/Shift+Tab/1-9/B/F.
Terminal search bar via Ctrl+F (SearchAddon).
Tab badges: protocol dots, ROOT warning, environment pills.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:36:06 -04:00
Vantz Stockwell
c75da74ecd feat: Phase 4 complete — RDP via ironrdp
Rust RDP service: ironrdp client with full connection handshake
(TCP -> TLS -> CredSSP -> NLA), pixel buffer frame delivery,
mouse/keyboard input via scancode mapping, graceful disconnect.
Runs in dedicated thread with own tokio runtime to avoid Send
lifetime issues with ironrdp trait objects.

Vue frontend: RdpView canvas renderer with 30fps polling,
mouse/keyboard capture, RdpToolbar with Ctrl+Alt+Del and
clipboard. SessionContainer handles both SSH and RDP tabs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:05:11 -04:00
Vantz Stockwell
a8656b0812 feat: Phase 3 complete — SFTP sidebar with full file operations
Rust SFTP service: russh-sftp client on same SSH connection,
DashMap storage, list/read/write/mkdir/delete/rename/stat ops.
5MB file size guard. Non-fatal SFTP failure (terminal still works).

Vue frontend: FileTree with all toolbar buttons wired (upload,
download, delete, mkdir, refresh), TransferProgress panel,
useSftp composable with CWD following via Tauri events.
MainLayout wired with SFTP sidebar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 15:46:35 -04:00
Vantz Stockwell
737491d3f0 feat: Phase 2 complete — SSH terminal + frontend UI
Rust SSH service: russh async client, DashMap session registry,
TOFU host key verification, CWD tracking via separate exec channel
(never touches terminal stream), base64 event emission for terminal
I/O. 52/52 tests passing.

Vue 3 frontend: ported from Wails v3 to Tauri v2 — useTerminal
composable with streaming TextDecoder + rAF batching, session store
with multi-connection support, connection store/tree, sidebar, tab
bar, status bar, keyboard shortcuts. All Wails imports replaced
with Tauri API equivalents.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 15:28:18 -04:00
Vantz Stockwell
0802ae0753 chore: add .gitignore, remove node_modules and target from tracking 2026-03-17 15:10:00 -04:00
Vantz Stockwell
2848d79915 feat: Phase 1 complete — Tauri v2 foundation
Rust backend: SQLite (WAL mode, 8 tables), vault encryption
(Argon2id + AES-256-GCM), settings/connections/credentials
services, 19 Tauri command wrappers. 46/46 tests passing.

Vue 3 frontend: unlock/create vault flow, Pinia app store,
Tailwind CSS v4 dark theme with Wraith branding.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 15:09:41 -04:00