Five rules that governed this repo lived in wiki prose, a workplan, and a comment at the top of catalog.yaml. All were followed; none was addressable. A reader outside ops-warden could not cite one, could not tell whether it was current, and — the point of this change — could not tell whether it was ours to change or someone else's that we merely obey. ADR-0001 The routing catalog is a pointer layer, never a second copy ADR-0002 ops-warden is a transparent conduit, never a secret broker ADR-0003 Cover gaps, but never silently own them ADR-0004 High-risk lanes refuse raw value streaming to agent sessions ADR-0005 Implement one lane narrowly, route everything else Each carries owner: ops-warden, which is the load-bearing field. It says we follow the rule AND we are responsible for changing it — by superseding ADR, never an in-place edit. The failure this prevents runs both ways: a rule we own mistaken for inherited canon never gets fixed, because we wait for an owner who does not exist; inherited canon mistaken for ours gets quietly bent, and the drift is invisible until it breaks a repo that trusted the canonical version. Rules we follow but do not own — NetKingdom canon, the IAM profile, the credential-management standard, the-custodian's ADR-001 workplan convention — are cited, never copied into docs/adr/. Copying them would recreate exactly the second-source-of-truth failure ADR-0001 exists to prevent. architecture.md also now flags the three-digit/four-digit ADR-001 vs ADR-0001 collision, which is itself an ours-versus-inherited confusion waiting to happen. Publication verified rather than assumed: all five render through policy-nexus tools/render.py, and owner reaches the reader in three places — the page eyebrow (render.py:346), the index Owner column (build_site.py:123,137), and the publication manifest. build_site.py:179 makes title/status/owner required, so ownership cannot be dropped on the way out. policy-nexus publishes and never writes back; docs/adr/ stays the source of truth. Documentation adapted: SCOPE.md gains a Governing rules section and an orientation entry; .claude/rules/architecture.md replaced its stub with the ADR index, the owned-versus-inherited rule, and ADR-over-wiki precedence; finding-routing.md's ADR-gap section closed; catalog.yaml's no-double-source header now cites ADR-0001 rather than the originating workplan. uv run pytest -q → 338 passed, 4 deselected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
79 lines
3.2 KiB
Markdown
79 lines
3.2 KiB
Markdown
---
|
|
id: ops-warden-adr-0005
|
|
type: adr
|
|
title: "ADR-0005 — Implement one lane narrowly, route everything else"
|
|
domain: infotech
|
|
repo: ops-warden
|
|
status: accepted
|
|
version: "1.0"
|
|
revision: "1"
|
|
owner: ops-warden
|
|
binds: "ops-warden"
|
|
created: "2026-06-18"
|
|
updated: "2026-08-18"
|
|
last_reviewed: "2026-08-18"
|
|
review_interval: 6m
|
|
enforced_by: "SCOPE.md; registry/routing/catalog.yaml warden_executes"
|
|
supersedes: ""
|
|
successor: ""
|
|
---
|
|
|
|
# ADR-0005 — Implement one lane narrowly, route everything else
|
|
|
|
## Status
|
|
|
|
Accepted. The founding charter decision, taken 2026-06-18
|
|
(`history/2026-06-18-access-routing-intent-shift-assessment.md`).
|
|
|
|
## Context
|
|
|
|
ops-warden began as an SSH certificate manager. It then became the place workers
|
|
asked when they did not know where a credential came from — which is a real need,
|
|
and the obvious way to serve it is to start fetching credentials.
|
|
|
|
Down that path is a component that issues SSH certificates, vends API keys, brokers
|
|
tokens, and holds authority over all of them: a single point whose compromise is
|
|
total. NetKingdom's architecture deliberately separates identity (key-cape),
|
|
authorization (flex-auth), and secrets (OpenBao). A helpful front door that absorbed
|
|
all three would quietly undo that separation, one convenience at a time.
|
|
|
|
## Decision
|
|
|
|
**ops-warden executes exactly one lane with its own authority: SSH certificate
|
|
issuance for `adm`/`agt`/`atm` actors.** `warden_executes: true` appears on one
|
|
catalog entry and is expected to stay that way.
|
|
|
|
**For every other need it routes, and where the lane is `exec_capable` it may assist
|
|
by proxying as the caller** under `ADR-0002`. Routing is not a lesser service — it is
|
|
the service. Knowing which subsystem owns a need, and being right about it, is what
|
|
this repo sells.
|
|
|
|
**Scope growth is tested by ownership, not by usefulness.** "Would this be handy in
|
|
ops-warden?" is the wrong question and almost always answers yes. The right question
|
|
is "does ops-warden have the authority to own this, permanently?" If the answer is no,
|
|
the correct outcome is a pointer, or an `interim` cover recorded under `ADR-0003`.
|
|
|
|
## Consequences
|
|
|
|
**The blast radius stays bounded and known.** Compromising ops-warden yields the SSH
|
|
signing lane. That is worth defending well precisely because it is the only thing here.
|
|
|
|
**We say no to requests that would be easy to say yes to.** `warden secret`,
|
|
`warden login`, `warden bao`, `warden tunnel` do not exist and must not be invented;
|
|
the agent instructions name them as anti-patterns because agents keep reaching for
|
|
them. Each would be a day's work and a permanent widening.
|
|
|
|
**Being useful therefore depends on the pointers being right**, which is the whole
|
|
weight behind `ADR-0001`'s anchor enforcement and the catalog's review dates. A router
|
|
that routes wrongly is worse than no router.
|
|
|
|
**It leaves real gaps visible rather than filled.** Six workload lanes and three
|
|
tenant lanes are covered interim because secrets-engine and tenant-engine have not
|
|
shipped front doors. Under this ADR that is the correct state, tracked under
|
|
`ADR-0003`, and not a signal that ops-warden should absorb them.
|
|
|
|
## Related
|
|
|
|
- `SCOPE.md` — the issue-vs-route table
|
|
- `wiki/AccessRouting.md` — role and boundary
|
|
- `ADR-0001`, `ADR-0002`, `ADR-0003` — the three rules that follow from this one
|