clusev/resources/views/components
boban 07fe404ce9 feat(terminal): web terminal — per-server SSH + Clusev host PTY (xterm.js + node sidecar)
A dedicated /terminal page with a target rail: one terminal per fleet server (SSH)
plus one for the Clusev host itself. php-fpm cannot hold an interactive PTY, so a
small Node sidecar (ws + ssh2 + node-pty) bridges xterm.js to the PTY.

Flow: the Livewire page mints a single-use, 60s TerminalSession token and dispatches
it to an Alpine xterm island; the browser opens a same-origin WS (/terminal/ws,
proxied by nginx in dev / Caddy in prod to terminal:3000); the sidecar burns the
token at an internal resolve endpoint (shared-secret header, private network only)
for a connection spec, then opens an SSH PTY (decrypted credential, never sent to the
browser) or a local host PTY. Real shell = native Tab/Shift-Tab completion.

Security:
- token burned ATOMICALLY (single conditional UPDATE) — no double-open race
- resolve endpoint guarded by hash_equals shared secret, exempt from CSRF + PanelScheme
  host enforcement (private net only), returns decrypted creds over the internal net
- sidecar enforces same-origin on the WS upgrade (hostname match, port-agnostic)
- single-use 60s tokens, swept daily so the table can't grow unbounded

Verified in-browser (R12): host + server terminals connect, accept keyboard input,
run commands, Tab-complete; cross-origin WS rejected; zero console errors. 9 feature
tests cover minting, the resolve spec, single-use burn, expiry, and locked creds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 03:21:10 +02:00
..
.gitkeep feat: scaffold — Dockerized Laravel 13 + Livewire 3 + Tailwind 4 + Reverb 2026-06-12 00:31:50 +02:00
badge.blade.php feat(wireguard): SSH lock + peer config download (v0.9.40) 2026-06-21 09:25:19 +02:00
btn.blade.php feat(ui): uniform bordered button kit; retire ghost variants 2026-06-14 10:18:47 +02:00
checkbox.blade.php fix(ui): themed x-checkbox component (accent, visible check) for login-protection + remember-me 2026-06-20 20:04:47 +02:00
command-palette.blade.php feat(help): in-panel help page scaffold + overview topic 2026-06-19 22:14:15 +02:00
icon.blade.php feat(terminal): web terminal — per-server SSH + Clusev host PTY (xterm.js + node sidecar) 2026-06-25 03:21:10 +02:00
kpi.blade.php style: align UI to the BASTION reference (atmosphere + depth) 2026-06-12 13:39:57 +02:00
lang-switch.blade.php feat(i18n): bilingual foundation (DE/EN) + localize auth/dashboard/servers/fleet/account 2026-06-13 22:36:16 +02:00
metric.blade.php feat: reference-depth dashboard (sparkline KPIs + live dual chart + table) 2026-06-12 14:44:11 +02:00
modal-trigger.blade.php fix(modals): reliable open + spinner/error feedback on every modal trigger 2026-06-15 21:07:25 +02:00
nav-item.blade.php fix(versions): show what's-new (v-prefixed ref) + sidebar update badge (v0.9.51) 2026-06-22 00:19:27 +02:00
panel.blade.php style: align UI to the BASTION reference (atmosphere + depth) 2026-06-12 13:39:57 +02:00
ring.blade.php fix(live): poll-driven metrics (chart + gauges), bigger donuts, drop fake fleet 2026-06-12 22:38:51 +02:00
server-item.blade.php feat(ui): add "Initialisierung" (pending) server status 2026-06-14 10:20:32 +02:00
sidebar.blade.php feat(terminal): web terminal — per-server SSH + Clusev host PTY (xterm.js + node sidecar) 2026-06-25 03:21:10 +02:00
skeleton.blade.php perf+ux: lazy-load pages (skeletons), fix modal, normalize buttons + spinners 2026-06-12 23:17:02 +02:00
source-comment.blade.php chore(release): point public-facing URLs at github.com/clusev/clusev — 0.9.58 2026-06-22 21:41:52 +02:00
status-dot.blade.php feat(ui): add "Initialisierung" (pending) server status 2026-06-14 10:20:32 +02:00
status-pill.blade.php feat(ui): add "Initialisierung" (pending) server status 2026-06-14 10:20:32 +02:00
topbar.blade.php fix(blade): garbled header on every signed-in page + private metrics channel (v0.4.1) 2026-06-14 08:34:07 +02:00
two-factor-badge.blade.php fix(ui): unify the 2FA status badge into one x-two-factor-badge component 2026-06-20 20:07:59 +02:00