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>
95 lines
3.9 KiB
Markdown
95 lines
3.9 KiB
Markdown
---
|
|
id: ops-warden-adr-0003
|
|
type: adr
|
|
title: "ADR-0003 — Cover gaps, but never silently own them"
|
|
domain: infotech
|
|
repo: ops-warden
|
|
status: accepted
|
|
version: "1.0"
|
|
revision: "1"
|
|
owner: ops-warden
|
|
binds: "ops-warden"
|
|
created: "2026-07-01"
|
|
updated: "2026-08-18"
|
|
last_reviewed: "2026-08-18"
|
|
review_interval: 6m
|
|
enforced_by: "registry/routing/catalog.yaml delegation:; warden route gaps"
|
|
supersedes: ""
|
|
successor: ""
|
|
---
|
|
|
|
# ADR-0003 — Cover gaps, but never silently own them
|
|
|
|
## Status
|
|
|
|
Accepted. Stated as INTENT §9, made structural by WARDEN-WP-0030 (delegation
|
|
register).
|
|
|
|
## Context
|
|
|
|
ops-warden owns exactly one lane: SSH certificate issuance. It nonetheless fronts
|
|
around eleven credential lanes as a caller-identity proxy, because no other
|
|
component fronts them yet and a worker blocked on a credential is a worker blocked.
|
|
|
|
Covering a gap is legitimate and this repo intends to keep doing it. The failure is
|
|
subtler: **a cover that is never recorded as a cover becomes ownership by default.**
|
|
Nobody decides to permanently own another component's lane. It happens because the
|
|
interim arrangement worked, nobody wrote down that it was interim, and the intended
|
|
owner never learned they were expected to build a front door.
|
|
|
|
By August 2026 the primitive to hand a lane back existed and was proven — `exec_owner`
|
|
/ `exec_command`, used by secrets-engine for npm publish and by the railiance-platform
|
|
credential broker for warden-sign — and was used by 2 of 24 lanes. The other
|
|
twenty-two had no record of who *should* own them.
|
|
|
|
## Decision
|
|
|
|
**Every catalog entry carries a `delegation:` block**, with a `mode:` of:
|
|
|
|
| `mode` | Meaning |
|
|
| --- | --- |
|
|
| `permanent` | Ours forever. SSH certificate issuance, and nothing else |
|
|
| `native` | The owner has a front door; we route to it and execute nothing |
|
|
| `interim` | We are covering a gap. Requires `intended_owner:` and `blocked_on:` |
|
|
|
|
**`interim` without an `intended_owner` is not permitted.** If we cannot name who
|
|
should own it, we have not understood the lane well enough to be fronting it.
|
|
|
|
**`blocked_on:` must name a specific condition, not a mood.** "No front door yet" is
|
|
not a blocker; "secrets-engine has not confirmed whether `exec --catalog` generalizes
|
|
over arbitrary OpenBao lanes (asked 2026-08-11, msg 7d55d332)" is. A blocker with a
|
|
question and a date can be chased. A blocker without one is an excuse with a
|
|
timestamp.
|
|
|
|
**The interim set is queryable**: `warden route gaps` lists it with review dates and
|
|
staleness. A cover that nobody can enumerate is a cover nobody will retire.
|
|
|
|
**A blocker is a claim about the world at a date, and expires.** `reviewed:` is
|
|
bumped only on a real re-check, never inherited. This was learned the hard way:
|
|
`RISK-F-0001` invalidated one of our blockers within a day and nothing would have
|
|
re-checked it.
|
|
|
|
## Consequences
|
|
|
|
**Retiring a cover is a normal, expected event rather than a renegotiation.** When
|
|
an owner ships their front door the lane flips `interim` → `native`. This has
|
|
happened twice and both were routine.
|
|
|
|
**Other repos can see what we are holding for them.** The register is why key-cape
|
|
and user-engine were able to confirm or decline lanes in August 2026 — the question
|
|
was answerable because it had been written down. One of those answers was "not ours",
|
|
which is a legitimate and useful outcome.
|
|
|
|
**We accept looking worse than we are.** `warden route gaps` publishes a list of
|
|
things this repo is doing that it would rather not be doing. That is the intent: the
|
|
alternative is a repo that looks clean because nobody counted.
|
|
|
|
**This register is not a risk register.** Interim lanes are tracked work with an
|
|
owner and a date, not defects. They do not get bulk-filed into `risk-nexus`, which
|
|
needs to stay small enough to read. Defects go there; gaps stay here.
|
|
|
|
## Related
|
|
|
|
- `INTENT.md` §9 — the principle this formalizes
|
|
- `history/2026-08-11-delegation-surface-assessment.md` — the assessment that forced it
|
|
- `.claude/rules/finding-routing.md` — the register-versus-findings boundary
|