Skip to content

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

  1. CLI parses verb + options; harness identity from MEMBUS_HARNESS/--harness (never guessed).
  2. Scope.TryParse — closed grammar (house-all, local-llms-house, {family}-house, council:<pc>, frontier:<pc>); anything else = usage error.
  3. Allowlist check; council scopes default TTL 14 days.
  4. Provenance.For(...) stamps scope, origin_harness, origin_machine, timestamp, trust_level, ttl_days, dedupe_key, schema_version into the memory's metadata.
  5. MemBusClient.SendAsync posts {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 ANDYGREATROOMPC requires 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.