emma-hermes/docs/profile-isolation/closing-notes.md

6.2 KiB

Profile Isolation / Download-Link Hardening — Closing Notes

Summary

This batch closes the remaining follow-up items after principal-scoped session, memory, and managed-download isolation landed.

The final scope completed here is:

  • prevent live SSE streaming from briefly exposing host-local artifact paths such as /Users/... or C:\...
  • carry download_link_mode one layer higher so OpenWebUI-facing runs can request private vs public managed-download behavior
  • document a safe restart / recovery procedure for gateway + API server + OpenWebUI runs proxy

Landed repo changes

gateway/platforms/api_server.py

  • added a streaming artifact rewrite guard for SSE output
  • buffers split local-path prefixes until they can be rewritten safely
  • rewrites completed local artifact references to managed-download links during streaming
  • falls back to filename-only text if a buffered local path reaches stream end without a safe rewrite
  • fixed the carry-buffer logic so normal assistant text is not delayed
  • tightened path-prefix detection so https://... is not misclassified as a Windows-style drive path

tests/gateway/test_api_server.py

  • updated the managed-download helper expectation to match the tuple return shape
  • verified ordinary streamed text still appears immediately
  • verified None tool-call sentinels do not break streaming
  • verified /v1/responses streaming completed events carry rewritten managed-download URLs and hook metadata

tests/gateway/test_openwebui_runs_proxy_handoff.py

  • added regression coverage for extracting download_link_mode
  • added regression coverage ensuring owner metadata + link mode are passed into managed-download URL rewriting

docs/profile-isolation/*

  • updated README.md read order
  • updated implementation-status.md to reflect the streaming rewrite fix and OpenWebUI proxy hook landing
  • added restart-recovery-runbook.md
  • added this closing-notes file

Non-repo local changes

These changes are operational/local and are not part of the git repo:

/Users/hermes/.hermes/scripts/openwebui_runs_proxy.py

  • now accepts download_link_mode from top-level request payload or metadata.hermes.download_link_mode
  • forwards download_link_mode upstream to the Hermes API server
  • rewrites local file paths using owner-aware managed-download mode instead of always minting public links
  • appends a small note when private mode is used and the caller may want a future public link

~/Library/LaunchAgents/ai.hermes.gateway.plist

  • removed --replace from the steady-state LaunchAgent command line
  • this change only affects future reloads/restarts; it does not rewrite the currently running process until launchd reloads the job

Live rollout lesson captured for future debugging

  • launchctl kickstart -k restarted the already-loaded gateway job but did not apply the edited plist definition
  • the live gateway arguments stayed on gateway run --replace until the job definition was reloaded with launchctl bootout ...plist + launchctl bootstrap ...plist
  • after the controlled plist reload, gateway recovered health on try 13 of a 1-second poll loop and launchctl print showed live arguments updated to plain gateway run
  • the OpenWebUI runs proxy recovered on try 2 of the same 1-second poll loop after its own bootout + bootstrap reload

Verification performed

Verified successfully:

python3 -m py_compile \
  gateway/platforms/api_server.py \
  tests/gateway/test_api_server.py \
  tests/gateway/test_session_api.py \
  tests/gateway/test_openwebui_runs_proxy_handoff.py \
  /Users/hermes/.hermes/scripts/openwebui_runs_proxy.py

pytest -q \
  tests/gateway/test_api_server.py \
  tests/gateway/test_session_api.py \
  tests/gateway/test_openwebui_runs_proxy_handoff.py

Observed result:

  • 221 passed, 5 warnings in 16.53s

Warnings were third-party deprecation warnings from pkg_resources under lark_oapi, not failures in the isolation changes.

Live runtime facts verified before restart

Observed from the live system during this session:

  • 8642/health was healthy
  • 8653/health was healthy
  • 8646/line/webhook/health was healthy
  • the active gateway LaunchAgent runtime still showed gateway run --replace before reload
  • launchctl print gui/$(id -u)/ai.hermes.gateway showed repeated restarts (runs = 41, forks = 2400, last terminating signal = Killed: 9)

Interpretation:

  • current service was up
  • but the old long-lived launchd configuration had real flap risk and should not remain on --replace

Restart recommendation

Use the runbook in restart-recovery-runbook.md.

Short version:

  1. ensure tests are green
  2. ensure ai.hermes.gateway.plist no longer contains --replace
  3. if the plist changed, reload gateway with bootout + bootstrap (not only kickstart -k) and wait for 8642/health
  4. if the proxy plist or launch context changed, reload OpenWebUI runs proxy with bootout + bootstrap and wait for 8653/health
  5. re-check 8646/line/webhook/health
  6. inspect launchctl print to confirm gateway live arguments no longer include --replace
  7. smoke-test streaming + managed-download rewrite immediately after restart

Known limitation in this chat session

Direct restart commands from this active agent session were blocked by safety guards because restarting the supervised gateway from inside the gateway tool context can create SIGTERM/self-respawn loops.

That blocker is expected behavior, not a code failure.

The correct way to perform the live restart is from an external shell / independent operator context. A background delegated verifier was dispatched to try the isolated-path verification separately.

Suggested PR / merge summary

Title:

  • fix: harden streaming artifact rewrite and propagate download_link_mode to runs proxy

Body bullets:

  • prevent live SSE deltas from leaking host-local artifact paths before managed-download rewrite
  • preserve ordinary streamed text and tool-call progress semantics
  • propagate download_link_mode through the OpenWebUI runs proxy
  • add regression coverage for streaming rewrite behavior and proxy link-mode extraction
  • document safe restart/recovery procedure and remove --replace from the steady-state gateway LaunchAgent config