- 12 links in mother-hive.md (6 EN, 6 SL): ../packaging/ → ../../packaging/ (packaging/ lives at repo root, not under docs/) - Remove untracked astro/wiki/src/content/ (stray staging dir) - Add src/content/ to astro/wiki/.gitignore
5.7 KiB
1|# Mother hive
2|
3|← index
4|
5|## What this is
6|
7|The mother node (OSA) coordinates USB operator nodes via MCP over SSH →
8|PostgreSQL. USB nodes send hardware profiles; mother derives capabilities and
9|maintains the hive registry. This page records the decisions behind the
10|implementation — the rationale the code can't express. For setup instructions,
11|architecture diagrams, and the first-run checklist, see
12|packaging/mother/MOTHER-SETUP.md.
13|
14|## Decisions
15|
16|### Forced-command SSH boundary (not a listening daemon)
17|
18|USB nodes reach mother by spawning ssh colibri@mother (no remote command).
19|On the mother side, authorized_keys enforces
20|command="/usr/local/bin/colibri-mcp-ssh",restrict,... — the connection
21|cannot run an interactive shell or any command except the wrapper.
22|
23|The wrapper (colibri-mcp-ssh) further allowlists SSH_ORIGINAL_COMMAND to
24|"" (stdio MCP mode) or "tools" (one-shot discovery). Every other value is
25|rejected.
26|
27|Why not a listening daemon (HTTP, gRPC, raw TCP): Tailscale encrypts the
28|wire, so the SSH layer adds authentication + confinement without extra
29|infrastructure (no TLS certs, no auth tokens, no open ports). The forced-command
30|boundary is a second lock on top of the SSH key — even a compromised USB that
31|holds the key can only invoke the wrapper, and the wrapper only delegates to
32|colibri-mcp. Defense in depth, deployed as one OpenSSH feature.
33|
34|→ colibri-mcp-ssh, MOTHER-SETUP.md §Security
35|
36|### Single home for mother infra (colibri, not clawdie-iso)
37|
38|The mother MCP scripts (node-register-mcp, geodesic-dome-mcp, etc.) were
39|originally copied into both repos. The clawdie-iso copy drifted — its
40|node-register-mcp used E'${...}' string interpolation (SQL-injectable)
41|while the colibri copy used parameterized psql -v :'variable'. The iso copy
42|was removed in clawdie-iso PR #129.
43|
44|Lesson: a script in two repos will drift. The wiki lint is single-repo
45|and can't see cross-repo duplicates. The mitigation is discipline: mother infra
46|lives in one place.
47|
48|→ naming-decisions §Structural ("Single home" row)
49|
50|### hive_nodes — not usb_nodes
51|
52|The original table name assumed only USB-booted nodes would register. But a
53|node is any host that joins the hive — USB, NVMe, a jail. Renamed to
54|hive_nodes with a node_type column (colibri #161). The derive_capabilities()
55|trigger is table-agnostic and auto-computes has_gpu, gpu_vendor,
56|can_run_local_llm, has_wifi, max_model on INSERT.
57|
58|→ mother_schema.sql,
59|naming-decisions (usb_nodes → hive_nodes row)
60|
61|### PostgreSQL peer auth (no passwords)
62|
63|The colibri OS user connects to mother_hive via peer authentication — the
64|kernel attests the Unix user, no password needed. node-register-mcp runs as
65|this user and inherits the trust. No pgpass files, no env vars, no credential
66|rotation. One moving part: the pg_hba.conf peer rule must precede any
67|catch-all local all all line (first-match).
68|
69|Why not a password or certificate: passwords rotate and leak; certificates
70|need a CA. Peer auth is built into PostgreSQL on every Unix and works for a
71|localhost connection with zero configuration beyond one pg_hba.conf line.
72|
73|→ MOTHER-SETUP.md §Setup step 6
74|
75|### Key on seed partition, not in the image
76|
77|The mother-mcp private key is placed on the CLAWDIESEED partition, not baked
78|into the ISO. The build script has a release guard that refuses to bake it
79|into a release image. The seed importer (clawdie-live-seed) installs it at
80|boot time.
81|
82|Why: a release ISO is a downloadable artifact. Baking a private key into it
83|would give every downloader access to the mother MCP. The seed partition is a
84|separate physical medium that the operator controls. Even without a seed, the
85|ISO boots and runs — the daemon's external MCP connection to mother fails
86|gracefully (SSH: "config file not found"), and the node operates standalone.
87|
88|→ naming-decisions ("Known residue"), clawdie-iso #133
89|
90|### Daemon user, not operator
91|
92|The colibri daemon runs as the colibri user (/var/db/colibri), not as the
93|operator (clawdie, /home/clawdie). The external MCP SSH connection to mother
94|is spawned by the daemon — so the SSH key, config, and known_hosts must be in
95|the daemon's home. The seed importer installs SSH material to both homes
96|(operator + daemon).
97|
98|Why not just put it in clawdie's home and sudo: the daemon is not the
99|operator. Running as a separate user means the blast radius of a daemon
100|compromise is limited to what the colibri user can do — MCP calls to mother,
101|not operator files or sudo.
102|
103|→ clawdie-live-seed (clawdie-iso),
104|MOTHER-SETUP.md §Key management
105|
106|## See also
107|
108|- agent-harness — the zot/Colibri split; autospawn
109|- naming-decisions — usb_nodes → hive_nodes, autospawn flag rename
110|- quality-gates — the gate that should catch drift at PR time
111|