Release V — stage-339 (v0.51.46)
5 PRs from 3 contributors, merged in this order:
- #2084 by @ai-ag2026 — CSP report-only header (refs #1909)
- #2085 by @bergeouss — Logs panel: clipboard fallback + severity filter (closes #2081)
- #2089 by @plerohellec — Plugin slash commands surface in WebUI (closes #1935)
- #2059 by @ai-ag2026 — Crash-safe turn journal writer (RFC #2042 minimal slice)
- #2062 by @ai-ag2026 — Turn journal lifecycle events (stacked on #2059)
Stage augmentations (Opus advisor SHOULD-FIX)
96ca83bf— Three security/quality fixes:server.py:_CSP_REPORT_ONLYdrop'unsafe-eval'(verified zeroeval()/new Function()/ string-form timeout/interval in production JS)server.py:_CSP_REPORT_ONLYaddhttps://cdn.jsdelivr.nettoscript-src/style-src(Prism, xterm.js, katex CDN assets with SRI hashes — without this every page load fires known-good violations)api/commands.py:execute_plugin_commandsanitize plugin error (returntype(exc).__name__instead of rawstr(exc)which would leak paths/env fromFileNotFoundError('/etc/...')-shape exceptions; full traceback now logged at WARNING)
Pre-release verification
-
Opus advisor (claude-opus-4-7 thinking): SHIP after 3 SHOULD-FIX items (all applied). Risk areas A–G all PASS:
- A. CSP report-only —
unsafe-inlinefor scripts/styles verified necessary (6 inline scripts + ~157on{event}=handlers + ~210 inlinestyle=attrs in index.html).unsafe-evalverified NOT needed. - B. /api/commands/exec route security — auth at
server.py:226,246, CSRF atroutes.py:3800,_NEVER_EXPOSEfilter applied. Error leakage fix applied. - C. Frontend intercept coexistence — parallel to existing
cli_onlyintercept, fail-safe to send-to-agent if_agentCmdundefined. - D. Turn-journal writer concurrency —
O_APPENDPOSIX atomicity ≤ PIPE_BUF (4096), audit doesn't fire false positives (sidecar-without-journal invisible). - E. Lifecycle event placement —
worker_startedinside worker thread (line 2017),completedvsinterruptedmutually exclusive in normal case,append_turn_journal_event_for_streamfalls back to freshturn_idif submitted missing. - F/G. Cross-PR / Release-U coexistence — no
_ENV_LOCKdeadlock (lifecycle calls outside critical sections), no circular imports.
- A. CSP report-only —
-
pytest: 5231 passed / 11 skipped / 1 xfailed / 2 xpassed in 97s. Clean.
Follow-up issues to file post-merge
- CSP collector endpoint (
POST /api/csp-report+report-to/report-uridirective). Without it report-only mode is invisible outside individual devtools consoles. - fsync hot-path latency — move
append_turn_journal_event(..., "submitted")to a writer thread / queue, or document the disk-latency cost (1-10ms SSD, 50-200ms rotational, in/api/chat/startcritical path). - Lifecycle double-write — add a
terminalfield oncompleted/interruptedand let the audit detect double-terminal turns rather than collapsing oncreated_at. - Multi-process append safety — long submitted messages exceeding PIPE_BUF (4KB). Per-process journal files or flock-based writer if multi-worker deployments become supported.
- Localize logs-panel i18n keys — Opus noted
// TODO: translateplaceholders in 8 non-English locales from #2085. Translation ticket, not blocking.
What's Changed
- Release V — v0.51.46 (5-PR contributor batch — CSP report-only + logs panel polish + plugin slash commands + turn-journal crash-safe writer + lifecycle events) by @nesquena-hermes in #2094
- feat: add crash-safe turn journal writer by @ai-ag2026 in #2059
- feat: record turn journal lifecycle events by @ai-ag2026 in #2062
- fix: add report-only CSP header by @ai-ag2026 in #2084
- fix(logs): clipboard fallback + severity filter for Logs panel (#2081) by @bergeouss in #2085
- support slash commands implemented in hermes plugin by @plerohellec in #2089
New Contributors
- @plerohellec made their first contribution in #2089
Full Changelog: v0.51.45...v0.51.46