feat: ship agent-first mission control v0.2.57
CI - Build & Test / Backend (.NET) (push) Successful in 42s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 2m46s
CI - Build & Test / Security Check (push) Successful in 3s
CI - Build & Test / Deploy Nexus (push) Successful in 56s

This commit is contained in:
AzuTear
2026-07-31 22:39:47 +02:00
parent 3bc7622977
commit f5552218bc
535 changed files with 95242 additions and 8791 deletions
+64 -68
View File
@@ -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`