Production Readiness Hardening
Comprehensive code review and fixes across 31 findings (27 fixed, 3 deferred, 1 by-design).
Security
- Path traversal prevention: Session names validated at all CLI entry points — rejects
/,.., null bytes - IPC payload size limit: 16MB max prevents OOM from corrupted/malicious messages
- Socket permissions: Unix socket
chmod 0700for owner-only access
Reliability
- Race condition fix:
switchErrinAttach()now usesatomic.Pointer— no more data race - Goroutine leak fix: Connection closed after done signal to unblock stdin relay
- PTY write errors: Detected and trigger clean shutdown instead of silent failure
- SendMessage errors: Client stdin relay exits on broken connection
- Broadcast filtering: Only attached clients receive output — probe connections skipped
- SpawnDaemon: Returns error when daemon fails to start instead of false success
- Kill dedup:
sync.Onceprevents redundant signal+sleep sequences from multiple clients - Double-close fix:
TagDetachAllno longer double-closes the calling client's connection
Performance
- Scrollback
TailLines: Scans bytes backwards — eliminates 30-40MB transient allocations - NormalizeOptions cached: No longer recalculated on every keypress and render
- SQLite connection: WAL mode + 1s busy timeout + read-only for agent status queries
- JSONL parser: Skips partial first line after mid-file seek
Bug Fixes
- Unicode highlight:
highlightMatchuses rune-based offsets — no more garbled multi-byte display - Log scroll vs palette:
[/]keys no longer conflict with inline filter input - Focus state:
removeFocusSessionhandlesCurrent == Previouspointing to same session - Stack overflow prevention: Cycle detection in
sumTreeRSSanddetectAgentKind - Session name loop: Capped at 10k iterations with proper error return
MaxSessionNameLen: Clamped to 0 instead of returning negative- Stale socket cleanup: Handles all probe failures, not just
*net.OpError - Dead code removed: Unreachable
int/int64type switch cases, permanently-skipped test
DX
!cgobuild stub: Full test suite now runs without Ghostty (CGO_ENABLED=0 go test ./...)- Field copy helpers:
mergeProcessInfo/copyProcessInfoFromSessionreplace fragile 30+ field duplicated blocks displayAgentKind: Title-cases properly instead of misusingDisplayAgentModel- Tests:
t.Chdirfor parallel safety, CGO-dependent tests skip gracefully
Full Changelog: v0.4.2...v0.5.0