--- id: ops-warden-adr-0002 type: adr title: "ADR-0002 — ops-warden is a transparent conduit, never a secret broker" domain: infotech repo: ops-warden status: accepted version: "1.0" revision: "1" owner: ops-warden binds: "ops-warden" created: "2026-06-26" updated: "2026-08-18" last_reviewed: "2026-08-18" review_interval: 6m enforced_by: "src/warden/access.py; wiki/OperatorAccessAssist.md" supersedes: "" successor: "" --- # ADR-0002 — ops-warden is a transparent conduit, never a secret broker ## Status Accepted. Decided during WARDEN-WP-0014 (operator access assist), tightened by WARDEN-WP-0026 (disclosure hygiene). ## Context `warden access` is the operator front door for every credential need in the estate. For lanes marked `exec_capable` it does more than advise: it runs the owner's tool and returns the value. Anything that fetches secrets on request looks like a broker, and the gravity toward becoming one is strong — a broker is more convenient at every individual call site. The distinction is not stylistic. A broker holds authority; a conduit borrows the caller's. Only one of those creates a new thing worth attacking. ## Decision **ops-warden runs the owner's tool with the caller's own identity, and takes no custody of the value.** The caller's credentials do the work. ops-warden holds nothing after the command returns, stores nothing, and caches nothing. **Forbidden: a standing broker.** ops-warden must not hold its own long-lived secret-read credential in order to serve values to callers who could not have fetched them themselves. If the caller lacks authority, the correct outcome is a denial from the owner's system — not a fetch performed on their behalf by a more privileged intermediary. The test is a question: *could the caller have run this themselves?* If yes, we are a conduit and may proxy. If no, proxying is privilege laundering and is refused. **Owner-native front doors outrank the proxy.** Where an owner has shipped their own exec surface — `secrets-engine exec`, the railiance-platform credential broker — we route there and do not proxy. The proxy is a fallback for lanes nobody fronts yet, not a preferred path. This is why `whynot-design-npm-publish` and `ops-warden-warden-sign-token` are `native` rather than `interim`. **The value must not land somewhere it will be logged.** Sanctioned transports are `--out` (mode-0600 file), `--exec` (child process env), and `--wrap` (a single-use OpenBao wrapping token). Streaming to a non-terminal stdout is refused without an explicit `--unsafe-stdout`, which exists for interactive humans only. ## Consequences **ops-warden never becomes a credential store, and gains no value by being compromised beyond the SSH CA it already holds.** This is the whole point. An attacker who owns ops-warden gets the SSH signing lane — serious, bounded, and already the thing this repo is hardened around — not a key to every secret in the estate. **Some requests cannot be served, and that is the correct answer.** When a caller lacks authority, ops-warden routes and explains rather than fetching. This reads as unhelpfulness at the moment it happens; it is the property that makes the front door safe to point every agent at. **Every proxied fetch is auditable and attributable to the caller**, because it ran as them. `audit.jsonl` records metadata only — never values, guarded in code. **The `--unsafe-stdout` escape hatch is a known liability.** It exists because humans in terminals legitimately need to see values. It is also exactly the shape of the 2026-07-16 disclosure, where a value reached a captured stdout. `ADR-0004` constrains it further for agent sessions. ## Related - `wiki/OperatorAccessAssist.md#the-conduit-vs-broker-boundary-the-security-model` - `ADR-0004` — the agent-session read boundary built on top of this - `ADR-0003` — why proxied lanes are tracked as interim rather than owned