feat: ship agent-first mission control v0.2.57
This commit is contained in:
@@ -1,84 +1,80 @@
|
||||
# Agent Identity Architecture (P4)
|
||||
# Agent identity architecture
|
||||
|
||||
> Status: ✅ Implemented (2026-07-13)
|
||||
> Task: `4291d694-dd40-410d-b0d5-4742d334547a`
|
||||
> Status: Live OpenClaw RPC authority implemented and verified on 2026-07-30.
|
||||
> The former `agents-sanitized.json` design is retired.
|
||||
|
||||
## Problem
|
||||
## Authority contract
|
||||
|
||||
Nexus needed agent identity data (id, name, role, sub-agents, model) for the board/bridge
|
||||
operations, but reading directly from `/home/node/.openclaw/openclaw.json` would expose
|
||||
secrets (gateway password, API keys, auth profiles, channel tokens).
|
||||
OpenClaw is the sole runtime authority for agent identity, model assignment,
|
||||
workspace metadata and agent bootstrap files. Nexus does not copy that data
|
||||
into a second configuration and does not derive a host path from an agent ID.
|
||||
|
||||
## Solution: Sanitized Agent Config File
|
||||
```text
|
||||
OpenClaw Gateway
|
||||
agents.list
|
||||
|
|
||||
v
|
||||
Nexus backend
|
||||
IOpenClawControlService
|
||||
|
|
||||
+--> /api/v1/agents
|
||||
+--> /api/v1/agents/{id}
|
||||
+--> Dashboard and allow-listed agent operations
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
openclaw.json (full config, SECRETS)
|
||||
│
|
||||
├── Deploy-time: jq extract → agents-sanitized.json (NO secrets)
|
||||
│ └── deploy-nexus.sh: extracts only {"agents": ...} from openclaw.json
|
||||
│
|
||||
├── Manual sync: scripts/sync-agents-sanitized.mjs
|
||||
│ └── node scripts/sync-agents-sanitized.mjs --once
|
||||
│
|
||||
└── Nexus API reads: agents-sanitized.json (read-only mount in compose)
|
||||
├── AgentService.LoadAgentConfigsAsync()
|
||||
├── OpenClawGatewayClient.LoadAgentIdsFromConfig()
|
||||
└── AgentService.GetAllowedAgentIdsAsync()
|
||||
OpenClaw Gateway
|
||||
agents.files.list/get/set
|
||||
agents.workspace.list/get
|
||||
|
|
||||
v
|
||||
Nexus owner-only agent configuration facade
|
||||
```
|
||||
|
||||
### Key Design Decisions
|
||||
New OpenClaw agents therefore appear without a Compose change, deploy-time
|
||||
sanitizer or static fallback catalog.
|
||||
|
||||
1. **Single sanitized source**: `agents-sanitized.json` contains ONLY the `agents` key
|
||||
(list + defaults) — no `gateway`, `auth`, `channels`, `tools`, `plugins`, etc.
|
||||
|
||||
2. **Read-only mount**: Compose mounts as `:ro` — no write access from the API container
|
||||
## Security properties
|
||||
|
||||
3. **No ACL dependency**: No uid-1654 ACL needed; the sanitized file is root-owned and
|
||||
world-readable
|
||||
- The browser talks only to typed Nexus endpoints; it never receives Gateway
|
||||
credentials, provider credentials or raw OpenClaw configuration.
|
||||
- `agents.list` supplies the current allow-list. A caller-provided agent ID is
|
||||
metadata after authentication, not identity proof.
|
||||
- Supported bootstrap files use `agents.files.*`. Writes require owner,
|
||||
management consent, advertised capability, `operator.admin`,
|
||||
`Idempotency-Key`, `expectedHash`, pre-write re-read and post-write
|
||||
verification.
|
||||
- Additional files use `agents.workspace.*` and remain read-only because the
|
||||
pinned OpenClaw contract has no safe arbitrary workspace-write RPC.
|
||||
- Nexus never reads `openclaw.json` and never maps an agent ID to
|
||||
`/mnt/workspace-{agentId}`.
|
||||
- The separate Memory, Docs and Incidents surfaces may retain one explicitly
|
||||
configured, confined Iris content root until equivalent safe OpenClaw RPCs
|
||||
exist. That bounded compatibility reader is not an agent-identity or
|
||||
per-agent-configuration source.
|
||||
|
||||
4. **Graceful fallback**: If the sanitized file is missing, both `AgentService` and
|
||||
`OpenClawGatewayClient` fall back to hardcoded agent IDs from `AgentIdentityCatalog`
|
||||
## Retired design
|
||||
|
||||
5. **Auto-sync on deploy**: The deploy pipeline (`deploy-nexus.sh`) regenerates the
|
||||
sanitized file from `openclaw.json` using `jq` in an alpine container
|
||||
The 2026-07-13 implementation generated and mounted
|
||||
`agents-sanitized.json`. It also depended on a static fallback catalog and
|
||||
required deployment synchronization. The 2026-07-30 RPC cutover removed these
|
||||
production dependencies:
|
||||
|
||||
6. **Manual sync available**: `scripts/sync-agents-sanitized.mjs` provides on-demand
|
||||
and watch-mode sync
|
||||
- no `AgentConfigPath`;
|
||||
- no sanitized-agent Compose mount;
|
||||
- no deploy-time or watch-mode sanitizer;
|
||||
- no hardcoded fallback as runtime authority; and
|
||||
- no fixed workspace derivation.
|
||||
|
||||
### File Layout
|
||||
## Verification
|
||||
|
||||
| File | Location | Purpose |
|
||||
|------|----------|---------|
|
||||
| `openclaw.json` | `/home/node/.openclaw/openclaw.json` | Full config with secrets (gateway only) |
|
||||
| `agents-sanitized.json` | `/home/node/.openclaw/agents-sanitized.json` | Agents-only, no secrets |
|
||||
| Compose mount | `compose.yaml` → API container | `agents-sanitized.json:ro` |
|
||||
| Deploy sanitizer | `.gitea/scripts/deploy-nexus.sh` | jq extraction on deploy |
|
||||
| Sync script | `scripts/sync-agents-sanitized.mjs` | Node.js manual/watch sync |
|
||||
| Config path | `backend/appsettings.json` | `AgentConfigPath` key |
|
||||
The final 2026-07-30 backend suite passed 312/312 tests. Focused tests cover
|
||||
live inventory, nonstandard workspace metadata such as `workspace-po`, session
|
||||
model resolution, file hash conflicts, verified read-back and session-history
|
||||
fallback. Repository search found no remaining `AgentConfigPath`,
|
||||
`agents-sanitized` or `/mnt/workspace-{agentId}` dependency in production
|
||||
backend code or backend tests.
|
||||
|
||||
### Security Guarantees
|
||||
Canonical integration and release boundaries are documented in:
|
||||
|
||||
- ✅ No `password`, `token`, `secret`, or `api_key` values in `agents-sanitized.json`
|
||||
- ✅ API endpoints (`/api/v1/agents`, `/api/v1/agents/{id}`) return ZERO secrets
|
||||
- ✅ Gateway bridge controller (`/api/bridge/*`) uses only agent IDs from sanitized config
|
||||
- ✅ No direct `openclaw.json` reads in any C# code path
|
||||
- ✅ Agent identity catalog (`AgentIdentityCatalog`) is a hardcoded fallback, not a primary source
|
||||
|
||||
### Verification
|
||||
|
||||
```bash
|
||||
# Check sanitized file has no secrets
|
||||
curl -s http://nexus-api-1:8080/api/v1/agents \
|
||||
-H "X-Api-Key: <key>" | grep -i "password\|secret\|token\|apikey"
|
||||
# Expected: no output
|
||||
|
||||
# Verify only "agents" key exists in sanitized file
|
||||
python3 -c "
|
||||
import json
|
||||
with open('agents-sanitized.json') as f:
|
||||
data = json.load(f)
|
||||
print(list(data.keys())) # Should print ['agents']
|
||||
"
|
||||
```
|
||||
- `docs/OPENCLAW_GATEWAY_CONNECTION.md`
|
||||
- `docs/AGENT_FIRST_MISSION_CONTROL.md`
|
||||
- `docs/audits/2026-07-30/openclaw-attach-adopt/IMPLEMENTATION_AND_ACCEPTANCE.md`
|
||||
|
||||
Reference in New Issue
Block a user