ops-warden/.claude/rules/finding-routing.md
tegwick 35aff380a3
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Lift ops-warden's binding rules into owned ADRs
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>
2026-08-18 13:35:13 +02:00

5.5 KiB

Finding routing (risk-nexus) and policy publication (policy-nexus)

Two estate repos exist that did not when most of ops-warden's practices were written. Both are owned by the-custodian and both are downstream by construction — the same rule ops-warden's own catalog lives under.

Repo Owns ops-warden's relationship
risk-nexus Findings, severity, disclosure timing, escalation, regulatory intake. Serves risk.coulomb.social Route findings to it. It does not fix; ops-warden fixes what ops-warden owns
policy-nexus Publication of canon and ADRs at permanent addresses. Serves policy.coulomb.social Source repo. It publishes; it never writes back

When a session discovers or receives a defect, route it

A design question is not a finding. A defect is. The distinction matters because ops-warden receives both through the same channel — the State Hub inbox.

This was gotten wrong on 2026-08-17. flex-auth reported directly to ops-warden that /v1/check authenticates no caller — a live authorization bypass in the service ops-warden's own pre-sign gate consults. ops-warden answered the design question well and wrote the recommendation into wiki/NetKingdomSecurityMap.md. It did not route the finding. rapp-postgres filed it as RISK-F-0001, which is why that record reads reported_via: rapp-postgres and not ops-warden, despite ops-warden being a first-hand recipient and the affected PEP.

The failure mode is exactly the one risk-nexus/INTENT.md names: "findings landed in whichever document was open." A wiki section answers the question; it does not carry a severity, an owner, a date, or a review that fires when nobody looks.

So: when an inbound message or a session turns up a defect — in any repo — answer it and route it. They are not alternatives.

How to route

Write the finding file into ~/risk-nexus/findings/ following RISK-F-0001/RISK-F-0002, and commit it there. This is the established pattern: a repo routes a finding by writing the record.

Leave severity, disclosure, and escalation unset. They are risk-nexus's to set, not the reporter's. The reporter says what is true; that repo says how bad it is and who hears about it. State exposure only as far as you can support it — do not infer a mitigating control (a NetworkPolicy, a deployment flag) on a system you do not own; say it should be verified.

What does not go there

risk-nexus/INTENT.md is explicit that a register nobody can read is worse than none: "if a finding would not change anyone's decision, it is a note, not a risk."

The delegation register is not a findings feed. warden route gaps lists interim lanes with an intended owner, a blocker and a review date — that is already tracked, already legible, and already ops-warden's. Do not bulk-file it. What goes to risk-nexus from ops-warden is a defect or an exposure, not a known gap that is being worked under a workplan.

Also re-read a blocker before trusting it. A blocker is a claim about the world at a date; RISK-F-0001 invalidated one of ops-warden's in a day and nothing would have re-checked it.

Escalation: ops-warden already solved this shape

risk-nexus carries an unwritten escalation duty — deciding what reaches the operator personally rather than sitting in a register — and says the rule "must be written down rather than exercised by instinct".

ops-warden shipped that classifier for the credential domain in WP-0029. warden plan "<need>" returns autonomous / founder_required / unroutable, and when it escalates it returns a typed act (approve, login, provision) plus the reasons that produced the verdict, with warden desk as the surface that actually executes the act. The transferable design properties:

  • escalation is decided by properties of the thing (lane type, status, request signals), not by the assessor's judgement in the moment
  • every verdict carries its reasons, so the rule is auditable after the fact
  • there is a typed act, so "needs the operator" says what the operator does
  • there is a real surface for the act, so escalation is not just a flag

Offer this rather than let a second, incompatible escalation vocabulary grow. Do not implement it for them — routing work is theirs to own.

Policy publication (closed 2026-08-18)

This section previously recorded that ops-warden had no ADRs and that its binding rules — the no-double-source catalog rule, conduit-not-broker, interim-by-default, the agent read-boundary — sat in wiki prose, unaddressable and unpublishable.

That is now resolved. They live in docs/adr/ as ADR-0001ADR-0005, each carrying owner: ops-warden, and each verified to render through policy-nexus's own tools/render.py. See .claude/rules/architecture.md for the owned-versus- inherited rule and the three-digit/four-digit ADR naming collision.

What matters when routing something to policy-nexus: it requires title, status and owner on every published document (tools/build_site.py:179), renders owner in both the page eyebrow and the index Owner column, and records source repo, path, revision and content digest in its manifest. Ownership survives publication — a reader landing on the URL can tell the rule is ours.

policy-nexus publishes and never writes back. The file in docs/adr/ is the source of truth; if the site disagrees, the site is the defect.

When you record a new binding rule, write the ADR. Not a wiki section — that is the habit this whole rule file exists to correct, in the other direction.