github nesquena/hermes-webui v0.51.42
v0.51.42 — Release R (session recovery state.db reconciliation + RFC convention + MEDIA_ALLOWED_ROOTS + Slack cron delivery)

latest releases: v0.51.44, v0.51.43
5 hours ago

v0.51.42 — Release R

5-PR contributor batch + maintainer hardening on top of #2041.

Session recovery now has a complete bottom-of-stack: when both the JSON sidecar and the .json.bak are gone, but the canonical state.db.sessions row remains, an operator can POST /api/session/recovery/repair-safe and the session reappears in the sidebar with messages intact. Live-fire verified.

What landed

  • #2040 by @ai-ag2026 — Two new endpoints: GET /api/session/recovery/audit for read-only recovery reports and POST /api/session/recovery/repair-safe for deterministic repairs. Returns HTTP 409 when audit findings remain post-repair (no false ok).
  • #2041 by @ai-ag2026 — Reconstructs missing JSON sidecars from state.db rows. Never overwrites an existing sidecar; atomic write with os.link() create-or-fail; per-pid/tid tmp file. Only source='webui' rows are materialized.
  • #2042 by @ai-ag2026 — Crash-safe turn-journal RFC at docs/rfcs/turn-journal.md. Establishes the docs/rfcs/ convention for design documents on durability and recovery surfaces.
  • #2044 by @watzonMEDIA_ALLOWED_ROOTS env var extends /api/media allowed-roots whitelist with a colon-separated list of paths. Opt-in, additive; path-traversal validation unchanged. First-time contributor.
  • #2045 by @georgebdavis — Slack appears in the cron delivery dropdown. Backend already routes deliver=slack. First-time contributor.

Maintainer hardening

Two concurrency hazards in #2041 fixed in the staged release rather than left as follow-up, after Opus pre-release review:

  1. Per-pid/tid suffix on .json.reconcile.tmp (was a fixed path per SID, vulnerable to corruption under concurrent reconcile calls).
  2. os.link() create-or-fail replacing tmp.replace(target) — closes the TOCTOU window where a concurrent Session.save() for the same SID would be silently overwritten by the lossier state.db reconstruction.

Plus a round-trip schema-parity test (Session.load() on a materialized sidecar) and a guard test asserting the pid+tid tmp suffix is present.

Test infrastructure

  • tests/conftest.py autouse session fixture strips HERMES_WEBUI_SKIP_ONBOARDING from the pytest environment. Tests that legitimately validate the short-circuit behavior can opt back in with monkeypatch.setenv. Catches a class of bug where tests passed only because the dev env happened to lack the var.
  • Slice window in test_media_html_inline_keeps_csp_sandbox widened from 4000 → 5000 after #2044's insertion pushed the CSP block past the original window.

Tests

5108 → 5120 passing, 8 skipped, 1 xfailed, 2 xpassed, 0 regressions. Suite ~161s on Python 3.11 with HERMES_HOME isolation.

Follow-ups (deferred from Opus review)

Filed as a polish issue: silently-dropped empty-message-rows audit visibility, ok-flag semantic on repair_safe_session_recovery, os.pathsep for Windows MEDIA_ALLOWED_ROOTS compat, and readability tweak on the duplicate-detail guard.

Contributors

@ai-ag2026 (×3) · @watzon · @georgebdavis

Don't miss a new hermes-webui release

NewReleases is sending notifications on new releases.