openova/products
e3mrah 7b59292cad
feat(catalyst-ui): X2+E — xterm.js logs viewer + Guacamole exec + session list + replay (slice X2+E1+E2+E3, #1099) (#1169)
EPIC-4 final slice. Replaces the Logs/Exec placeholders shipped by R
(#1167) with target-state implementations and lays the surface for the
Guacamole-fronted recorded shell flow.

UI (catalyst-ui):
  - widgets/cloud-list/LogViewer.tsx — xterm.js viewer for the X1
    Pod-log WebSocket. Container picker (multi-container Pods),
    search box (⌃F / ⌘F), 10k scrollback, reconnect-with-since on
    disconnect (per X1 resume protocol).
  - widgets/cloud-list/ExecPanel.tsx — Open Shell button → POST
    /k8s/exec/.../session → Guacamole iframe. 5s iframe-load timeout
    OR onError → falls through to xterm.js + X1-style fallback
    WebSocket; banner explains "recording disabled" on fallback.
  - pages/sovereign/sessions/SessionsPage.tsx — guacamole session list
    + filter (pod/user) + paginate + Replay modal. Mounted on both
    /provision/$id/sessions (mothership) and /sessions (chroot).
  - pages/sovereign/cloud-list/ResourceDetailPage.tsx — Logs tab now
    renders LogViewer; Exec tab now renders ExecPanel. Non-Pod kinds
    surface a "drill into Tree to find Pods" hint.
  - resource.api.ts — adds logsWebSocketURL + execWebSocketURL +
    createExecSession + listSessions + getSessionReplay helpers (single
    URL truth per INVIOLABLE-PRINCIPLES #4).

API (catalyst-api):
  - internal/handler/k8s_exec.go — three new endpoints:
      POST /api/v1/sovereigns/{id}/k8s/exec/{ns}/{pod}/{container}/session
        (tier-developer or higher; calls GuacamoleClient.CreateSession;
        emits guacamole-session-opened audit)
      GET  /api/v1/sovereigns/{id}/sessions?from=&to=&pod=&user=&page=
        (tier-admin or higher; paginated; reads from GuacamoleClient
        OR in-memory fallback when no client is wired)
      GET  /api/v1/sovereigns/{id}/sessions/{sessionId}/replay
        (admin/owner only — sessions.playback per EPIC-3 §6.2; emits
        guacamole-session-replayed audit)
  - internal/handler/k8s_exec_ws.go — direct WebSocket exec fallback
    (bidi pump; xterm.js client) for when Guacamole iframe is blocked.
  - GuacamoleClient interface + in-memory fallback session store: the
    chroot Sovereign / CI flow renders cleanly even when Guacamole isn't
    deployed; production wires the real client via SetGuacamoleClient.
  - Audit-type predicate IsGuacamoleAuditType + 3 canonical type names
    (guacamole-session-opened/closed/replayed). Reuses the EPIC-3 U5-U8
    audit Bus + the slice K+P+X1+G's reservation per the canonical seam
    map; future audit consumers filter via prefix `guacamole-*`.

Tests:
  - 9 LogViewer / ExecPanel / SessionsPage vitest test files, 38 tests
    passing in `pages/sovereign/cloud-list/` + `widgets/cloud-list/` +
    `pages/sovereign/sessions/`.
  - 22 Go test functions in k8s_exec_test.go + k8s_exec_ws_test.go
    covering happy/forbidden/not-found/audit-emit/pagination/filter
    paths. `go test -count=1 -race ./internal/handler/` clean.
  - 6 Playwright snapshot tests at 1440x900 in
    `e2e/logs-exec-sessions.spec.ts` covering LogViewer / search box /
    ExecPanel idle / ExecPanel post-click / SessionsPage list / filter.

`npm run typecheck` clean. `go vet ./...` clean. Pre-existing UI test
failures (12 files, 99 tests) confirmed identical to main per canon §7.

Co-authored-by: hatiyildiz <hati.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 11:18:06 +04:00
..
axon feat(axon): make qwen3-coder thinking mode toggleable via request parameter 2026-04-26 09:20:33 +02:00
catalyst feat(catalyst-ui): X2+E — xterm.js logs viewer + Guacamole exec + session list + replay (slice X2+E1+E2+E3, #1099) (#1169) 2026-05-09 11:18:06 +04:00
continuum feat(continuum): F — dry-run report + post-switchover health check + audit-emit coverage (slice F-1+F-2+F-3, #1101) (#1161) 2026-05-09 08:33:37 +04:00
cortex docs(pass-52): bundled date-sweep + cross-component namespace clean; knative clean 2026-04-28 00:37:21 +02:00
fabric docs(seaweedfs+guacamole): replace MinIO with SeaweedFS as unified S3 encapsulation; add Guacamole to bp-relay 2026-04-28 10:23:46 +02:00
fingate docs(pass-52): bundled date-sweep + cross-component namespace clean; knative clean 2026-04-28 00:37:21 +02:00
relay docs(seaweedfs+guacamole): replace MinIO with SeaweedFS as unified S3 encapsulation; add Guacamole to bp-relay 2026-04-28 10:23:46 +02:00