feat: add session replay with terminal playback via xterm.js
Persist byte-level I/O events from SSH sessions to SQLite and add a web
UI to replay them with original timing. Events are buffered in memory
and flushed every 2s to avoid blocking SSH I/O on database writes.
- Add session_events table (migration 002)
- Add SessionEvent type and storage methods (SQLite + MemoryStore)
- Change RecordingChannel to support multiple callbacks
- Add EventRecorder for buffered event persistence
- Add session detail page with xterm.js terminal replay
- Add /api/sessions/{id}/events JSON endpoint
- Linkify session IDs in dashboard and active sessions
- Vendor xterm.js v5.3.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -213,12 +213,18 @@ func (s *Server) handleSession(channel ssh.Channel, requests <-chan *ssh.Request
|
||||
// Wrap channel in RecordingChannel.
|
||||
recorder := shell.NewRecordingChannel(channel)
|
||||
|
||||
// Always record session events for replay.
|
||||
eventRec := shell.NewEventRecorder(sessionID, s.store, s.logger)
|
||||
eventRec.Start(context.Background())
|
||||
defer eventRec.Close()
|
||||
recorder.AddCallback(eventRec.RecordEvent)
|
||||
|
||||
// Set up detection scorer if enabled.
|
||||
var scorer *detection.Scorer
|
||||
var scoreCancel context.CancelFunc
|
||||
if s.cfg.Detection.Enabled {
|
||||
scorer = detection.NewScorer()
|
||||
recorder.WithCallback(func(ts time.Time, direction int, data []byte) {
|
||||
recorder.AddCallback(func(ts time.Time, direction int, data []byte) {
|
||||
scorer.RecordEvent(ts, direction, data)
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user