ops-warden/wiki/playbooks/agent-read-boundary.md
tegwick 7ce58ae638
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
feat: adopt security zones and explicit workload refs
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0291a-1e87-7151-9934-fcbfe3f65eb1
2026-08-22 15:36:37 +02:00

78 lines
2.8 KiB
Markdown

# Agent read-boundary on high-risk lanes
Date: 2026-07-16
Workplan: WARDEN-WP-0026 T04
OpenBao policy: `railiance-platform/openbao/policies/agent-high-risk-boundary.hcl`
Coding agents must not hold **raw data-read** on high-risk secrets. They may
inspect **capabilities** and **metadata**, and may receive values only through
sanctioned transports (file / exec env / response-wrapping token) under a human
operator identity.
---
## Risk classification (catalog `risk:`)
| Class | Criteria | Catalog default |
| --- | --- | --- |
| `high` | Recovery escrow (e.g. age private keys), upload tokens to external stores, site-admin PATs, high-spend provider keys | explicit `risk: high` |
| `standard` | Ordinary workload secrets (ESO-fed API keys without escrow/admin blast radius) | omitted / `standard` |
**Current high-risk lanes (ops-warden catalog):**
| Catalog id | Why high |
| --- | --- |
| `railiance-backup-offsite-lane` | Nextcloud upload + `AGE_PRIVATE_KEY` recovery escrow |
| `forgejo-admin-api-token` | Forgejo site-admin PAT |
| `openrouter-llm-connect` | Provider key (spend + prompt-adjacent) |
| `binky-company-email-imap` | Tenant mailbox IMAP password (`tenants/binky/…`) |
Keep this table in sync with `risk: high` rows in `registry/routing/catalog.yaml`
and path denials in `agent-high-risk-boundary.hcl`.
---
## OpenBao side
1. **Operator OIDC roles** keep `workload-kv-read-*` for the lane (data `read`).
2. **Agent identities** attach `agent-high-risk-boundary` (or equivalent) and
**must not** also attach the lane's `workload-kv-read-*` policy.
3. Verify with capabilities only (never `kv get` for deny tests):
```bash
# Agent-shaped token
AGENT=$(bao token create -policy=agent-high-risk-boundary -ttl=5m -field=token)
bao token capabilities "$AGENT" platform/data/workloads/railiance/backup/offsite-lane
# → deny
bao token capabilities "$AGENT" platform/metadata/workloads/railiance/backup/offsite-lane
# → read
bao token revoke "$AGENT"
```
Wrapped/proxied access for agents: a human operator (or credential broker with
response-wrap) fetches under an operator identity and delivers via
`warden access … --wrap` / `--out` / `--exec`. Agents do not unwrap into chat.
---
## ops-warden side
When `WARDEN_AGENT_ID` is set and the lane is `risk: high`, `warden access --fetch`
**refuses raw value streaming** (exit 7). Use:
```bash
export WARDEN_AGENT_ID=grok # or claude, codex
warden access railiance-backup-offsite-lane --out /tmp/nc.token
warden access railiance-backup-offsite-lane --wrap
warden access railiance-backup-offsite-lane --fingerprint
```
`warden route show <id> --json` includes `"risk"` and `"high_risk"`.
---
## See also
- `.claude/rules/credential-routing.md` — safe transports
- `wiki/playbooks/exposed-taint.md` — EXPOSED metadata convention
- `history/2026-07-16-credential-disclosure-lessons.md`