From d7f4ebcfe0769dc704b37f5dbac14957ec826318 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 21:55:33 +0200 Subject: [PATCH 1/3] Re-emit the high-risk path artifact after the NetKingdom SSO lanes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit c374d41 added net-kingdom-lldap-bind-credential and net-kingdom-privacyidea-admin-token as `risk: high` and did not re-run the emitter, so registry/generated/high-risk-data-paths.yaml still described the catalog at 0fae090. railiance-platform consumes that file instead of hand-maintaining its deny list, and it has been reading a census two lanes short since 2026-08-23. This is precisely the drift WARDEN-WP-0033-T03 built the guard for — a lane graded high after the last emit silently failing to reach the consumer. The guard fired; nothing had acted on it. The deny list itself does not move: both lanes are blocked on their OpenBao path being published, so they land in `no_concrete_path` and concrete_path_count stays 14. What changes is the count the consumer sees — 23 high-risk lanes, two of which have no address yet. That is the honest signal and the reason the bucket is listed rather than omitted. check_agent_read_boundary.py still reports 0 uncovered. The workload-join census moves 9 -> 11 not-applicable: both lanes are provider/control-plane credentials rather than workload delivery lanes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- registry/generated/high-risk-data-paths.yaml | 10 ++++++---- tests/test_workload_join.py | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/registry/generated/high-risk-data-paths.yaml b/registry/generated/high-risk-data-paths.yaml index 6c2c341..a0b7ea0 100644 --- a/registry/generated/high-risk-data-paths.yaml +++ b/registry/generated/high-risk-data-paths.yaml @@ -10,12 +10,12 @@ # declares it, and is null where the field set has not been established -- # null means unknown, never 'one field'. -generated_at: "2026-08-22T23:31:10Z" +generated_at: "2026-08-28T19:54:29Z" source: ops-warden/registry/routing/catalog.yaml -catalog_revision: "0fae0904ce8d8694338dd53a8a79abec5fec788d" -catalog_revision_date: "2026-08-23T01:31:05+02:00" +catalog_revision: "c374d41a4925720ae7706dfda020537b60a07eb9" +catalog_revision_date: "2026-08-23T21:43:12+02:00" catalog_dirty: false -high_risk_lane_count: 21 +high_risk_lane_count: 23 concrete_path_count: 14 # Graded high but not a single KV address -- a routing pattern, a broker @@ -23,6 +23,8 @@ concrete_path_count: 14 no_concrete_path: - database-dynamic-credentials - inter-hub-bootstrap-ssh + - net-kingdom-lldap-bind-credential + - net-kingdom-privacyidea-admin-token - object-storage-sts - openbao-api-key - openbao-platform-admin-login diff --git a/tests/test_workload_join.py b/tests/test_workload_join.py index 559a875..dab4df8 100644 --- a/tests/test_workload_join.py +++ b/tests/test_workload_join.py @@ -14,7 +14,9 @@ def test_repo_catalog_uses_only_explicit_workload_references(): assert report["ok"] is True assert len(report["resolved"]) == 3 assert len(report["unknown"]) == 17 - assert len(report["not_applicable"]) == 9 + # 11 since WARDEN-WP-0033: the two NetKingdom SSO lanes (c374d41) are + # provider/control-plane credentials, not workload delivery lanes. + assert len(report["not_applicable"]) == 11 assert {row["lane"] for row in report["resolved"]} == { "ops-warden-warden-sign-token", "issue-core-ingestion-api-key", From ee94c189385271194f22a53998b2c6e12e961ea9 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 22:00:09 +0200 Subject: [PATCH 2/3] =?UTF-8?q?WARDEN-WP-0033=20finished=20=E2=80=94=20key?= =?UTF-8?q?-cape=20accepted=20the=20issuance=20question=20five=20days=20ag?= =?UTF-8?q?o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit T04 was the last open task, waiting on key-cape to accept or refuse ownership of the coding-agent OpenBao issuance identity. They accepted, in KEY-WP-0009-T03, on 2026-08-23: codex-railiance-platform is published in their config/service-clients.example.yaml with subject service:codex:railiance-platform, role coding-agent, scope openbao:login, 15m lifetime, and the service-auth semantics in docs/openbao-service-auth-contract.md. The split is the one we routed for — KeyCape issues, railiance-platform binds the OpenBao role, OpenBao enforces, no secret value in either repo. We found it by reading their repository. KEY-WP-0009-T04 records replying to ops-warden; the inbox has zero messages from key-cape, read or unread. The task sat `wait` on an answer that already existed. That is T05's own lesson arriving on T04: a blocker is a claim about the world at a date. So the same pass re-verified the two lanes pointing at key-cape against their source instead of bumping dates: - rapp-qonto-keycape-client -> verified: source-read. KEY-WP-0009-T02 did add bounded service-auth, but that is client_credentials JWT issuance for OpenBao machine login and does not front this client_secret_basic exchange or its rotation. Blocker stands, now with evidence rather than memory. - key-cape-oidc-login -> asked of key-cape today, which the entry had recorded as still outstanding since 2026-08-21. Also cleared the inbox that hid this: 9 stale unread, all superseded by shipped work, with late closes sent to secrets-engine and llm-connect on the two threads that had asked ops-warden something and never got an answer. 391 tests pass, ruff clean, boundary coverage 0 uncovered. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- registry/generated/high-risk-data-paths.yaml | 4 +-- registry/routing/catalog.yaml | 10 +++--- .../WARDEN-WP-0033-native-lane-handoff.md | 33 +++++++++++++++++-- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/registry/generated/high-risk-data-paths.yaml b/registry/generated/high-risk-data-paths.yaml index a0b7ea0..35d494b 100644 --- a/registry/generated/high-risk-data-paths.yaml +++ b/registry/generated/high-risk-data-paths.yaml @@ -10,11 +10,11 @@ # declares it, and is null where the field set has not been established -- # null means unknown, never 'one field'. -generated_at: "2026-08-28T19:54:29Z" +generated_at: "2026-08-28T19:58:57Z" source: ops-warden/registry/routing/catalog.yaml catalog_revision: "c374d41a4925720ae7706dfda020537b60a07eb9" catalog_revision_date: "2026-08-23T21:43:12+02:00" -catalog_dirty: false +catalog_dirty: true high_risk_lane_count: 23 concrete_path_count: 14 diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index 0ab246b..09f690e 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -281,8 +281,8 @@ entries: delegation: mode: interim intended_owner: key-cape - blocked_on: "REFUSED by secrets-engine 2026-08-21: login, MFA and identity-token issuance are key-cape/Keycloak's; secrets-engine may consume OIDC for OpenBao auth but does not own the login capability. ops-warden agrees — intended_owner corrected from secrets-engine to key-cape. Not yet asked of key-cape." - reviewed: "2026-08-21" + blocked_on: "REFUSED by secrets-engine 2026-08-21: login, MFA and identity-token issuance are key-cape/Keycloak's; secrets-engine may consume OIDC for OpenBao auth but does not own the login capability. ops-warden agrees — intended_owner corrected from secrets-engine to key-cape. Asked of key-cape 2026-08-28; KEY-WP-0009 accepting issuance ownership for machine identities is the precedent that makes it answerable." + reviewed: "2026-08-28" verified: asked-and-waiting # Login lane (WP-0014 T4) — interactive auth bootstrap, not a secret read. No # secret-read gate (you have no identity yet) and no caller-auth precheck (the @@ -710,9 +710,9 @@ entries: delegation: mode: interim intended_owner: key-cape - blocked_on: "client_secret_basic exchange is a key-cape protocol procedure, not a KV read; KEY-WP-0008 finished 2026-08-15 without a key-cape-native exchange/rotation command, and the workplan that would add one is not yet opened (key-cape acked interim 2026-08-15)" - reviewed: "2026-08-17" - verified: unverified + blocked_on: "client_secret_basic exchange is a key-cape protocol procedure, not a KV read; still no key-cape-native exchange/rotation command. Re-checked against key-cape source 2026-08-28: KEY-WP-0009 finished 2026-08-23 and did add bounded service-auth (per-client tokenLifetime, docs/openbao-service-auth-contract.md), but that is client_credentials JWT issuance for OpenBao machine login — it does not front this client_secret_basic exchange or its rotation. The server advertises client_secret_basic (src/internal/server/oidc/discovery.go) without exposing an owner command for it. Blocker stands." + reviewed: "2026-08-28" + verified: source-read risk: high workload_ref: applicability: applicable diff --git a/workplans/WARDEN-WP-0033-native-lane-handoff.md b/workplans/WARDEN-WP-0033-native-lane-handoff.md index 1e20015..55cd015 100644 --- a/workplans/WARDEN-WP-0033-native-lane-handoff.md +++ b/workplans/WARDEN-WP-0033-native-lane-handoff.md @@ -4,14 +4,14 @@ type: workplan title: "Native lane handoff — review secrets-engine's catalog admission, and fix what it exposed" domain: infotech repo: ops-warden -status: active +status: finished owner: ops-warden topic_slug: netkingdom planning_priority: P1 depends_on_workplans: - WARDEN-WP-0030 created: "2026-08-21" -updated: "2026-08-23" +updated: "2026-08-28" state_hub_workstream_id: "4627d89b-4b00-562a-81e9-76e96f90fa7e" --- @@ -160,7 +160,7 @@ railiance-platform may deny more, deny less, or dispute a grade (`ADR-0002`). ```task id: WARDEN-WP-0033-T04 -status: wait +status: done priority: medium state_hub_task_id: "5acac140-a586-5db3-b231-bbf236710786" ``` @@ -212,6 +212,33 @@ accept that target identity with an authoritative workplan/interface, or refuse and name the actual owner. T04 remains `wait` until one of those two answers is recorded; the live AppRole is operational evidence, not an ownership answer. +**Answered — accepted. Closed 2026-08-28.** `key-cape` accepted issuance +ownership in `KEY-WP-0009-T03` (`status: done`, 2026-08-23): the non-secret static +registration `codex-railiance-platform` is published in +`key-cape/config/service-clients.example.yaml` — subject +`service:codex:railiance-platform`, tenant `tenant:coulomb`, role `coding-agent`, +scope `openbao:login`, `client_credentials`, 15-minute lifetime — with the +service-auth claims, renewal, expiry and failure semantics in +`key-cape/docs/openbao-service-auth-contract.md` (`T02`). The split is exactly the +one the routing asked for: KeyCape owns JWT issuance and client disablement, +railiance-platform owns the exact-bound OpenBao role and policy, OpenBao owns +enforcement, and no secret value enters either repository. + +**The answer was found by reading their repo, not by receiving it.** +`KEY-WP-0009-T04` records replying to ops-warden; no such message exists in the +ops-warden inbox — 0 messages from `key-cape`, read or unread. The acceptance had +been sitting done for five days while this task sat `wait` on it. + +That is the T05 lesson landing on T04: a blocker is a claim about the world at a +date, and this one had stopped being true. `verified: source-read` is doing real +work here — it is the difference between "we asked" and "we checked". The +mechanism is right; what it needs is for someone to run it, which is why the +lanes below were re-verified in the same pass rather than date-bumped. + +Consequence for `ADR-0004`: the honour-system `WARDEN_AGENT_ID` marker now has a +real issuance identity behind it on the OpenBao side. ops-warden remains a +consumer of that identity and does not own it. + ```task id: WARDEN-WP-0033-T05 status: done From 61c992923c3c99604eddcbe3653cbe8d92e29e37 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 22:01:47 +0200 Subject: [PATCH 3/3] WARDEN-WP-0027-T02: the owner gate closed five days ago MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit railiance-platform accepted ops-warden revision 0fae0904 on 2026-08-23, in RPF-WP-0017 (status: finished), together with railiance-infra approval at 186b030 and all five acceptance criteria met. T02 has been sitting `progress` on a gate that was already open. Verified rather than trusted: the receipt at bc1966da hashes to d2ba444ed16989590325697e69d25283dc75a9432c29a72e627e80bf9fd987e4, matching their record exactly. One reason it went unnoticed is an identifier mismatch — T02 cites the remediation interface as RAILIANCE-WP-0026-T01, but it is RPF-WP-0017-T01 in the owner repo, and the cited id resolves to an unrelated workplan there. Their acceptance is source acceptance only and authorizes no live drill, so T02 stays progress: what unblocks is preparing a NEW scenario, which needs a fresh human GO and is the platform owner s to execute. Surfaced, not taken. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- ...-WP-0027-credential-governance-lockdown.md | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/workplans/WARDEN-WP-0027-credential-governance-lockdown.md b/workplans/WARDEN-WP-0027-credential-governance-lockdown.md index 840f291..a111c31 100644 --- a/workplans/WARDEN-WP-0027-credential-governance-lockdown.md +++ b/workplans/WARDEN-WP-0027-credential-governance-lockdown.md @@ -222,6 +222,39 @@ test results, and infra acceptance. T02 remains `progress` until that owner gate is open; acceptance will permit preparation of a new scenario, not execution or reuse of the terminal one. +**Owner gate CLOSED — accepted 2026-08-23, found 2026-08-28.** +`railiance-platform` accepted the exact revision `0fae0904`. Recorded in their +`RPF-WP-0017-attended-login-output-containment.md` (`status: finished`), which +also records railiance-infra's independent approval at `186b030` and marks all +five acceptance criteria met. The receipt digest was verified here rather than +taken on trust: `docs/evidence/RAILIANCE-WP-0026-T01-ops-warden-receipt.json` at +ops-warden `bc1966da` hashes to +`d2ba444ed16989590325697e69d25283dc75a9432c29a72e627e80bf9fd987e4`, matching +their record exactly. + +Note the identifier: the remediation interface recorded above as +`RAILIANCE-WP-0026-T01` is `RPF-WP-0017-T01` in the owner's repo. Searching for +the cited id finds an unrelated workplan, which is part of why this sat unnoticed. + +**Their acceptance is source acceptance only and authorizes no live OIDC or +drill** — their words, and the boundary holds. So T02's state changes but its +`Done when` does not: what was blocked was *preparing a new scenario*, and that +is now permitted. The terminal NO-GO scenario and its receipts remain unusable. + +**Third instance of the same failure this session.** The acceptance existed for +five days; no message reached ops-warden. Identically, `key-cape` accepted the +WP-0033-T04 question on 2026-08-23 with no message, and nine unread messages +were sitting on already-superseded threads. The `verified:` field added by +WP-0033-T05 was built for exactly this and it works — what does not work is +waiting for a counterparty to tell you. Re-checking a blocker means reading the +owner's repository. + +**Remaining to close T02:** one attended production emergency seal/unseal drill, +requiring a new scenario id, fresh owner receipts from platform/infra/master, a +fully parameterized green preflight, and a new human GO. It is executed by the +platform owner, never by a coding agent. That is an operator decision, not an +agent one, so T02 stays `progress` and the decision is surfaced rather than taken. + ## Task: Tamper-evident policy governance + reconcile ```task