# 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 --no-policy --out /tmp/nc.token warden access railiance-backup-offsite-lane --no-policy --wrap warden access railiance-backup-offsite-lane --no-policy --fingerprint ``` `warden route show --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`