Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ members = [
"crates/buzz-search",
"crates/buzz-audit",
"crates/buzz-acp",
"crates/buzz-backend-hermes",
"crates/buzz-agent",
"crates/sprig",
"crates/buzz-test-client",
Expand Down
12 changes: 12 additions & 0 deletions crates/buzz-backend-hermes/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "buzz-backend-hermes"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true

[dependencies]
base64.workspace = true
serde.workspace = true
serde_json.workspace = true
42 changes: 42 additions & 0 deletions crates/buzz-backend-hermes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# buzz-backend-hermes

Buzz Desktop provider for an existing, remotely supervised native Hermes
gateway.

The provider is discovered as `buzz-backend-hermes` and implements the Buzz
provider `info`/`deploy` protocol plus native-Hermes `stop` and authenticated
`cleanup` extensions. Cleanup bootouts the gateway and removes only the
provider-owned Buzz environment block before Desktop deletes the identity.
`deploy` sends the agent payload over SSH to the configured host, writes the
protected Hermes Buzz environment, applies `model.default` and
`model.provider`, and restarts the existing launchd/systemd unit. It never
starts a local ACP process and refuses non-Hermes agent commands.

Provider configuration is non-secret:

- `host` and explicit SSH `user`
- `profile`, `supervisor`, and `unit` (plus an optional launchd `plist` path)
- optional Hermes home/profile paths and executable paths
- Buzz channel UUIDs and home channel
- explicit `allowed_users` and `allow_all_users` relay authorization policy

SSH authentication is ambient (`ssh-agent`/user SSH configuration); no SSH
private key or Nostr secret belongs in `provider_config`. The Nostr private key
and NIP-OA auth tag arrive only in the Desktop deploy payload and are written
remotely with mode `0600`.

Relay authorization is explicit: `allow_all_users` defaults to false and
must be enabled in the provider configuration when the deployment policy is to
allow relay users, while `require_mention` remains enforced by the generated
configuration. The provider snapshots and restores the profile `.env` and
`config.yaml` if model configuration or supervisor restart fails.

This provider assumes the remote Hermes gateway and its supervisor already
exist. Deploy and stop operations take an exclusive per-profile remote lock. Configured Hermes home/profile paths must be canonical
(no symlink or dot-segment aliases), and the profile must remain beneath the
Hermes home. On launchd, stop uses `bootout` and deploy bootstraps/enables the plist again, so
KeepAlive cannot silently restart a stopped gateway.
Desktop also enforces one managed identity per `(host, profile, unit)` because
one supervised Hermes gateway is one lifecycle scope. It is therefore a remote
reconfiguration/deployment provider, not an identity importer that pretends an
unowned process is local.
Loading