Apply P18: memoryd, the one owner of memory

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-24 13:11:48 -07:00
co-authored by Claude Opus 5.5
parent 428b87d31d
commit 9685289242
2 changed files with 10 additions and 7 deletions
+9 -6
View File
@@ -47,9 +47,10 @@ cloud-led orchestration as the default, in-process third-party code of any kind.
| Role | Purpose | Holds | Can reach | Never holds |
|---|---|---|---|---|
| `gatewayd` | Carries messages between the owner's Mattermost and the harness. | Mattermost bot token, allowlist, message queue | Mattermost server (outbound only), `loopd` socket | Tool secrets, grants |
| `loopd` | Runs the conversation: builds each prompt, calls the model, and asks `brokerd` for every tool call. | Session logs, prompt assembly, memory files | Three Unix sockets: `gatewayd`, `brokerd`, `inferproxy` | Any credential, any network interface |
| `loopd` | Runs the conversation: builds each prompt, calls the model, and asks `brokerd` for every tool call. | Session logs, prompt assembly | Four Unix sockets: `gatewayd`, `brokerd`, `inferproxy`, `memoryd` | Any credential, any network interface |
| `inferproxy` | Lets `loopd` reach the model without having a network. | The `llama-server` address | `llama-server` only | Anything else; it forwards bytes and logs nothing |
| `brokerd` | Decides whether each tool call may run, runs it in a fresh container, and records the decision. | Grants (read-only), secrets, audit log | Container runtime, `gatewayd` socket (for approvals) | Conversation history |
| `memoryd` | Keeps the memory files and their index, syncs finished turns to Honcho, and runs every memory tool call `brokerd` has decided. | `memory/`, `index/`, Honcho's address and workspace list (and its key, if any) | Honcho only; sockets from `loopd` (finished turns in, the memory files out once per epoch) and from `brokerd` (memory tool calls); `sessions/` read-only, for reindexing | Grants, tool secrets, the Mattermost token |
| tool containers | Do one approved tool call and then cease to exist. | Only what one call was granted | Only what one call was granted | Anything persistent |
v0 runs all roles on one host. The interfaces must not assume co-location with `llama-server`.
@@ -60,17 +61,19 @@ The host's tailnet identity is shared by every container that has a network, so
ordinary outbound networking can reach the whole tailnet and the internet as the host.
1. `loopd` runs with no network namespace interfaces except loopback (`--network=none`). Its only
I/O is three Unix sockets on a shared volume.
I/O is four Unix sockets on a shared volume.
2. `inferproxy` is a forwarder of about 100 lines: one Unix socket in, one fixed upstream out. The
upstream is the shared router's TCP listener on the host. It is required: `loopd` has no
network, and the router stays on TCP for its other clients.
3. `gatewayd` has outbound network only. It opens no listening TCP port. Approvals are commands
(`!approve`, `!deny`) replied in the approval's thread, which arrive over the Mattermost
WebSocket, so no callback URL is needed.
4. Tool containers get no network unless the grant names hosts. Granted network access goes through
4. `memoryd` reaches Honcho and nothing else. It does not index sessions above a configured data
class.
5. Tool containers get no network unless the grant names hosts. Granted network access goes through
an allowlisting egress proxy that `brokerd` configures per call.
5. Tailnet ACLs (kept in `deploy/`) limit the host's node to `llama-server` and Mattermost, plus
whatever tool grants need. This is defence in depth, not the role boundary.
6. Tailnet ACLs (kept in `deploy/`) limit the host's node to `llama-server`, Mattermost and Honcho,
plus whatever tool grants need. This is defence in depth, not the role boundary.
## Channel: Mattermost
@@ -227,7 +230,7 @@ Files are the source of truth. SQLite is allowed only for rebuildable indexes an
## Code constraints
- Rust stable, Cargo workspace. One crate per role in the table above (`loopd`, `brokerd`,
`gatewayd`, `inferproxy`), plus three that are not roles:
`gatewayd`, `inferproxy`, `memoryd`), plus three that are not roles:
| Crate | Purpose |
|---|---|