The bridge is the security boundary between a small device and Hermes. An ESP32 never receives the Hermes API key and cannot call arbitrary Hermes endpoints.
- The operator token can register devices, read all messages, and use the browser or CLI voice client. Keep it on an operator computer and the Hermes host. Do not flash it to a device.
- Every device token is random and bound to one device ID. A device can check in, send prompts, and read messages only for that ID.
- The bridge stores only SHA-256 hashes of device tokens. The raw token is returned once when a device is registered.
- Rotating a device token invalidates the old token immediately. Rotation must
be explicit with
hermes32 setup --device-id ID --rotate-device-token; normal setup and bridge updates do not rotate credentials.
Token files used by the CLI must have mode 0600. The bridge database is also
forced to mode 0600. The provided systemd service runs as a dedicated user,
uses a private state directory, and removes unneeded Linux privileges.
Remote install/update uploads a locally built pure-Python wheel. Dependencies are pinned with hashes, downloaded as binary wheels by the SSH user, and then installed offline as root. Updates fail closed if the existing Hermes API key cannot be read safely; they never rotate it as a recovery shortcut.
Bearer tokens are secrets in transit. Operator access always uses HTTPS. The
ESP32 may use plain HTTP only when --allow-insecure-http explicitly accepts a
trusted local network; this sends its narrowly scoped device token, never the
operator token. That flag is an acknowledgement, not encryption.
The browser console refuses operator login on an insecure, non-localhost page. The CLI launches it with a random, one-use code that expires after 5 minutes; the bridge exchanges that code for the operator token over HTTPS. The token then stays only in page memory and is not stored in browser storage or the URL.
Hermes API credentials may use HTTP only for loopback services on the same host. Authenticated bridge and upstream clients refuse redirects so bearer tokens cannot be forwarded to another origin.
The bridge limits prompt length, audio size, request frequency, total active
work, active work per device, small JSON route bodies, and retained messages.
Voice transcripts use the same prompt limit as text. Timed-out, cancelled, or
approval-blocked work asks Hermes to stop before releasing the local slot. On
restart, unfinished messages are marked failed instead of remaining stuck. See
deploy/bridge.env.example for the tunable limits.
- Anyone with physical access to an ESP32 may be able to extract its Wi-Fi and
device credentials. Use
--rotate-device-tokenwhen replacing a lost board. - A stolen operator token has full bridge access. Replace
BRIDGE_OPERATOR_TOKEN, restart the bridge, and update trusted operator clients. - Hermes requests that need human approval cannot currently be completed from the device.