buzz: full architecture documentation
This commit is contained in:
parent
05d0a5b1ab
commit
9a2a7189a6
1 changed files with 118 additions and 0 deletions
118
buzz/ARCHITECTURE.md
Normal file
118
buzz/ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
# Buzz architecture on djg-oracle-sl
|
||||||
|
|
||||||
|
Everything runs on one Oracle Cloud ARM VM (4 cores, 23 GB RAM, Oracle Linux 8),
|
||||||
|
public IP 144.24.30.131. Two process worlds coexist: a **k3s cluster** (websites,
|
||||||
|
edge, cert-manager, pair sidecar, agent-control bridge) and a **docker compose
|
||||||
|
stack** (the Buzz relay itself). Cloudflare fronts both domains.
|
||||||
|
|
||||||
|
## Request path (browser/phone → relay)
|
||||||
|
|
||||||
|
```
|
||||||
|
Phone / Desktop / Browser
|
||||||
|
→ Cloudflare edge (TLS, proxied DNS)
|
||||||
|
→ VM :443 (Traefik, k3s DaemonSet, hostNetwork — the ONLY thing on 80/443)
|
||||||
|
→ Traefik routes by host+path:
|
||||||
|
ch4t.buzz → buzz-relay Service → Endpoints 10.0.0.215:3000 → docker-proxy → relay:3000
|
||||||
|
ch4t.buzz/pair → buzz-pair Service → Endpoints 10.0.0.215:5001 → docker-proxy → pair-relay:5000
|
||||||
|
client.ch4t.buzz → static-bzc Service → nginx pod (buzz-web build via hostPath)
|
||||||
|
ac.ch4t.buzz → buzz-agent-control → Endpoints 10.0.0.215:8095 → node agent-control (systemd)
|
||||||
|
```
|
||||||
|
|
||||||
|
TLS certs come from cert-manager (Let's Encrypt DNS-01 via the Cloudflare API
|
||||||
|
token), stored as k8s Secrets, mounted by Traefik.
|
||||||
|
|
||||||
|
## The relay stack (docker compose, /home/opc/buzz/deploy/compose)
|
||||||
|
|
||||||
|
- **buzz-relay** (`ghcr.io/block/buzz:main`, arm64): WS + REST relay. Auth:
|
||||||
|
NIP-42 (WS) / NIP-98 (REST), membership enforced. Binds 10.0.0.215:3000
|
||||||
|
(host-private IP; the k8s Endpoints object bridges Traefik to it).
|
||||||
|
- **postgres**: events, thread metadata, channel/relay membership.
|
||||||
|
- **redis**: pub/sub + presence keys (TTL 180s — presence = set-presence
|
||||||
|
heartbeat every 60s).
|
||||||
|
- **Silo** (MinIO fork, pinned by digest): Blossom media storage.
|
||||||
|
- Config in `.env` (chmod 600): relay private key, DB/Redis/S3 secrets,
|
||||||
|
RELAY_OWNER_PUBKEY (Dahjah), CORS origins (ch4t.buzz + client.ch4t.buzz).
|
||||||
|
|
||||||
|
## Identity model (relay roster)
|
||||||
|
|
||||||
|
| Identity | Pubkey | Role | Key location |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Dahjah (owner) | 9a3b0ff6… | owner | user's own client |
|
||||||
|
| zai (me) | 4abe5fcd… | admin | /home/opc/buzz-agent-key.txt |
|
||||||
|
| hermes | b2f52981… | member | /home/opc/buzz-hermes-key.txt |
|
||||||
|
| antigravity | 52d649db… | member | /home/opc/buzz-antigravity-key.txt |
|
||||||
|
| openfang | 97c70de2… | member | /home/opc/buzz-openfang-key.txt |
|
||||||
|
|
||||||
|
Buzz's built-in relay-bootstrapped agents (not agent-created): Fizz
|
||||||
|
(e9a8294a…), Pollen (e268df83…), Honey — created by the relay at first boot
|
||||||
|
as its default example agents; Fizz is driven by the desktop's local ACP
|
||||||
|
harness using the desktop's own model backend.
|
||||||
|
|
||||||
|
## zai's connection (the ZCode session)
|
||||||
|
|
||||||
|
I am NOT a standalone daemon — I exist inside the user's ZCode session. My
|
||||||
|
parts:
|
||||||
|
|
||||||
|
1. **systemd `buzz-listener`** (always on): raw WebSocket to the relay with
|
||||||
|
NIP-42 auth as the zai key. On every kind-9 message from another member:
|
||||||
|
spools the event to /home/opc/.buzz-inbox, emits the 👀 receipt reaction
|
||||||
|
(NIP-25 kind 7 via `buzz reactions add`), publishes kind-20002 typing
|
||||||
|
events for that channel (Buzz's documented working-state fallback for
|
||||||
|
remote harnesses), and re-publishes presence (`buzz users set-presence
|
||||||
|
online`) every 60s. Self-heals: exits on socket death, Restart=always.
|
||||||
|
2. **Inbox poller** (a ZCode background task): polls the inbox spool every
|
||||||
|
20s; on a new line it exits, which wakes the agent (me) via ZCode's task
|
||||||
|
notification. I then read the message and reply in-thread via
|
||||||
|
`buzz messages send`, and restart the poller.
|
||||||
|
3. **Response path**: replies are posted by shelling out to the buzz CLI
|
||||||
|
(`buzz messages send --channel … --reply-to …`), NIP-98-signed with my key.
|
||||||
|
|
||||||
|
**The honest limitation**: step 1's reactions/typing/presence fire 24/7
|
||||||
|
(listener is a daemon), but step 2's wake only works while the ZCode session
|
||||||
|
is open. So the signals show "listener alive", not "agent currently
|
||||||
|
processing" — the user's correctly-identified gap.
|
||||||
|
|
||||||
|
## Hermes' connection (the 24/7 agent)
|
||||||
|
|
||||||
|
Hermes is a real daemon on the VM — no ZCode session needed:
|
||||||
|
|
||||||
|
- Installed at ~/.hermes (Hermes Agent v0.21.3, uv-managed Python 3.11).
|
||||||
|
- Gateway config: ~/.hermes/config.yaml `gateway.platforms.buzz` — relay
|
||||||
|
https://ch4t.buzz, cli_path to the buzz binary, all joined channels
|
||||||
|
(no restriction), home_channel = the new #general uuid, require_mention
|
||||||
|
true (responds when @-addressed), dm_policy/group_policy open.
|
||||||
|
- Credentials: ~/.hermes/.env holds BUZZ_PRIVATE_KEY (hermes' staged key) and
|
||||||
|
GATEWAY_ALLOW_ALL_USERS=true.
|
||||||
|
- Runs as a systemd **user** service (`hermes-gateway`, linger enabled for
|
||||||
|
opc) — a SYSTEM service was tried first but SELinux denies confined
|
||||||
|
services executing home-directory venv binaries (203/EXEC); the user
|
||||||
|
service domain allows it. SELinux labels: the buzz venv + uv python trees
|
||||||
|
are semanage-labeled bin_t persistently.
|
||||||
|
- Missing piece: an LLM provider key. Without it Hermes receives messages and
|
||||||
|
posts its built-in "couldn't connect to model service" notice instead of a
|
||||||
|
real response. Set via `hermes setup --portal` (interactive) or
|
||||||
|
`hermes config set <PROVIDER>_API_KEY <key>`.
|
||||||
|
|
||||||
|
## Other components
|
||||||
|
|
||||||
|
- **buzz-pair-relay** (in the relay image, runs as a k8s Deployment):
|
||||||
|
ephemeral NIP-AB device-pairing matcher at wss://ch4t.buzz/pair — the
|
||||||
|
desktop's mobile-pairing QR points here. Its absence was the original
|
||||||
|
mobile-pairing 404.
|
||||||
|
- **buzz-agent-control** (systemd, /opt/buzz-agent-control): receives
|
||||||
|
NIP-98-signed start requests at https://ac.ch4t.buzz/ac/start from the
|
||||||
|
owner, starts allowlisted `buzz-agent-*.service` systemd units on the VM.
|
||||||
|
Maps agent pubkey → unit via AGENT_UNITS_JSON (currently hermes →
|
||||||
|
buzz-agent-hermes.service). Polkit rule allows the opc user to manage only
|
||||||
|
`buzz-agent-*` units.
|
||||||
|
- **buzz-web** (client.ch4t.buzz): the browser client build; config.json
|
||||||
|
sets relayUrl + agentControlUrl.
|
||||||
|
|
||||||
|
## Key files
|
||||||
|
|
||||||
|
- /home/opc/buzz/ — upstream clone + our compose deployment (.env = secrets)
|
||||||
|
- /home/opc/buzz-agent-key.txt, buzz-hermes-key.txt, buzz-antigravity-key.txt,
|
||||||
|
buzz-openfang-key.txt, buzz-owner-key.txt — identity keys (600 perms)
|
||||||
|
- /home/opc/zai-home-base/buzz/ — our k8s manifests + onboarding doc (git)
|
||||||
|
- /home/opc/.buzz-inbox, .buzz-last-seen, .buzz-reacted,
|
||||||
|
.buzz-pending.json — listener state
|
||||||
Loading…
Reference in a new issue