Commit Graph

11 Commits

Author SHA1 Message Date
Vantz Stockwell
a75e21138e fix: RDP keyboard capture yields to form elements in modals and toolbars
Keyboard events now check if focus is on an input, textarea, select, or
contenteditable element and let the browser handle them normally. Also
fixes connectRdp type (Awaited<>) and async onMounted in RdpCanvas.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:49:30 -04:00
Vantz Stockwell
93811b59cb fix(security): auth hardening — httpOnly cookies, Argon2id passwords, TOTP encryption, rate limiting
C-2: JWT moved from localStorage to httpOnly cookie (eliminates XSS token theft)
C-3: WebSocket auth via short-lived single-use tickets (JWT no longer in URLs)
H-1: JWT expiry reduced from 7 days to 4 hours
H-3: TOTP secrets encrypted at rest with vault EncryptionService (auto-migrates plaintext)
H-6: Rate limiting via @nestjs/throttler (60 req/min global, tighten on auth)
H-8: Constant-time login — Argon2id verify runs against dummy hash for non-existent users
H-9: Password hashing upgraded from bcrypt(10) to Argon2id (auto-upgrades on login)
H-10: Credential list API no longer returns encrypted blobs
H-16: Admin pages use Nuxt route middleware instead of client-side guard
Plus: auth bootstrap plugin, cookie-parser middleware, all frontend Authorization headers removed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 14:24:35 -04:00
Vantz Stockwell
95271f065a fix(rdp): proper display scaling via Guacamole display.scale()
Remove CSS width/height !important override that broke Guacamole's
internal rendering pipeline. Replace with display.scale() auto-fitting
using ResizeObserver for responsive container sizing. Scale mouse
coordinates back to remote display space to keep input accurate.
Clean up diagnostic instruction logging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 12:20:21 -04:00
Vantz Stockwell
f9070c81f3 diag(rdp): expand instruction logging to find desktop frames
Log first 50 instructions, then every 200th, plus any draw operation
targeting layer 0 (main display). Need to determine if RDPGFX desktop
frames are arriving or if only cursor operations are being received.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 12:11:12 -04:00
Vantz Stockwell
6ddd343234 diag(rdp): add instruction + display dimension logging
Temporary diagnostics to debug blank screen after successful RDP connection.
Logs first 30 instruction opcodes and display dimensions on ready.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 12:04:25 -04:00
Vantz Stockwell
34bea52e0b fix(rdp): TCP stream buffering + error surfacing for guacd pipeline
Three bugs fixed:

1. TCP stream fragmentation — guacd→browser data pipe treated each TCP
   chunk as a complete instruction. TCP is a stream protocol; instructions
   WILL be split across chunks (especially display/image data). Added
   instruction buffer that accumulates data and only forwards complete
   instructions (terminated by ';').

2. Missing client.onerror — when guacd fails the RDP connection (NLA,
   auth, TLS), it sends a Guacamole error instruction. No handler was
   registered, so errors were silently swallowed. User saw blank canvas
   with no feedback. Now surfaces errors via console and gateway callback.

3. Missing client.onstatechange — no connection state tracking. Added
   state transition logging for diagnostics.

Also improved CONNECT handshake logging to surface connection parameters
(host, port, user, domain, security mode) without exposing passwords.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 06:17:32 -04:00
Vantz Stockwell
72526487c3 fix(rdp): replace class extends with direct instance method override on Guacamole.Tunnel 2026-03-14 04:51:03 -04:00
Vantz Stockwell
76db0a6936 fix(rdp): override Guacamole.Tunnel instance methods, fix sendMessage encoding 2026-03-14 04:39:44 -04:00
Vantz Stockwell
f124d4b7d2 fix(rdp): convert to manual ws.Server, fix URL path, fix double session 2026-03-14 02:40:37 -04:00
Vantz Stockwell
aa457b54d4 fix: infinite remount loop — use stable key for session components
When replaceSession changed the session ID from pending-XXX to a
real UUID, Vue's :key="session.id" treated it as a new element,
destroyed and recreated TerminalInstance, which called connectToHost
again, got another UUID, replaced again — infinite loop.

Added a stable `key` field to sessions that never changes after
creation, used as the Vue :key instead of the mutable `id`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 01:51:31 -04:00
Vantz Stockwell
e2e03be2dd feat: RDP frontend — Guacamole client with custom JSON WebSocket tunnel
- useRdp.ts: JsonWsTunnel class extends Guacamole.Tunnel to bridge
  guacamole-common-js (expects raw protocol) with our JSON gateway
  (consistent with SSH/SFTP message envelope pattern). Parses
  length-prefixed Guacamole instructions, dispatches to Guacamole.Client.
  Handles mouse/keyboard input, clipboard send, and session lifecycle.
- RdpCanvas.vue: full-size container that mounts the Guacamole display
  canvas. Calls useRdp().connectRdp() on mount, cleans up on unmount.
  Exposes sendClipboard() and disconnect() for toolbar integration.
- RdpToolbar.vue: auto-hiding floating toolbar (3s idle timeout) with
  clipboard paste dialog, fullscreen toggle (HTML5 Fullscreen API),
  settings panel stub, and disconnect button.
- SessionContainer.vue: renders RdpCanvas + RdpToolbar when
  session.protocol === 'rdp', replacing the Phase 3 placeholder.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 17:27:19 -04:00