Uptime Kuma has no REST API for monitor data; connect over the same
Socket.IO session the web UI uses (login, then read monitorList and
heartbeat events) so connected monitors now surface as Resources.
Switches the integration's credentials from an API key to
username/password, matching what Uptime Kuma's session login expects.
Adds a remote_desktop integration type and a /api/guacamole websocket
route that drives guacamole-lite's ClientConnection directly (bypassing
its Server class, which would otherwise attach an unfiltered upgrade
listener that conflicts with the existing @fastify/websocket routes).
The frontend RemoteDesktop page renders the Guacamole protocol stream
via guacamole-common-js. Verified end-to-end against a real guacd and
VNC server, including in an actual browser session.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
Ephemeral per-request SFTP connections, whole-file-in-memory view/edit
with a 50MB cap and binary detection, streaming download for files of
any size, multipart upload. No sudo/permission-elevation or
server-to-server transfer in this pass (documented gaps, matching
Termix's own scope for the latter).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
- terminal.ts: connectWithCertificate() shells out to system ssh via
node-pty for OpenSSH certificate auth (ssh2 has no native support);
list_tmux WS message + tmuxSession connect param for tmux
attach/create with shell-injection-safe name validation;
sessionLogging config field appends terminal output to disk.
- Settings.tsx: certificate secret field and sessionLogging checkbox
for SSH host integrations.
- Terminal.tsx: tmux session picker in each pane's header.
- Verified end-to-end against a real test SSH server running real
bash/tmux processes (plain shell, tmux create+list, session log
written to disk). Cert auth path type-checks but is unverified in
this sandbox (no ssh CLI available) - documented as a gap in
TERMIX_MIGRATION.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
Implements the minimal-viable terminal described in TERMIX_MIGRATION.md
Phase 1a: a real interactive SSH session in the browser over a
WebSocket, using xterm.js on the frontend and ssh2 on the backend.
Reuses ArchNest's existing SSH integrations (host/port/username/
password/privateKey/passphrase) instead of introducing a second,
duplicate host-management system the way Termix has one.
Backend: new /api/terminal WebSocket route (registered via
@fastify/websocket) handling connect/input/resize/disconnect messages,
authenticated via a JWT passed as a query param (browsers can't set
custom headers on the WS handshake). Extracted the integration secret
loader out of routes/integrations.ts into db/secrets.ts so the new
terminal route can reuse it without duplicating the decrypt logic.
Frontend: new Terminal.tsx page listing configured SSH hosts and
rendering an xterm.js terminal wired to the WebSocket; wired into
App.tsx at /terminal. vite.config.ts's dev proxy now forwards
WebSocket upgrades (ws: true) so this works under `npm run dev`.
Verified end-to-end against a real (test) ssh2-based SSH server:
connect, shell banner, keystroke echo, and prompt redraw all worked
correctly over the actual WebSocket protocol.
Deliberately deferred to Phase 1b/1c per the migration doc: jump-host
chaining, tab/split-pane UI, terminal theme/font settings, OPKSSH cert
auth, tmux session monitor, session recording.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
Proxmox ships with a self-signed cert by default, which Node's fetch
rejected outright; route Proxmox requests through an undici Agent with
rejectUnauthorized disabled so real Proxmox hosts can be connected.
Also bump @fastify/jwt to v10, which pulls in a patched fast-jwt and
resolves the critical advisories (crit-header bypass, algorithm
confusion, cache collision, ReDoS, empty-HMAC-secret auth bypass) that
npm audit flagged on the old v9/fast-jwt<=6.2.3 pairing. Verified auth
still works end-to-end (setup, valid token, rejected bad token) after
the upgrade; npm audit now reports 0 vulnerabilities.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
Many self-hosted machines have no management API, so add an SSH-based
adapter (using ssh2) that connects with password or key auth and probes
hostname/disk/mem/load via a single shell command, surfacing health
status like the other integrations. Also fixes routes/integrations.ts's
hardcoded type enum, which was out of sync with the IntegrationType
union and rejected the new 'ssh' type.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
Implements testConnection via STS GetCallerIdentity and listResources via
EC2 DescribeInstances, mapping instance state to resource health. Verified
end-to-end against real AWS endpoints — invalid credentials return AWS's
actual rejection message rather than crashing. Intended for use with a
dedicated, least-privilege IAM user (ec2:DescribeInstances + sts:GetCallerIdentity).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
- Single-user JWT auth with a first-run /api/setup endpoint, gated by
GET /api/system/setup-status, to back an upcoming enrollment page
- SQLite schema for users, integrations, secrets (AES-256-GCM encrypted),
bookmarks, and bookmark categories
- Integration adapter registry with real health-check adapters for
Uptime Kuma and Docker, stubs for the rest, wired to
POST /api/integrations/:id/test
- CRUD routes for integrations and bookmarks
- backend/ as its own Docker service in docker-compose.yml, Vite dev
proxy for /api, .env.example for required secrets
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF