membus technical architecture¶
Thin C# adapter over the claude-mem house server (:37877, Docker: server + Postgres + Valkey).
membus owns contracts (scopes, allowlists, provenance, key custody); storage/search/generation
stay in claude-mem. Council-mandated principle: governance as code, not prose.
Components¶
flowchart TD
subgraph anyPC [any house PC]
H[harness process\nclaude / codex / agy / grok / ollama / odysseus] -->|MEMBUS_HARNESS identity| CLI[membus CLI]
CLI --> AL[WriteAllowlist\nclient gate, exit 3]
CLI --> KR[Keyring ~/.membus/keyring.json\nper-scope Bearer keys]
end
AL --> C[MemBusClient]
KR --> C
C -->|POST /v1/memories\nPOST /v1/search\nGET /healthz| S[(claude-mem server :37877)]
S --> PG[(Postgres\none project row per scope\nAPI keys bound to one project)]
S -->|403 key/project mismatch| C
Scope → projectId¶
ScopeRegistry derives RFC 4122 v5 UUIDs from a fixed namespace GUID
(6d656d62-7573-5f76-3100-…) + the scope's canonical string. Deterministic → zero config sync
across machines. house-all is pinned to the pre-existing shared project
(a8295af4-…) so historical memories become the house-all pool. The namespace GUID must never
change — changing it strands every derived scope's data.
Enforcement layers¶
| Layer | Mechanism | Defeats |
|---|---|---|
| 1. Client allowlist | WriteAllowlist.MayWrite(harness, machine, scope); denial = exit 3, no HTTP built |
accidents, non-compliant small models |
| 2. Key custody | server binds each API key to ONE project; keyring holds per-scope keys; derived scope w/o key = refused client-side, 403 server-side | wrong/forged scope writes, unlisted projectIds |
| 3. Host allowlist | Bearer keys only sent to ANDYGREATROOMPC / localhost / 10.0.0.0/24 / MEMBUS_ALLOWED_HOSTS; MEMBUS_UNSAFE_SERVER=1 to override |
key exfiltration via --server |
Not defended (accepted, see README threat model): hostile local process with the machine keyring; LAN sniffing of HTTP Bearer traffic. Both graduate to P6 (per-harness keyrings, TLS).
Write path¶
- CLI parses verb + options; harness identity from
MEMBUS_HARNESS/--harness(never guessed). Scope.TryParse— closed grammar (house-all,local-llms-house,{family}-house,council:<pc>,frontier:<pc>); anything else = usage error.- Allowlist check; council scopes default TTL 14 days.
Provenance.For(...)stampsscope, origin_harness, origin_machine, timestamp, trust_level, ttl_days, dedupe_key, schema_versioninto the memory's metadata.MemBusClient.SendAsyncposts{content, projectId, kind, metadata}with the scope's key.
Provisioning¶
scripts/provision-scopes.ps1 (main PC, idempotent): computes catalog via the CLI, INSERTs
project rows (ON CONFLICT DO NOTHING, team 4a6f4502-…), mints one
memories:read,memories:write key per scope via the container admin CLI, writes the keyring
after every mint. Admin CLI gotcha: server api-key create has no --help — unknown flags
run the command with defaults; revoke strays immediately.
Operational notes¶
- Server hostname
ANDYGREATROOMPCrequires the main PC on AlphaPhiAlpha Wi-Fi (10.0.0.53); Wi-Fi drift to NSBE breaks inbound house traffic (memory: main-pc-wifi-drift-nsbe). - Keyring distribution: scp over the SSH mesh only — never OneDrive-wide shares, never git.
- Exit codes: 0 ok · 2 usage/config · 3 write denied · 4 server/transport error.