From 8010ab3b3cb8f2248a36ea2be4b64742d4e7d86d Mon Sep 17 00:00:00 2001 From: Clawdie AI Date: Sun, 19 Apr 2026 08:32:29 +0200 Subject: [PATCH] docs: document hostd API proxy architecture for jail agents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hostd-bridge now routes through the controlplane API instead of direct Unix socket. 6 files updated: - ARCHITECTURE.md: jail isolation section — hostd via API, no socket mount - doc/CONTROLPLANE-ARCHITECTURE.md: hostd tree shows API proxy route - doc/CONTROLPLANE-MESSAGE-CONTRACT.md: add POST /api/controlplane/hostd endpoint with request/response examples - docs/public/operate/security.md: hostd section describes HTTP proxy model with CONTROLPLANE_SHARED_SECRET auth - .env.example: document CONTROLPLANE_HOST_IP (default 10.0.1.1) - doc/HANDOFF-ISO-AGENT.md: add sections 4 (hostd API proxy) and 5 (legacy agent ID removal) to breaking changes Build: pass | Tests: not run (Linux) (Sam & Claude) --- .env.example | 2 ++ ARCHITECTURE.md | 2 ++ doc/CONTROLPLANE-ARCHITECTURE.md | 1 + doc/CONTROLPLANE-MESSAGE-CONTRACT.md | 26 ++++++++++++++++++++++++++ doc/HANDOFF-ISO-AGENT.md | 16 ++++++++++++++++ docs/public/operate/security.md | 2 ++ 6 files changed, 49 insertions(+) diff --git a/.env.example b/.env.example index 7a03de6..ff7f6d3 100644 --- a/.env.example +++ b/.env.example @@ -190,6 +190,8 @@ CONTROLPLANE_NAME=clawdie CONTROLPLANE_DAILY_TOKENS=100000 CONTROLPLANE_PORT=3100 CONTROLPLANE_BIND_HOST=0.0.0.0 +# IP address that jailed agents use to reach the host API (default: 10.0.1.1). +# CONTROLPLANE_HOST_IP=10.0.1.1 CONTROLPLANE_AUTH_MODE=local_trusted # Shared secret for agent-to-API Bearer token auth (required for agent subprocesses). # Generate with: openssl rand -base64 32 diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index d5d8ad3..4a65e52 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -77,6 +77,8 @@ Skills are injected as a compact index (~200 tokens) instead of full content (~1 When `CONTROLPLANE_JAIL_ISOLATION=YES`, specialist agents run inside dedicated thin jails. Each jail gets scoped secrets (DB creds for db-worker, SSH keys for git-worker) and restricted network access via PF. Feature flag defaults to `NO`. +Jail agents reach hostd **through the controlplane API** (`POST /api/controlplane/hostd`), not via direct Unix socket. The API authenticates the request and proxies to the hostd daemon. This means no socket mount is needed inside jails — only network access to `CONTROLPLANE_HOST_IP:CONTROLPLANE_API_PORT`. + ## Split-Brain Database All three databases run on the same PostgreSQL 18 instance, each with its own user and permissions: diff --git a/doc/CONTROLPLANE-ARCHITECTURE.md b/doc/CONTROLPLANE-ARCHITECTURE.md index c79de2b..87ccfb2 100644 --- a/doc/CONTROLPLANE-ARCHITECTURE.md +++ b/doc/CONTROLPLANE-ARCHITECTURE.md @@ -48,6 +48,7 @@ HOST (osa) │ ├── hostd daemon (existing) │ └── Privileged ops (bastille, zfs, pf) via Unix socket +│ └── API proxy: POST /api/controlplane/hostd (for jail agents) │ └── PostgreSQL jail (10.0.0.3, existing) ├── clawdie_ai_* tables (existing) diff --git a/doc/CONTROLPLANE-MESSAGE-CONTRACT.md b/doc/CONTROLPLANE-MESSAGE-CONTRACT.md index 8bac2ee..4e4e28f 100644 --- a/doc/CONTROLPLANE-MESSAGE-CONTRACT.md +++ b/doc/CONTROLPLANE-MESSAGE-CONTRACT.md @@ -122,6 +122,32 @@ Authorization: Bearer {CONTROLPLANE_SHARED_SECRET} } ``` +### 6. Proxy hostd Operation (jail agents) + +Jail agents use this endpoint to execute privileged host operations (bastille, zfs, pf) through the controlplane API instead of direct Unix socket access. + +```http +POST /api/controlplane/hostd +Authorization: Bearer {CONTROLPLANE_SHARED_SECRET} + +{ + "op": "bastille-list", + "params": {} +} +``` + +**Response:** + +```json +{ + "ok": true, + "output": "JID IP Address Hostname Path", + "exitCode": 0 +} +``` + +The API proxies the request to the hostd daemon on the host. Available ops match those in `src/hostd/privileged-commands.ts` (bastille-list, bastille-cmd, zfs-snapshot, etc.). + --- ## Agent Posts diff --git a/doc/HANDOFF-ISO-AGENT.md b/doc/HANDOFF-ISO-AGENT.md index 604d84c..421694e 100644 --- a/doc/HANDOFF-ISO-AGENT.md +++ b/doc/HANDOFF-ISO-AGENT.md @@ -56,6 +56,22 @@ - rc.d service uses `run-${AGENT_NAME}.sh` written by `generateRunScript()` - ISO should run `just setup-service` which generates the correct script +### 4. hostd routed through controlplane API (cac8b4a) + +- Jail agents no longer connect to hostd Unix socket directly +- `hostd-bridge.ts` rewritten as HTTP client → `POST /api/controlplane/hostd` +- API authenticates via `CONTROLPLANE_SHARED_SECRET`, proxies to hostd daemon +- No socket mount needed in jails — only network access to host IP +- New config var: `CONTROLPLANE_HOST_IP` (default `10.0.1.1`) — IP jails use to reach the API +- Jail env `CONTROLPLANE_API_URL` now uses `http://${CONTROLPLANE_HOST_IP}:${CONTROLPLANE_API_PORT}` instead of `localhost` + +### 5. Legacy agent IDs removed (0f7fbc4) + +- 8 agents → 5 agents (removed `sysadmin`, `db-admin`, `git-admin` alias rows) +- `resolveCanonicalAgentId()` removed — identity function since legacy IDs gone +- `CANONICAL_AGENT_MAP` deleted, `AGENT_JAIL_MAP` trimmed to canonical IDs only +- Role constraint in schema updated (removed legacy role values) + ## What still works unchanged - `.pi/extensions/clawdie-harness/skill-tools.ts` — self-contained, reads `/opt/skills` in jails diff --git a/docs/public/operate/security.md b/docs/public/operate/security.md index 0b13258..95d73d2 100644 --- a/docs/public/operate/security.md +++ b/docs/public/operate/security.md @@ -60,6 +60,8 @@ At runtime, privileged host operations from the agent go through `hostd` The agent user calls `hostd(op, params)`; the daemon validates params with Zod and runs the handler as root. Unknown ops and invalid params are rejected. +**Jail agents call hostd through the controlplane API** (`POST /api/controlplane/hostd`), not via direct socket. The extension's `hostd-bridge.ts` sends an HTTP request to the API, which authenticates via `CONTROLPLANE_SHARED_SECRET` and proxies to the hostd daemon. This eliminates the need to mount the Unix socket into jails — only network access to the host IP is required. + Shell injection prevention: `hostd` applies Zod regex validators on all string parameters in `src/privileged-commands.ts` — `jailName`, `datasetName`, `snapshotTag`, and `serviceName` must match strict patterns before any command