docs: update changelog and version to v0.17.1

Covers PRs #11, #13, #14, #15: Sprint 15 features, security hardening,
OpenRouter routing fix, project picker UX fixes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nathan Esquenazi
2026-04-02 01:18:53 -07:00
parent 95645d651e
commit 9452f56821
2 changed files with 42 additions and 1 deletions

View File

@@ -5,6 +5,47 @@
--- ---
## [v0.17.1] Security + Bug Fixes
*April 2, 2026 | 237 tests*
### Security
- **Path traversal in static file server.** `_serve_static()` now sandboxes
resolved paths inside `static/` via `.relative_to()`. Previously
`GET /static/../../.hermes/config.yaml` could expose API keys.
- **XSS in markdown renderer.** All captured groups in bold, italic, headings,
blockquotes, list items, table cells, and link labels now run through `esc()`
before `innerHTML` insertion.
- **Skill category path traversal.** Category param validated to reject `/`
and `..` to prevent writing outside `~/.hermes/skills/`.
- **Debug endpoint locked to localhost.** `/api/approval/inject_test` returns
404 to any non-loopback client.
- **CDN resources pinned with SRI hashes.** PrismJS and Mermaid tags now have
`integrity` + `crossorigin` attributes. Mermaid pinned to `@10.9.3`.
- **Project color CSS injection.** Color field validated against
`^#[0-9a-fA-F]{3,8}$` to prevent `style.background` injection.
- **Project name length limit.** Capped at 128 chars, empty-after-strip rejected.
### Bug Fixes
- **OpenRouter model routing regression.** `resolve_model_provider()` was
incorrectly stripping provider prefixes from OpenRouter model IDs (e.g.
`openai/gpt-5.4-mini` became `gpt-5.4-mini` with provider `openai`),
causing AIAgent to look for OPENAI_API_KEY and crash. Fix: only strip
prefix when `config.provider` explicitly matches that direct-API provider.
- **Project picker invisible.** Dropdown was clipped by `.session-item`
`overflow:hidden`. Now appended to `document.body` with `position:fixed`.
- **Project picker stretched full width.** Added `max-width:220px;
width:max-content` to constrain the fixed-positioned picker.
- **No way to create project from picker.** Added "+ New project" item at
the bottom of the picker dropdown.
- **Folder button undiscoverable.** Now shows persistently (blue, 60%
opacity) when session belongs to a project.
- **Picker event listener leak.** `removeEventListener` added to all picker
item onclick handlers.
- **Redundant sys.path.insert calls removed.** Two cron handler imports no
longer prepend the agent dir (already on sys.path via config.py).
---
## [v0.17] Sprint 15 -- Session Projects + Code Copy + Tool Card Toggle ## [v0.17] Sprint 15 -- Session Projects + Code Copy + Tool Card Toggle
*April 1, 2026 | 237 tests* *April 1, 2026 | 237 tests*

View File

@@ -13,7 +13,7 @@
<body> <body>
<div class="layout"> <div class="layout">
<aside class="sidebar"> <aside class="sidebar">
<div class="sidebar-header"><div class="logo">H</div><div><h1 style="margin:0;font-size:15px;font-weight:700;letter-spacing:-.01em">Hermes</h1><div style="font-size:10px;color:var(--muted);opacity:.8;margin-top:1px">v0.16</div></div></div> <div class="sidebar-header"><div class="logo">H</div><div><h1 style="margin:0;font-size:15px;font-weight:700;letter-spacing:-.01em">Hermes</h1><div style="font-size:10px;color:var(--muted);opacity:.8;margin-top:1px">v0.17.1</div></div></div>
<div class="sidebar-nav"> <div class="sidebar-nav">
<button class="nav-tab active" data-panel="chat" data-label="Chat" onclick="switchPanel('chat')" title="Chat">&#128172;</button> <button class="nav-tab active" data-panel="chat" data-label="Chat" onclick="switchPanel('chat')" title="Chat">&#128172;</button>
<button class="nav-tab" data-panel="tasks" data-label="Tasks" onclick="switchPanel('tasks')" title="Tasks">&#128197;</button> <button class="nav-tab" data-panel="tasks" data-label="Tasks" onclick="switchPanel('tasks')" title="Tasks">&#128197;</button>