Commit Graph

27 Commits

Author SHA1 Message Date
Vantz Stockwell
6262ab6e7e debug: verify ssh2 key parsing and log derived public key
Uses ssh2 utils.parseKey() to check if the key decrypts and
parses correctly, logs the key type and public key fingerprint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 01:13:51 -04:00
Vantz Stockwell
36c8527c28 debug: add SSH auth diagnostic logging
Logs key format, length, auth method selection, and ssh2 debug
output for auth/key events to diagnose why key auth is rejected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 01:08:54 -04:00
Vantz Stockwell
11e1705110 fix: detect orphaned SSH key references and missing auth methods
When a credential's sshKeyId points to a deleted/missing SSH key row,
the connection attempt silently had zero auth methods. Now throws a
clear error explaining the SSH key is missing. Also catches the case
where a credential has neither password nor SSH key configured.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 01:04:41 -04:00
Vantz Stockwell
639ac329a8 fix: TDZ crash on SSH connect failure — sessionId referenced before assignment
When SSH timed out, the onClose callback referenced `const sessionId`
before connect() resolved, causing a Temporal Dead Zone ReferenceError
that killed the process. Changed to `let` with try/catch so connection
failures send an error message to the client instead of crashing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 00:50:35 -04:00
Vantz Stockwell
8d95fc5652 fix: add crash handlers to catch process-killing exceptions
Process-level uncaughtException/unhandledRejection handlers plus
try/catch around upgrade and connection handlers. This will log
whatever is crashing the server on browser WebSocket connections
before the process dies, instead of silently restarting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 00:36:44 -04:00
Vantz Stockwell
8207b78b36 fix: hijack upgrade event before WsAdapter can consume the socket
WsAdapter registered its upgrade handler first and destroyed sockets
for non-matching paths. Now we remove all existing upgrade listeners,
install ours first, and forward non-terminal/sftp upgrades to the
original WsAdapter handlers for RDP.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:28:54 -04:00
Vantz Stockwell
55b944bfc5 fix: restore WsAdapter for RdpModule gateway, manual handler coexists
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:21:48 -04:00
Vantz Stockwell
734ab5633e fix: bypass NestJS WsAdapter — manual WebSocket upgrade handling
The NestJS WsAdapter silently swallowed WebSocket connections through
NPM despite 101 responses in the access log. Replaced with manual
ws.Server instances using noServer mode and explicit HTTP upgrade
event handling. Gateways are now plain @Injectable services, not
@WebSocketGateway decorators.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:12:01 -04:00
Vantz Stockwell
10f3537b01 fix: move WebSocket paths under /api/ prefix to work through NPM proxy
NPM forwards /api/* correctly but silently drops WebSocket upgrades on
/ws/* despite toggle being enabled and custom nginx config. Moving
gateways to /api/ws/terminal and /api/ws/sftp so they ride the same
proxy rules that already work for REST endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:13:45 -04:00
Vantz Stockwell
9dc5938fa6 debug: add HTTP upgrade event listener to diagnose WebSocket routing
handleConnection never fires despite browser getting open event.
Adding server-level upgrade listener to see if upgrades reach NestJS.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:34:19 -04:00
Vantz Stockwell
77a76262f5 debug: add verbose WebSocket logging to terminal gateway
Need to see if handleConnection is even being called.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:27:43 -04:00
Vantz Stockwell
c4d7ad1833 fix: WebSocket auth always fails — client object has no URL property
With the NestJS ws adapter, the JWT token URL is on the HTTP upgrade
request (second arg to handleConnection), not on the WebSocket client
object. client.url was undefined, new URL(undefined) threw, catch
returned null, and every connection got 4001 Unauthorized.

Fix: Pass the IncomingMessage req to validateClient and prefer req.url.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:16:03 -04:00
Vantz Stockwell
f778213c32 fix: inline modals in index.vue, proper DTO for profile update
Dialogs: bypassed component-based dialogs entirely — inlined modals
directly in index.vue with inline style fallbacks for z-index/colors.
If button clicks work, we see the modal. Period.

Profile 500: created UpdateProfileDto with class-validator decorators
so ValidationPipe processes it correctly. Added error logging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:09:05 -04:00
Vantz Stockwell
13111ae007 feat: nav bar (Home link), profile management, TOTP 2FA
- Add Home/Profile links to nav bar alongside Vault/Settings/Logout
- Profile page: change email, display name, password
- TOTP 2FA: setup with QR code, verify, disable with password
- Login flow: two-step TOTP challenge when 2FA is enabled
- Backend: new endpoints PUT /profile, POST /totp/setup|verify|disable
- Migration: add totp_secret and totp_enabled columns to users

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:36:03 -04:00
Vantz Stockwell
f1e3892572 fix: correct dist path (dist/src/main.js), static path, explicit schema for migrate 2026-03-13 08:23:52 -04:00
Vantz Stockwell
bced9728d3 fix: add initial Prisma migration so migrate deploy creates tables 2026-03-13 08:22:27 -04:00
Vantz Stockwell
5c82bbbb79 fix: auto-run Prisma migrate + seed on container startup 2026-03-13 08:19:46 -04:00
Vantz Stockwell
5d75869bb4 feat: RDP backend — Guacamole TCP tunnel to guacd over WebSocket
- guacamole.service.ts: raw TCP client to guacd on GUACD_HOST:GUACD_PORT.
  Performs SELECT rdp → CONNECT handshake with full RDP parameter set.
  Provides encode/decode helpers for length-prefixed Guacamole wire format.
- rdp.gateway.ts: WebSocket gateway at /ws/rdp. JWT auth via WsAuthGuard.
  Handles connect (host lookup, credential decrypt, guacd tunnel open) and
  guac (bidirectional instruction forwarding). Updates lastConnectedAt and
  creates ConnectionLog on connect (same pattern as SSH gateway).
- rdp.module.ts: imports VaultModule, ConnectionsModule, AuthModule.
- app.module.ts: registers RdpModule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 17:27:09 -04:00
Vantz Stockwell
56be3fc102 feat: SFTP gateway — file operations over WebSocket
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:17:18 -04:00
Vantz Stockwell
60d7b6b024 feat: SSH terminal gateway — ssh2 proxy over WebSocket
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:17:12 -04:00
Vantz Stockwell
fd916fa4ef fix: add @types/jest, fix WsAuthGuard TS error 2026-03-12 17:13:50 -04:00
Vantz Stockwell
6fa8f6c5d8 feat: settings — key/value store with CRUD API
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:09:08 -04:00
Vantz Stockwell
5762eb706e feat: vault — encrypted credentials + SSH key management
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:08:53 -04:00
Vantz Stockwell
41411b0cb8 feat: connection manager — hosts + groups CRUD with search
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:08:00 -04:00
Vantz Stockwell
3b9a0118b5 feat: AES-256-GCM encryption service + auth module (JWT, guards, seed)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:07:14 -04:00
Vantz Stockwell
5a6c376821 feat: Prisma schema (7 models) + NestJS bootstrap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:06:09 -04:00
Vantz Stockwell
88dbb99f9d feat: project scaffold — Docker, NestJS, Nuxt 3, Prisma config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:05:37 -04:00