docs: preserve reviewed NetKingdom session artifacts
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Reject generated-only commits / generated-commit-guard (push) Successful in 13s

This commit is contained in:
codex 2026-11-01 23:37:27 +01:00
parent be0f891619
commit 6d14339f24
50 changed files with 8196 additions and 0 deletions

View file

@ -0,0 +1,113 @@
---
id: WARDEN-WP-0043
type: workplan
title: "Route supplier credentials under platform/suppliers"
domain: infotech
repo: ops-warden
status: finished
flavor: implementation
owner: grok
topic_slug: platform-suppliers
created: "2026-10-08"
updated: "2026-10-09"
depends_on: []
related:
- repo:railiance-platform
- repo:llm-connect
state_hub_workstream_id: "16aac061-977a-536b-a074-aba059f2475f"
---
# WARDEN-WP-0043 — Supplier credentials under platform/suppliers
Founder decision 2026-10-08: account credentials we hold with a supplier
live at `platform/suppliers/<supplier>/<account>` on the existing `platform`
KV mount. ops-warden routes that shape. It does not store the values and it
does not apply OpenBao. The KV write and the credential-change allowlist
belong to railiance-platform. Tenant commercial secrets stay on `tenants/`.
Workload and rein paths that already have a reader stay where they are
until that reader is retargeted:
| Account | Path today |
| --- | --- |
| OpenRouter, llm-connect | `platform/workloads/activity-core/llm-connect/llm-connect-provider-secrets` |
| OpenRouter, rein-openweights | `reins/rein-openweights/openrouter` |
| Scaleway bootstrap | `platform/workloads/railiance/scaleway/bootstrap` |
| Scaleway backup space | `platform/workloads/railiance/backup/object-storage` |
| IONOS transactional mailbox | `platform/workloads/email-connect/transactional` |
| IONOS library mailbox | `platform/workloads/inbound-library/imap` |
The future homes are `platform/suppliers/openrouter/llm-connect`,
`platform/suppliers/openrouter/rein-openweights`,
`platform/suppliers/scaleway/bootstrap`, `platform/suppliers/scaleway/backup`,
`platform/suppliers/ionos/email-connect-smtp`, and
`platform/suppliers/ionos/library-imap`. Further suppliers use the same
two-level shape. llm-connect already tries the llm-connect supplier path
and then the live workload path before `OPENROUTER_API_KEY`.
## Catalog pointer
```task
id: WARDEN-WP-0043-T01
status: done
priority: high
state_hub_task_id: "7a86d91a-fcbd-5dc8-b3cf-4c28ad963474"
```
Add a pointer catalog entry and a short playbook for
`platform/suppliers/<supplier>/<account>`. `warden_executes: false`. The
owner of the KV write is railiance-platform. No secret values, no fetch
of a live field, and no new `warden` verb.
Done 2026-10-08: catalog `platform-supplier-credentials` plus
`wiki/playbooks/platform-supplier-credentials.md`.
## Allow the path in credential changes
```task
id: WARDEN-WP-0043-T02
status: done
priority: high
state_hub_task_id: "c384b228-e710-580d-a3de-a3046a86e666"
```
`railiance-platform/scripts/credential-change.py` accepts `platform/workloads/`
and `tenants/` for a delegated change. `platform/suppliers/` needs that
allowlist widened before a CCR can create these paths. ops-warden does not
apply the change.
Done 2026-10-09: railiance-platform `b77cb41` maps mount `platform` to
`platform/workloads/` and `platform/suppliers/`. Under `suppliers/` it requires
exactly two non-empty segments, and tests cover `platform/suppliers/ionos/main`.
The IONOS CCR can now be drafted against this shape.
## Provision supplier accounts
```task
id: WARDEN-WP-0043-T03
status: done
priority: medium
needs_human: true
state_hub_task_id: "87996bc7-2f7a-578d-9f7c-8bd876605a47"
```
New supplier material is written from a mode-0600 file on a trusted
terminal, into `platform/suppliers/<supplier>/<account>`. IONOS is the
first account that still needs that home. Existing workload and rein
readers keep their current paths until each one is retargeted. Values do
not go into git, State Hub, workplans, logs, or chat.
2026-10-09: the IONOS stub exists. The founder ran the write through the
contained `openbao-platform-admin-login` envelope:
`bao kv put -cas=0 platform/suppliers/ionos/main` as version 1, with keys
`CUSTOMER_NUMBER`, `LOGIN`, `PASSWORD`, `API_KEY_PREFIX` and `API_KEY_SECRET`,
each set to the placeholder `FILL_ME`. A metadata-only check through the same
envelope exited 0. The founder fills the real values as version 2 in the
OpenBao UI. This task closes once that is done. No reader policy exists for the
path; a reader is requested through a railiance-platform CCR when a workload
needs it.
2026-10-09: done. The founder filled in the real values as version 2 through
the OpenBao UI. ops-warden did not read or verify any value. Further supplier
accounts follow the same playbook; existing workload and rein readers move only
when each reader is retargeted.

View file

@ -0,0 +1,356 @@
---
id: WARDEN-WP-0044
type: workplan
title: "Follow through on KnownSecurityCases along their type's route"
domain: infotech
repo: ops-warden
status: active
flavor: implementation
owner: claude-code
topic_slug: netkingdom
created: "2026-10-08"
updated: "2026-10-11"
depends_on: []
related_repos:
- net-kingdom
- ops-mason
- key-cape
- railiance-platform
state_hub_workstream_id: "f7e81013-6868-5d99-8528-ba75a442eca9"
---
# WARDEN-WP-0044 — Follow through on KnownSecurityCases along their type's route
## Why
NetKingdom is introducing SecurityCaseTypes (net-kingdom `NK-WP-0048`, canon
`security-case-types_v0.1`, proposed). Once a case of an implemented type is
accepted and ops-mason has materialized its structure (`MASON-WP-0010`),
ops-warden carries out the remaining steps. These are the owners' declared entry
points, run on the authentication path the type defines, followed by the type's
verification.
Today ops-warden routes needs and, for `exec_capable` lanes, proxies fetches as
the caller. It does not yet know about cases, and each new integration ends with
a founder running a hand-written script (for example the proposed KEY-WP-0038-T02
rollout). This plan gives ops-warden the follow-through role, without widening
what it may do: each step still runs under its owner's entry point and the
caller's identity.
## Tasks
```task
id: WARDEN-WP-0044-T01
status: done
depends_on: [NK-WP-0048-T03]
priority: high
state_hub_task_id: "ef0920fc-418e-52cb-acff-9a5c0c728bf5"
```
### T01 — Define the type's follow-through section
Propose the `follow_through` part of the SecurityCaseType schema together with
net-kingdom. For each step it names the owner entry point, `warden_executes`,
the auth method and lane, whether an attended human login is unavoidable (with
the type's justification), and the verification command. Write it for the first
type, `oidc-browser-relying-party`, covering key-cape client registration,
custody minting and LLDAP group membership.
2026-10-08: NK-WP-0048-T03/T04 landed with a drafted section. Review is in
`history/2026-10-08-oidc-rp-follow-through-review.md`. It requires three
changes before T02: a per-step `lane`, a narrow `warden_executes`, and
`value_handling`. It also lists four refinements. This task is done when
net-kingdom acknowledges the review (NK-WP-0048-T05).
2026-10-09: R4 was withdrawn in favour of ops-mason's per-case
`{consuming_service}-keycape-client`, with the entry body templated in the type
(R4′, see the addendum in the review).
2026-10-09: the revised 1.0 type and canon now carry R1–R3, R4′, R5–R7.
`warden case check-type <type.yaml>` (`src/warden/case_type.py`, tests in
`tests/test_case_type.py`) checks a type's follow-through mechanically: the
live type is schema-conformant, with one attended session
(`key-cape-oidc-login`). It is not yet plannable, because two lanes are not
in the catalog: `identity-provisioner-groups` (net-kingdom) and
`keycape-client-secret-generate` (railiance-platform). These gate T02, not
T01. T01 still closes on net-kingdom's acknowledgement (NK-WP-0048-T05).
2026-10-09: ops-warden cannot add `identity-provisioner-groups` as the type
declares it. The provisioner accepts only user-engine's runtime token and
admits only user-engine pods, so no caller-identity path exists. R8 (review
addendum) asks net-kingdom either to move `ensure-groups` into the existing
attended session (recommended) or to give the provisioner an operator
credential. `keycape-client-secret-generate` needs a generate-in-custody entry
point from railiance-platform, and the broker does not have one yet. Both were
sent to their owners.
2026-10-09: done. net-kingdom took R8 option 1, so `ensure-groups` runs attended
in the `register-client` session and `identity-provisioner-groups` is dropped
(net-kingdom `0e86f95`). The founder acknowledged the type with memo r4 (hub
decision `e418263e`, NK-WP-0048-T05 done).
```task
id: WARDEN-WP-0044-T02
status: done
depends_on: [WARDEN-WP-0044-T01]
priority: high
state_hub_task_id: "5f68c991-f490-58f8-a121-92f74073d272"
```
### T02 — Plan a case run
`warden case plan <case.yaml>` checks that the case is accepted and materialized,
resolves each step to its catalog entry and entry point, and prints the run:
which steps warden executes, which run as the attended caller, what the
verification is. No secret values; no execution.
Tests: refuse an unaccepted or unmaterialized case; refuse a step whose catalog
entry is missing or not reviewed; show attended steps explicitly.
2026-10-09: done. `warden case plan <case.yaml> [--type] [--json]`
(`src/warden/case_plan.py`, 14 tests in `tests/test_case_plan.py`). It refuses:
- a case that is not `materialized`, or has no acceptance record
- a type that is mismatched or not acknowledged
- any `case check-type` finding, including a missing or unreviewed lane
- undeclared, type-fixed or secret-sensitivity parameters
- a placeholder the case does not set, or an unsupported `when`
It fills type defaults (`issuer`), evaluates `<param> == <value>` conditions,
renders owner, entry point, auth and ready_check, groups attended steps per
lane, and lists the applicable verification.
The live Forgejo case is correctly refused: it is `accepted`, not
materialized. A materialized copy, with a stand-in lane for
`keycape-client-secret-generate`, renders six steps: two attended steps plus
`register-client` in one `key-cape-oidc-login` session, one warden step
(`mint-secret`), and two owner steps. Seven checks follow.
Observation for net-kingdom (not blocking): `bind-env` runs before
`register-client`, in type order. Its entry carries a literal
`KEYCAPE_<CLIENT_ID>_CLIENT_SECRET`, which is not a `{param}` placeholder, so it
reaches the plan unrendered.
2026-10-09 follow-up:
- **Format specs.** `_render` supports net-kingdom's `{param:env}` spec (upper
case, `-` as `_`, the same as `keycape-client.py env_name`) and refuses any
other spec or `!conversion`.
- **Case reference.** The plan prints `case-ref: <case_id>@sha256:<hex>` over the
case file's exact bytes. This is the reference proposed to railiance-platform
for `credential.py generate --case-ref` (RPF-WP-0054-T01); the broker
re-derives it from the file.
- 18 tests now.
```task
id: WARDEN-WP-0044-T03
status: progress
depends_on: [WARDEN-WP-0044-T02, MASON-WP-0010-T03]
blocking_reason: "Local durable execution kernel and injected failure harness implemented. Native acceptance still requires authenticated owner machine descriptors/adapters, actual Forgejo materialization receipt, contained session integration, ordered verification and first native run."
priority: high
state_hub_task_id: "bcbf6c91-2c04-5c16-ae8c-5d6c06fd6b89"
```
### T03 — Run and verify a case
`warden case run <case.yaml>` executes the plan. Owner entry points run through
the existing proxy as the caller; steps that need an attended login use the
existing contained login envelope (silent command, session revoked afterwards),
grouped into as few attended sessions as possible. Then it runs the type's
verification and writes a receipt without values. `warden case rollback`
reverses exactly this case's steps.
Acceptance: the Forgejo reference case (NK-WP-0048-T06) reaches `live` through
this path, with no case-specific script.
2026-10-17: original-intent lookup/context interface for NK-WP-0048-T15, source
and synthetic tests only. `src/warden/case_run.py`: `Executor.run` writes an
`OriginalIntent` (schema `warden.case.original-intent.v1`: the dispatched run
Invocation — attempt, step, owner, target, actor, principal, lane, all six pins,
tenant, realm — plus admitted adapter source) in the same SQLite transaction as
the pre-dispatch journal row. `Journal.original_intent(binding, current, source)`
returns it after restart and refuses on a missing record or any
pins/source/step/owner/target/actor/principal/lane/tenant/realm mismatch, before any
journal write, so the step stays uncertain. An adapter's
`reconcile_original(ReconcileContext(original, attempt))` receives the original
intent separately from the new reconcile attempt. This is Warden's record of what
it dispatched, not owner created-only provenance. Current Executor.admit leaves
tenant/realm empty; the reserved coordinates establish no admitted provenance.
Owner descriptors/adapters, contained session integration, Forgejo
materialization and the native run remain open.
2026-10-17 source consistency follow-through: retained the additive intents table
and reconcile_original callback and fixed four reproduced local defects: original
actor mismatch, payload/SQL attempt-ID mismatch, orphan intent without its
matching original running receipt, and arbitrary nonmetadata values accepted by
the original-intent serializer. Exact bounded field validation, duplicate-free
bounded decode and save-time intent/invocation/running-state equality now preserve
the original receipt linkage before owner lookup. No new context store, native
verifier, trust root, adapter activation or authority migration was introduced.
The actual canonical focused kernel and new consistency suite passes 54 checks;
owner-installed Ruff check/format passes. The existing generated-data/synthetic
owner fixture and a distinct interpreter prove source correspondence/refusal,
not independent native custody or creation. Earlier comparison probes and failed
preparation are retained. Current caller and fresh session/grant revocation checks
remain required; original owner payload/revocation, exact native readback and
created-only provenance still need independent authenticated owner admission.
No JSON/SQL context, unknown tenant/realm, changed run-sheet or legacy missing
intent supplies recovery, replay or undo authority. T03 remains progress and all
native acceptance gates/statuses/dependencies/UUIDs remain unchanged. Evidence:
Custodian original-context-compare-r2 and original-context-owner-followthrough-r3
under docs/changes/netkingdom-target-2026-10-17/; publication/projection is separate.
Agreed with railiance-platform (RPF-WP-0054-T01, 2026-10-09):
- `mint-secret` runs `credential.py generate --grant keycape/client-secret-generate
--client-id <id> --case-ref <case-ref> --case-file <case.yaml>` as the caller's
child process. The broker re-derives the case-ref and checks status and
client_id.
- warden refuses that step when `WARDEN_AGENT_ID` is set.
2026-10-10: railiance-platform implemented the command (RPF-WP-0054-T03). It is
catalogued as draft `keycape-client-secret-generate`, with `exec_owner`
railiance-platform and `exec_capable: false`. `warden case check-type` now
reports the lane as LANE-UNREVIEWED rather than LANE-MISSING. Before it can be
activated:
- the founder binds the issuer policy to the operator OIDC role
- key-cape confirms the secret format
- the RPF-WP-0054-T05 probe passes
2026-10-10 (later):
- **Broker lane.** The issuer role is bound (CCR-2026-0043) and the T05 probe
passed (railiance-platform `21b8af3`). Only key-cape's format confirmation is
left. The playbook now includes the issuer-role login, a 15m token with
unlimited uses that `warden case run` must group with the attended session.
- **Env spec.** net-kingdom adopted `{client_id:env}` as a 1.0 patch
(`9a9b8e3`). The plan renders `KEYCAPE_FORGEJO_CLIENT_SECRET`.
- **Forgejo case.** Rendered and built by ops-mason. It is not yet
`materialized`: MASON-WP-0010-T03 waits on the railiance-platform CCRs and
their founder apply.
2026-10-10: `keycape-client-secret-generate` activated on railiance-platform's
go-ahead (message 20973a9c) after key-cape confirmed the format (4e0213b3).
`warden case check-type` on the live type now reports `plannable=True`. The
only thing T03 still waits on is the Forgejo case reaching `materialized`
(MASON-WP-0010-T03).
2026-10-10: net-kingdom moved the type to 1.1 (`e2174ce`) and re-pinned the
Forgejo case. 1.1 adds the verification `consumer-enforces-groups` and requires
the hand-over to enforce `access_groups`. `check-type` on 1.1 reports
`plannable=True`, and a materialized copy renders six steps and the new check.
The case-ref digest covers the whole case file, including `status`, so it
changes when the case becomes `materialized`. `warden case run` therefore takes
it from the file at run time, and the broker re-derives it from the same file.
```task
id: WARDEN-WP-0044-T04
status: wait
depends_on: [WARDEN-WP-0044-T03]
blocking_reason: "Catalog integration follows a proven run."
priority: medium
state_hub_task_id: "4a0fa4a7-5ca9-518a-ab92-a79a5e2cf93e"
```
### T04 — Catalog entries from types
Let a type contribute reviewed catalog entries once, so that every case of that
type routes without a new catalog edit. Cases add parameter values, not routes.
`warden route find` should be able to answer "which SecurityCaseType covers this
need?" before anyone builds by hand.
2026-10-10 consolidation source prototype (not an accepted owner adapter API):
`src/warden/case_receipt_state.py` provides a pure immutable receipt reducer,
with exact case/type/adapter/catalog/acceptance/run-sheet pins, running intent
before dispatch, uncertain recovery after a lost result, no success replay,
explicit retry-safe failed-before-change retry and created-only reverse undo.
It executes nothing and accepts no command output. The caller must durably
persist running before any future side effect; storage/authenticated owner
receipts/live adapters are not implemented. Focused offline tests cover changed
pins, lost receipts, retry/refusal, uncertain rollback and shared-object
preservation. Source proposal: `docs/security-case-execution-proposal.md`.
T03 remains open: typed owner execution/receipt contracts require review, the
Forgejo structural materialization needs owner receipts, and CLI dispatch,
contained sessions, native verification and provenance remain unimplemented.
There is a circularity to resolve with net-kingdom/ops-mason: materialization
cannot require mint-secret if mint-secret is itself a follow-through step whose
planning requires materialized. No case status is changed by this prototype.
2026-10-11: the exact execution-design memo version1 has confirmed native human
acceptance (approval e46b149b-ec3c-4b3b-98a7-dcb4934448ca). The approved proposal
bytes remain unchanged. `src/warden/case_run.py` now implements a closed v1 local
execution seam, independent admission/evidence callbacks, private transactional
SQLite receipt storage, process locking, running-before-dispatch, crash recovery
to uncertainty, explicit safe retry, separately required broker-grant and parent-session revocation
proofs, native owner reconciliation and created-only
reverse rollback. Thirty-seven kernel tests and fourteen reducer tests pass;
ruff checks pass. See `docs/security-case-execution-kernel-v1.md` for exact scope
and receipt provenance. No installed native adapter or live CLI execution is
claimed. Current prose types stay plan-only; acknowledged descriptor/type machine
seams and authenticated owner/caller receipts are still required. T03 progresses
for implementation but cannot finish before ordered native Forgejo acceptance.
2026-10-16 source preparation (isolated checkout; no native acceptance):
T03's browser parameter mismatch now has a producer-validator-backed projection
in `case_inputs.py`, explicitly configured on the real Executor. Exact 1.1/1.2
parameter definitions and all four reviewed producer modules are pinned; full case
validation admits reviewed security-sensitive metadata while unknown/fixed/secret
inputs and type/producer drift refuse. Only the reviewed descriptor target
reaches the owner callback; no parameter journal payload is added. Actual
Executor/producer tests cover positive versions and refusal/containment paths.
Acknowledged machine descriptors, authenticated owner evidence, real Forgejo
materialization and contained native sessions remain mandatory and unimplemented;
T03 stays progress, T04 stays wait. No type or case status changed.
2026-10-16 producer source refresh: independently reviewed NetKingdom
`015694ee414c802dc2ef1fa0120dfed610086e69` optional descriptor-map repair.
Only the validator/evidence source pins change; exact parameter and transitive
source identity remain enforced. Actual canonical producer, Executor and reducer
suite passes 87 checks, including 14 new malformed-map integration cases; all
four missing/changed modules still refuse. Review:
`docs/reviews/2026-10-16-browser-producer-pin-refresh.md`. No adapter attestation,
native acceptance, credential use or privileged dispatch. T03 remains progress.
## T03 source correction and safe-test follow-through — 2026-10-17
The reviewed KERNEL-2/3 source now authenticates and parses the actual catalog
snapshot, checks lane owner/risk/delegation, and resolves each type step's Warden,
attended or owner dispatch mode. Four proposed attended-change lanes remain
DRAFT; no lane is promoted and PARAMETER_PINS still contains only 1.1/1.2.
Independent review KR1-F1/F2 found cached attended run/rollback/reconcile could
lose the human/runtime boundary, and actual admission lacked the planner's
establishing-login checks. The exact successor retains the mode and authenticated
catalog bytes and repeats caller/session, agent marker and attended-lane checks
before any journal write or callback on all three operations. Planner and executor
share active/reviewed login/session-lane validation. Two unresolved Apps session
lanes correctly remain refused. Integration tests now explicitly disclose all
fixture authority substitutions; they establish no owner or native authority.
The new 19-test regression matrix reproduces 13 failures on its predecessor and
passes on the candidate. A fresh independent reviewer adds changed-authority and
catalog-snapshot probes: 90 focused checks and six guarded integration checks
pass; the combined predecessor comparison has 22 expected failures. Author's
isolated full suite passes 765 with four integration-marked tests deselected.
Evidence: Custodian warden-1.3-kernel-fixes-r1 and warden-1.3-kernel-review-r2
under docs/changes/netkingdom-target-2026-10-17. Original unsuccessful review,
invalid setup attempts and unknown ambient-lookup outcome are retained.
A separate reviewed test-only fix stubs ambient OpenBao identity in access CLI
unit tests and adds a synthetic sentinel regression which fails before any
subprocess can launch on the predecessor; 26 access/helper checks pass. The real
production helper is unchanged. The first old review's unisolated launches may
have invoked ambient `bao token lookup`; remote reach/success remain unknown,
with no secret displayed. This patch does not erase that adverse outcome.
Explicit remaining safe-test work is retained in this live T03 scope, owned by
ops-warden: replace or wrap the ordinary unit-test entry path with allowlisted
environment/empty synthetic HOME and guarded subprocess/network execution,
including nested validator children. Completion requires representative access
and case tests to refuse token-file/environment and live provider access under
synthetic negative controls while permitted local fixtures remain usable. Until
then use the preserved isolated review runner, not the ambient `make test` path.
No credential lookup, live investigation or rotation is authorized by this note.
T03 remains progress; contained sessions, authenticated owner provenance,
materialization, exact type acknowledgment/pin and first native case remain open.

View file

@ -0,0 +1,335 @@
---
id: WARDEN-WP-0001
type: workplan
title: "OpsWarden Initial Implementation"
domain: custodian
repo: ops-warden
status: archived
owner: Bernd
topic_slug: custodian
created: "2026-03-28"
updated: "2026-03-28"
state_hub_workstream_id: "c3118cc6-adfb-428c-a9c6-edd0ee152ae6"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0001 — OpsWarden Initial Implementation
> **Note:** This workplan is authored in `ops-bridge` because `ops-warden` does not yet exist.
> Move it to `workplans/WARDEN-WP-0001-initial-implementation.md` in the new repo as the
> first commit action.
**Scope:** Bootstrap the `ops-warden` repository and deliver a working `warden` CLI that
implements the SSH CA and certificate lifecycle defined in `wiki/AccessManagementDirective.md`.
**Out of scope:** Vault HA/cluster setup, Ansible playbooks for host principal deployment
(those live in `railiance-infra`), session recording, and SSO integration (trigger §6.2 of
the directive when scale requires it).
---
## Goal
Create a new `ops-warden` repository that owns **credential issuance only** — the CA,
certificate signing, actor identity registry, and scorecard tooling. Its sole public surface
to sibling repos is a well-defined `cert_command` interface that any tool (principally
`ops-bridge`) can call to obtain a short-lived, CA-signed SSH certificate for a named actor.
---
## Reference Documents
| Document | Location |
|---|---|
| AccessManagementDirective | `ops-bridge/wiki/AccessManagementDirective.md` |
| ops-bridge SCOPE.md | `ops-bridge/SCOPE.md` |
---
## Architecture
```
ops-warden/
├── SCOPE.md
├── CLAUDE.md
├── pyproject.toml
├── src/warden/
│ ├── cli.py # Typer CLI: sign / issue / status / inventory / scorecard
│ ├── models.py # ActorType enum, CertSpec, CertRecord, PrincipalsInventory
│ ├── ca.py # LocalCA backend (file-based, for dev / non-Vault)
│ ├── vault.py # VaultCA backend (Vault SSH engine, for production)
│ ├── inventory.py # YAML principals inventory read/write
│ ├── scorecard.py # §5 compliance checks
│ └── config.py # ~/.config/warden/warden.yaml loader
├── tests/
└── wiki/ # (symlink or copy of AccessManagementDirective.md)
```
**Backends are swappable.** Config key `backend: local | vault` selects which CA
implementation is used. This means the tool is fully functional without Vault for local lab
use, and production-grade with Vault — the same CLI surface, the same `cert_command`
interface, the same principals inventory format.
**cert_command interface contract:**
```
warden sign <actor-name> --pubkey <path>
```
Writes the signed certificate to stdout (the cert text). Exits non-zero on failure.
`ops-bridge` calls this verbatim via `cert_command` in `tunnels.yaml`.
---
## Stack
- **Language:** Python 3.11+
- **CLI framework:** Typer
- **Dependencies:** typer, pyyaml, httpx, cryptography (for cert parsing / TTL reading)
- **Vault SDK:** `hvac` (optional; only required for vault backend)
- **Packaging:** `uv tool install`
---
## Tasks
### T1 — Repository bootstrap
```task
id: WARDEN-WP-0001-T1
state_hub_task_id: 6d643e9d-5e97-4224-9d82-87267b5ba6bc
status: done
priority: high
```
- [x] Create `ops-warden` repo; copy CLAUDE.md template from `ops-bridge`; add
`workplans/WARDEN-WP-0001-initial-implementation.md` (this file)
- [x] Write `SCOPE.md` (see template in §SCOPE below)
- [x] `pyproject.toml`: `[project.scripts] warden = "warden.cli:app"`
- [x] Register repo with state-hub (`register_repo`)
- [x] Create state-hub workstream for this workplan
### T2 — Models and config
```task
id: WARDEN-WP-0001-T2
state_hub_task_id: c66fc65a-0b16-4ba2-9e70-a83d875572ec
status: done
priority: high
```
- [x] `models.py`: `ActorType` enum (`adm | agt | atm`); `CertSpec` (actor_name, pubkey_path,
ttl_hours, principals); `CertRecord` (identity, valid_before, cert_path, signed_at)
- [x] `config.py`: load `~/.config/warden/warden.yaml`; required fields: `backend`,
`ca_key` (local) or `vault_addr` + `vault_role_map` (vault); optional:
`inventory_path`, `state_dir`
- [x] Validate actor name prefix matches `ActorType` (`adm-*`, `agt-*`, `atm-*`)
### T3 — LocalCA backend
```task
id: WARDEN-WP-0001-T3
state_hub_task_id: a5a41e58-1c6d-42a9-9b11-2088f17c29b5
status: done
priority: high
```
- [x] `ca.py`: `LocalCA.sign(spec: CertSpec) -> CertRecord`
- Calls `ssh-keygen -s <ca_key> -I <identity> -n <principals> -V +<ttl>h <pubkey>`
- Parses `ssh-keygen -L -f <cert>` output to extract `Valid before`, `Key ID`,
`Principals`
- Returns `CertRecord`; writes cert to `~/.local/state/warden/<actor>.cert.pub`
- [x] Default TTLs enforced per `ActorType`: adm → 48 h, agt → 24 h, atm → 8 h
(overridable per actor in inventory)
- [x] `LocalCA.generate_keypair(actor_name) -> (privkey_path, pubkey_path)` — for agt/atm
actors that do not bring their own key
### T4 — VaultCA backend
```task
id: WARDEN-WP-0001-T4
state_hub_task_id: b2067ee6-c9ce-423b-9d60-0d28069fb304
status: done
priority: medium
```
- [x] `vault.py`: `VaultCA.sign(spec: CertSpec) -> CertRecord`
- `POST /v1/ssh/sign/<role>` with `public_key`, `valid_principals`, `ttl`
- Parse response `signed_key` field; write to state dir; extract metadata via
`ssh-keygen -L`
- [x] Role map in config: `vault_role_map: {adm: adm-role, agt: agt-role, atm: atm-role}`
- [x] Graceful error message when Vault is unreachable (with `--backend local` fallback hint)
### T5 — Principals inventory
```task
id: WARDEN-WP-0001-T5
state_hub_task_id: 6d13f8cd-1850-44c9-b769-b21250348319
status: done
priority: high
```
- [x] `inventory.py`: load/save `inventory.yaml` (format mirrors §4.1 of directive):
```yaml
actors:
agt-state-hub-bridge:
type: agt
principals: [agt-task-bridge]
ttl_hours: 24
description: "ops-bridge tunnel actor"
hosts:
coulombcore:
allowed_principals:
agt: [agt-task-bridge]
atm: [atm-backup-daily]
```
- [x] `warden inventory list` — print table
- [x] `warden inventory add <actor-name> --type <adm|agt|atm> --principals <...>`
- [x] `warden inventory remove <actor-name>`
### T6 — CLI commands
```task
id: WARDEN-WP-0001-T6
state_hub_task_id: 656a4615-92bb-4b5d-9406-e86d24fa15d0
status: done
priority: high
```
- [x] `warden sign <actor-name> --pubkey <path>` — sign existing pubkey; write cert to
stdout (the `cert_command` interface for ops-bridge)
- [x] `warden issue <actor-name>` — generate keypair + sign; output JSON with
`privkey`, `cert`, `valid_before`, `identity`
- [x] `warden status [actor-name]` — show cert validity, identity, principals, TTL
remaining; `--all` flag to show all actors in state dir
- [x] `warden scorecard` — run §5 checks (see T7)
- [x] `warden inventory <subcommand>` (list / add / remove)
### T7 — Scorecard runner
```task
id: WARDEN-WP-0001-T7
state_hub_task_id: 7818bcc5-f40e-4793-b117-d36f653ffeed
status: done
priority: medium
```
- [x] `scorecard.py`: implement each §5 row as a named check function returning
`CheckResult(name, passed, detail)`
- [x] Checks in scope for `ops-warden` (local checks, not host-side):
- All certs in state dir respect TTL policy for their `ActorType`
- No actor in inventory lacks a `principals` entry
- Actor name prefix matches declared type
- No cert expired by more than 5 min still present in state dir (stale cleanup)
- [x] Host-side checks (password auth disabled, root login disabled, etc.) are out of scope
— those live in the Ansible `ssh-access-audit.yml` playbook in `railiance-infra`
- [x] `warden scorecard --json` for machine-readable output
### T8 — ops-ssh-wrapper script
```task
id: WARDEN-WP-0001-T8
state_hub_task_id: e9c28152-5785-4995-83a5-439985ed3db9
status: done
priority: medium
```
- [x] Ship `scripts/ops-ssh-wrapper` (the Python snippet from §4.1, hardened):
- Reads `WARDEN_ACTOR` and `SSH_PUBKEY` env vars
- Calls `warden sign $WARDEN_ACTOR --pubkey $SSH_PUBKEY`
- Loads cert via `ssh-add`; execs the given command
- [x] Install as part of `uv tool install` entry points
### T9 — Tests
```task
id: WARDEN-WP-0001-T9
state_hub_task_id: 950139ab-cc17-4f1d-9a17-d5744e402ddf
status: done
priority: high
```
- [x] Unit tests for `LocalCA` (mock `ssh-keygen` subprocess)
- [x] Unit tests for inventory YAML round-trip
- [x] Unit tests for actor name prefix validation
- [x] Integration test: `LocalCA.sign` on a real test keypair (requires `ssh-keygen` in PATH)
- [x] Scorecard unit tests (mock cert records)
### T10 — Documentation
```task
id: WARDEN-WP-0001-T10
state_hub_task_id: 271d6759-e359-41ce-80e4-76c574634a87
status: done
priority: medium
```
- [x] `SCOPE.md` (see below)
- [x] `wiki/AccessManagementDirective.md` — copy from `ops-bridge/wiki/`
- [x] `wiki/OpsWardenConfig.md` — annotated `warden.yaml` reference
- [x] `wiki/CertCommandInterface.md` — contract for `cert_command` callers (ops-bridge etc.)
---
## SCOPE.md Template
```
# SCOPE
## One-liner
SSH Certificate Authority and credential issuance for the ops fleet —
signs short-lived certs for adm/agt/atm actors; provides the cert_command
interface consumed by ops-bridge and other tooling.
## Core Idea
Implements AccessManagementDirective §§1–5. Owns the CA key, actor inventory,
signing logic, and scorecard. Does not own tunnel lifecycle, host provisioning,
or SSH key generation for humans.
## In Scope
- Local CA backend (ssh-keygen -s) for lab / non-Vault use
- Vault SSH engine backend for production
- Actor identity registry (inventory.yaml)
- cert_command CLI interface: `warden sign <actor> --pubkey <path>`
- TTL policy enforcement per ActorType (adm/agt/atm)
- Certificate status and stale-cert cleanup
- Scorecard checks (local / cert-side only)
- ops-ssh-wrapper script for agt/atm startup automation
## Out of Scope
- Host-side principal deployment (railiance-infra Ansible)
- SSH key generation for human admins (self-service: ssh-keygen)
- Vault cluster setup / HA
- Session recording, audit forwarding to SIEM (host-side)
- Tunnel lifecycle (ops-bridge)
- SSO / Teleport (trigger when §6.2 scale thresholds are hit)
## Relevant When
- Issuing or refreshing a cert for any adm/agt/atm actor
- Checking cert validity / scorecard compliance
- ops-bridge needs cert_command to be defined
- Adding a new actor to the principals inventory
## Not Relevant When
- Managing tunnel lifecycle (ops-bridge)
- Deploying SSH config to hosts (railiance-infra)
- All access is via static keys with no TTL (legacy mode)
## Current State
Status: planned (WARDEN-WP-0001 not yet started)
## Related Repositories
- ops-bridge — primary consumer of cert_command interface
- railiance-infra — owns host-side principal deployment
- the-custodian/state-hub — registers domain/workstreams
```
---
## Acceptance Criteria
- [x] `warden sign agt-test-actor --pubkey /tmp/test.pub` outputs a valid cert (local backend)
- [x] `warden status agt-test-actor` shows correct identity, principals, and time-to-expiry
- [x] `warden scorecard` returns 5/5 on a clean test inventory
- [x] `warden sign` called from ops-bridge `cert_command` in an integration test tunnel
- [x] All tests pass: `uv run pytest`
- [x] All lints pass: `uv run ruff check .`

View file

@ -0,0 +1,178 @@
---
id: WARDEN-WP-0002
type: workplan
title: "OpsWarden Correctness and Operational Completeness"
domain: custodian
repo: ops-warden
status: archived
owner: Bernd
topic_slug: custodian
planning_priority: high
planning_order: 2
created: "2026-05-15"
updated: "2026-05-15"
state_hub_workstream_id: "5a9fba2c-6161-49a4-a231-e750fa4ab572"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0002 — Correctness and Operational Completeness
**Scope:** Fix three functional gaps identified after WARDEN-WP-0001: TTL max
enforcement (directive compliance), stale cert cleanup (SCOPE.md promises it),
and an outgoing signatures log (audit traceability for every signing operation).
**Out of scope:** Test coverage improvements (WARDEN-WP-0003), Vault cluster
setup, host-side principal deployment.
---
## Goal
After this workplan:
1. `warden sign` and `warden issue` reject TTLs that exceed the type maximum
defined in the AccessManagementDirective — no cert can be silently issued
with a longer-than-allowed validity window.
2. Stale/expired certs do not accumulate in the state dir. `warden cleanup`
provides an on-demand sweep; `LocalCA.sign()` auto-evicts the previous cert
for the same actor before writing the new one.
3. Every successful signing operation is recorded in an append-only
`signatures.log` in the state dir. `warden log` provides a human-readable
and machine-readable view of the signing history.
---
## Reference Documents
| Document | Location |
|---|---|
| AccessManagementDirective | `wiki/AccessManagementDirective.md` |
| WARDEN-WP-0001 | `workplans/WARDEN-WP-0001-initial-implementation.md` |
| SCOPE.md | `SCOPE.md` |
---
## Design Decisions
### TTL enforcement: reject, don't clamp
When `spec.ttl_hours > DEFAULT_TTL_HOURS[actor_type]`, raise `CAError` rather
than silently clamping. A silent clamp would mask configuration errors and hide
directive violations from operators. An explicit error forces a deliberate
decision.
The check lives in `CABackend.sign()` before the subprocess call so it applies
to both `LocalCA` and `VaultCA`. Vault's own role `max_ttl` provides a second
layer; this check is the warden-side gate.
### Cleanup: proactive (on sign) + reactive (on demand)
`LocalCA.sign()` removes the previous cert for the same actor before writing the
new one — this keeps state_dir from growing unboundedly under normal operation.
`warden cleanup` handles the edge cases: certs whose actor is no longer in the
inventory, certs from aborted sessions, certs left by actors that were renamed.
`VaultCA.sign()` also evicts before writing (same logic, same helper function).
### Signatures log: JSONL, append-only, in state_dir
One line per signing event, written after a successful `CertRecord` is produced.
Format: `{"timestamp": ..., "actor": ..., "actor_type": ..., "identity": ...,
"principals": [...], "ttl_hours": ..., "valid_before": ..., "backend": ...}`.
The log lives alongside certs in `state_dir` so a single directory backup
captures the full operational history. No rotation at this scope — add rotation
in a follow-up if the file grows beyond a few MB in practice.
`warden log` is read-only. No deletion via CLI — the log is an audit artefact.
---
## Tasks
### T1 — TTL max enforcement per ActorType
```task
id: WARDEN-WP-0002-T1
state_hub_task_id: b0d0b5f7-a181-4590-be26-c48ae28cd964
status: done
priority: high
```
- [x] `models.py`: add `MAX_TTL_HOURS = DEFAULT_TTL_HOURS` alias (same values,
explicit name signals policy intent); add helper
`enforce_ttl(spec: CertSpec) -> None` that raises `CAError` when
`spec.ttl_hours > MAX_TTL_HOURS[spec.actor_type]`
- [x] `ca.py`: call `enforce_ttl(spec)` at the top of `CABackend.sign()` base
(or in both `LocalCA.sign()` and `VaultCA.sign()` if no shared base call)
- [x] `scorecard.py`: add `check_ttl_policy(state_dir, inventory)` — parse each
cert in state_dir via `ssh-keygen -L`; compare cert validity window
duration against `MAX_TTL_HOURS[actor_type]`; flag if exceeded
- [x] Add `check_ttl_policy` to `run_scorecard()`
- [x] Update tests: `test_ca.py` — assert `CAError` raised when `ttl_hours`
exceeds max for each type; assert no error at exactly the max
### T2 — Stale cert cleanup command
```task
id: WARDEN-WP-0002-T2
state_hub_task_id: aeeefbad-c0bd-4ae8-a3fe-9f72321b4caa
status: done
priority: medium
```
- [x] `ca.py`: extract `_evict_cert(actor_name, state_dir)` — removes
`state_dir/<actor_name>-cert.pub` if it exists; call at the top of
`LocalCA.sign()` and `VaultCA.sign()` before writing the new cert
- [x] `cli.py`: add `warden cleanup [actor-name]` command
- No actor-name: iterate `state_dir/*.cert.pub`, remove any whose
`valid_before < now - 5 min`
- With actor-name: remove only that actor's cert if stale
- `--dry-run`: print what would be removed without deleting
- Exit 0 always (cleanup is idempotent; nothing to clean is not an error)
- [x] Update `check_no_stale_certs` scorecard check detail message to suggest
running `warden cleanup`
- [x] Update tests: verify `_evict_cert` is called during sign; verify cleanup
command removes stale file; verify `--dry-run` does not delete
### T3 — Outgoing signatures log
```task
id: WARDEN-WP-0002-T3
state_hub_task_id: 0194d24f-a8fe-4f6d-88e6-addea3542c0e
status: done
priority: medium
```
- [x] `ca.py`: after a successful `CertRecord` is produced in `LocalCA.sign()`
and `VaultCA.sign()`, call `_append_signature_log(record, spec, state_dir,
backend)` which appends a JSONL line to
`state_dir/signatures.log`
Fields: `timestamp` (ISO 8601 UTC), `actor`, `actor_type`, `identity`,
`principals`, `ttl_hours`, `valid_before`, `cert_path`, `backend`
- [x] `cli.py`: add `warden log [actor-name]` command
- Reads `state_dir/signatures.log` (empty list if absent)
- `--last N` (default 20): show last N entries
- `--actor <name>`: filter by actor
- `--json`: output newline-delimited JSON; default: Rich table
- Exit 0 always
- [x] Update tests: verify log entry written after sign; verify log not written
on CAError; verify `warden log` filters correctly
---
## Acceptance Criteria
- [x] `warden sign agt-test --pubkey /tmp/k.pub --ttl 100` raises `CAError`
(agt max is 24h)
- [x] `warden sign agt-test --pubkey /tmp/k.pub --ttl 24` succeeds
- [x] `warden scorecard` includes TTL policy check; fails when a cert exceeds type max
- [x] After `warden sign`, `state_dir/signatures.log` has one new line; valid JSON
- [x] `warden log` renders a table; `warden log --json` is parseable
- [x] `warden log --actor agt-test` returns only entries for that actor
- [x] `warden cleanup --dry-run` lists stale certs without deleting
- [x] `warden cleanup` removes stale certs; scorecard `no_stale_certs` passes after
- [x] Re-signing an actor replaces its cert file (no accumulation)
- [x] All tests pass: `uv run pytest`
- [x] All lints pass: `uv run ruff check .`

View file

@ -0,0 +1,211 @@
---
id: WARDEN-WP-0003
type: workplan
title: "OpsWarden Test Coverage and Code Quality"
domain: custodian
repo: ops-warden
status: archived
owner: Bernd
topic_slug: custodian
planning_priority: medium
planning_order: 3
created: "2026-05-15"
updated: "2026-05-15"
state_hub_workstream_id: "cb2bbf3c-848a-4af6-ba64-8361e64cd4d7"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0003 — Test Coverage and Code Quality
**Scope:** Close the test coverage gaps left after WARDEN-WP-0001: VaultCA has
zero tests, `generate_keypair` is untested, no CLI tests exist, and no real
`ssh-keygen` integration test was written. Also fix file permission enforcement
(security) and add `--state-dir` override to `warden status` (usability).
**Out of scope:** Functional behaviour changes (WARDEN-WP-0002), Vault cluster
setup, host-side tooling.
---
## Goal
After this workplan:
1. VaultCA has a full unit test suite covering success, auth failure, network
failure, and role-map misconfiguration.
2. `generate_keypair` has direct unit tests alongside the existing `sign` tests.
3. A `tests/test_cli.py` covers every command's exit codes and output shape.
4. A `tests/test_integration.py` marked `@pytest.mark.integration` exercises
`LocalCA.sign()` against a real `ssh-keygen` without any mocking.
5. Cert and key files written by warden are always mode 600; a scorecard check
flags world-readable files.
6. `warden status --state-dir <path>` works without a `warden.yaml`.
---
## Reference Documents
| Document | Location |
|---|---|
| WARDEN-WP-0001 | `workplans/WARDEN-WP-0001-initial-implementation.md` |
| WARDEN-WP-0002 | `workplans/WARDEN-WP-0002-correctness-and-completeness.md` |
| CertCommandInterface | `wiki/CertCommandInterface.md` |
---
## Design Decisions
### Integration tests: separate marker, not separate directory
Use `@pytest.mark.integration` and skip when `ssh-keygen` is not in PATH. Tests
live in `tests/test_integration.py`. The unit suite (`uv run pytest`) excludes
integration tests via `pytest.ini_options addopts = "-m 'not integration'"`;
`uv run pytest -m integration` runs them explicitly. This keeps CI fast while
making the real-ssh-keygen path easy to invoke manually.
### File permissions: at write time, not at read time
`os.chmod(path, 0o600)` is called immediately after each `path.write_text()` or
`shutil.copy2()` that writes a key or cert. No deferred or scheduled chmod. The
scorecard check catches files that were written by older versions of warden or by
external tools.
### `warden status --state-dir`: config bypass, not config optional
When `--state-dir` is provided, skip `load_config()` entirely — don't try to
load a partial config. This makes the flag useful on remote machines that have
received a cert via ops-bridge but have no warden installation.
---
## Tasks
### T1 — VaultCA tests
```task
id: WARDEN-WP-0003-T1
state_hub_task_id: eff074ce-c027-4df5-8006-0990296592ac
status: done
priority: high
```
- [x] Create `tests/test_vault.py`
- [x] Test `VaultCA.sign()` success: mock `httpx.post` returning a valid
`signed_key`; assert `CertRecord` fields; assert cert file written to
state_dir
- [x] Test HTTP 403: `httpx.HTTPStatusError` → `CAError` with status code in message
- [x] Test unreachable Vault: `httpx.RequestError` → `CAError` with fallback hint
- [x] Test missing `VAULT_TOKEN`: `_token()` raises `CAError` before HTTP call
- [x] Test missing role in `role_map`: `CAError` before HTTP call
- [x] Test missing pubkey file: `CAError` before HTTP call
### T2 — LocalCA.generate_keypair tests
```task
id: WARDEN-WP-0003-T2
state_hub_task_id: ddfe5331-0a3b-4783-bdf4-f5ebcdf7965c
status: done
priority: medium
```
- [x] Add `TestGenerateKeypair` class to `tests/test_ca.py`
- [x] Test success: mock `subprocess.run`; assert privkey and pubkey paths returned
- [x] Test ssh-keygen called with `-t ed25519`, `-N ""`, `-C actor_name`
- [x] Test existing files are unlinked before generation (write dummy files first)
- [x] Test `CAError` raised on non-zero ssh-keygen exit code
- [x] Test output files land in `state_dir/keys/`
### T3 — CLI tests
```task
id: WARDEN-WP-0003-T3
state_hub_task_id: 040ce3a1-0efb-4816-a2d9-357162dd1612
status: done
priority: high
```
- [x] Create `tests/test_cli.py` using `typer.testing.CliRunner`
- [x] `warden sign`: exits 0 and stdout is cert text (mock CA); exits 1 on
unknown actor; exits 1 on config error
- [x] `warden issue`: exits 1 on vault backend; exits 0 on local backend (mock CA)
- [x] `warden status`: exits 0 and prints "no cert" message when state_dir empty;
exits 1 when cert is expired (mock `parse_cert_metadata`)
- [x] `warden scorecard`: exits 0 on clean inventory + empty state_dir;
exits 1 when a check fails
- [x] `warden inventory add / list / remove`: round-trip via tmp inventory file
- [x] `warden log`: exits 0 with empty output when no log; `--json` is valid JSON
(after WARDEN-WP-0002 T3 adds the log command)
- [x] `warden cleanup --dry-run`: exits 0, no files deleted
(after WARDEN-WP-0002 T2 adds cleanup)
### T4 — Real ssh-keygen integration test
```task
id: WARDEN-WP-0003-T4
state_hub_task_id: 434fb008-103f-410c-85fd-e77b33e61fe4
status: done
priority: medium
```
- [x] Create `tests/test_integration.py`
- [x] Mark all tests `@pytest.mark.integration`
- [x] Add `pytest.ini_options` to `pyproject.toml`:
`addopts = "-m 'not integration'"` so unit suite skips them by default
- [x] Test `LocalCA.sign()` end-to-end: generate a real CA keypair and actor
keypair via subprocess ssh-keygen in tmp_path; call `LocalCA.sign()`;
assert `CertRecord.valid_before > datetime.now(utc)`; assert cert file
exists; assert `parse_cert_metadata()` succeeds on it without mocking
- [x] Skip test if `shutil.which("ssh-keygen") is None`
- [x] Document in README: `uv run pytest -m integration` to run real-CA tests
### T5 — File permissions enforcement (mode 600)
```task
id: WARDEN-WP-0003-T5
state_hub_task_id: ac146fe6-d1fd-4186-91bd-6f098de72449
status: done
priority: medium
```
- [x] `ca.py` `LocalCA.sign()`: call `os.chmod(dest, 0o600)` after `shutil.copy2`
- [x] `ca.py` `LocalCA.generate_keypair()`: call `os.chmod(privkey, 0o600)` and
`os.chmod(pubkey, 0o644)` after generation
- [x] `vault.py` `VaultCA.sign()`: call `os.chmod(dest, 0o600)` after `dest.write_text`
- [x] `scorecard.py`: add `check_file_permissions(state_dir)` — flag any
`*-cert.pub` or `keys/*` file where `stat().st_mode & 0o044 != 0`
- [x] Add `check_file_permissions` to `run_scorecard()`
- [x] Update `test_ca.py`: assert `os.chmod` called with correct mode after sign
and generate_keypair (patch os.chmod or check stat on actual files in
tmp_path)
### T6 — warden status --state-dir override
```task
id: WARDEN-WP-0003-T6
state_hub_task_id: 1c9f1987-7b11-43c1-a5e3-c2fd8d1c1589
status: done
priority: low
```
- [x] `cli.py` `status()`: add
`state_dir_override: Annotated[Optional[Path], typer.Option("--state-dir")] = None`
- [x] When `--state-dir` is provided: use it directly, skip `_load_cfg()` entirely
- [x] When absent: load config as today
- [x] Add test in `test_cli.py`: invoke `warden status --state-dir <tmp_path>`
without a config file; assert exit 0
---
## Acceptance Criteria
- [x] `uv run pytest` runs unit suite only; all pass; VaultCA and generate_keypair
covered
- [x] `uv run pytest -m integration` succeeds (requires ssh-keygen in PATH)
- [x] `test_cli.py` covers all commands; no mocked subprocess in CLI tests where
avoidable (use tmp inventory files and mocked CA)
- [x] `ls -la ~/.local/state/warden/*.pub` shows mode 600 for newly signed certs
- [x] Scorecard `file_permissions` check passes on a clean state dir; fails on a
world-readable cert
- [x] `warden status --state-dir /tmp/some-dir` runs without a `warden.yaml`
- [x] All lints pass: `uv run ruff check .`

View file

@ -0,0 +1,95 @@
---
id: WARDEN-WP-0004
type: workplan
title: "OpsWarden Repo Hygiene and Hub Sync"
domain: custodian
repo: ops-warden
status: archived
owner: codex
topic_slug: custodian
created: "2026-06-17"
updated: "2026-06-17"
state_hub_workstream_id: "3c4b6e68-550a-4fc6-a804-95f1f68936c3"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0004 — Repo Hygiene and Hub Sync
**Scope:** Bring repo orientation docs and agent rules in line with the shipped
`warden` CLI (WARDEN-WP-0001 through 0003 complete). Archive finished workplans
and sync State Hub.
**Out of scope:** OpenBao doc alignment (WARDEN-WP-0005), capability registry
publish, task-status canon migration in AGENTS.md.
---
## Goal
After this workplan, a new agent session can orient from accurate local files
without reading stale "planned / scaffolding only" language, and State Hub
reflects archived workplan status.
---
## Tasks
### T1 — Update orientation docs
```task
id: WARDEN-WP-0004-T01
status: done
priority: high
state_hub_task_id: "f9d3926c-8637-411c-a477-2960b754704c"
```
- [x] `SCOPE.md` Current State reflects shipped CLI (v0.1.0, workplans 0001–0003 done)
- [x] `README.md` replaces repo-seed template with install, config, and dev commands
### T2 — Fill agent rules
```task
id: WARDEN-WP-0004-T02
status: done
priority: medium
state_hub_task_id: "86c764a5-62fc-45fe-a8d2-332d6554a976"
```
- [x] `.claude/rules/stack-and-commands.md` — stack and `uv` dev commands
- [x] `.claude/rules/architecture.md` — module layout and data flow
- [x] `.claude/rules/repo-boundary.md` — adjacent repo ownership
### T3 — Archive finished workplans
```task
id: WARDEN-WP-0004-T03
status: done
priority: medium
state_hub_task_id: "d3e54e63-ce98-4632-bc08-0e2667f19f12"
```
- [x] Move WARDEN-WP-0001/0002/0003 to `workplans/archived/` with date prefix
- [x] Set frontmatter `status: archived` on moved files
### T4 — Sync State Hub
```task
id: WARDEN-WP-0004-T04
status: done
priority: medium
state_hub_task_id: "51729695-262f-4fe4-9c38-f99ee046d32a"
```
- [x] Run `make fix-consistency REPO=ops-warden` from state-hub
- [x] Verify `.custodian-brief.md` reflects archived workstreams
---
## Acceptance Criteria
- [x] `SCOPE.md` no longer says "planned" or "scaffolding only"
- [x] `README.md` documents `uv sync`, `uv run pytest`, and `warden --help`
- [x] Agent rules have no empty TODO blocks for stack, architecture, or boundary
- [x] Only WARDEN-WP-0004 remains in `workplans/` root (archived plans moved)
- [x] `make fix-consistency REPO=ops-warden` completes without error

View file

@ -0,0 +1,65 @@
---
id: WARDEN-WP-0005
type: workplan
title: "OpsWarden OpenBao-First Documentation Alignment"
domain: custodian
repo: ops-warden
status: archived
owner: codex
topic_slug: custodian
created: "2026-06-17"
updated: "2026-06-17"
state_hub_workstream_id: "57f6ebf8-0ef3-4686-9a73-3f9d38288be9"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0005 — OpenBao-First Documentation Alignment
**Scope:** Update ops-warden documentation so production guidance names OpenBao
as the platform secrets service while preserving the existing `backend: vault`
config surface (Vault-compatible SSH secrets engine API). No code changes.
**Out of scope:** VaultCA backend rewrite, OpenBao SSH engine deployment in
`railiance-platform`, AccessManagementDirective canon updates.
**Reference:** `RAIL-PL-WP-0002` — Railiance standardizes on OpenBao; ops-warden
follow-up noted 2026-05-17.
---
## Tasks
### T1 — OpsWardenConfig.md
```task
id: WARDEN-WP-0005-T01
status: done
priority: high
state_hub_task_id: "bbbc4dda-9634-4c04-86e5-94b96c021b43"
```
- [x] OpenBao-first production section with Railiance URLs and `bao` CLI examples
- [x] Explain `backend: vault` / `vault:` keys as Vault-compatible API abstraction
- [x] Link to `railiance-platform/docs/openbao.md`
### T2 — Cross-reference updates
```task
id: WARDEN-WP-0005-T02
status: done
priority: medium
state_hub_task_id: "6391cb82-896e-405a-a59b-36640e6480ba"
```
- [x] `SCOPE.md` Core Idea and In Scope — OpenBao-first, Vault-compatible
- [x] `wiki/CertCommandInterface.md` — caller-agnostic wording includes OpenBao
---
## Acceptance Criteria
- [x] Production config example uses OpenBao (`bao.coulomb.social` or in-cluster URL)
- [x] No reader is told HashiCorp Vault is the platform standard
- [x] `backend: vault` config shape unchanged (code compatibility preserved)
- [x] `uv run pytest` still passes (docs-only change)

View file

@ -0,0 +1,140 @@
---
id: WARDEN-WP-0006
type: workplan
title: "NetKingdom Alignment and Operational Access Stewardship"
domain: custodian
repo: ops-warden
status: archived
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 6
created: "2026-06-17"
updated: "2026-06-17"
state_hub_workstream_id: "a5c9f24b-1ad4-46da-bc8e-b99897f8e302"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0006 — NetKingdom Alignment and Operational Access Stewardship
**Scope:** Close gaps identified in `history/2026-06-17-intent-scope-assessment.md`
between INTENT (operational access steward for NetKingdom security) and SCOPE
(shipped SSH CLI only). Documentation and alignment first; code changes limited
to optional CLI ergonomics.
**Out of scope:** flex-auth integration implementation, OpenBao cluster deploy,
universal credential broker, net-kingdom INTENT.md rewrite.
---
## Goal
After this workplan, a development worker or agent can:
1. Read ops-warden material and know **which NetKingdom subsystem** handles each
credential type.
2. Obtain **SSH certs** via documented actor patterns and production OpenBao path.
3. Find ops-warden recognized in **NetKingdom responsibility/platform** docs as
the operational SSH credential authority.
---
## Tasks
### T1 — Credential routing runbook
```task
id: WARDEN-WP-0006-T01
status: done
priority: high
state_hub_task_id: "ffc6a0c2-4312-4584-be7a-c8411cb01899"
```
- [x] `wiki/CredentialRouting.md` with decision tree and anti-examples
- [x] Linked from SCOPE, INTENT, README
### T2 — Actor inventory patterns
```task
id: WARDEN-WP-0006-T02
status: done
priority: high
state_hub_task_id: "3816463d-7dfd-469d-9324-fd7880b50608"
```
- [x] `wiki/ActorInventoryPatterns.md`
- [x] `examples/inventory.seed.yaml`
### T3 — NetKingdom cross-links (ops-warden side)
```task
id: WARDEN-WP-0006-T03
status: done
priority: high
state_hub_task_id: "f158366a-5746-48b8-acce-472dce8f925e"
```
- [x] `wiki/NetKingdomSecurityMap.md`
- [x] Registry capability stewardship summary
- [x] `.claude/rules/repo-boundary.md` routing table
### T4 — NetKingdom canon patch (coordination)
```task
id: WARDEN-WP-0006-T04
status: done
priority: medium
state_hub_task_id: "e40e4395-8f01-4f79-a539-d0de8e427321"
```
- [x] `net-kingdom/docs/responsibility-map.md` — Operational SSH dependency
- [x] `net-kingdom/docs/platform-identity-security-architecture.md` — Operational SSH Path
### T5 — OpenBao SSH engine operational checklist
```task
id: WARDEN-WP-0006-T05
status: done
priority: medium
state_hub_task_id: "a94e20a2-970b-4a0c-bd23-8510b841b938"
```
- [x] `wiki/OpenBaoSshEngineChecklist.md`
### T6 — Policy-gated signing design (design only)
```task
id: WARDEN-WP-0006-T06
status: done
priority: low
state_hub_task_id: "b10a4b4d-bfa1-4f49-b6a5-f339f1e6a2e1"
```
- [x] `wiki/PolicyGatedSigning.md`
### T7 — Re-assess INTENT ↔ SCOPE
```task
id: WARDEN-WP-0006-T07
status: done
priority: medium
state_hub_task_id: "ef8b5c57-2343-4cfc-9fee-48db1e56f69a"
```
- [x] `history/2026-06-17-intent-scope-reassessment.md`
- [x] SCOPE.md Current State updated
- [x] `make fix-consistency REPO=ops-warden`
---
## Acceptance Criteria
- [x] `wiki/CredentialRouting.md` exists and is linked from README/SCOPE
- [x] `wiki/ActorInventoryPatterns.md` exists
- [x] `wiki/NetKingdomSecurityMap.md` exists
- [x] NetKingdom responsibility-map recognizes ops-warden SSH lane (T4)
- [x] OpenBao SSH checklist documented (T5)
- [x] Policy-gated signing design drafted (T6)
- [x] INTENT ↔ SCOPE re-assessment recorded (T7)
- [x] `reuse-surface validate --root .` passes

View file

@ -0,0 +1,88 @@
---
id: WARDEN-WP-0007
type: workplan
title: "Policy Gate and Production OpenBao Verification"
domain: custodian
repo: ops-warden
status: archived
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 7
created: "2026-06-17"
updated: "2026-06-17"
state_hub_workstream_id: "3718ac07-2fa2-47d0-a02a-c9a7b83a5ba9"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0007 — Policy Gate and Production OpenBao Verification
**Scope:** Record production OpenBao reachability evidence; implement opt-in
flex-auth policy gate before `warden sign` / `warden issue` per
`wiki/PolicyGatedSigning.md`.
**Out of scope:** flex-auth policy package authoring, OpenBao SSH engine mount
on Railiance (operator), identity claim requirement (v2.1).
---
## Tasks
### T1 — Production OpenBao verification evidence
```task
id: WARDEN-WP-0007-T01
status: done
priority: high
state_hub_task_id: "344540ad-5912-4118-b406-450b96e13c40"
```
- [x] Probe `https://bao.coulomb.social/v1/sys/health`
- [x] Document results in `history/2026-06-17-openbao-production-verify.md`
- [x] Note blockers for full `warden sign` (scoped token, SSH engine roles)
### T2 — Policy config and flex-auth client
```task
id: WARDEN-WP-0007-T02
status: done
priority: high
state_hub_task_id: "05424ddf-5fe9-43a1-a2f8-c47235a012c8"
```
- [x] `PolicyConfig` in `config.py` (`policy.enabled`, `flex_auth_url`, `fail_closed`)
- [x] `policy.py` — POST `/v1/check`, pubkey fingerprint, CAError on deny
### T3 — Wire policy gate into sign/issue
```task
id: WARDEN-WP-0007-T03
status: done
priority: high
state_hub_task_id: "f5ae8e6e-8cce-4526-b18c-0452a135af49"
```
- [x] Call policy check before `ca.sign()` when enabled
- [x] Store `policy_decision_id` in `signatures.log`
### T4 — Tests and docs
```task
id: WARDEN-WP-0007-T04
status: done
priority: medium
state_hub_task_id: "ea921d56-033b-4619-8032-61af7992e610"
```
- [x] `tests/test_policy.py`
- [x] Update `wiki/OpsWardenConfig.md`, `wiki/PolicyGatedSigning.md`
---
## Acceptance Criteria
- [x] Production health evidence recorded (non-secret)
- [x] `policy.enabled: false` default — no behavior change
- [x] `policy.enabled: true` calls flex-auth; deny blocks sign
- [x] All unit tests pass

View file

@ -0,0 +1,153 @@
---
id: WARDEN-WP-0008
type: workplan
title: "Production SSH Path and Stewardship Closeout"
domain: custodian
repo: ops-warden
status: finished
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 8
created: "2026-06-17"
updated: "2026-06-18"
state_hub_workstream_id: "a174963a-4ff1-4565-b19f-896cd4ff14a0"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0008 — Production SSH Path and Stewardship Closeout
**Scope:** Close the reliability gap left after WARDEN-WP-0007 — prove the
production OpenBao SSH signing path end-to-end, refresh INTENT/SCOPE canon for
the shipped flex-auth policy gate, adapt repo docs to State Hub task-status
canon, and archive finished workplans.
**Out of scope:** OpenBao cluster deploy or SSH engine bootstrap (operator /
`railiance-platform`), flex-auth policy package authoring, NK-WP-0009 joint
tutorial (coordinate separately), populating non-SSH secrets (e.g. OpenRouter
API keys — route to OpenBao per `wiki/CredentialRouting.md`).
---
## Goal
Move ops-warden from **documented + code-shipped** (WP-0006/0007) to
**production-verified SSH issuance** with up-to-date stewardship canon:
1. A scoped operator can run `warden sign` against `https://bao.coulomb.social`
and record non-secret evidence.
2. `SCOPE.md` and reassessment history reflect WP-0007 policy gate as implemented.
3. Agent/workplan docs use State Hub task lifecycle (`wait` / `todo` / `progress`
/ `done` / `cancel`).
4. Finished workplans WP-0004–0007 are archived under `workplans/archived/`.
---
## Tasks
### T1 — Post-WP-0007 INTENT/SCOPE reassessment
```task
id: WARDEN-WP-0008-T01
status: done
priority: high
state_hub_task_id: "05379da4-79d0-4742-8638-9e9565cccf72"
```
- [x] Write `history/2026-06-17-post-wp0007-reassessment.md` (vector D5/A3/C4/R2)
- [x] Update `SCOPE.md` — policy gate implemented, WP-0008 active
- [x] Resolve remaining `PolicyGatedSigning.md (not implemented)` references in SCOPE/README
### T2 — Production OpenBao end-to-end sign verification
```task
id: WARDEN-WP-0008-T02
status: done
priority: high
state_hub_task_id: "b1a1831d-b2b3-4204-95f6-04dc7f29f67c"
```
- [x] Operator provides scoped `VAULT_TOKEN` (warden-sign policy token)
- [x] Confirm SSH engine mounted and roles per `wiki/OpenBaoSshEngineChecklist.md`
- [x] Run `warden sign` + `warden status` + `warden log` against production OpenBao
- [x] Append pass/fail evidence to `history/2026-06-17-openbao-production-verify.md`
- [ ] Optional: cert_command smoke via ops-bridge tunnel — deferred; tunnels still
static-key mode (`agt-claude-*`); wire when ops-bridge adopts `cert_command` for
`agt-state-hub-bridge`
### T3 — State Hub task status canon migration
```task
id: WARDEN-WP-0008-T03
status: done
priority: medium
state_hub_task_id: "876827c4-4a86-4e58-9a1f-ac87045dc903"
```
- [x] Update `AGENTS.md` task status values and examples (`progress`, `wait`, `cancel`)
- [x] Update `.claude/rules/workplan-convention.md` task block examples
- [x] Mark state-hub interface change `649102a2-4373-4621-9848-cc257e67c262` resolved
- [x] Reply to inbox message `c4072e5a-2afb-44ba-bfa2-7d4cb9979c6e` (read + note adaptation)
### T4 — Production config example and archive hygiene
```task
id: WARDEN-WP-0008-T04
status: done
priority: medium
state_hub_task_id: "75b9f366-3d7a-419d-98ad-bc10ab90a697"
```
- [x] Add `examples/warden.production.example.yaml` (no secrets; OpenBao addr + policy off)
- [x] Archive finished workplans → `workplans/archived/260617-WARDEN-WP-000{4,5,6,7}-*.md`
- [x] `make fix-consistency REPO=ops-warden` after archive
### T5 — flex-auth policy gate production readiness (coordination)
```task
id: WARDEN-WP-0008-T05
status: cancel
priority: low
state_hub_task_id: "03b412a5-5b99-42df-a154-733dd4156000"
```
Spun out to **WARDEN-WP-0009** (flex-auth owner dependency). ops-warden gate code
and docs shipped in WP-0007; production enablement waits on flex-auth policies.
---
## Acceptance Criteria
- [x] Post-WP-0007 reassessment on file; SCOPE current
- [x] Production `warden sign` evidence recorded (`history/2026-06-17-openbao-production-verify.md`)
- [x] AGENTS.md uses canonical task statuses
- [x] WP-0004–0007 archived; hub consistency pass
- [x] Production example config committed (no secrets)
---
## Closeout (2026-06-18)
T1–T4 and T2 complete. T5 cancelled — continued in WARDEN-WP-0009. Optional
ops-bridge `cert_command` smoke deferred until tunnel configs adopt warden signing.
---
## Dependencies
| Dependency | Owner | Blocks |
| --- | --- | --- |
| OpenBao SSH engine + host CA automation | NET-WP-0020 / railiance-* | T2 |
| flex-auth ssh-certificate policies | flex-auth | T5 |
| NK-WP-0009 SSH tutorial | net-kingdom + ops-warden | — (parallel track) |
---
## See also
- `history/2026-06-17-openbao-production-verify.md` — health probe (WP-0007)
- `history/2026-06-17-post-wp0007-reassessment.md` — latest assessment
- `examples/warden.production.example.yaml` — operator config template
- `wiki/OpenBaoSshEngineChecklist.md`
- `wiki/PolicyGatedSigning.md` — opt-in gate (implemented WP-0007)

View file

@ -0,0 +1,97 @@
---
id: WARDEN-WP-0009
type: workplan
title: "flex-auth Policy Gate Production Readiness"
domain: infotech
repo: ops-warden
status: archived
owner: codex
topic_slug: custodian
planning_priority: low
planning_order: 9
created: "2026-06-18"
updated: "2026-06-23"
state_hub_workstream_id: "9213b262-e2f5-480e-a5bc-56635d5eb4c9"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0009 — flex-auth Policy Gate Production Readiness
**Scope:** Enable and verify the opt-in flex-auth pre-sign gate (`policy.enabled`)
in production after flex-auth publishes `ssh-certificate` resource policies.
**Out of scope:** flex-auth policy package authoring (flex-auth owner — delivered
FLEX-WP-0006 2026-06-23); OpenBao SSH engine and host CA (complete — NET-WP-0020
T5 / WP-0008 T2); in-cluster flex-auth deployment (continued in flex-auth
`FLEX-WP-0007`).
**Spun out from:** WARDEN-WP-0008 T5 (2026-06-18 closeout).
---
## Tasks
### T1 — flex-auth policy package confirmation
```task
id: WARDEN-WP-0009-T01
status: done
priority: medium
state_hub_task_id: "f988ed2e-0f63-4e89-abc4-183a7f23ddc2"
```
- [x] Confirm flex-auth policies for resource type `ssh-certificate` exist
- [x] Document tenant/subject bindings for `adm` / `agt` / `atm` sign paths
- [x] Coordinate with flex-auth owner on deny/allow test fixtures
### T2 — Production enablement and smoke
```task
id: WARDEN-WP-0009-T02
status: done
priority: medium
state_hub_task_id: "9d0fabc2-10ef-426d-a3d2-d4970d377029"
```
- [x] Document operator steps to set `policy.enabled: true` (see `wiki/PolicyGatedSigning.md`)
- [x] Local smoke — allow/deny paths with `policy_decision_id` / `ttl_out_of_bounds`
- [x] Production registry slice from inventory (`registry/flex-auth/production_registry_snapshot.json`)
- [x] Production registry smoke — allow `agt-state-hub-bridge` (`decision:032b096c433ad80c`)
- [x] Production registry smoke — deny `--ttl 999` (`ttl_out_of_bounds`)
---
## Deliverables
| Artifact | Path |
| --- | --- |
| Registry builder | `scripts/build_flex_auth_registry.py` |
| Production registry | `registry/flex-auth/production_registry_snapshot.json` |
| Smoke runner | `scripts/policy_gate_production_smoke.sh` |
| Local smoke evidence | `history/2026-06-23-flex-auth-policy-gate-local-smoke.md` |
| Production smoke evidence | `history/2026-06-23-flex-auth-policy-gate-production-smoke.md` |
| flex-auth pickup brief | `history/2026-06-23-flex-auth-production-pickup-suggestion.md` |
---
## Closeout (2026-06-23)
T1–T2 complete. ops-warden caller side and production-registry smoke verified.
Production `policy.enabled: true` flip deferred until flex-auth runtime is
reachable — tracked in flex-auth `FLEX-WP-0007`, not this workplan.
**Operator follow-up (FLEX-WP-0007):**
- Deploy registry + policy package to in-cluster flex-auth; set `policy.flex_auth_url`
- Refresh scoped `VAULT_TOKEN` and run `SMOKE_VAULT=1 ./scripts/policy_gate_production_smoke.sh`
- Set `policy.enabled: true` in `~/.config/warden/warden.yaml` when flex-auth is reachable
---
## See also
- `wiki/PolicyGatedSigning.md`
- `~/flex-auth/docs/ops-warden-policy-gate-handoff.md`
- `~/flex-auth/workplans/FLEX-WP-0007-ops-warden-policy-gate-production-deployment.md`
- `examples/warden.production.example.yaml`

View file

@ -0,0 +1,178 @@
---
id: WARDEN-WP-0010
type: workplan
title: "Access Routing — Charter and Pointer Catalog"
domain: infotech
repo: ops-warden
status: archived
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 10
created: "2026-06-18"
updated: "2026-06-24"
state_hub_workstream_id: "e93de9fd-0192-4d02-bb7c-5e859fb76b9b"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0010 — Access Routing — Charter and Pointer Catalog
**Scope:** Sharpen the existing steward framing so it cannot be misread as a desk
API that wraps every subsystem. ops-warden **issues SSH certificates** and
**points workers to the owning subsystem** for everything else. This workplan
updates INTENT/SCOPE wording and adds a machine-readable routing catalog that is
a **pointer layer**, not a second copy of NetKingdom canon.
**Not a new security lane.** This is wording + a thin lookup surface. SSH issuance
remains the only thing ops-warden executes. Maturity moves Availability A3 → A4
(structured lookup for agents); Completeness and Reliability for SSH are unchanged.
**Out of scope:** Secret-vending, OIDC, policy PDP, tunnel, or host-hardening code
in this repo; flex-auth policy packages (WARDEN-WP-0009); any universal broker.
**Depends on:** WARDEN-WP-0006 stewardship canon (routing wiki, security map) — shipped.
**Feeds:** WARDEN-WP-0011 (routing CLI over the catalog).
---
## Principles (target)
1. **Point, don't proxy** — Name the owner and the doc; do not wrap a foreign API
unless the answer is an SSH certificate.
2. **Direct interaction** — Workers (humans, agents, CI, operators) call OpenBao,
key-cape, flex-auth, ops-bridge, and railiance repos themselves.
3. **One source of truth** — Routing procedure for non-SSH needs lives in the wiki
(aligned to net-kingdom canon) and upstream canon, **not** restated in the
catalog. The catalog carries identifiers and pointers only. ops-warden authors
procedure for exactly one lane: SSH certificate issuance, which it owns.
4. **Same truth, two shapes** — Humans read the wiki; agents read the catalog. The
catalog references wiki sections by anchor so they cannot drift apart.
---
## No-double-source rule (binding on T3)
The catalog must not contain step-by-step procedure for any subsystem ops-warden
does not own. For non-SSH scenarios an entry carries:
- `owner_repo`, `subsystem` — who to talk to
- `wiki_ref` — anchor into an in-repo wiki section (the authoritative restatement)
- `canon_ref` — upstream net-kingdom doc the wiki section tracks
- `need_keywords`, `title`, `id` — lookup metadata
- `warden_executes: false`
Only `warden_executes: true` (SSH) entries may carry an authored `steps` block and
the `cert_command` pattern — because that is the lane ops-warden owns. A CI test
(WP-0011 T5) enforces this structurally: non-SSH entries with a `steps` block fail.
---
## Tasks
### T1 — INTENT wording
```task
id: WARDEN-WP-0010-T01
status: done
priority: high
state_hub_task_id: "589081a6-d1f5-47b4-bec0-e82d9c3444f4"
```
- [x] `INTENT.md` — keep "operational access steward"; replaced the "operational
access **desk**" phrasing with plain "issues SSH certs and routes everything
else to its owner." Removed metaphors implying a wrapping service.
- [x] Non-goals: added "duplicating or restating another subsystem's procedure."
- [x] Cross-linked this workplan from the assessment note.
> SCOPE.md (A3 → A4 plain statement + "issue vs route" table) is handled as a
> deliberate manual step **after** the loop retires, not as a ralph task.
### T2 — Routing-role wiki page
```task
id: WARDEN-WP-0010-T02
status: done
priority: high
state_hub_task_id: "9ac333f7-5fc4-4fa2-82f3-d5ece8ff0d92"
```
- [x] Create `wiki/AccessRouting.md` — what ops-warden answers (where + who owns
it), what it executes (SSH only), anti-patterns (no `warden secret`,
`warden login`, `warden policy`), and audience notes.
- [x] Include the **issue-vs-route** matrix (subsystem × ops-warden role × who acts).
- [x] Link from README, `CredentialRouting.md`, `NetKingdomSecurityMap.md`.
### T3 — Pointer catalog schema + seed
```task
id: WARDEN-WP-0010-T03
status: done
priority: high
state_hub_task_id: "59e0f480-694a-482a-b35e-b7bc4930aa41"
```
- [x] Define `registry/routing/catalog.yaml` per the **No-double-source rule** above:
`id`, `title`, `need_keywords`, `owner_repo`, `subsystem`, `warden_executes`,
`wiki_ref`, `canon_ref`, `reviewed` (date), `status` (active|draft); plus
`steps` + `cert_command` **only** when `warden_executes: true`.
- [x] Seed from existing WP-0006 scenarios: SSH cert (executes), OpenBao API key,
flex-auth policy, key-cape OIDC, ops-bridge tunnel, railiance-infra principals.
- [x] Add `issue-core-ingestion-api-key` as `status: draft` (owner path TBD by
railiance-platform) — draft entries are not surfaced by default lookup.
- [x] Validated: 6 active + 1 draft, no non-SSH `steps`, every `wiki_ref` anchor resolves.
### T4 — Routing index in CredentialRouting.md
```task
id: WARDEN-WP-0010-T04
status: done
priority: medium
state_hub_task_id: "aabd28c0-db2d-4267-be98-95be272c687d"
```
- [x] Add a playbook index table to `wiki/CredentialRouting.md` keyed to catalog `id`.
- [x] Add "what ops-warden answers vs what the worker does next on the owner system"
examples — without restating the owner's procedure.
- [x] Refresh the duplicate-interface anti-examples section (points at canonical
anti-pattern table; not restated).
### T5 — Registry and repo-boundary alignment
```task
id: WARDEN-WP-0010-T05
status: done
priority: medium
state_hub_task_id: "3335a689-922c-4319-98d0-4263ab13790b"
```
- [x] Update `registry/capabilities/capability.security.ssh-certificate-issuance.md`
— note routing lookup in discovery; target availability notes the routing CLI.
- [x] Update `.claude/rules/repo-boundary.md` and `AGENTS.md` one-liner (no new
metaphor — "issues SSH certs; routes other credential needs to their owner").
- [x] Extend the existing capability entry rather than minting a second capability.
---
## Acceptance
- A reader of INTENT + `wiki/AccessRouting.md` understands ops-warden **issues** SSH
certs and **routes** everything else, with no implication it proxies any API.
- `registry/routing/catalog.yaml` exists with ≥6 active scenarios; every non-SSH
entry has `wiki_ref` + `canon_ref` and **no** authored `steps`.
- No new secret-storage or foreign-API code.
---
## See also
- `INTENT.md` · `SCOPE.md`
- `history/2026-06-18-access-routing-intent-shift-assessment.md` — decision record
- `WARDEN-WP-0011` — routing CLI
- `WARDEN-WP-0012` — scenario playbook expansion (backlog)
---
## Closeout (2026-06-24)
Archived during WARDEN-WP-0013 T2. All tasks complete.

View file

@ -0,0 +1,163 @@
---
id: WARDEN-WP-0011
type: workplan
title: "Routing Lookup CLI"
domain: infotech
repo: ops-warden
status: archived
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 11
created: "2026-06-18"
updated: "2026-06-24"
state_hub_workstream_id: "0a520f8e-01b4-48f1-9af3-2f3f69fd0672"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0011 — Routing Lookup CLI
**Scope:** A `warden route` command group that reads the pointer catalog and tells
a worker which subsystem owns a need, what the prerequisites are, and which
wiki/canon doc to follow **on that system**. ops-warden does not call OpenBao,
flex-auth, or key-cape on the worker's behalf.
**Out of scope:** HTTP API; live probes against any subsystem; secret generation or
retrieval; a separate health/precondition command (see "Dropped" below); replacing
subsystem CLIs.
**Depends on:** WARDEN-WP-0010 T3 (catalog schema + seed).
**Unlocks:** Agents run `warden route show <id> --json` instead of re-deriving
routing from wiki prose each session.
---
## Target CLI
```text
warden route list [--json] [--tag <tag>]
warden route show <id> [--json]
warden route find <query> [--json] # keyword match against need_keywords
```
`list`/`find` show only `status: active` entries by default (`--all` includes draft).
### Behaviour
| Command | Does | Does not |
| --- | --- | --- |
| `list` / `show` | Return owner, wiki/canon pointers, `warden_executes`, anti-patterns | Return secret material |
| `find` | Rank scenarios by keyword overlap | Invoke any external API |
When `warden_executes: true` (SSH), `show` appends the catalog's authored `steps`
and the `warden sign` / `cert_command` pattern, plus a local precondition hint
("actor in inventory? backend configured? run `warden status`"). For all other
scenarios `show` ends with **"next action on `<owner_repo>` — see `<wiki_ref>`"**
and never implies warden performed anything.
### Dropped: separate `check` command
The earlier draft had `warden coach check`. Cut. For SSH, `warden status` already
covers local preconditions; duplicating it invites scope creep toward probing
foreign subsystems. SSH precondition hints live inside `show` instead.
---
## Tasks
### T1 — Catalog loader and models
```task
id: WARDEN-WP-0011-T01
status: done
priority: high
state_hub_task_id: "55b8422c-ad3c-4084-9e00-acaa4c360906"
```
- [x] Add `src/warden/routing/` package: `models.py`, `catalog.py`.
- [x] Load and validate `registry/routing/catalog.yaml`.
- [x] Enforce the no-double-source rule: non-SSH entries with a `steps` block are a
validation error. Clear errors for missing file, schema violations, dup `id`.
### T2 — `warden route list` and `show`
```task
id: WARDEN-WP-0011-T02
status: done
priority: high
state_hub_task_id: "60b679c5-79bd-4186-b5a6-ac576931f06c"
```
- [x] Register `route` Typer sub-app on the main CLI.
- [x] `list` — Rich table + `--json` array of summaries; active-only unless `--all`.
- [x] `show` — owner, prerequisites, pointers (`wiki_ref`, `canon_ref`),
`warden_executes`, anti-patterns; SSH entries also append `steps` + cert pattern.
- [x] Exit 1 with a `find` hint when `show` id is unknown.
### T3 — `warden route find`
```task
id: WARDEN-WP-0011-T03
status: done
priority: high
state_hub_task_id: "d307701f-0117-44f0-80fd-ca6f7ae06f42"
```
- [x] Tokenize query; match against `need_keywords`, `title`, `id`.
- [x] Rank, show top matches (default 5); `--json` for agents.
- [x] Fixtures: "issue core api key", "ssh tunnel", "openrouter key".
### T4 — Tests
```task
id: WARDEN-WP-0011-T04
status: done
priority: high
state_hub_task_id: "00a76e0f-8ab6-4f9a-ac6a-00eae633342c"
```
- [x] `tests/test_routing.py` — catalog load, no-double-source validation rejects a
non-SSH `steps` block, find ranking, show JSON shape, SSH `show` includes cert
pattern.
- [x] No integration test requires a live subsystem.
### T5 — Doc consistency + drift guard
```task
id: WARDEN-WP-0011-T05
status: done
priority: high
state_hub_task_id: "bf848375-eca7-4116-bb1d-fb7df6395c70"
```
- [x] CI/test: every `wiki_ref` anchor resolves to an existing in-repo wiki section;
every entry has a `reviewed` date.
- [x] `wiki/AccessRouting.md` — CLI section with agent-oriented examples.
- [x] README — `warden route --help` quick reference.
- [x] Bump SCOPE availability note A3 → A4 on ship.
---
## Acceptance
- `uv run warden route find "issue core api key"` returns the draft scenario only
with `--all`, and never a generated key.
- `uv run warden route show ssh-cert-host-access --json` includes
`warden_executes: true` and the cert_command pattern.
- A non-SSH catalog entry carrying a `steps` block fails `test_routing.py`.
- `uv run pytest tests/test_routing.py` passes with no live-subsystem dependency.
---
## See also
- `WARDEN-WP-0010` — charter and catalog schema
- `WARDEN-WP-0012` — expanded per-scenario playbooks
- `history/2026-06-17-intent-scope-assessment.md` — prior `warden guide` proposal (P4)
---
## Closeout (2026-06-24)
Archived during WARDEN-WP-0013 T2. All tasks complete.

View file

@ -0,0 +1,204 @@
---
id: WARDEN-WP-0013
type: workplan
title: "Production Integration & Stewardship Closeout"
domain: infotech
repo: ops-warden
status: archived
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 13
depends_on_workplans:
- WARDEN-WP-0008
- WARDEN-WP-0009
- WARDEN-WP-0010
- WARDEN-WP-0011
related_workplans:
- WARDEN-WP-0012
- FLEX-WP-0007
created: "2026-06-24"
updated: "2026-06-24"
state_hub_workstream_id: "4678c41a-c1d0-48cd-9988-4ea0380e8258"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0013 — Production Integration & Stewardship Closeout
## Purpose
Close the remaining **ops-warden-owned** gaps after policy gate and routing shipped:
refresh INTENT/SCOPE canon, archive finished workplans, document ops-bridge
`cert_command` migration, operator OpenBao token hygiene, principals drift checks,
and the policy-gate production flip checklist.
This workplan addresses the deferred **Production SSH Integration Closeout** strand
from `history/2026-06-18-post-wp0008-intent-scope-reassessment.md` §6, updated for
post-WP-0009 state.
**Gap analysis:** `history/2026-06-24-intent-scope-gap-analysis.md`
## Scope
- Post-WP-0009 reassessment and SCOPE alignment
- Archive hygiene for WP-0010 and WP-0011
- ops-bridge `cert_command` migration documentation (pilot `agt-state-hub-bridge`)
- Operator runbook for scoped OpenBao tokens (no root in `VAULT_TOKEN`)
- Principals drift check between warden inventory and railiance-infra
- Policy gate production enablement checklist (coordinate FLEX-WP-0007)
## Out of scope
- flex-auth runtime deployment (flex-auth **FLEX-WP-0007**)
- ops-bridge tunnel config changes in the ops-bridge repo (coordinate only)
- Routing scenario playbook expansion (**WARDEN-WP-0012** — parallel track)
- OpenBao cluster deploy, flex-auth policy authoring, NK-WP-0009 tutorial
- Implementing secret vending or foreign API proxies
## Ownership boundary
| Concern | Owner |
| --- | --- |
| cert_command migration playbook | ops-warden (doc); ops-bridge (tunnel config) |
| OpenBao token hygiene runbook | ops-warden (doc); operator (execution) |
| Principals drift | ops-warden (check doc/script); railiance-infra (host deploy) |
| `policy.enabled: true` flip | operator (after FLEX-WP-0007) |
---
## T1 — Post-gap reassessment and SCOPE refresh
```task
id: WARDEN-WP-0013-T01
status: done
priority: high
state_hub_task_id: "de46f9a2-bf11-4651-a23c-430c63f396c8"
```
- [x] Write `history/2026-06-24-intent-scope-gap-analysis.md`
- [x] Update `SCOPE.md` active workplan table (WP-0013, WP-0012 ready)
- [x] Note maturity vector and partial INTENT criterion (ops-bridge) in SCOPE
**Acceptance:** Gap analysis on file; SCOPE reflects 2026-06-24 repo state.
---
## T2 — Archive hygiene (WP-0010, WP-0011)
```task
id: WARDEN-WP-0013-T02
status: done
priority: medium
state_hub_task_id: "1b35321d-63ad-40da-a1aa-0b66190a0733"
```
- [x] Move `WARDEN-WP-0010-access-routing-charter.md` to
`workplans/archived/260624-WARDEN-WP-0010-access-routing-charter.md`
- [x] Move `WARDEN-WP-0011-routing-guide-cli.md` to
`workplans/archived/260624-WARDEN-WP-0011-routing-guide-cli.md`
- [x] Set frontmatter `status: archived` on both; add closeout notes
- [x] Operator runs `make fix-consistency REPO=ops-warden` from `~/state-hub`
**Acceptance:** Only WP-0012 (ready) and WP-0013 (active when started) remain in
`workplans/` root; hub synced.
---
## T3 — ops-bridge cert_command migration playbook
```task
id: WARDEN-WP-0013-T03
status: done
priority: high
state_hub_task_id: "ad8588b2-9ae9-4f94-bd77-8025851a38f5"
```
- [x] Write `wiki/playbooks/ops-bridge-tunnel-cert.md` — static-key → `cert_command`
migration checklist for tunnel configs
- [x] Document pilot tunnel `agt-state-hub-bridge`: actor, pubkey path, cert_command
string, inventory prerequisites
- [x] Upgrade catalog entry `ops-bridge-tunnel` `wiki_ref` to the new playbook
- [x] Coordinate with ops-bridge owner for pilot tunnel config change (State Hub message)
- [ ] Record non-secret smoke evidence when pilot completes (`history/` entry — pending ops-bridge)
**Acceptance:** Playbook exists; catalog points at it; pilot steps documented even
if ops-bridge execution is pending.
**Unlocks:** INTENT success criterion #3 moves from partial toward met.
---
## T4 — Operator OpenBao token hygiene runbook
```task
id: WARDEN-WP-0013-T04
status: done
priority: medium
state_hub_task_id: "5cb35829-32eb-4d59-97a1-f4d92ce8e239"
```
- [x] Add `wiki/playbooks/operator-openbao-token-hygiene.md` covering scoped tokens,
`VAULT_TOKEN` session pattern, OIDC route, HTTP 403 recovery
- [x] Cross-link from `wiki/OpsWardenConfig.md` and production example yaml
**Acceptance:** Operator can follow runbook without asking ops-warden for token values.
---
## T5 — Principals inventory drift check
```task
id: WARDEN-WP-0013-T05
status: done
priority: medium
state_hub_task_id: "4025cd32-89f8-42c3-b1e8-eaf78497d91f"
```
- [x] `scripts/check_principals_drift.py` compares inventory `hosts` vs
`railiance-infra/ansible/inventory/ssh_principals.yaml`
- [x] Script notes flex-auth registry regeneration via `build_flex_auth_registry.py`
- [x] Tests in `tests/test_principals_drift.py`
**Acceptance:** Drift check runnable or documented; no secret material in script output.
---
## T6 — Policy gate production enablement checklist
```task
id: WARDEN-WP-0013-T06
status: done
priority: medium
state_hub_task_id: "51663f65-79cb-4108-87c8-9721f9476259"
```
- [x] Operator checklist in `wiki/PolicyGatedSigning.md` § Production rollout
- [x] Cross-link FLEX-WP-0007 and pickup brief
- [x] Explicit: keep `policy.enabled: false` until flex-auth reachable
**Acceptance:** Operator checklist is sequential and references cross-repo owners;
no ops-warden code changes required for flex-auth deploy.
---
## Exit criteria
- Gap analysis and SCOPE current
- WP-0010 and WP-0011 archived
- ops-bridge cert_command playbook + catalog upgrade
- Operator token hygiene runbook
- Principals drift procedure
- Policy gate production flip checklist (coordinate FLEX-WP-0007)
## Parallel track
**WARDEN-WP-0012** (routing scenario playbooks) — promoted to `ready`; start when
P1 integration doc bandwidth allows or in parallel if staffed.
## See also
- `history/2026-06-24-intent-scope-gap-analysis.md`
- `history/2026-06-18-post-wp0008-intent-scope-reassessment.md`
- `wiki/CertCommandInterface.md`
- `~/flex-auth/workplans/FLEX-WP-0007-ops-warden-policy-gate-production-deployment.md`

View file

@ -0,0 +1,147 @@
---
id: WARDEN-WP-0012
type: workplan
title: "Routing Scenario Playbooks"
domain: infotech
repo: ops-warden
status: finished
owner: codex
topic_slug: custodian
planning_priority: medium
planning_order: 12
created: "2026-06-18"
updated: "2026-06-24"
state_hub_workstream_id: "a7e712a0-02f8-4f83-944e-6b207e77bc4c"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0012 — Routing Scenario Playbooks
**Scope:** Grow the routing catalog and wiki playbooks for high-frequency NetKingdom
access scenarios. Each wiki playbook restates **what the worker does on the owning
system** and tracks an upstream canon doc; the catalog only points at it. ops-warden
authors procedure only for the SSH lane.
**Out of scope:** Implementing custody in ops-warden; creating OpenBao paths in
railiance-platform (coordinate only); authoring flex-auth policy; restating an
owner's procedure inside the catalog.
**Depends on:** WARDEN-WP-0010 (charter + catalog schema), WARDEN-WP-0011 (routing CLI).
**Status:** `finished` — playbooks shipped; draft entries await owner path promotion.
---
## Anti-stale rule
A scenario is added to the catalog as `status: active` **only when its owning repo's
path actually exists** and a `wiki_ref` is written. Until then it stays `status:
draft` and is hidden from default `warden route find`/`list`. We do not seed
agent-visible entries for paths that owners have not shipped — a confident-looking
pointer to a non-existent path is worse than no entry.
---
## Scenario backlog
| Catalog id | Routing focus | Executing owner | Gate |
| --- | --- | --- | --- |
| `issue-core-ingestion-api-key` | OpenBao KV path, K8s injection, rotation | railiance-platform + issue-core | path exists |
| `activity-core-issue-sink` | `ISSUE_CORE_URL` + consumer key custody | activity-core + issue-core | path exists |
| `inter-hub-bootstrap-ssh` | SSH envelope + on-host wrapper reads OpenBao | ops-warden SSH + railiance-infra | ready (SSH lane) |
| `openrouter-llm-connect` | OpenBao → K8s Secret in activity-core | railiance-platform | path exists |
| `object-storage-sts` | NK-WP-0007 vending path | net-kingdom + flex-auth + OpenBao | canon exists |
| `ops-bridge-tunnel-cert` | cert_command vs static-key migration | ops-bridge | done (WP-0013) |
| `human-oidc-login` | key-cape / Keycloak IAM Profile | key-cape | canon exists |
| `flex-auth-resource-check` | Policy decision before sensitive action | flex-auth | canon exists |
| `host-principal-deploy` | auth_principals sync | railiance-infra | canon exists |
---
## Tasks
### T1 — issue-core ingestion key playbook
```task
id: WARDEN-WP-0012-T01
status: done
priority: high
state_hub_task_id: "830bb512-0288-4dba-9dd4-ccfd28a4921f"
```
- [x] Coordinate with railiance-platform to canonicalize the OpenBao path first.
(Documented expected path from `railiance-platform/docs/argocd-gitops.md`;
live KV path not yet shipped — promotion blocked per anti-stale rule.)
- [x] Then write `wiki/playbooks/issue-core-ingestion-api-key.md` (prerequisites,
ESO pattern, rotation, privileged-read policy) and promote the catalog entry
from `draft` to `active` with a `wiki_ref`. (Playbook + `wiki_ref` done;
stays `draft` until path ships.)
### T2 — Inter-Hub and bootstrap lanes
```task
id: WARDEN-WP-0012-T02
status: done
priority: medium
state_hub_task_id: "7726a703-6e00-4e49-9380-ed3fb3268827"
```
- [x] Align `wiki/InterHubBootstrapAccessLane.md` with catalog id `inter-hub-bootstrap-ssh`
- [x] Document attended vs unattended bootstrap branches
- [x] Cross-link flex-auth and OpenBao expectations (pointers, not restated steps)
- [x] Promote catalog entry to `active` with `wiki_ref`
### T3 — ops-bridge tunnel migration
```task
id: WARDEN-WP-0012-T03
status: done
priority: medium
state_hub_task_id: "9fb397f0-0abb-48f5-bb62-7e77edae93bb"
```
- [x] Playbook: `wiki/playbooks/ops-bridge-tunnel-cert.md` (WARDEN-WP-0013)
- [x] Pilot tunnel `agt-state-hub-bridge` documented; ops-bridge coordination sent
### T4 — Platform secret scenarios (LLM, STS, DB)
```task
id: WARDEN-WP-0012-T04
status: done
priority: low
state_hub_task_id: "edcf4ed7-f18d-4a92-a42d-8cc7ca0ab792"
```
- [x] Playbooks for OpenRouter, object-storage STS, DB dynamic creds.
- [x] Each ends with an owner-repo action; no warden secret code; pointers to canon.
### T5 — Drift review cadence
```task
id: WARDEN-WP-0012-T05
status: done
priority: low
state_hub_task_id: "db98d655-8551-487b-9413-41bf97fc06e1"
```
- [x] Document a review cadence against net-kingdom canon.
- [x] `warden route list --stale` keyed off the `reviewed:` date field.
- [x] Process note in `wiki/AccessRouting.md`.
---
## Acceptance
- Every active catalog entry has a `wiki_ref` to an existing section; no active entry
points at a path its owner has not shipped (those stay `draft`).
- `warden route find` resolves common agent queries without wiki grep.
- Playbooks and catalog contain no secret material — only owners, pointers, checklists.
---
## See also
- `WARDEN-WP-0010`, `WARDEN-WP-0011`
- `wiki/CredentialRouting.md`
- `history/2026-06-18-post-wp0008-intent-scope-reassessment.md`

View file

@ -0,0 +1,215 @@
---
id: WARDEN-WP-0014
type: workplan
title: "Operator Access Assist — warden access front door"
domain: infotech
repo: ops-warden
status: finished
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 14
created: "2026-06-27"
updated: "2026-06-27"
state_hub_workstream_id: "3c30b2ed-6ede-4b95-a438-fde6da6f6633"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0014 — Operator Access Assist (`warden access`)
**Scope:** Make ops-warden the consistent operator-facing front door for **every**
NetKingdom security/access need — not just the SSH lane. Add a `warden access`
command surface that (a) advises: emits the auth method, path, policy context, and
exact command skeleton for any credential need, and (b) **proxies**: transparently
fetches the value from the owning subsystem *as the caller* and streams it to the
operator's destination, **without ops-warden ever persisting, caching, or logging
the secret, and without ops-warden holding any standing privileged credential.**
Centralize **knowledge and policy** in ops-warden; leave **custody and execution
detail** in the owning subsystems (OpenBao, key-cape, flex-auth). ops-warden becomes
a transparent, policy-gated, audited conduit — `vault exec` / `op run` shaped — never
a standing secret broker.
**Charter note:** This extends the WP-0010 routing charter from a *pointer layer*
("who owns it") to an *assist layer* ("here is exactly how to get it, gated and
audited"). It does **not** move custody into ops-warden. See the three non-negotiable
guardrails below — they are the line between a transparent conduit (sanctioned) and a
standing broker/honeypot (forbidden).
**Out of scope:**
- ops-warden holding a long-lived OpenBao/secret-read token of its own.
- Persisting, caching, or logging any secret **value** anywhere (disk, log, hub, git).
- Creating OpenBao paths or policies (coordinate with railiance-platform / flex-auth).
- Restating an owner's procedure as prose in the catalog (reference canon, don't copy).
- Identity/MFA implementation (key-cape owns it; we orchestrate its CLI only).
**Depends on:** WP-0010 (charter + catalog schema), WP-0011 (`warden route` CLI),
WP-0007/0009 (flex-auth policy gate — reused as the fetch-path gate).
**Status:** `proposed` — awaiting Bernd's review before implementation.
---
## Three non-negotiable guardrails (acceptance-blocking)
These are the design invariants that keep proxy mode safe. Any task that violates one
is rejected regardless of convenience.
1. **Operator identity, never warden's.** `--fetch`/`--exec` authenticate as the
*caller* (their OIDC/OpenBao token, the agent's own auth). ops-warden carries **no**
standing secret-read credential. If the caller has no valid auth, the command fails
with a routing pointer to the auth step — it does not fall back to a warden token.
2. **Transit only — no persistence, no logging of values.** The secret flows
subsystem → caller destination (env of a child process, or stdout) via a streamed
`exec`. ops-warden must not buffer it to disk, cache it, echo it to logs, or write
it to the State Hub. Audit records **metadata only** (who, need id, owner path, time,
policy decision id) — never the value.
3. **Policy gate on the fetch path.** `--fetch`/`--exec` run the flex-auth check
**before** proxying (reusing the WP-0007 gate). When `policy.enabled: false`, fetch
is **advisory-only** by default and requires an explicit `--no-policy` acknowledgement
to proxy ungated — surfaced loudly in output and audit.
---
## Phasing decision (default — adjust in review)
OpenBao lane **first** (covers the immediate npm/API/DB need), key-cape/login lane in
a later task within the same WP. Rationale: OpenBao KV is the highest-frequency operator
need and the one this conversation surfaced; login flows are a thinner orchestration of
an interactive tool and lower risk to defer.
---
## Tasks
### T1 — Catalog schema: structured handoff fields
```task
id: WARDEN-WP-0014-T01
status: done
priority: high
state_hub_task_id: "abb0e722-6524-4224-8638-6ee1573ed3e0"
```
- [x] Extend `registry/routing/catalog.yaml` entry schema with optional structured
handoff fields for non-SSH lanes: `auth_method`, `path_template`,
`fetch_command`, `exec_capable` (bool), `policy_ref`. (`RouteEntry` +
`_parse_entry`; `has_handoff` helper.)
- [x] Fields are **structured pointers/templates**, not prose restatements — each
sits alongside the owner's `canon_ref` for the authoritative procedure (no drift).
- [x] Populate for `openbao-api-key` (covers the coulomb_social npm shape: keyword
`npm_auth_token` added) as the reference example; `draft` entries untouched.
- [x] Validation: `_assert_no_secret_material` rejects known token prefixes and
high-entropy runs in any handoff field; `exec_capable` requires `fetch_command`.
Tests in `tests/test_routing.py` (handoff parse, real-catalog, secret-leak
matrix, placeholder-accepted).
### T2 — `warden access` advisory surface
```task
id: WARDEN-WP-0014-T02
status: done
priority: high
state_hub_task_id: "c1497263-7124-459f-b63a-d0c0c7005c86"
```
- [x] `warden access <need> [--domain X] [--json]` — resolves via the same matcher as
`warden route find` and renders the **structured handoff**: owner, auth method,
path template, command skeleton, policy ref + gate status, proxy hint, and the
`<…>` owner-confirmed-name note. (`warden/access.py` pure module + `access`
command in `cli.py`.)
- [x] Advisory is the **default** behavior (no value fetched); SSH lane points at
`warden sign`; routed lanes end with "warden advises, the owner vends".
- [x] `--json` output for agentic operators — stable, secret-free shape
(`handoff` block + `next_action`); `--domain` substitutes `<domain>` only.
- [x] Tests: `tests/test_access.py` (expansion, gate status, advisory/SSH/JSON/no-match).
### T3 — OpenBao proxy lane (`--fetch` / `--exec`)
```task
id: WARDEN-WP-0014-T03
status: done
priority: high
state_hub_task_id: "6d3eb0e4-309c-4065-893e-6c4053fb0db2"
```
- [x] `warden access <need> --fetch` — policy-gate (G3) → run the owning tool
(`bao kv get ...`) **as the caller** with **inherited stdout** → value streams to
stdout and never enters warden's memory (`proxy_fetch`). No buffering, no log.
- [x] `warden access <need> --exec -- <cmd>` — runs the child with the secret injected
into *its* env only (`proxy_exec`); value never lands in the caller's shell env;
`--field` names the env var (e.g. `NPM_AUTH_TOKEN`).
- [x] Guardrails G1–G3 in code (`warden/proxy.py`, `_access_proxy` in `cli.py`):
G1 caller token only (no warden credential; `caller_auth_present`); G2 transit-only
(inherit-stdout fetch; no disk/log write); G3 `check_fetch_policy` before any exec,
`--no-policy` required to proxy ungated. `tests/test_proxy.py` asserts all three,
plus `resolve_fetch_command` refuses unresolved `<…>` placeholders. Live smoke
against a fake `bao` confirmed gate-refusal, stream, exec-inject, and a
secret-free audit log.
- [x] Metadata-only audit per call (`write_audit` → `state_dir/access-audit.log`).
### T4 — key-cape / login orchestration lane
```task
id: WARDEN-WP-0014-T04
status: done
priority: medium
state_hub_task_id: "481997e4-193d-4724-84a6-61cbc2940153"
```
- [x] Extend `warden access` to orchestrate the key-cape/Keycloak OIDC login flow
under the same advisory/proxy split. New `lane: secret|login` field on
`RouteEntry`; `key-cape-oidc-login` populated as a `login` lane entry.
- [x] Login lane semantics: no caller-auth precheck (you have no token yet) and no
secret-read gate (it bootstraps the identity the gate needs); runs interactively
as the caller via inherited stdio; `--exec` rejected. Token stays in the caller's
own store — warden never captures it (G2 holds). Audited as `action: login`.
- [x] Tests in `tests/test_proxy.py` (runs without token/ack, rejects --exec, real
catalog lane, invalid-lane rejection). Live fake-`bao login` smoke confirmed.
### T5 — Docs, security model, and INTENT/SCOPE alignment
```task
id: WARDEN-WP-0014-T05
status: done
priority: medium
state_hub_task_id: "a5eb616e-4edf-42db-a4fb-bf296cdb92bc"
```
- [x] `wiki/OperatorAccessAssist.md` — the `warden access` contract, the conduit-vs-broker
boundary, and the three guardrails (+ the catalog secret-material guard) as a
security-model statement; lanes documented.
- [x] Updated `wiki/AccessRouting.md` (issue/route/**assist** roles + reconciled the
anti-patterns table so the conduit doesn't contradict it) and the
`.claude/rules/credential-routing.md` agent rule (added `warden access` + the
"standing broker forbidden, transparent `--fetch` sanctioned" anti-pattern).
- [x] SCOPE/INTENT: recorded the pointer→assist charter extension; SCOPE implemented
list + Getting Oriented updated; maturity vector A4 → **A5** on Availability.
- [x] `history/2026-06-27-operator-access-assist-charter.md` — decision record.
---
## Acceptance
- `warden access <need>` advises for any catalog need; `--fetch`/`--exec` proxy the
OpenBao lane end to end against a real KV path.
- All three guardrails hold under test: **no** secret value touches disk/log/hub/git;
ops-warden holds **no** standing secret-read credential; the policy gate runs **before**
every fetch.
- Catalog carries structured handoff fields that reference (never restate) owner canon.
- Docs state the conduit-vs-broker boundary explicitly; the agent rule forbids the
broker pattern.
- No secret material anywhere in code, catalog, docs, logs, or tests.
---
## See also
- `WARDEN-WP-0010` (routing charter), `WARDEN-WP-0011` (`warden route` CLI)
- `WARDEN-WP-0007` / `WARDEN-WP-0009` (flex-auth policy gate — reused as fetch gate)
- `wiki/AccessRouting.md`, `wiki/CredentialRouting.md`, `wiki/PolicyGatedSigning.md`
- `.claude/rules/credential-routing.md`
- `history/2026-06-24-intent-scope-gap-analysis.md`

View file

@ -0,0 +1,247 @@
---
id: WARDEN-WP-0015
type: workplan
title: "Workload Security Posture — env posture × maturity + conformance"
domain: infotech
repo: ops-warden
status: finished
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 15
created: "2026-06-27"
updated: "2026-06-27"
state_hub_workstream_id: "99f4a0e1-853c-456f-8aa7-8ff0f318ea65"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# WARDEN-WP-0015 — Workload Security Posture (two-axis) + conformance
**Scope:** Establish a NetKingdom standard for IT-security posture across **two
orthogonal axes**, and make ops-warden the **conformance steward** for it:
- **Axis A — Environment posture** (`dev → test → prod`): how the *secret store* is
secured (mock / OpenBao `-dev` / sealed). Identical contracts, divergent posture.
- **Axis B — Workload maturity** (`M0 → M3`): how *trusted* a workload is to receive
secrets and handle classified data (PoC → alpha/early-access → beta/GA → critical).
The axes combine in a **secret-flow lattice**: a secret may be delivered to a workload
only if the workload's posture *and* maturity meet the secret's requirements. ops-warden
authors the ops-security slice, ships machine-readable descriptors + a conformance
checker (incl. the lattice check), and the dev-tier **contract-double** fixture library
(the "fake bao" pattern generalized).
**Decisions locked (2026-06-27):**
- Two-axis model folded into this WP (was "Secret Lifecycle Tiering", env posture only).
- Authoritative **NetKingdom requirements** (M0–M3 table, secret-flow gates, env-posture
ceremonies) live in **net-kingdom canon**; the **generic `WorkloadMaturityLevel`
concept + lattice** is contributed to **info-tech-canon** (DevSecOps/Landscape),
reusing its governed `DataClassification`. ops-warden authors the ops-security slice +
conformance tooling.
- ops-warden role = **author + conformance checks**, **not** runtime enforcement.
**Reuse, don't reinvent (info-tech-canon already defines the primitives):**
`DataClassification` (`confidential`/`restricted`…) in the Data Model; promotion /
quality gates / policy gates / `DeploymentVerification` + progressive delivery in the
DevSecOps Model; asset/business **criticality** in the Security Model; access semantics
in the CARING Access Governance Standard. This WP **assembles** these into a named
maturity ladder + flow rule; it does not fork them.
**Hard boundary (responsibility-map, ~line 154):** ops-warden "must not become a
universal secret broker — runtime secrets remain OpenBao; authorization remains
flex-auth." ops-warden = policy author + conformance verifier only. OpenBao holds the
secrets; flex-auth makes allow/deny decisions; CARING governs access semantics.
**Cross-repo note:** T1/T5 author content destined for **net-kingdom** and
**info-tech-canon**. ops-warden drafts; landing it is coordinated through each repo's
own process (inbox/PR), not a unilateral write from here.
**Depends on / relates to:** WARDEN-WP-0014 (the `warden access` proxy is the
posture-aware fetch surface; its caller-identity/transit guardrails are prod-compatible).
**Status:** `finished` — all five tasks done. T1 authored the standard, T2 shipped the
descriptors + `warden policy`, T3 the read-only conformance checker, T4 the dev-double
library, T5 the INTENT/SCOPE alignment. Canon landing in net-kingdom / info-tech-canon
is owner-driven and tracked via the open coordination messages (not closed here).
---
## The model (to be encoded by this WP)
### Axis A — Environment posture (the secret store)
**R1 — Contract parity, posture divergence.** Identical interface at every tier; only
the backend's security posture changes. Automation written once runs at all tiers
unchanged (this is why contract doubles work).
**R2 — Promote topology, regenerate material.** Secret *values* are never promoted up
the ladder; only *structure* (paths, policy shape, names). Values are generated fresh
per tier. Test conveniences (reuse, single-unseal) are quarantined in test.
**R3 — Dev touches no real data, ever.** Insecure personal mock store is sanctioned
*iff* dev uses only synthetic data. Absolute.
**R4 — Phase-changes are ceremonies, not copies.** test→prod is a gated checklist
referencing net-kingdom `security-bootstrap-*` / unseal-custody docs.
| | dev | test | prod |
| --- | --- | --- | --- |
| backend | mock / contract double | OpenBao `-dev` (single-unseal) | OpenBao sealed (Shamir 3-of-5) |
| real values | forbidden (synthetic) | generated, reuse allowed | generated fresh, reuse forbidden |
| unseal | n/a | single key / auto | 3-of-5 + break-glass |
| real user/business data | never | never | allowed |
| audit | optional | on | full, tamper-evident |
### Axis B — Workload maturity (the trust to receive secrets/data)
**Production is a posture, not a maturity.** A workload can be prod-posture yet low
maturity (alpha with friendly customers). Maturity gates *which secrets and data
classes* a prod workload may touch.
| Level | Phase | Max DataClassification | Promotion gate (reuses DevSecOps gates) |
| --- | --- | --- | --- |
| **M0** | Experimental / PoC | synthetic only | — |
| **M1** | Alpha / early-access | low-criticality, loss-acceptable; no confidential/restricted | friendly-customer scope, basic SLO, data-handling note |
| **M2** | Beta / GA | up to `confidential`; SLOs; audited | security review, SLO history, on-call, incident runbooks |
| **M3** | Critical / regulated | `restricted`; break-glass; compliance | pen-test, 3-of-5 custody, human-in-loop, compliance audit |
### The combined rule (secret-flow lattice)
```
deliver(secret → workload) permitted only if
workload.env_posture == prod # Axis A
AND workload.maturity >= secret.required_maturity # Axis B (no-write-down)
AND workload.maturity >= required_maturity(dataclass(secret))
```
"Critical secrets must not be transferred to workloads below maturity M" is exactly
this no-write-down constraint. Checkable by ops-warden; enforceable by flex-auth.
---
## Tasks
### T1 — Author the two-axis Workload Security Posture standard (canon-bound)
```task
id: WARDEN-WP-0015-T01
status: done
priority: high
state_hub_task_id: "85aeb676-a593-4056-986a-db14d4c5209f"
```
- [x] Drafted the standard: Axis A (R1–R4 + env-posture matrix + phase-change ceremonies)
and Axis B (M0–M3 ladder + promotion gates) unified by the secret-flow lattice —
`wiki/WorkloadSecurityPosture.md`.
- [x] Layered it: doc marks the generic `WorkloadMaturityLevel` + lattice → **info-tech-canon**
(reusing `DataClassification`) and the NetKingdom M0–M3 requirements + env-posture
ceremonies → **net-kingdom canon**, with a canon-layering table.
- [x] Cross-linked the unseal/bootstrap/responsibility canon + info-tech-canon
Security/DevSecOps/Data/CARING models. Staged in ops-warden; **coordination
opened** to net-kingdom (msg 8d6f8d83) and info-tech-canon (msg ca07b085).
- [x] Encoded ops-warden's role: author + conformance, not enforcement/custody.
- Note: canon **landing** in the two repos is owner-driven; tracked to closure in T5.
### T2 — Machine-readable posture descriptors (both axes)
```task
id: WARDEN-WP-0015-T02
status: done
priority: high
state_hub_task_id: "011fb0af-154d-40f4-a03e-3172c325321a"
```
- [x] `registry/policy/security-posture.yaml` — env-posture tiers (backend, value-policy,
unseal, data-class, audit) **and** maturity levels (M0–M3, max DataClassification,
promotion gates), `dataclass_floor` mapping, and the lattice rule. No secret material.
- [x] Loader + validation in `src/warden/posture.py` (mirrors `routing/catalog.py`):
unique/contiguous ranks, dataclass_floor references known levels, lattice env
posture exists. Includes the pure `can_deliver` lattice helper (reused by T3).
- [x] `warden policy list|show` lookup (mirrors `warden route`; `--json`).
- [x] Tests: `tests/test_posture.py` (load, lattice allow/deny matrix, validation
rejections, CLI). 184 pass, lint clean.
### T3 — Conformance checker (incl. secret-flow lattice)
```task
id: WARDEN-WP-0015-T03
status: done
priority: high
state_hub_task_id: "c1a0e987-19d0-478e-ac08-2dbe98e64e09"
```
- [x] `scripts/check_secret_posture_conformance.py` — asserts env-posture matches the
standard (`backend`/`unseal`/`real_values` per tier) **and** evaluates the lattice
via `posture.can_deliver`: flags any secret whose `required_maturity` or data-class
floor exceeds a target workload's maturity, or that targets a non-prod workload.
Drift-style report, like `check_principals_drift.py`. Read-only; exit 0/1/2.
- [x] Surfaces conformance + lattice violations; never reads or prints a secret value
(manifest is metadata-only). Example: `examples/posture-conformance.example.yaml`.
- [x] Tests: `tests/test_posture_conformance.py` (env mismatch, unknown env, lattice
deny/allow, missing workload, exit codes). 8 cases, lint clean.
### T4 — Dev-tier contract-double fixture library
```task
id: WARDEN-WP-0015-T04
status: done
priority: medium
state_hub_task_id: "e556fd2e-4e39-4c7d-bd94-b4330e4bef45"
```
- [x] Generalized "fake bao" into `src/warden/doubles.py`: `materialize_doubles()`
writes hermetic dev-tier doubles for routed subsystems (`bao`, `key-cape`)
honoring each contract (argv/stdout/exit), emitting **synthetic values only**
(`synthetic-` prefix, asserted in tests). `doubles_path_prepended()` puts them
ahead on PATH for fully offline dev/test of access flows.
- [x] Documented the pattern in the standard (R1) as the sanctioned `dev` backend.
- [x] Tests: `tests/test_doubles.py` (contract honoring, synthetic-only, unknown
contract → exit 2, end-to-end proxy fetch offline against the double). 9 cases.
### T5 — INTENT/SCOPE alignment + canon contributions
```task
id: WARDEN-WP-0015-T05
status: done
priority: medium
state_hub_task_id: "298c9b09-4a5a-41bf-a3bd-6c572385236b"
```
- [x] `INTENT.md`: ops-warden stewards **security-policy conformance** of the
infrastructure (authoring the two-axis posture standard + conformance checks + dev
doubles), scoped to author+check — **not** enforcement or custody.
- [x] SCOPE: add the posture policy + conformance surface; note the net-kingdom /
info-tech-canon homes; bump the maturity vector where warranted.
- [x] Canon landing tracked to a documented hand-off. The contributions are **drafted
and offered**: info-tech-canon (generic `WorkloadMaturityLevel` + lattice, msg
`ca07b085`) and net-kingdom (M0–M3 requirements + env-posture ceremonies, msg
`8d6f8d83`). **Landing is owner-driven and out of ops-warden's control** — it is
tracked through each repo's own inbox/PR process, not closed unilaterally here.
ops-warden's authored slice + conformance tooling are complete.
- [x] `history/2026-06-27-workload-security-posture-charter.md` — decision record.
2026-06-27 progress: shipped the T3 conformance checker and T4 dev-double library
with tests (200 passing, lint clean); updated `INTENT.md` / `SCOPE.md` /
`wiki/WorkloadSecurityPosture.md` for the author+conformance role. Canon landing in
net-kingdom / info-tech-canon remains owner-driven via the open coordination messages.
---
## Acceptance
- A coherent two-axis standard exists: generic concept in info-tech-canon, NetKingdom
M0–M3 + env-posture requirements in net-kingdom canon, authored by ops-warden.
- ops-warden ships posture descriptors + a read-only conformance checker (incl. the
secret-flow lattice) + dev-tier doubles.
- No secret material in any descriptor, checker, fixture, doc, or log.
- ops-warden's role is documented as author+conformance; OpenBao custody, flex-auth
authorization, and CARING access boundaries are explicitly preserved.
- INTENT/SCOPE reflect the conformance-steward role without overclaiming enforcement.
---
## See also
- `WARDEN-WP-0014` (operator access assist; the posture-aware fetch surface)
- `net-kingdom/docs/openbao-unseal-custody-models.md`, `responsibility-map.md`,
`platform-root-custody.md`, `security-bootstrap-*`
- `info-tech-canon` Security / DevSecOps / Data Models + CARING Access Governance
- `flex-auth` (runtime enforcement of the lattice, as a follow-up)

View file

@ -0,0 +1,52 @@
---
id: WARDEN-WP-ADHOC-2026-07-07
type: workplan
title: "Ad Hoc Tasks — 2026-07-07"
domain: infotech
repo: ops-warden
status: finished
owner: grok
topic_slug: custodian
created: "2026-07-07"
updated: "2026-07-07"
state_hub_workstream_id: "90568b1e-8395-5c67-9c69-851ed08ff3d3"
---
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
# Ad Hoc Tasks — 2026-07-07
### T01 — Roll out proxy pipe fix (be3b4a2)
```task
id: WARDEN-WP-ADHOC-2026-07-07-T01
status: done
priority: high
state_hub_task_id: "bf985c95-bea6-5057-94f9-9cfa7e1c9dd8"
```
`warden access` failed on `reuse-surface-hub-write-token` because `shlex.split`
treated `kubectl … | base64 -d` as literal argv. Fixed in `be3b4a2`; rollout
requires refreshing the installed CLI (cached `0.1.0` wheel does not pick up
source changes).
- [x] Code fix merged and pushed (`be3b4a2`)
- [x] Version bumped `0.1.0` → `0.1.1` so `uv tool install` invalidates stale wheels
- [x] Workstation rollout: `git pull && make install-all` (after cache clean if needed)
- [x] Smoke: `warden access reuse-surface-hub-write-token --no-policy --fetch` — no
`unknown shorthand flag: 'd'`; token fetched via shell pipeline
**Operator upgrade on any machine using `warden access`:**
```bash
cd ~/ops-warden && git pull --ff-only
make install-all
warden route show reuse-surface-hub-write-token --json
```
If `warden` still lacks `ResolvedFetch` / pipe handling after install:
```bash
uv cache clean ops-warden
uv tool install . --with-editable ../phase-memory --reinstall --force
```

View file

@ -0,0 +1,60 @@
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
# Custodian Brief — ops-warden
**Domain:** infotech
**Last synced:** 2026-10-16 00:05 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
### Adopt unknown -> fail_closed behind signing-target classification coverage
Progress: 1/4 done | workplan_id: `c8ee441e-1be1-5219-910c-e79ff23cc9ec`
**Open tasks:**
- ! Tasks `611f0901`
*(wait: Warden's own declaration cannot classify the repair-path target workloads; the owner must declare the continuity actor/target and its z2-continuity resolution (see 2026-09-28 review).)*
- ! Tasks `54ad4864`
*(wait: Owners of agt-codex-interhub-bootstrap (ops-hub) and agt-state-hub-bridge (ops-bridge) must publish authoritative workload identity declarations; atm-backup-daily declared by activity-core and compiled 2026-10-09 (z2-protected, admission unsatisfied: M1 below M2 floor).)*
- ! Tasks `93eaf1f2`
*(wait: Gated on T01 and on layer model v0.8 (or successor) reaching accepted; never convert against a proposed standard.)*
### Layer model v0.7 conformance — state the deadline, bind the agent boundary, steward the estate's newest rule
Progress: 5/6 done | workplan_id: `ae3ff76f-883d-5e2f-b6aa-144d61e8fdef`
**Open tasks:**
- ! Tasks `7d1b3c82`
*(wait: Two items to route, not absorb: ops-mason has published no stance map; the second is another repository's to own.)*
### Follow through on KnownSecurityCases along their type's route
Progress: 2/4 done | workplan_id: `f7e81013-6868-5d99-8528-ba75a442eca9`
**Open tasks:**
- ! T03 — Run and verify a case `4a0fa4a7`
*(wait: Catalog integration follows a proven run.)*
- ► T02 — Plan a case run `bcbf6c91`
### Tamper-resistant credential governance + mass rotation/lockdown (Strand B)
Progress: 2/3 done | workplan_id: `21528e8d-a049-523d-9ae1-da7a27cb8bbf`
**Open tasks:**
- · Task: Graded lockdown / break-glass with explicit trust-root `cae498ee`
### Repoint the whynot-design npm lane to Forgejo
Progress: 2/3 done | workplan_id: `42a097db-1c24-558e-a724-030bb2b4443e`
**Open tasks:**
- ! Prove routing and publication `a8b1b855`
*(wait: Hold kept by D3 until SECRETS-WP-0006-T06 moves publishing off the legacy whynot-design npm path; then rotate and prove a fresh publish.)*
## Inbox Hygiene
**Stale unread:** 2 message(s) older than 3 day(s) — triage at session start.
**Missing thread_id:** 3 unread message(s) lack supersession chains.
---
## MCP Orientation (when available)
If the state-hub MCP server is reachable, call:
`get_domain_summary("infotech")`
This provides richer cross-domain context.
If the MCP call fails, use this file as your orientation source.

View file

@ -0,0 +1,188 @@
# Work Records — ops-warden
> Generated by `statehub fix-consistency` (CUST-WP-0061-T04, work-record
> stage 3). Do not edit by hand — edit the source file/block listed for
> each record and re-run fix-consistency to refresh this index. Archived
> workplans are omitted; closed decisions/intakes/engagements stay listed
> so recently-resolved work is still visible. [auto]
| Kind | ID | Status | Lane | Source |
| --- | --- | --- | --- | --- |
| workplan | WARDEN-WP-ADHOC-2026-06-27 | finished | — | workplans/ADHOC-2026-06-27.md |
| workplan | WARDEN-WP-ADHOC-2026-06-29 | finished | — | workplans/ADHOC-2026-06-29.md |
| workplan | WARDEN-WP-ADHOC-2026-08-11 | finished | — | workplans/ADHOC-2026-08-11.md |
| workplan | WARDEN-WP-ADHOC-2026-08-17 | finished | — | workplans/ADHOC-2026-08-17.md |
| workplan | WARDEN-WP-ADHOC-2026-09-08 | finished | — | workplans/ADHOC-2026-09-08.md |
| workplan | WARDEN-WP-ADHOC-2026-10-03 | finished | — | workplans/ADHOC-2026-10-03.md |
| workplan | WARDEN-WP-0016 | finished | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| workplan | WARDEN-WP-0017 | finished | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| workplan | WARDEN-WP-0018 | finished | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| workplan | WARDEN-WP-0019 | finished | — | workplans/WARDEN-WP-0019-route-to-secrets-engine.md |
| workplan | WARDEN-WP-0020 | finished | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| workplan | WARDEN-WP-0021 | finished | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| workplan | WARDEN-WP-0022 | finished | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| workplan | WARDEN-WP-0023 | finished | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| workplan | WARDEN-WP-0024 | finished | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| workplan | WARDEN-WP-0025 | finished | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| workplan | WARDEN-WP-0026 | finished | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| workplan | WARDEN-WP-0027 | blocked | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| workplan | WARDEN-WP-0028 | finished | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| workplan | WARDEN-WP-0029 | finished | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| workplan | WARDEN-WP-0030 | finished | — | workplans/WARDEN-WP-0030-delegation-register.md |
| workplan | WARDEN-WP-0031 | finished | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| workplan | WARDEN-WP-0032 | finished | — | workplans/WARDEN-WP-0032-security-zones.md |
| workplan | WARDEN-WP-0033 | finished | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| workplan | WARDEN-WP-0034 | active | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| workplan | WARDEN-WP-0035 | finished | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md |
| workplan | WARDEN-WP-0036 | finished | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md |
| workplan | WARDEN-WP-0037 | blocked | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| workplan | WARDEN-WP-0038 | finished | — | workplans/WARDEN-WP-0038-plan-mutation-intent.md |
| workplan | WARDEN-WP-0039 | finished | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| workplan | WARDEN-WP-0040 | active | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| workplan | WARDEN-WP-0041 | finished | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| workplan | WARDEN-WP-0042 | finished | — | workplans/WARDEN-WP-0042-openbao-structure-survey-route.md |
| workplan | WARDEN-WP-0043 | finished | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| workplan | WARDEN-WP-0044 | active | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-ADHOC-2026-06-27-T01 | done | — | workplans/ADHOC-2026-06-27.md |
| task | WARDEN-WP-ADHOC-2026-06-29-T01 | done | — | workplans/ADHOC-2026-06-29.md |
| task | WARDEN-WP-ADHOC-2026-08-11-T01 | done | — | workplans/ADHOC-2026-08-11.md |
| task | WARDEN-WP-ADHOC-2026-08-11-T02 | done | — | workplans/ADHOC-2026-08-11.md |
| task | WARDEN-WP-ADHOC-2026-08-11-T03 | done | — | workplans/ADHOC-2026-08-11.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T01 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T02 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T03 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T04 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T01 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T02 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T03 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T04 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T05 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T06 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-10-03-T01 | done | — | workplans/ADHOC-2026-10-03.md |
| task | WARDEN-WP-0016-T01 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0016-T02 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0016-T03 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0016-T04 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0017-T01 | done | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| task | WARDEN-WP-0017-T02 | done | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| task | WARDEN-WP-0017-T03 | done | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| task | WARDEN-WP-0018-T01 | done | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| task | WARDEN-WP-0018-T02 | done | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| task | WARDEN-WP-0018-T03 | done | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| task | WARDEN-WP-0019-T01 | done | — | workplans/WARDEN-WP-0019-route-to-secrets-engine.md |
| task | WARDEN-WP-0019-T02 | done | — | workplans/WARDEN-WP-0019-route-to-secrets-engine.md |
| task | WARDEN-WP-0020-T01 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T02 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T03 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T04 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T05 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0021-T01 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T02 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T03 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T04 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T05 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0022-T01 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0022-T02 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0022-T03 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0022-T04 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0023-T01 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T02 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T03 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T04 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T05 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T06 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T07 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0024-T01 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T02 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T03 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T04 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T05 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T06 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T07 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0025-T01 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T02 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T03 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T04 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T05 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0026-T01 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T02 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T03 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T04 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T05 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T06 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T07 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0027-T01 | cancel | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| task | WARDEN-WP-0027-T02 | todo | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| task | WARDEN-WP-0027-T03 | cancel | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| task | WARDEN-WP-0028-T01 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T02 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T03 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T04 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T05 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T06 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T07 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0029-T01 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T02 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T03 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T04 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T05 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0030-T01 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T02 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T03 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T04 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T05 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0031-T01 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T02 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T03 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T04 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T05 | cancel | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0032-T01 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T02 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T03 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T04 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T05 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T06 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T07 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0033-T01 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T02 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T03 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T04 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T05 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T06 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0034-T01 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T02 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T03 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T04 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T05 | wait | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T06 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0035-T01 | done | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md |
| task | WARDEN-WP-0035-T02 | done | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md |
| task | WARDEN-WP-0036-T01 | done | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md |
| task | WARDEN-WP-0036-T02 | done | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md |
| task | WARDEN-WP-0037-T01 | done | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| task | WARDEN-WP-0037-T02 | done | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| task | WARDEN-WP-0037-T03 | wait | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| task | WARDEN-WP-0038-T01 | done | — | workplans/WARDEN-WP-0038-plan-mutation-intent.md |
| task | WARDEN-WP-0039-T01 | done | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| task | WARDEN-WP-0039-T02 | done | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| task | WARDEN-WP-0039-T03 | done | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| task | WARDEN-WP-0040-T01 | wait | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0040-T02 | wait | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0040-T03 | wait | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0040-T04 | done | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0041-T01 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0041-T02 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0041-T03 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0041-T04 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0042-T01 | done | — | workplans/WARDEN-WP-0042-openbao-structure-survey-route.md |
| task | WARDEN-WP-0042-T02 | done | — | workplans/WARDEN-WP-0042-openbao-structure-survey-route.md |
| task | WARDEN-WP-0043-T01 | done | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| task | WARDEN-WP-0043-T02 | done | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| task | WARDEN-WP-0043-T03 | done | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| task | WARDEN-WP-0044-T01 | done | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-0044-T02 | done | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-0044-T03 | progress | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-0044-T04 | wait | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| intake | WARDEN-IN-0001 | closed | — | intakes/intakes.md |
| intake | WARDEN-IN-0002 | closed | — | intakes/intakes.md |
| intake | WARDEN-IN-0003 | closed | — | intakes/intakes.md |

View file

@ -0,0 +1,60 @@
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
# Custodian Brief — ops-warden
**Domain:** infotech
**Last synced:** 2026-10-16 00:05 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
### Adopt unknown -> fail_closed behind signing-target classification coverage
Progress: 1/4 done | workplan_id: `c8ee441e-1be1-5219-910c-e79ff23cc9ec`
**Open tasks:**
- ! Tasks `611f0901`
*(wait: Warden's own declaration cannot classify the repair-path target workloads; the owner must declare the continuity actor/target and its z2-continuity resolution (see 2026-09-28 review).)*
- ! Tasks `54ad4864`
*(wait: Owners of agt-codex-interhub-bootstrap (ops-hub) and agt-state-hub-bridge (ops-bridge) must publish authoritative workload identity declarations; atm-backup-daily declared by activity-core and compiled 2026-10-09 (z2-protected, admission unsatisfied: M1 below M2 floor).)*
- ! Tasks `93eaf1f2`
*(wait: Gated on T01 and on layer model v0.8 (or successor) reaching accepted; never convert against a proposed standard.)*
### Layer model v0.7 conformance — state the deadline, bind the agent boundary, steward the estate's newest rule
Progress: 5/6 done | workplan_id: `ae3ff76f-883d-5e2f-b6aa-144d61e8fdef`
**Open tasks:**
- ! Tasks `7d1b3c82`
*(wait: Two items to route, not absorb: ops-mason has published no stance map; the second is another repository's to own.)*
### Follow through on KnownSecurityCases along their type's route
Progress: 2/4 done | workplan_id: `f7e81013-6868-5d99-8528-ba75a442eca9`
**Open tasks:**
- ! T03 — Run and verify a case `4a0fa4a7`
*(wait: Catalog integration follows a proven run.)*
- ► T02 — Plan a case run `bcbf6c91`
### Tamper-resistant credential governance + mass rotation/lockdown (Strand B)
Progress: 2/3 done | workplan_id: `21528e8d-a049-523d-9ae1-da7a27cb8bbf`
**Open tasks:**
- · Task: Graded lockdown / break-glass with explicit trust-root `cae498ee`
### Repoint the whynot-design npm lane to Forgejo
Progress: 2/3 done | workplan_id: `42a097db-1c24-558e-a724-030bb2b4443e`
**Open tasks:**
- ! Prove routing and publication `a8b1b855`
*(wait: Hold kept by D3 until SECRETS-WP-0006-T06 moves publishing off the legacy whynot-design npm path; then rotate and prove a fresh publish.)*
## Inbox Hygiene
**Stale unread:** 2 message(s) older than 3 day(s) — triage at session start.
**Missing thread_id:** 3 unread message(s) lack supersession chains.
---
## MCP Orientation (when available)
If the state-hub MCP server is reachable, call:
`get_domain_summary("infotech")`
This provides richer cross-domain context.
If the MCP call fails, use this file as your orientation source.

View file

@ -0,0 +1,188 @@
# Work Records — ops-warden
> Generated by `statehub fix-consistency` (CUST-WP-0061-T04, work-record
> stage 3). Do not edit by hand — edit the source file/block listed for
> each record and re-run fix-consistency to refresh this index. Archived
> workplans are omitted; closed decisions/intakes/engagements stay listed
> so recently-resolved work is still visible. [auto]
| Kind | ID | Status | Lane | Source |
| --- | --- | --- | --- | --- |
| workplan | WARDEN-WP-ADHOC-2026-06-27 | finished | — | workplans/ADHOC-2026-06-27.md |
| workplan | WARDEN-WP-ADHOC-2026-06-29 | finished | — | workplans/ADHOC-2026-06-29.md |
| workplan | WARDEN-WP-ADHOC-2026-08-11 | finished | — | workplans/ADHOC-2026-08-11.md |
| workplan | WARDEN-WP-ADHOC-2026-08-17 | finished | — | workplans/ADHOC-2026-08-17.md |
| workplan | WARDEN-WP-ADHOC-2026-09-08 | finished | — | workplans/ADHOC-2026-09-08.md |
| workplan | WARDEN-WP-ADHOC-2026-10-03 | finished | — | workplans/ADHOC-2026-10-03.md |
| workplan | WARDEN-WP-0016 | finished | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| workplan | WARDEN-WP-0017 | finished | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| workplan | WARDEN-WP-0018 | finished | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| workplan | WARDEN-WP-0019 | finished | — | workplans/WARDEN-WP-0019-route-to-secrets-engine.md |
| workplan | WARDEN-WP-0020 | finished | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| workplan | WARDEN-WP-0021 | finished | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| workplan | WARDEN-WP-0022 | finished | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| workplan | WARDEN-WP-0023 | finished | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| workplan | WARDEN-WP-0024 | finished | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| workplan | WARDEN-WP-0025 | finished | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| workplan | WARDEN-WP-0026 | finished | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| workplan | WARDEN-WP-0027 | blocked | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| workplan | WARDEN-WP-0028 | finished | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| workplan | WARDEN-WP-0029 | finished | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| workplan | WARDEN-WP-0030 | finished | — | workplans/WARDEN-WP-0030-delegation-register.md |
| workplan | WARDEN-WP-0031 | finished | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| workplan | WARDEN-WP-0032 | finished | — | workplans/WARDEN-WP-0032-security-zones.md |
| workplan | WARDEN-WP-0033 | finished | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| workplan | WARDEN-WP-0034 | active | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| workplan | WARDEN-WP-0035 | finished | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md |
| workplan | WARDEN-WP-0036 | finished | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md |
| workplan | WARDEN-WP-0037 | blocked | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| workplan | WARDEN-WP-0038 | finished | — | workplans/WARDEN-WP-0038-plan-mutation-intent.md |
| workplan | WARDEN-WP-0039 | finished | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| workplan | WARDEN-WP-0040 | active | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| workplan | WARDEN-WP-0041 | finished | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| workplan | WARDEN-WP-0042 | finished | — | workplans/WARDEN-WP-0042-openbao-structure-survey-route.md |
| workplan | WARDEN-WP-0043 | finished | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| workplan | WARDEN-WP-0044 | active | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-ADHOC-2026-06-27-T01 | done | — | workplans/ADHOC-2026-06-27.md |
| task | WARDEN-WP-ADHOC-2026-06-29-T01 | done | — | workplans/ADHOC-2026-06-29.md |
| task | WARDEN-WP-ADHOC-2026-08-11-T01 | done | — | workplans/ADHOC-2026-08-11.md |
| task | WARDEN-WP-ADHOC-2026-08-11-T02 | done | — | workplans/ADHOC-2026-08-11.md |
| task | WARDEN-WP-ADHOC-2026-08-11-T03 | done | — | workplans/ADHOC-2026-08-11.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T01 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T02 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T03 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T04 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T01 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T02 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T03 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T04 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T05 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T06 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-10-03-T01 | done | — | workplans/ADHOC-2026-10-03.md |
| task | WARDEN-WP-0016-T01 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0016-T02 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0016-T03 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0016-T04 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0017-T01 | done | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| task | WARDEN-WP-0017-T02 | done | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| task | WARDEN-WP-0017-T03 | done | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| task | WARDEN-WP-0018-T01 | done | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| task | WARDEN-WP-0018-T02 | done | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| task | WARDEN-WP-0018-T03 | done | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| task | WARDEN-WP-0019-T01 | done | — | workplans/WARDEN-WP-0019-route-to-secrets-engine.md |
| task | WARDEN-WP-0019-T02 | done | — | workplans/WARDEN-WP-0019-route-to-secrets-engine.md |
| task | WARDEN-WP-0020-T01 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T02 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T03 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T04 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T05 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0021-T01 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T02 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T03 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T04 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T05 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0022-T01 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0022-T02 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0022-T03 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0022-T04 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0023-T01 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T02 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T03 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T04 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T05 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T06 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T07 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0024-T01 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T02 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T03 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T04 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T05 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T06 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T07 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0025-T01 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T02 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T03 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T04 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T05 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0026-T01 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T02 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T03 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T04 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T05 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T06 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T07 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0027-T01 | cancel | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| task | WARDEN-WP-0027-T02 | todo | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| task | WARDEN-WP-0027-T03 | cancel | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| task | WARDEN-WP-0028-T01 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T02 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T03 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T04 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T05 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T06 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T07 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0029-T01 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T02 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T03 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T04 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T05 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0030-T01 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T02 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T03 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T04 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T05 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0031-T01 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T02 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T03 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T04 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T05 | cancel | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0032-T01 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T02 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T03 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T04 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T05 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T06 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T07 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0033-T01 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T02 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T03 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T04 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T05 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T06 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0034-T01 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T02 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T03 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T04 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T05 | wait | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T06 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0035-T01 | done | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md |
| task | WARDEN-WP-0035-T02 | done | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md |
| task | WARDEN-WP-0036-T01 | done | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md |
| task | WARDEN-WP-0036-T02 | done | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md |
| task | WARDEN-WP-0037-T01 | done | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| task | WARDEN-WP-0037-T02 | done | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| task | WARDEN-WP-0037-T03 | wait | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| task | WARDEN-WP-0038-T01 | done | — | workplans/WARDEN-WP-0038-plan-mutation-intent.md |
| task | WARDEN-WP-0039-T01 | done | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| task | WARDEN-WP-0039-T02 | done | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| task | WARDEN-WP-0039-T03 | done | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| task | WARDEN-WP-0040-T01 | wait | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0040-T02 | wait | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0040-T03 | wait | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0040-T04 | done | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0041-T01 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0041-T02 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0041-T03 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0041-T04 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0042-T01 | done | — | workplans/WARDEN-WP-0042-openbao-structure-survey-route.md |
| task | WARDEN-WP-0042-T02 | done | — | workplans/WARDEN-WP-0042-openbao-structure-survey-route.md |
| task | WARDEN-WP-0043-T01 | done | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| task | WARDEN-WP-0043-T02 | done | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| task | WARDEN-WP-0043-T03 | done | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| task | WARDEN-WP-0044-T01 | done | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-0044-T02 | done | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-0044-T03 | progress | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-0044-T04 | wait | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| intake | WARDEN-IN-0001 | closed | — | intakes/intakes.md |
| intake | WARDEN-IN-0002 | closed | — | intakes/intakes.md |
| intake | WARDEN-IN-0003 | closed | — | intakes/intakes.md |

View file

@ -0,0 +1,10 @@
[
{
"path": ".custodian-brief.md",
"index": "100644 34573d262327057c11628ce8a7ca78292968545b 0\t.custodian-brief.md"
},
{
"path": "WORK-RECORDS.md",
"index": "100644 34cf268862326a5832a7d0be9e84eb296e5601bb 0\tWORK-RECORDS.md"
}
]

View file

@ -0,0 +1,60 @@
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
# Custodian Brief — ops-warden
**Domain:** infotech
**Last synced:** 2026-10-16 00:05 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
### Adopt unknown -> fail_closed behind signing-target classification coverage
Progress: 1/4 done | workplan_id: `c8ee441e-1be1-5219-910c-e79ff23cc9ec`
**Open tasks:**
- ! Tasks `611f0901`
*(wait: Warden's own declaration cannot classify the repair-path target workloads; the owner must declare the continuity actor/target and its z2-continuity resolution (see 2026-09-28 review).)*
- ! Tasks `54ad4864`
*(wait: Owners of agt-codex-interhub-bootstrap (ops-hub) and agt-state-hub-bridge (ops-bridge) must publish authoritative workload identity declarations; atm-backup-daily declared by activity-core and compiled 2026-10-09 (z2-protected, admission unsatisfied: M1 below M2 floor).)*
- ! Tasks `93eaf1f2`
*(wait: Gated on T01 and on layer model v0.8 (or successor) reaching accepted; never convert against a proposed standard.)*
### Layer model v0.7 conformance — state the deadline, bind the agent boundary, steward the estate's newest rule
Progress: 5/6 done | workplan_id: `ae3ff76f-883d-5e2f-b6aa-144d61e8fdef`
**Open tasks:**
- ! Tasks `7d1b3c82`
*(wait: Two items to route, not absorb: ops-mason has published no stance map; the second is another repository's to own.)*
### Follow through on KnownSecurityCases along their type's route
Progress: 2/4 done | workplan_id: `f7e81013-6868-5d99-8528-ba75a442eca9`
**Open tasks:**
- ! T03 — Run and verify a case `4a0fa4a7`
*(wait: Catalog integration follows a proven run.)*
- ► T02 — Plan a case run `bcbf6c91`
### Tamper-resistant credential governance + mass rotation/lockdown (Strand B)
Progress: 2/3 done | workplan_id: `21528e8d-a049-523d-9ae1-da7a27cb8bbf`
**Open tasks:**
- · Task: Graded lockdown / break-glass with explicit trust-root `cae498ee`
### Repoint the whynot-design npm lane to Forgejo
Progress: 2/3 done | workplan_id: `42a097db-1c24-558e-a724-030bb2b4443e`
**Open tasks:**
- ! Prove routing and publication `a8b1b855`
*(wait: Hold kept by D3 until SECRETS-WP-0006-T06 moves publishing off the legacy whynot-design npm path; then rotate and prove a fresh publish.)*
## Inbox Hygiene
**Stale unread:** 2 message(s) older than 3 day(s) — triage at session start.
**Missing thread_id:** 3 unread message(s) lack supersession chains.
---
## MCP Orientation (when available)
If the state-hub MCP server is reachable, call:
`get_domain_summary("infotech")`
This provides richer cross-domain context.
If the MCP call fails, use this file as your orientation source.

View file

@ -0,0 +1,188 @@
# Work Records — ops-warden
> Generated by `statehub fix-consistency` (CUST-WP-0061-T04, work-record
> stage 3). Do not edit by hand — edit the source file/block listed for
> each record and re-run fix-consistency to refresh this index. Archived
> workplans are omitted; closed decisions/intakes/engagements stay listed
> so recently-resolved work is still visible. [auto]
| Kind | ID | Status | Lane | Source |
| --- | --- | --- | --- | --- |
| workplan | WARDEN-WP-ADHOC-2026-06-27 | finished | — | workplans/ADHOC-2026-06-27.md |
| workplan | WARDEN-WP-ADHOC-2026-06-29 | finished | — | workplans/ADHOC-2026-06-29.md |
| workplan | WARDEN-WP-ADHOC-2026-08-11 | finished | — | workplans/ADHOC-2026-08-11.md |
| workplan | WARDEN-WP-ADHOC-2026-08-17 | finished | — | workplans/ADHOC-2026-08-17.md |
| workplan | WARDEN-WP-ADHOC-2026-09-08 | finished | — | workplans/ADHOC-2026-09-08.md |
| workplan | WARDEN-WP-ADHOC-2026-10-03 | finished | — | workplans/ADHOC-2026-10-03.md |
| workplan | WARDEN-WP-0016 | finished | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| workplan | WARDEN-WP-0017 | finished | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| workplan | WARDEN-WP-0018 | finished | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| workplan | WARDEN-WP-0019 | finished | — | workplans/WARDEN-WP-0019-route-to-secrets-engine.md |
| workplan | WARDEN-WP-0020 | finished | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| workplan | WARDEN-WP-0021 | finished | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| workplan | WARDEN-WP-0022 | finished | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| workplan | WARDEN-WP-0023 | finished | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| workplan | WARDEN-WP-0024 | finished | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| workplan | WARDEN-WP-0025 | finished | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| workplan | WARDEN-WP-0026 | finished | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| workplan | WARDEN-WP-0027 | blocked | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| workplan | WARDEN-WP-0028 | finished | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| workplan | WARDEN-WP-0029 | finished | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| workplan | WARDEN-WP-0030 | finished | — | workplans/WARDEN-WP-0030-delegation-register.md |
| workplan | WARDEN-WP-0031 | finished | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| workplan | WARDEN-WP-0032 | finished | — | workplans/WARDEN-WP-0032-security-zones.md |
| workplan | WARDEN-WP-0033 | finished | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| workplan | WARDEN-WP-0034 | active | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| workplan | WARDEN-WP-0035 | finished | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md |
| workplan | WARDEN-WP-0036 | finished | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md |
| workplan | WARDEN-WP-0037 | blocked | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| workplan | WARDEN-WP-0038 | finished | — | workplans/WARDEN-WP-0038-plan-mutation-intent.md |
| workplan | WARDEN-WP-0039 | finished | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| workplan | WARDEN-WP-0040 | active | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| workplan | WARDEN-WP-0041 | finished | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| workplan | WARDEN-WP-0042 | finished | — | workplans/WARDEN-WP-0042-openbao-structure-survey-route.md |
| workplan | WARDEN-WP-0043 | finished | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| workplan | WARDEN-WP-0044 | active | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-ADHOC-2026-06-27-T01 | done | — | workplans/ADHOC-2026-06-27.md |
| task | WARDEN-WP-ADHOC-2026-06-29-T01 | done | — | workplans/ADHOC-2026-06-29.md |
| task | WARDEN-WP-ADHOC-2026-08-11-T01 | done | — | workplans/ADHOC-2026-08-11.md |
| task | WARDEN-WP-ADHOC-2026-08-11-T02 | done | — | workplans/ADHOC-2026-08-11.md |
| task | WARDEN-WP-ADHOC-2026-08-11-T03 | done | — | workplans/ADHOC-2026-08-11.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T01 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T02 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T03 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-08-17-T04 | done | — | workplans/ADHOC-2026-08-17.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T01 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T02 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T03 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T04 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T05 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-09-08-T06 | done | — | workplans/ADHOC-2026-09-08.md |
| task | WARDEN-WP-ADHOC-2026-10-03-T01 | done | — | workplans/ADHOC-2026-10-03.md |
| task | WARDEN-WP-0016-T01 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0016-T02 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0016-T03 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0016-T04 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md |
| task | WARDEN-WP-0017-T01 | done | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| task | WARDEN-WP-0017-T02 | done | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| task | WARDEN-WP-0017-T03 | done | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md |
| task | WARDEN-WP-0018-T01 | done | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| task | WARDEN-WP-0018-T02 | done | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| task | WARDEN-WP-0018-T03 | done | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md |
| task | WARDEN-WP-0019-T01 | done | — | workplans/WARDEN-WP-0019-route-to-secrets-engine.md |
| task | WARDEN-WP-0019-T02 | done | — | workplans/WARDEN-WP-0019-route-to-secrets-engine.md |
| task | WARDEN-WP-0020-T01 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T02 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T03 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T04 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0020-T05 | done | — | workplans/WARDEN-WP-0020-ops-warden-worker.md |
| task | WARDEN-WP-0021-T01 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T02 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T03 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T04 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0021-T05 | done | — | workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md |
| task | WARDEN-WP-0022-T01 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0022-T02 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0022-T03 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0022-T04 | done | — | workplans/WARDEN-WP-0022-audit-trail-and-activity.md |
| task | WARDEN-WP-0023-T01 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T02 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T03 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T04 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T05 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T06 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0023-T07 | done | — | workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md |
| task | WARDEN-WP-0024-T01 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T02 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T03 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T04 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T05 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T06 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0024-T07 | done | — | workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md |
| task | WARDEN-WP-0025-T01 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T02 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T03 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T04 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0025-T05 | done | — | workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md |
| task | WARDEN-WP-0026-T01 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T02 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T03 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T04 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T05 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T06 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0026-T07 | done | — | workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md |
| task | WARDEN-WP-0027-T01 | cancel | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| task | WARDEN-WP-0027-T02 | todo | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| task | WARDEN-WP-0027-T03 | cancel | — | workplans/WARDEN-WP-0027-credential-governance-lockdown.md |
| task | WARDEN-WP-0028-T01 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T02 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T03 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T04 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T05 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T06 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0028-T07 | done | — | workplans/WARDEN-WP-0028-tenant-secret-custody.md |
| task | WARDEN-WP-0029-T01 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T02 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T03 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T04 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0029-T05 | done | — | workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md |
| task | WARDEN-WP-0030-T01 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T02 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T03 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T04 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0030-T05 | done | — | workplans/WARDEN-WP-0030-delegation-register.md |
| task | WARDEN-WP-0031-T01 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T02 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T03 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T04 | done | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0031-T05 | cancel | — | workplans/WARDEN-WP-0031-policy-caller-identity.md |
| task | WARDEN-WP-0032-T01 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T02 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T03 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T04 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T05 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T06 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0032-T07 | done | — | workplans/WARDEN-WP-0032-security-zones.md |
| task | WARDEN-WP-0033-T01 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T02 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T03 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T04 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T05 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0033-T06 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md |
| task | WARDEN-WP-0034-T01 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T02 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T03 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T04 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T05 | wait | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0034-T06 | done | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md |
| task | WARDEN-WP-0035-T01 | done | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md |
| task | WARDEN-WP-0035-T02 | done | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md |
| task | WARDEN-WP-0036-T01 | done | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md |
| task | WARDEN-WP-0036-T02 | done | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md |
| task | WARDEN-WP-0037-T01 | done | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| task | WARDEN-WP-0037-T02 | done | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| task | WARDEN-WP-0037-T03 | wait | — | workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md |
| task | WARDEN-WP-0038-T01 | done | — | workplans/WARDEN-WP-0038-plan-mutation-intent.md |
| task | WARDEN-WP-0039-T01 | done | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| task | WARDEN-WP-0039-T02 | done | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| task | WARDEN-WP-0039-T03 | done | — | workplans/WARDEN-WP-0039-explicit-policy-refusal.md |
| task | WARDEN-WP-0040-T01 | wait | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0040-T02 | wait | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0040-T03 | wait | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0040-T04 | done | — | workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md |
| task | WARDEN-WP-0041-T01 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0041-T02 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0041-T03 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0041-T04 | done | — | workplans/WARDEN-WP-0041-catalog-lane-scaffolding.md |
| task | WARDEN-WP-0042-T01 | done | — | workplans/WARDEN-WP-0042-openbao-structure-survey-route.md |
| task | WARDEN-WP-0042-T02 | done | — | workplans/WARDEN-WP-0042-openbao-structure-survey-route.md |
| task | WARDEN-WP-0043-T01 | done | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| task | WARDEN-WP-0043-T02 | done | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| task | WARDEN-WP-0043-T03 | done | — | workplans/WARDEN-WP-0043-platform-supplier-credentials.md |
| task | WARDEN-WP-0044-T01 | done | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-0044-T02 | done | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-0044-T03 | progress | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| task | WARDEN-WP-0044-T04 | wait | — | workplans/WARDEN-WP-0044-security-case-follow-through.md |
| intake | WARDEN-IN-0001 | closed | — | intakes/intakes.md |
| intake | WARDEN-IN-0002 | closed | — | intakes/intakes.md |
| intake | WARDEN-IN-0003 | closed | — | intakes/intakes.md |

View file

@ -0,0 +1,41 @@
---
id: WARDEN-WP-ADHOC-2026-06-27
type: workplan
title: "Ad Hoc Tasks — 2026-06-27"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
created: "2026-06-27"
updated: "2026-06-27"
state_hub_workstream_id: "a222c91f-3bb5-58a4-b6b2-f0fb18cdd5c3"
---
# Ad Hoc Tasks — 2026-06-27
Low-risk opportunistic fixes completed directly during the consolidation session.
### T01 — Fix stale `warden` CLI install + make it usable outside the repo
```task
id: WARDEN-WP-ADHOC-2026-06-27-T01
status: done
priority: medium
state_hub_task_id: "9176b560-8ca5-5143-888d-479857fe60f0"
```
issue-core reported (msg `70bcf238`) that the `warden` CLI on `~/.local/bin` lacked
the `route` subcommand, forcing a `uv run warden` fallback.
- [x] Root cause: `uv tool install` had reused a **cached wheel** (version stayed
`0.1.0`), so the installed `warden.cli` predated the `route`/`access`/`policy`
subcommands. `uv cache clean ops-warden` + `uv tool install . --reinstall` fixed it.
- [x] Deeper cause: even rebuilt, `warden route`/`policy` failed outside a checkout
because the catalog + posture descriptors live in `registry/` at repo root,
outside the package. Bundled `registry/` into the wheel via hatch
`force-include` → `warden/_registry`, and added a packaged-data fallback in
`find_catalog_path` / `find_posture_path` (after the repo walk, so source runs
still prefer the repo's `registry/` as the single source of truth).
- [x] Verified `warden route list` / `warden policy list` work from `/tmp`; 200 tests
pass, lint clean.

View file

@ -0,0 +1,40 @@
---
id: WARDEN-WP-ADHOC-2026-06-29
type: workplan
title: "Ad Hoc Tasks — 2026-06-29"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
created: "2026-06-29"
updated: "2026-06-29"
state_hub_workstream_id: "13fa845f-852e-55ec-a2a5-2296996e0216"
---
# Ad Hoc Tasks — 2026-06-29
### T01 — Joint-smoke mode for the deployed flex-auth (assist FLEX-WP-0007 T4)
```task
id: WARDEN-WP-ADHOC-2026-06-29-T01
status: done
priority: medium
state_hub_task_id: "62540533-f4ca-5176-9237-32adbeb292ee"
```
flex-auth (msg `ea00620b`) asked ops-warden to help close FLEX-WP-0007 T4 (joint OpenBao
+ policy-gate production smoke). Their deployed runtime is reachable on CoulombCore via
the flex-auth-coulombcore tunnel at `127.0.0.1:18090`, but `policy_gate_production_smoke.sh`
spawned its **own** local flex-auth binary — so it never exercised the deployed runtime.
- [x] Added `FLEX_AUTH_EXTERNAL=1` mode to `scripts/policy_gate_production_smoke.sh`: skips
the local `serve`/`load-registry` and runs the allow/deny/vault paths against the
already-running deployed flex-auth, with a `/healthz` precheck that fails fast with a
"is the flex-auth-coulombcore tunnel up?" hint (verified: clean exit 2 when down).
- [x] Verified the committed `production_registry_snapshot.json` is **current** (rebuilt
from `~/.config/warden/inventory.yaml`, diff-clean; 4 actors).
- [x] Answered flex-auth's three questions and handed the operator the exact CoulombCore
runbook (see reply). Remaining T4 steps are operator-gated and cannot run from the
workstation: mint a scoped `VAULT_TOKEN` (ops-warden holds no standing token by
design), run the joint smoke on CoulombCore, then flip `policy.enabled: true`.

View file

@ -0,0 +1,145 @@
---
id: WARDEN-WP-ADHOC-2026-08-11
type: workplan
title: "Ad Hoc Tasks — 2026-08-11"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
created: "2026-08-11"
updated: "2026-08-15"
state_hub_workstream_id: "9f99cc64-4682-5f20-b13e-89af2b6f7c70"
---
# Ad Hoc Tasks — 2026-08-11
### T01 — Repair stale `rapp-qonto-keycape-client` wiki anchor (restore green routing suite)
```task
id: WARDEN-WP-ADHOC-2026-08-11-T01
status: done
priority: medium
state_hub_task_id: "0771d121-278c-556e-9509-841cf6e657c3"
```
rapp-postgres (msg `96907986`, residual from RAPP-POSTGRES-WP-0002-T04) reported the
focused routing suite at 60/61: `test_every_wiki_ref_anchor_resolves` failed because
`rapp-qonto-keycape-client` pointed at `wiki/CredentialRouting.md#credential-routing-catalog`,
an anchor that does not exist. The intended heading is `## Routing catalog index`.
- [x] Repointed `rapp-qonto-keycape-client.wiki_ref` to
`wiki/CredentialRouting.md#routing-catalog-index` (the live heading). No other
entry used the stale anchor.
- [x] `uv run pytest tests/test_routing.py -q` → **61 passed**.
- [x] `warden route find "database credential"` still returns the active
`database-dynamic-credentials` rapp-postgres entry; that T04 route is untouched —
still `warden_executes: false` with no `steps:` block (pointer, not procedure).
### T02 — Triage the stale ops-warden inbox (11 unread, C-28/C-29)
```task
id: WARDEN-WP-ADHOC-2026-08-11-T02
status: done
priority: medium
state_hub_task_id: "0ed58145-732f-5102-b6a8-b931d9b6ba08"
```
`fix-consistency` flagged 11 unread messages older than 3 days, two of them as possible
work requests (C-29). All eleven triaged, answered where an answer was owed, and marked
read. Inbox is now empty.
- [x] **railiance-platform front-door thread** (`72d3ee84`, `cb50ea3c`, `6b058584`,
`5d47caaa`, `78c1c075`) — confirmed both lanes active and placeholder-free
(`issue-core-ingestion-api-key` catalog.yaml:219, `openrouter-llm-connect`
catalog.yaml:283, promoted in 364eb7d), closing RAILIANCE-WP-0009-T06 and
RAILIANCE-WP-0010-T06. Answered their open question: the stable ops-warden
selector is **`openrouter-llm-connect`**, not `llm-connect-openrouter-api-key`;
asked them to cross-reference the id in CCR-2026-0003 rather than have ops-warden
rename an active, test-referenced lane.
- [x] **railiance01 / activity-core** (`467153f3`, `3b9c6a77`, `fe796249`, `674f02e0`) —
superseded. STATE-WP-0071 finished; the `.git/FETCH_HEAD` blocker was filesystem
ownership, not SSH, and no `warden sign` was needed. Nothing was ever open for
ops-warden. Pointed activity-core at `warden plan` / `warden route find` instead of
hub round-trips for access questions.
- [x] **llm-connect LLM-WP-0006** (`f5975211`) — superseded: `OPENROUTER_API_KEY` was
provisioned through OpenBao custody 2026-07-02 (CCR-2026-0003), ES synced,
llm-connect rolled out. Restated the boundary — ops-warden does not populate
Secrets — and pointed at the now-active catalog lane. `LLM_CONNECT_URL` wiring
remains activity-core's.
- [x] **secrets-engine warden-sign** (`80456912`) — see T03; replied with status and
referred the live-apply question to the owner.
### T03 — warden-sign AppRole: PARKED pending WP-0027 break-glass + ops-bridge cutover
```task
id: WARDEN-WP-ADHOC-2026-08-11-T03
status: done
priority: medium
state_hub_task_id: "337ae793-c6b0-59e9-8a07-3a7ccba237aa"
```
secrets-engine (msg `80456912`, 2026-06-29) is holding a validated non-mutating dry-run
for policy + AppRole `warden-sign` (exact `update` grants on `ssh/sign/{agt,adm,atm}-role`).
It is blocked on two **operator** actions: recording/approving the SECRETS-WP-0004
decision, and providing the mode-0600 lane bootstrap token
(`~/.secrets-engine/bootstrap/prod-warden-sign.token`). secrets-engine correctly refused
to substitute the broader platform-admin token.
**The request has been overtaken by events.** Since 2026-07-01 the scoped `VAULT_TOKEN`
need is served by the railiance-platform credential broker
(`ops-warden-warden-sign-token`, active; `credential.py exec --grant ops-warden/warden-sign`,
proven via `make credential-exec-ops-warden-smoke`) — no AppRole involved.
**Resolved 2026-08-11: parked** — neither withdrawn nor proceeding. Founder decision
after reviewing the mechanics. Communicated to secrets-engine (msg `863c7b57`) with an
explicit instruction to stop holding apply readiness.
An initial recommendation to **withdraw** was revised on inspection:
- `warden sign` reads `VAULT_TOKEN` from the environment and has no AppRole login path
(`src/warden/vault.py:24-27`). The AppRole is a way for a *host* to obtain a token,
not an ops-warden code path — withdrawing costs no code and removes no working
capability. For the workstation, the broker plus attended operator OIDC is sufficient.
- The uncovered case is **unattended signing on a remote host** — the pending ops-bridge
cert_command cutover. `wiki/playbooks/ops-bridge-tunnel-cert.md:61` still falls back to
a manually exported `VAULT_TOKEN` there.
- Running the broker on that host means placing the railiance-platform checkout *and its
issuer token* (`credential-broker-warden-sign-issuer` — authority to mint warden-sign
tokens repeatedly) on it. The AppRole exchanges for a `warden-sign`-only token
(`update` on `ssh/sign/{agt,adm,atm}-role`). Both are standing credentials on a remote
host; **the AppRole is the narrower one**, and is the established NetKingdom pattern
for this shape (`rein-openweights-openrouter-approle`,
`agent-harness-binky-mail-approle`).
No circular dependency exists today: OpenBao is a public endpoint
(`https://bao.coulomb.social`), so obtaining a cert never requires already holding one.
**Un-park triggers** (either one re-opens the question):
1. **WARDEN-WP-0027** (backlog) designs the graded lockdown / break-glass path and its
explicit trust-root — a second autonomous path to signing is an input to that design,
not an isolated decision.
2. **ops-bridge cert_command live cutover** reaches unattended signing on a remote host.
Cheap to reverse: the secrets-engine dry-run plan is validated, re-runnable, and correct
as drafted. The two operator gates (SECRETS-WP-0004 decision, mode-0600 lane bootstrap
token) are deliberately *not* being satisfied while parked.
**Closed 2026-08-15.** Neither un-park trigger has fired:
1. `WARDEN-WP-0027` is still `backlog`; T02 (graded lockdown / break-glass) stays
`cancel` with the workplan. The parked AppRole remains an input on that task.
2. ops-bridge live cert_command cutover has not reached unattended signing on a
remote host. WP-0016 is finished as *pilot-ready and handed off*, not migrated.
This ad-hoc's job was the operator question (withdraw vs keep). The 2026-08-11
answer stands: **neither — park and hand off**. Applying or withdrawing the
AppRole is out of scope here and would re-open the operator gates that were
deliberately left unsatisfied. Long-term ownership is `WARDEN-WP-0027-T02`
(and the ops-bridge cutover if that arrives first). secrets-engine already has
the park instruction (msg `863c7b57`); no new apply/withdraw ask.
- [x] Park decision recorded and communicated (2026-08-11)
- [x] Ownership transferred to `WARDEN-WP-0027` T02; playbook pointer updated
- [x] Ad-hoc closed so a `wait` item does not linger past the handoff

View file

@ -0,0 +1,129 @@
---
id: WARDEN-WP-ADHOC-2026-08-17
type: workplan
title: "Ad Hoc Tasks — 2026-08-17"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
created: "2026-08-17"
updated: "2026-08-17"
state_hub_workstream_id: "5c6c2bbb-b944-5afd-b89c-20d865518849"
---
# Ad Hoc Tasks — 2026-08-17
Inbox triage session. Three unread messages, all follow-on from the WP-0030 delegation
register plus one new design question that lands on ops-warden as the estate's
workload-identity owner.
### T01 — Answer flex-auth: how should `/v1/check` authenticate its callers?
```task
id: WARDEN-WP-ADHOC-2026-08-17-T01
status: done
priority: high
state_hub_task_id: "04a2f8f9-e70b-5eed-ad87-343c8f9ef501"
```
flex-auth (msg `130a148c`, FLEX-WP-0015 T02) reported that `POST /v1/check` and
`/v1/batch_check` authenticate no caller — any workload with cluster network reach can
assert any subject/tenant and receive an authoritative allow. It lands on ops-warden
because ops-warden owns how workloads prove identity in this estate, and because the
ops-warden pre-sign gate is a flex-auth PEP that would implement the calling side.
Their four questions answered in `wiki/NetKingdomSecurityMap.md`
§ *Service-to-service caller authentication (in-cluster)*:
- [x] **Q1 — is there an existing estate pattern to adopt?** No. Surveyed what exists:
ops-warden SSH certs (host reachability, not pod→pod HTTP), KeyCape
`client_credentials` (`rapp-qonto-keycape-client` — a custodied client secret per
caller), OpenBao AppRole (host-standing; the WP-0030 register already flags it as
having no owner front door). None covers in-cluster service→service HTTP, so
flex-auth is not growing a parallel mechanism by adopting one.
- [x] **Q2 — which mechanism?** Confirmed their instinct: **(a) Kubernetes
ServiceAccount TokenReview**, with a *projected* token carrying an explicit
`audience`, keeping `automountServiceAccountToken: false` and adding the volume
per Deployment. Rejected (c) shared-secret header — it manufactures a `risk: high`
credential lane with a rotation owner per caller, on the authorization path, which
is exactly the interim-proxy debt WP-0030 exists to stop growing, and ops-warden
would end up fronting it. Deferred (b) mTLS as the stronger end state that first
needs an answer to *who owns the workload X.509 CA* — nobody does; ops-warden
issues SSH certs, not workload X.509.
- [x] **Q3 — authenticate only, or also constrain?** Both, but split: bind the asserted
`system` to the authenticated ServiceAccount and reject a mismatch (identity
binding, no per-consumer operational cost). Keep the *resource-type* allowlist
("only ops-warden may ask about `ssh-certificate`") in the policy package, not in
the auth middleware — flex-auth is the policy engine, and encoding it in its own
admission layer puts authorization in two places where only one is versioned.
- [x] **Q4 — rollout shape?** Warn-only first, as they proposed; ops-warden adopts the
calling side on its own schedule. Binding condition is sequencing, not a date:
`policy.enabled` must not flip anywhere while `/v1/check` still answers
unauthenticated callers.
- [x] Recorded as a **pattern**, not a catalog entry — `registry/routing/catalog.yaml`
indexes credential needs and their owners; caller authentication is neither.
- [x] Noted the division of the call: mechanism is ops-warden's/architectural; accepting
the pod-spec change and rollout timing are the operator's.
### T02 — user-engine: USER_ENGINE_PROXY_SECRET stays railiance-apps; record consumer-only
```task
id: WARDEN-WP-ADHOC-2026-08-17-T02
status: done
priority: medium
state_hub_task_id: "0e815282-2fad-5c8d-be34-398e492737d0"
```
user-engine (msg `2af4a124`) answered the open confirm question on
`coulomb-social-runtime-env`. Decided by Bernd 2026-08-16, State Hub decision
`8fe22037-5bbb-4487-bb86-e4beccee454b` against USER-WP-0021: the secret is
infrastructure trust between ingress and workload, not a user-domain fact; user-engine
consumes it and has no authority over custody, rotation, or issuance.
- [x] `intended_owner` stays `railiance-apps`; dropped the now-answered
"confirm whether user-engine should front USER_ENGINE_PROXY_SECRET" clause from
`blocked_on`, which now names only the real remaining blocker (CCR not applied).
- [x] Recorded the positive signal they asked for: `consumers: [user-engine]` on the
lane, with the decision id in a comment.
- [x] Their second point — `USER_ENGINE_EVENT_TOKEN`, `USER_ENGINE_MAIL_TOKEN`, and the
transactional SMTP lane gating public registration — checked against the catalog:
`audit-core-senders` (native → ops-mason) and `email-connect-transactional`
(interim → secrets-engine) already cover the event and mail token custody. No new
lane opened; told them which ids to watch.
### T03 — key-cape: `rapp-qonto-keycape-client` interim accepted; refresh the blocker
```task
id: WARDEN-WP-ADHOC-2026-08-17-T03
status: done
priority: medium
state_hub_task_id: "e21781d9-a35d-5916-b335-d12131f97a22"
```
key-cape (msg `099b7cba`) acknowledged the lane staying interim on ops-warden.
KEY-WP-0008 is finished and its closeout does **not** include a key-cape-native
`client_secret_basic` exchange/rotation command; that is a separate, not-yet-opened
workplan.
- [x] Refreshed `blocked_on` so it names the current reality rather than implying an
in-flight KEY-WP-0008 dependency: the native command is unopened work, and
key-cape has acked the interim hold.
- [x] `key-cape-oidc-login` left pointing at `secrets-engine` — key-cape explicitly did
not claim the generic-vs-per-lane custody split, and that lane's blocker is the
same unanswered secrets-engine question as the other six.
- [x] `reviewed` bumped to 2026-08-17 on both touched lanes so `warden route gaps`
staleness reflects a real re-check.
### T04 — Session hygiene
```task
id: WARDEN-WP-ADHOC-2026-08-17-T04
status: done
priority: low
state_hub_task_id: "b15724e0-c27a-5260-a810-4dd25bff2228"
```
- [x] `uv run pytest -q` → 338 passed, 4 deselected (routing anchor + no-double-source
checks green after the catalog edits).
- [x] All three messages replied to and marked read; inbox empty.

View file

@ -0,0 +1,179 @@
---
id: WARDEN-WP-ADHOC-2026-09-08
type: workplan
title: "Ad Hoc Tasks — 2026-09-08"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: netkingdom
created: "2026-09-08"
updated: "2026-09-08"
state_hub_workstream_id: "182f3aff-8c8a-5766-8a68-5fe35f423f7a"
---
# Ad Hoc Tasks — 2026-09-08
Four key-cape messages, all follow-on from `WARDEN-WP-0033`. Two carry answers
ops-warden's catalog was waiting for; both make a recorded blocker less true than
it reads. This is the T05 mechanism paying out — and this time the owner ran it
against us rather than us running it against them.
### T01 — Narrow the `rapp-qonto-keycape-client` blocker (msg `08d42f47`)
```task
id: WARDEN-WP-ADHOC-2026-09-08-T01
status: done
priority: high
state_hub_task_id: "29cef28a-d93b-5318-bfdb-69dbe11fa3ba"
```
The blocker recorded "still no key-cape-native exchange/rotation command",
`verified: source-read` against key-cape source on 2026-08-28. Accurate then;
two things landed after that read:
- `keycape service-token` (2026-09-05, KEY-WP-0014-T03) — the client_secret_basic
exchange the blocker records as absent.
- `keycape verify-client` (2026-09-08) — rotation step 3 as one command,
including predecessor rejection and identical-secret detection.
**Narrowed, not cleared**, as key-cape asked. What remains genuinely blocked is
steps 1-2: successor generation and the CAS write to both custodians. Those are
custody and deployment acts, key-cape deliberately ships no command for them, and
no admitted ops-warden lane authorizes them either (T03).
`verified` moved to `owner-confirmed` — the correction came from the owner.
`rotation.automatable` flipped `true` → `false`, which key-cape explicitly asked
us not to do "either way" without precision. Done with the precision they wanted,
in the only place the schema has room for it: the flag is a single hint consumed
by a future executable driver (`WARDEN-WP-0027` Strand B), and a driver told
`true` would attempt custody acts with no admitted transport — the dangerous
direction. So the flag fails safe and the *steps* now carry the per-step truth,
each naming whether it is automatable and why. Offered them a schema change if a
per-step field would serve better; not built on speculation.
### T02 — Record key-cape's acceptance of `key-cape-oidc-login` (msg `12f1bdfa`)
```task
id: WARDEN-WP-ADHOC-2026-09-08-T02
status: done
priority: high
state_hub_task_id: "8efb8013-7b90-52ef-a17c-d63f5ce3752c"
```
key-cape **accepted** ownership: interactive login, OIDC identity-token issuance
and MFA. This confirms the 2026-08-28 correction of `intended_owner` from
secrets-engine to key-cape, and confirms secrets-engine's 2026-08-21 refusal was
right. `verified: asked-and-waiting` → `owner-confirmed`.
**The lane stays `interim`.** Acceptance covers the identity half only. The
`fetch_command` yields an *OpenBao* token — the `netkingdom` mount, the
`role=<domain>` mapping, the token store and its enforcement are OpenBao's, with
role and policy definition railiance-platform's. `keycape login` yields a
key-cape issuer JWT to a private file: different credential type, different
verifier, different enforcement owner. Accepting an owner is not the same as the
owner fronting the lane, and `ADR-0003` says the interim cover is retired when
the front door exists, not when ownership is agreed. Retirement condition is now
recorded on the entry.
Their reading of the risk is right and we confirmed it: `warden_executes: false`
with a `wiki_ref` pointer, so per `ADR-0001` this is a pointer layer, not a code
path with programmatic consumers. `risk: standard` and
`workload_ref: not-applicable` are correct — a human identity act with no KV
path, consistent with how `ADR-0008` treats the other non-KV lanes.
### T03 — Answer "who executes Qonto rotation steps 1-2" (msg `0a6c9d88`)
```task
id: WARDEN-WP-ADHOC-2026-09-08-T03
status: done
priority: high
state_hub_task_id: "bd621821-2116-51c9-a09a-a3660b5e5557"
```
Answer: **nobody, admittedly, today** — and ops-warden must not invent one.
Steps 1-2 mutate custody on `platform/workloads/rapp-qonto/keycape-client` and
`sso/keycape-rapp-qonto-client`. Custody of platform workload paths is
railiance-platform's; the admitted execution front door for provisioned
secret-exec is `secrets-engine exec`. ops-warden owns neither and absorbing it
would be `ADR-0002` and `ADR-0005` violated in one act. Routed to
railiance-platform, with secrets-engine named as the transport owner — and
secrets-engine independently confirmed the same boundary three days earlier
(msg `15f0c0ca`): they will not rewrite a production lane's custody state from a
coordination message without owner confirmation.
key-cape was right not to treat a generic `warden route` match as authorization.
See T04 for what our own tool did when asked.
### T04 — `warden plan` returned `autonomous` for a custody *write* (defect)
```task
id: WARDEN-WP-ADHOC-2026-09-08-T04
status: done
priority: high
state_hub_task_id: "9ada01d2-b14b-579e-921c-275820f255db"
```
Verifying T03 against our own front door:
```
warden plan "generate a successor client secret ... and CAS-write it to
OpenBao platform/workloads/... and sso/..." --json
verdict: autonomous
lane_id: rapp-qonto-keycape-client
commands: warden access ... --exec / --out / --wrap
```
A need that says *generate* and *CAS-write* resolved to `autonomous` and was
answered with three **read** transports. This is the `WARDEN-WP-0033-T06` shape
recurring — a generic keyword match producing a confident wrong act — except T06
fixed one route by adding an exact lane, and the defect is in the classifier.
`warden plan` has no notion of read versus mutate intent, so every write need
matches the lane that *reads* the same path and comes back `autonomous`.
Not fixed here: a classifier is design work with an approval-semantics blast
radius, which the convention says is a workplan, not an adhoc.
Promoted to **`WARDEN-WP-0038`** (`proposed`).
Worth stating plainly: key-cape distrusted this output on principle and was right
to. Had they trusted it, our tool would have told them to proceed autonomously on
an unadmitted custody mutation.
### T05 — Acknowledge the KEY-WP-0009 handoff (msg `5bc58847`)
```task
id: WARDEN-WP-ADHOC-2026-09-08-T05
status: done
priority: low
state_hub_task_id: "06bf8508-d1a2-51b4-b951-02539524ebb9"
```
Informational; no route retired or changed. Their routing note matches ours:
"login / OIDC / MFA" → key-cape means **issuance only**, and secret *values*
route to OpenBao custody. Nothing to change in `wiki/CredentialRouting.md`.
Also records that the KEY-WP-0009 reply ops-warden reported never arriving indeed
never existed (KEY-WP-0014-T02, audited 2026-09-05). Our 2026-08-28 finding was
right, and the correction is theirs, recorded.
### T06 — Unpin two tests from a transient catalog state
```task
id: WARDEN-WP-ADHOC-2026-09-08-T06
status: done
priority: medium
state_hub_task_id: "a0b88db9-2886-54dd-a925-9e0521044aa0"
```
`test_stale_gaps_flags_unverified_even_when_the_date_is_today` and
`test_cli_route_gaps_fail_on_stale_exits_3` both asserted that
`key-cape-oidc-login` specifically sat `asked-and-waiting`. T02 answering that
question broke them — **the tests failed on good news**, not on a defect, and a
test that fails when a counterparty replies will get suppressed rather than read.
Both now assert the property they were always about: any lane whose blocker was
never re-established is stale regardless of its date, over whatever lanes are in
that state. The named-lane version of the claim already exists as a unit test on
`Delegation.is_verified`, which is where a fixture belongs.

View file

@ -0,0 +1,31 @@
---
id: WARDEN-WP-ADHOC-2026-10-03
type: workplan
title: "Documentary feedback on Emergent Security repository pilot"
domain: infotech
repo: ops-warden
status: finished
owner: codex
topic_slug: ops-warden
created: "2026-10-03"
updated: "2026-10-03"
state_hub_workstream_id: "246dc069-0f9b-516b-9db4-9914323da16f"
---
## Review retained pilot evidence against owner boundaries
```task
id: WARDEN-WP-ADHOC-2026-10-03-T01
status: done
priority: medium
state_hub_task_id: "c532cd72-88c4-543b-b6db-caf1bcb74a3d"
```
Evidence: docs/evidence/2026-10-03-emergent-pilot-owner-feedback.md.
Completed authorized documentary feedback on the retained read-only 0.2.0
Claude scenario; preserved original version and evidence limits, qualified
owner boundary wording and identified bounded 0.2.2 follow-up scenarios.
No provider session, runtime control, deployment, credential or institutional
adoption was performed. Next pilot/adoption gates remain existing
EMERGENT-WP-0002-T08/T09 and decision d20a9750-2b29-534e-8227-fb866581a6ca.
No new operational residual was created.

View file

@ -0,0 +1,124 @@
---
id: WARDEN-WP-0016
type: workplan
title: "ops-bridge cert_command pilot — readiness gate + handoff"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
planning_priority: high
planning_order: 16
created: "2026-06-27"
updated: "2026-06-27"
state_hub_workstream_id: "a56da8db-38bc-4bbe-8671-823360ec9245"
---
# WARDEN-WP-0016 — ops-bridge cert_command pilot (readiness gate + handoff)
**Scope:** Close ops-warden's side of the last **Partial** INTENT criterion — *"ops-bridge
integrates via a stable `cert_command`"*. The migration playbook
(`wiki/playbooks/ops-bridge-tunnel-cert.md`, WP-0013) and the `cert_command` contract
(`wiki/CertCommandInterface.md`) already exist, but the pilot has never been run because
the readiness checks are scattered manual checkboxes across three owners (ops-warden,
ops-bridge, railiance-infra). This WP ships the **automated readiness gate** an operator
runs *before* touching tunnel config, plus an offline `cert_command` contract smoke, and
hands the verified pilot to ops-bridge.
**Boundary (unchanged):** ops-warden issues certs and verifies its own side is ready.
The **live tunnel cutover is ops-bridge's to execute** — this WP does not (cannot) flip a
running tunnel. "Done" here means *pilot-ready and handed off*, not *tunnel migrated*.
**Out of scope:** editing `~/.config/bridge/tunnels.yaml` (ops-bridge owns it); deploying
host principals (railiance-infra); requiring a live OpenBao token for the contract smoke
(use the local backend).
**Depends on:** WP-0013 (playbook + contract), the SSH lane (prod-verified).
---
## Tasks
### T1 — Read-only `cert_command` readiness preflight
```task
id: WARDEN-WP-0016-T01
status: done
priority: high
state_hub_task_id: "fea84495-dbec-480a-b42b-90e39f414b78"
```
- [x] `scripts/check_tunnel_cert_readiness.py` — given `--actor`, `--pubkey`, `--config`
(warden.yaml) and optional `--infra` (ssh_principals.yaml), asserts the cert_command
path is ready **without signing anything**: config loads + backend known; actor in
inventory with a valid type + TTL within the type max; pubkey file exists, parses,
and is not a private key; actor principals present; (optional) principals deployed
in the infra file (mirrors `check_principals_drift._infra_principals`). Exit 0/1/2.
- [x] Checklist-style report (✓/✗/·); never prints a private key or token.
- [x] Tests: `tests/test_tunnel_cert_readiness.py` (ready, unknown actor, missing/private
pubkey, infra present/missing, TTL-over-max, cert_command string). 9 unit cases.
### T2 — Offline cert_command contract smoke
```task
id: WARDEN-WP-0016-T02
status: done
priority: medium
state_hub_task_id: "e34ae1a8-2ba9-4324-8d1a-005d61dae478"
```
- [x] Opt-in `--sign-smoke` mode runs the actual `cert_command` against the **local**
backend and validates the emitted cert: identity matches the actor, principals match
inventory, validity window within the type's max TTL. Refuses a vault backend (must
be offline). Proves the contract end to end with no live OpenBao.
- [x] Window measured from the cert's own `valid_from`→`valid_before` (via
`parse_cert_metadata`) so it is timezone-robust — fixes a CEST off-by-2h artifact
where local-time ssh-keygen output was read as UTC.
- [x] `integration`-marked test (needs `ssh-keygen`, skipped in the default suite) plus a
non-integration test that `--sign-smoke` refuses a vault backend.
### T3 — Playbook gate + ops-bridge handoff
```task
id: WARDEN-WP-0016-T03
status: done
priority: medium
state_hub_task_id: "330e01f4-4927-4280-b0e0-49d35b4416d6"
```
- [x] `wiki/playbooks/ops-bridge-tunnel-cert.md` now leads with **Step 0 — Readiness gate**
(the exact `check_tunnel_cert_readiness.py` invocation + `--sign-smoke` note); the
manual checklist remains as the human-readable backing.
- [x] Sent ops-bridge the coordination handoff (pilot `agt-state-hub-bridge`, the
readiness-gate command, and the cutover steps ops-bridge owns).
### T4 — INTENT/SCOPE alignment
```task
id: WARDEN-WP-0016-T04
status: done
priority: low
state_hub_task_id: "4726f5bb-4ffd-484f-8674-91ee5658434f"
```
- [x] SCOPE: INTENT gap row moved from "Partial — tunnels still static-key" to
"Pilot-ready — readiness gate shipped; live cutover handed to ops-bridge"; known-gaps
row updated; readiness script added to the implemented SSH-lane list.
---
## Acceptance
- `scripts/check_tunnel_cert_readiness.py` gates the pilot read-only and is tested.
- The offline contract smoke validates a real cert against the local backend.
- The playbook leads with the automated gate; ops-bridge has the handoff with exact steps.
- No secret material in any script, test, doc, or log. ops-warden's boundary is intact:
it verifies and hands off; ops-bridge executes the cutover.
---
## See also
- `wiki/playbooks/ops-bridge-tunnel-cert.md`, `wiki/CertCommandInterface.md`
- `scripts/check_principals_drift.py` (reused helpers)
- `history/2026-06-24-intent-scope-gap-analysis.md`

View file

@ -0,0 +1,120 @@
---
id: WARDEN-WP-0017
type: workplan
title: "Access front-door discoverability — stop reading as SSH-only"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
planning_priority: high
planning_order: 17
created: "2026-06-27"
updated: "2026-06-27"
state_hub_workstream_id: "cf8b392e-7624-4585-8935-a85e29202935"
---
# WARDEN-WP-0017 — Access front-door discoverability
**Problem:** WP-0014 made ops-warden the operator **access front door** — for
`exec_capable` lanes (OpenBao reads, key-cape login) `warden access <need> --fetch/--exec`
proxies the fetch **as the caller** and streams the value to them (ops-warden holds
nothing). But every *discovery* surface still tells the pre-WP-0014 story, so agents
(e.g. whynot-design needing `NPM_AUTH_TOKEN`) conclude "ops-warden only issues SSH certs
and replies with a pointer, not a token" and never find the proxy.
**Fix:** propagate the WP-0014 conduit charter to the surfaces agents actually read. This
is a *messaging/discoverability* change — **no** change to the security model: the conduit
stays a conduit (no custody, no standing broker; the responsibility-map boundary holds).
**Out of scope:** ops-warden holding/brokering token values (that would override the
WP-0014 charter); shipping the concrete OpenBao npm KV path (railiance-platform infra —
tracked separately); any new fetch capability (the proxy already exists).
**Depends on:** WP-0014 (the proxy lane being described).
---
## Surfaces that mislead today
| Surface | Says now | Should say |
| --- | --- | --- |
| `warden route` table `warden` column | binary `issue` / `route` | `issue` / **`assist`** (exec_capable) / `route` |
| `warden route` `--json` | no proxyability field | add `warden_role` + `exec_capable` |
| `warden access` closing line | "warden advises, the owner vends" | for exec_capable: "ops-warden can fetch this for you as the caller…" |
| `.claude/rules/credential-routing.md` | "issues SSH certs **only**… reply is a pointer, not a key" | issues SSH certs **and** is the access front door; exec_capable lanes proxy as you |
| Federated capability registry | only "SSH certificate issuance" | also "Operator access front door / caller-identity fetch proxy" |
| SCOPE one-liner + capability block | SSH + routing + posture | add the access-assist/proxy front door |
---
## Tasks
### T1 — CLI discoverability: route role + access framing
```task
id: WARDEN-WP-0017-T01
status: done
priority: high
state_hub_task_id: "6e98df42-b5b4-49f8-a444-3c6346c8abd7"
```
- [x] `warden route` table: three-valued `warden` column — `issue` / `assist`
(exec_capable) / `route`. `_entry_summary` JSON gains `warden_role` + `exec_capable`;
`route show` JSON `next_action` surfaces the proxy for exec_capable lanes.
- [x] `warden access` closing line: for `exec_capable` lanes leads with "ops-warden can
fetch this for you as the caller (`--fetch`/`--exec`); runs the owner's tool with
your identity, value never held/cached/logged." Non-exec lanes keep "advises, owner
vends." `_access_json` `next_action` mirrors it.
- [x] Tests in `tests/test_routing.py` (warden_role issue/assist) and `tests/test_access.py`
(front-door framing for exec lane, owner-vends for route-only lane). 210 pass.
### T2 — Agent rule + SCOPE reframe
```task
id: WARDEN-WP-0017-T02
status: done
priority: high
state_hub_task_id: "6e2a7067-1afc-4f38-8d99-4d5c36a4661c"
```
- [x] `.claude/rules/credential-routing.md`: reframed the lead ("issues SSH certs **and**
is the operator access front door…") and the quick routing table (`ops-warden role`
column: Issue / Assist / Route). Kept the true anti-pattern: don't POST a State Hub
message for a secret *value* — it comes from the CLI front door run as you.
- [x] SCOPE one-liner reframed to "steward **and front door**"; added a second `capability`
block "Operator access front door (caller-identity fetch proxy)".
### T3 — Federated capability registration
```task
id: WARDEN-WP-0017-T03
status: done
priority: medium
state_hub_task_id: "7199625b-e78e-4495-8ca0-076100ae9f08"
```
- [x] Registered the State Hub capability "Operator access front door (caller-identity
fetch proxy)" (id `708e46f6`, repo ops-warden) — the hub had **no** ops-warden
security capability before, so the front door was undiscoverable cross-domain.
- [x] Sent whynot-design (msg `83a3bb2e`) the corrected path: `warden access "npm auth
token" --fetch/--exec`, the CLI refresh, the OpenBao-auth prereq, and the
railiance-platform path caveat.
---
## Acceptance
- An agent doing the first-line `warden route find` / `--json` lookup can see ops-warden
*assists* (proxies) the OpenBao lane, not merely points.
- The credential-routing rule and federated capability registry describe the access
front door; none of them say "SSH certificates only".
- The conduit boundary is unchanged and explicit: ops-warden fetches *as the caller* and
holds nothing — no custody, no broker.
---
## See also
- `WARDEN-WP-0014` (the proxy lane), `wiki/OperatorAccessAssist.md`
- `.claude/rules/credential-routing.md`, `registry/routing/catalog.yaml`

View file

@ -0,0 +1,103 @@
---
id: WARDEN-WP-0018
type: workplan
title: "Activate whynot-design npm publish lane + resolvable readiness flag"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
planning_priority: high
planning_order: 18
created: "2026-06-29"
updated: "2026-06-29"
state_hub_workstream_id: "1256aca2-5979-4d21-818e-0de42c5d811b"
---
# WARDEN-WP-0018 — whynot-design npm lane activation + `resolvable` flag
**Trigger:** railiance-platform completed provisioning the whynot-design npm publish lane
(CCR-2026-0001, commit 8f617fc): `status=active`, `access_frontdoor.readiness=ready`,
`resolvable=true`, positive fetch passed + negative (non-whynot) login denied. They asked
ops-warden to activate the dedicated catalog selector and notify whynot-design. This is the
first concrete `warden access --fetch`-resolvable non-SSH lane — the end-to-end proof of the
WP-0014 conduit + WP-0017 discoverability work.
**whynot-design's spec** (msg 2687dc31) drove the shape: zero-placeholder command keyed by a
stable id, owner-confirmed concrete path/field/role, a machine-readable readiness flag, and a
publish-vs-read scope split.
**Boundary unchanged:** ops-warden holds no token; the lane proxies the read as the caller.
---
## Tasks
### T1 — Concrete catalog entry + playbook
```task
id: WARDEN-WP-0018-T01
status: done
priority: high
state_hub_task_id: "189d0883-22b9-42dc-bda0-89460509a87d"
```
- [x] Added `whynot-design-npm-publish` to `registry/routing/catalog.yaml` (`status: active`,
`exec_capable`, `lane: secret`) with the **owner-confirmed, zero-placeholder** handoff:
path `platform/workloads/coulomb/whynot-design/npm-publish` (the superseded
`whynot-design/whynot-design/…` form is **not** used), field `NPM_AUTH_TOKEN`, OIDC
`bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read`, policy
`workload-kv-read-whynot-design-npm-publish`, flex-auth `secret.read:whynot-design`.
- [x] `wiki/playbooks/whynot-design-npm-publish.md` — worker checklist, scopes, operator
go-ahead note (publish is immutable + outward-facing). Catalog `wiki_ref` points to it.
- [x] Passes the `_assert_no_secret_material` guard (templates/identifiers only, no value).
### T2 — `resolvable` readiness flag + stable-id resolution
```task
id: WARDEN-WP-0018-T02
status: done
priority: high
state_hub_task_id: "b5dc1013-5334-43ff-afd6-1f99d521358f"
```
- [x] `RouteEntry.resolvable` — true when a lane is active, exec_capable, and its fetch
command/path carry **no** unresolved `<…>` placeholder. Surfaced in the route/access
`--json` (`_entry_summary`). Generic `openbao-api-key` and the `<domain>` login lane
report `false`; `whynot-design-npm-publish` reports `true`.
- [x] `Catalog.find` now resolves an **exact catalog-id** match first, so
`warden access whynot-design-npm-publish …` is deterministic regardless of keyword
collisions (whynot-design's "stable keyed command").
- [x] Tests: `tests/test_routing.py` (concrete+resolvable lane, template lanes not
resolvable, exact-id wins); fixed a `test_access` no-match query that incidentally
substring-collided (`no` ⊂ `whynot`). 213 pass, lint clean.
### T3 — Close the loop
```task
id: WARDEN-WP-0018-T03
status: done
priority: medium
state_hub_task_id: "95b00ef8-477a-4f0d-bd71-6154fba401f5"
```
- [x] Notified whynot-design (reply 744977ae) with the zero-placeholder command
`warden access whynot-design-npm-publish --exec -- npm publish`, the `resolvable` gate,
the coulomb-tenant path correction, and the operator-go-ahead reminder.
- [x] Confirmed activation to railiance-platform (reply f76d3a9e). Sibling lanes
(`issue-core-ingestion-api-key`, `openrouter-llm-connect`) stay `draft` per their
deferral, pending CCR-2026-0002/0003 provisioning.
---
## Acceptance
- `warden access whynot-design-npm-publish` resolves to a concrete, owner-confirmed,
zero-placeholder lane; `--json` reports `resolvable: true`.
- Template/generic lanes report `resolvable: false`; exact-id lookup is deterministic.
- No secret value in catalog, playbook, tests, or logs; ops-warden holds nothing.
## See also
- `WARDEN-WP-0014` (proxy lane), `WARDEN-WP-0017` (discoverability)
- railiance-platform CCR-2026-0001, `docs/workload-kv-access-lanes.md`

View file

@ -0,0 +1,89 @@
---
id: WARDEN-WP-0019
type: workplan
title: "Route secret-exec lanes to secrets-engine (route-primary, proxy fallback)"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
planning_priority: high
planning_order: 19
created: "2026-06-29"
updated: "2026-06-29"
state_hub_workstream_id: "5e49abb6-497f-4640-a484-2da5f39a7c4e"
---
# WARDEN-WP-0019 — Route secret-exec lanes to secrets-engine
**Trigger:** secrets-engine (SECRETS-WP-0003, msg 765a03f0) shipped a native secret-exec
front door — `secrets-engine route <id> --json` and `secrets-engine exec --catalog <id> --
<cmd>` with canonical decision ids — and asked ops-warden to **route to it**. This is the
owner-native execution lane that ops-warden's `warden access --exec` proxy was filling as a
stopgap (WP-0014). whynot-design already published `@whynot/design@0.4.0` through the proxy
on this same lane, so both paths resolve today.
**Decision (Bernd, 2026-06-29): route-primary, proxy-fallback.** For lanes secrets-engine
owns, ops-warden surfaces `secrets-engine exec/route` as the **primary** path and keeps its
own `warden access --exec` as a documented **transparent fallback**. ops-warden stays the
discovery front door; secrets-engine is the exec owner. Boundary unchanged: ops-warden holds
or stores no token on either path.
**Out of scope:** ops-warden invoking `secrets-engine exec` itself (it routes/points, the
caller runs it); changing the proxy's security model; the production policy-gate flip.
---
## Tasks
### T1 — Catalog + CLI: surface the owner-native exec front door
```task
id: WARDEN-WP-0019-T01
status: done
priority: high
state_hub_task_id: "ea153605-7a14-4db7-8bce-d780ea143f8a"
```
- [x] `RouteEntry` gains `exec_owner` / `exec_command` / `pointer_command` (pointers only,
screened by `_assert_no_secret_material`) and a `has_native_exec` property.
- [x] `whynot-design-npm-publish` entry: `exec_owner: secrets-engine`,
`exec_command: secrets-engine exec --catalog whynot-design-npm-publish -- <cmd>`,
`pointer_command: secrets-engine route whynot-design-npm-publish --json`. Keep the
existing `fetch_command`/`exec_capable` (the proxy fallback).
- [x] `warden access`: when `exec_owner` is set, render the secrets-engine exec as the
**primary** line and the `warden access --exec` proxy as the **fallback**; JSON gains
`exec_owner`/`exec_command`/`pointer_command`. `route find/show` JSON too.
- [x] Tests in `tests/test_routing.py` / `tests/test_access.py`.
### T2 — Agent rule, SCOPE, playbook
```task
id: WARDEN-WP-0019-T02
status: done
priority: medium
state_hub_task_id: "96059b8a-8938-4763-b3d0-cc5a0eb2465c"
```
- [x] `.claude/rules/credential-routing.md`: add secrets-engine as the secret-exec owner;
for OpenBao-backed secret lanes the route is "secrets-engine `exec` (primary),
ops-warden `warden access --exec` (transparent fallback)".
- [x] SCOPE: add secrets-engine to Related Repos + the routing model; note the
whynot-design lane is **production-exercised** (real 0.4.0 publish), not just resolvable.
- [x] `wiki/playbooks/whynot-design-npm-publish.md`: lead with the secrets-engine exec
command; fix the fallback one-liner per whynot-design's field notes
(`--field NPM_AUTH_TOKEN`, and `--no-policy` while `policy.enabled=false`).
---
## Acceptance
- `warden access whynot-design-npm-publish` shows the secrets-engine exec as primary and the
warden proxy as fallback; `--json` carries `exec_owner`/`exec_command`.
- The credential-routing rule names secrets-engine as the secret-exec owner.
- No secret material anywhere; ops-warden holds no token on either path.
## See also
- secrets-engine SECRETS-WP-0003, decision e6381a56, `docs/whynot-design-real-publish-closeout.md`
- `WARDEN-WP-0014` (proxy), `WARDEN-WP-0017` (discoverability), `WARDEN-WP-0018` (lane activation)

View file

@ -0,0 +1,176 @@
---
id: WARDEN-WP-0020
type: workplan
title: "ops-warden worker — autonomous coordination via llm-connect"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
planning_priority: high
planning_order: 20
created: "2026-06-29"
updated: "2026-06-29"
state_hub_workstream_id: "c906ba1d-f991-4fb0-b113-59432ddf87c0"
---
# WARDEN-WP-0020 — ops-warden worker (`warden worker`)
**Problem:** ops-warden's coordination lane (State Hub inbox `to_agent=ops-warden`) is
handled only when a human spins up an ops-warden session and relays instructions. That
doesn't scale — Bernd is hand-relaying between flex-auth ↔ secrets-engine ↔ ops-warden
across sessions.
**Goal:** a `warden worker` CLI that pulls ops-warden's unread coordination requests and,
using **llm-connect** for inference, drives each to an ops-warden action (answer a routing
question, draft+send a reply, mark read, propose/commit a catalog diff, or escalate) — so
the inbox is handled without a human starting a session.
**Decisions (Bernd, 2026-06-29):** **full-auto in-scope** (worker executes any in-scope
action; escalates only secrets/prod/out-of-scope) and **scheduled/unattended** (cron or
activity-core). Because there is no human in the loop for in-scope actions, the guardrails
are load-bearing and the rollout is staged: **dry-run → manual → scheduled**.
**Build vs reuse:** inference = llm-connect (`/execute`); trigger = cron or activity-core
(reuse the durable task factory, don't reinvent scheduling). Worker logic lives in warden.
## Guardrails (non-negotiable — full-auto rests on these)
1. **Fixed charter, non-overridable.** The boundary (issue SSH; route everything else;
conduit-not-broker; never hold/print a secret value) is a fixed system policy. Message
content is **untrusted data**, never instructions that can relax it (prompt-injection
containment).
2. **Action allowlist.** Every action is validated against an allowlist before execution;
off-list → escalate. No secret handling, no prod-config writes, no irreversible/outward
actions without an explicit human ack.
3. **No-secret invariant.** Refuse any task requiring a secret value in hand or in a prompt.
4. **Full audit + dry-run.** Every action emits a progress event; `--dry-run` shows the
plan without executing. Scheduled mode only after a clean dry-run shakedown.
## Hard dependency
llm-connect must be operational — it needs its provider key (`OPENROUTER_API_KEY`,
CCR-2026-0003, currently deferred by railiance-platform/secrets-engine). The worker is
built against llm-connect's contract; it cannot run the brain until that lands.
---
## Tasks
### T1 — Worker scaffold (llm-connect-independent, safe)
```task
id: WARDEN-WP-0020-T01
status: done
priority: high
state_hub_task_id: "979c2d9b-0803-442f-aa2e-acb02bac07e9"
```
- [x] `src/warden/worker.py`: State Hub inbox client (`HubClient.unread`), a `Brain`
protocol, a deterministic `RuleBrain` default (answers clear routing questions;
escalates the rest), the `PlannedAction`/`WorkerPlan` model, the guardrail allowlist +
`validate_action` (enforced brain-agnostically in `build_plans`), and a `render_plans`
dry-run renderer (plan only, no execution).
- [x] `warden worker run [--once] [--dry-run]` CLI; `--dry-run` is the default and
`--execute` is refused (exit 2) until the guarded executor lands (T3).
- [x] `tests/test_worker.py` (RuleBrain routing/secret/prod/unknown, guardrail downgrades a
reckless brain on secret/prod, off-allowlist rejection, render, CLI). 18 cases.
- [x] Live dry-run against the real hub verified — read the inbox and produced a guardrailed
plan (it surfaced secrets-engine's OIDC-role reply, demonstrating the value).
### T2 — llm-connect brain
```task
id: WARDEN-WP-0020-T02
status: done
priority: high
state_hub_task_id: "52d281b2-7d48-44f5-b77e-80e3ed500b5f"
```
- [x] llm-connect brought operational (operator set OPENROUTER_API_KEY k8s secret + restart).
Contract discovered empirically from the running service: `POST /execute {"prompt":...}`
→ `{"content": "<text>", ...}` (no OpenAPI; custom JSON API). End-to-end verified (pong).
- [x] `LlmConnectBrain` (src/warden/worker.py): embeds the fixed charter + the message as
untrusted data into the prompt, calls `/execute`, parses a JSON action plan
(`_extract_json` tolerates fences/prose), and defensively escalates on malformed/empty/
transport-error. Configurable `LLM_CONNECT_URL`. The guardrail pass still enforces the
allowlist + no-secret invariant on whatever the model returns.
- [x] `warden worker run --brain rule|llm` selector (dry-run default). Tests:
`tests/test_worker.py` (extract_json, parse, escalate-on-flag/malformed/transport,
guardrail-catches-unsafe-LLM-action). **Live verified** against the real inbox: the LLM
brain produced a sensible reply+mark_read for the secrets-engine message and correctly
escalated the llm-connect secret-custody request. 236 tests, lint clean.
### T3 — Action dispatch + guardrails (full-auto in-scope)
```task
id: WARDEN-WP-0020-T03
status: done
priority: high
state_hub_task_id: "3a71965e-42d5-4258-9761-aced804c88e7"
```
- [x] `HubClient` gained writes (`mark_read`, `send_reply`, `add_progress`); `execute_plan`
/ `execute_plans` run the **safe, allowlisted** actions — route_answer (reply with the
computed answer + auto mark-read), reply (with an LLM-drafted body), progress_note,
mark_read. Escalated plans and non-auto-executable kinds are left for a human.
- [x] **Deliberate guardrail:** `propose_catalog_diff` (and any code/routing change) is NOT
auto-executed even under full-auto — a bad catalog commit could misroute credentials,
so it goes to human review (recoverability over convenience). AUTO_EXECUTABLE is the
messaging/hub tier only. No secret value is ever read, sent, or logged.
- [x] `warden worker run --execute` runs the guarded executor (dry-run still the default);
per-message audit summary. Tests in `tests/test_worker.py` (route_answer reply+mark,
reply-with/without-body, escalated skip, catalog-diff left-for-human, progress_note,
failure-without-crash). 243 pass, lint clean.
- [x] **Conservative tier is now the `--execute` default (Bernd's Option A, 2026-06-30):**
`run_conservative` triages NEW messages into a reviewed digest (`worker-digest.md`)
with drafted replies, posts ONE progress note, tracks seen ids (schedule-safe dedup),
and sends **nothing** to other agents / marks nothing read. `--full-auto` opts into the
auto-send path. Live-verified with the LLM brain: produced a high-quality draft reply
to secrets-engine and flagged the llm-connect request as NEEDS YOU. 244 tests.
Rationale: the guardrails prevent *security* harm but not LLM *content* errors, so replies
stay drafts-for-approval until quality is proven — matches the build-stage/recoverability
posture. Conservative mode is safe to schedule (T4).
### T4 — Scheduled trigger
```task
id: WARDEN-WP-0020-T04
status: done
priority: medium
state_hub_task_id: "7f77ea6d-c281-42c5-ad25-2a0bb9fd68de"
```
- [x] `scripts/worker-tick.sh` — scheduled tick for the conservative worker. `flock`
concurrency guard (no overlapping runs); brings up a short-lived kubectl port-forward
to llm-connect (or honors `LLM_CONNECT_URL`, or falls back to the rule brain offline).
Ships **disabled**; the header documents the cron entry to enable it (every 15 min).
Dry-shakedown done (the conservative live run + the rule-brain tick both verified).
Schedules the **conservative** tier only — never the auto-send path.
### T5 — Docs / SCOPE / INTENT
```task
id: WARDEN-WP-0020-T05
status: done
priority: medium
state_hub_task_id: "6e7ae317-7f8b-468a-bb5c-b08093ed43a0"
```
- [x] SCOPE: recorded the coordination worker (`warden worker`) as an implemented
capability — conservative triage default, full-auto opt-in, llm-connect brain, the
four guardrails, schedulable tick. The guardrails + the conservative-by-default
posture are documented as the worker's security-model statement (here + in the
build-stage decision 813899f9).
---
## Acceptance
- `warden worker run --dry-run` reads the real inbox and prints a guardrailed plan.
- Full-auto execution runs only in-scope, allowlisted actions; secrets/prod/out-of-scope
escalate; every action is audited. No secret value ever enters a prompt, log, or commit.
- Scheduled mode is enabled only after a dry-run shakedown.
## See also
- llm-connect (inference), activity-core (durable trigger), kaizen-agentic (personas)
- `.claude/rules/credential-routing.md` (the boundary the worker enforces)

View file

@ -0,0 +1,142 @@
---
id: WARDEN-WP-0021
type: workplan
title: "Enable the scheduled worker tick — conservative inbox triage, unattended"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
planning_priority: high
planning_order: 21
created: "2026-06-30"
updated: "2026-06-30"
state_hub_workstream_id: "8c487014-b630-4016-a4f0-31b971a473d2"
---
# WARDEN-WP-0021 — Enable the scheduled worker tick
**Goal:** turn the WP-0020 conservative worker from *built-but-disabled* into a reliable,
unattended schedule — so ops-warden's State Hub inbox is auto-triaged into a digest of
**drafted replies** the operator reviews and approves, without anyone starting a session.
This is the payoff of WP-0020: it ends the cross-session relay toil.
**Posture (unchanged):** schedule the **conservative** tier only — triage + draft, never
auto-send (Option A / build-stage decision `813899f9`). The four guardrails hold. Easy
kill switch is a requirement, not an afterthought (recoverability).
**What "enabled" means here:** (1) the tick runs on a schedule and survives the failure
modes (hub/llm-connect down → graceful degrade), (2) the operator actually *sees* new
drafts, (3) the operator can *act* on a draft with one command, (4) it's trivial to stop.
**Out of scope:** the full-auto (auto-send) path; flipping `policy.enabled`; moving the
worker off the workstation.
**Depends on / relates to:** WP-0020 (the worker + `scripts/worker-tick.sh`); the State
Hub migration to railiance01 (`cust-wp-0011`/`0038`) may change `WARDEN_HUB_URL` later —
the tick already honors that env var.
---
## Decisions to settle (first)
- **Scheduler:** `systemd --user` timer (recommended — clean logs via `journalctl`,
`systemctl --user status`, built-in scheduling) vs. plain cron (simplest) vs.
activity-core (ecosystem-native durable trigger; heavier for build stage). Recommend the
systemd user timer; cron documented as the one-liner fallback.
- **Cadence:** every 15 min (default) — adjustable.
- **llm-connect reachability:** per-tick short-lived port-forward (current behaviour) with
rule-brain fallback, vs. a persistent forward. Recommend keeping the per-tick forward +
fallback for build stage (no standing process).
---
## Tasks
### T1 — Scheduler install + enablement + kill switch
```task
id: WARDEN-WP-0021-T01
status: done
priority: high
state_hub_task_id: "10451fe6-7fab-4ae0-8494-e6cfdfbcf8cf"
```
- [ ] `systemd --user` timer + service units (`ops-warden-worker.{service,timer}`) that run
`scripts/worker-tick.sh` on the chosen cadence, with `WARDEN_HUB_URL` / `WORKER_BRAIN`
from an env file. Install script + documented cron fallback one-liner.
- [ ] Concurrency is already guarded by the tick's `flock`; verify under the timer.
- [ ] **Kill switch:** `systemctl --user disable --now ops-warden-worker.timer` (and the
env-file `WORKER_ENABLED=0` short-circuit) — one command to stop, documented.
### T2 — Scheduled-run robustness (graceful degradation)
```task
id: WARDEN-WP-0021-T02
status: done
priority: high
state_hub_task_id: "1f35f816-1af5-46ff-b48c-1715f3ae5784"
```
- [ ] Harden `worker-tick.sh` for unattended runs: bounded timeouts, hub-unreachable →
clean skip + log (no crash loop), llm-connect-unreachable → rule-brain fallback
(already present; verify), non-zero exit only on real faults.
- [ ] End-to-end verify a real timer-fired tick: new message → digest + progress note;
no new message → no-op; hub down → graceful skip.
### T3 — Operator visibility (see new drafts)
```task
id: WARDEN-WP-0021-T03
status: done
priority: medium
state_hub_task_id: "3c7f6423-8db0-4bc6-b67d-078d9d929c6d"
```
- [ ] Surface new drafts beyond the file: desktop `notify-send` on new digest (when a
display is present) and/or keep the hub progress note as the durable signal.
- [ ] `warden worker status` — last run time, pending-draft count, digest path, timer state.
### T4 — Review→send loop (`warden worker approve`)
```task
id: WARDEN-WP-0021-T04
status: done
priority: high
state_hub_task_id: "dabc9fc0-abb1-4e9d-b87e-5f0c5950693c"
```
- [ ] Persist structured drafts during the tick (`state_dir/worker-drafts.json`:
message_id → to_agent, subject, drafted body, thread_id — no secret material).
- [ ] `warden worker approve <message_id> [--edit]` — send the reviewed draft as the
caller's reply + mark read; `warden worker drafts` to list pending. This is what makes
the scheduled digest *actionable* in one command instead of hand-composing.
### T5 — Runbook + SCOPE
```task
id: WARDEN-WP-0021-T05
status: done
priority: medium
state_hub_task_id: "9915da96-1b33-4d0f-b752-408ea8d43333"
```
- [ ] `wiki/playbooks/scheduled-worker.md` — enable/disable, cadence, the approve workflow,
failure modes, and the build-stage posture (conservative only). SCOPE note.
---
## Acceptance
- A `systemd --user` timer (or cron) runs the conservative tick unattended; one command
disables it.
- A timer-fired tick triages new messages into a digest + progress note and degrades
gracefully when the hub or llm-connect is down.
- The operator is notified of new drafts and can send a reviewed draft with
`warden worker approve <id>`.
- Still conservative: nothing is auto-sent; no secret value is read, sent, or logged.
## See also
- `WARDEN-WP-0020` (the worker + `scripts/worker-tick.sh`), build-stage decision `813899f9`
- `cust-wp-0011`/`cust-wp-0038` (State Hub → railiance01; future `WARDEN_HUB_URL`)

View file

@ -0,0 +1,119 @@
---
id: WARDEN-WP-0022
type: workplan
title: "Audit trail + `warden activity` — one place to see what ops-warden did"
domain: infotech
repo: ops-warden
status: finished
owner: claude
topic_slug: custodian
planning_priority: high
planning_order: 22
created: "2026-07-01"
updated: "2026-07-01"
state_hub_workstream_id: "fc8afa28-68a7-4250-a19e-9754829f0cd5"
---
# WARDEN-WP-0022 — Audit trail + `warden activity`
**Problem:** ops-warden's actions are recorded in scattered places — `signatures.log`
`access-audit.log`, the systemd journal (worker ticks), and
State Hub progress notes (the narrative). There is **no single, structured audit trail**
and no one command to answer *"what did ops-warden do in the last N days?"*. For a security
steward, a coherent, metadata-only audit record is table stakes.
**Goal:** a unified, append-only audit log that captures **every** ops-warden action with a
common shape (never a secret value), and a single `warden activity` command to read it.
**Non-negotiable (this is a security tool's audit):** the audit record holds **metadata
only** — actor/subject, action, target/path id, decision id, TTL, outcome, timestamp — and
**never** a token, key, cert body, or other secret. A secret-material guard rejects any
event field that looks like a value (mirrors the catalog `_assert_no_secret_material`).
**Posture:** read/append-only, in-boundary (local logs + optional hub read). Tamper-evident
hash-chaining is noted as an optional hardening for when the ecosystem reaches testing.
**Relates to:** WP-0014 (`access-audit.log`), the SSH lane (`signatures.log`), WP-0020/0021
(the worker). Linger is now enabled (worker survives logout); full logged-out value also
needs the State Hub + tunnels to be login-independent (State Hub → railiance01,
`cust-wp-0011`).
---
## Tasks
### T1 — Unified audit event log
```task
id: WARDEN-WP-0022-T01
status: done
priority: high
state_hub_task_id: "7f8f768a-4c62-4096-bad8-912cea0f35a7"
```
- [x] `src/warden/audit.py`: append-only JSONL at `state_dir/audit.jsonl`. Common event
schema — `ts`, `kind` (`sign`|`access`|`worker`), `action`, `subject`, `target`,
`decision_id`, `outcome`, `source`. `record_event(**meta)` with a secret-material
guard (reject token prefixes / high-entropy runs) so no value can ever land here.
`read_events(*, since, kinds)` for the reader.
- [x] Log rotation / bound (size or age) so it stays manageable.
### T2 — Instrument the actions
```task
id: WARDEN-WP-0022-T02
status: done
priority: high
state_hub_task_id: "e7ae4037-ca79-4557-81f0-bfb8478ff647"
```
- [x] Emit an audit event from each ops-warden action: `warden sign` (cert issued —
actor, type, ttl, backend, policy_decision_id), `warden access --fetch/--exec`
(proxy — need id, owner, decision id), and the worker (`approve` → reply sent to X;
tick → triage summary N/drafted/escalated). Fold the existing `signatures.log` /
`access-audit.log` in as sources (keep back-compat; don't drop a record).
- [x] Assert no secret value reaches the audit in any path (tests).
### T3 — `warden activity` command
```task
id: WARDEN-WP-0022-T03
status: done
priority: high
state_hub_task_id: "4439bdd8-1461-47df-8b0b-048df7384a68"
```
- [x] `warden activity [--days N] [--kind sign|access|worker] [--json] [--hub]` — a single
chronological view merging the audit log (and, for back-compat, `signatures.log` /
`access-audit.log`); `--hub` also pulls recent ops-warden State Hub progress notes for
the narrative. Human table by default; stable `--json` for agents.
### T4 — Tests, runbook, SCOPE
```task
id: WARDEN-WP-0022-T04
status: done
priority: medium
state_hub_task_id: "bdfb8703-7a79-43e7-913b-19d61722f164"
```
- [x] Tests: audit append/read/rotation, the secret-material guard rejects values, the
instrumented actions emit events, `warden activity` filtering + `--json` shape.
- [x] `wiki/AuditTrail.md` (what's recorded, the no-secret guarantee, how to query, the
linger + login-independence note). SCOPE entry.
---
## Acceptance
- Every ops-warden action (sign, access proxy, worker send/tick) appends a metadata-only
audit event; the secret-material guard is proven to reject values.
- `warden activity --days 3` answers "what did ops-warden do" in one command; `--json`
gives agents a stable shape.
- No secret value appears in the audit log, ever.
## See also
- `WARDEN-WP-0014` (`access-audit.log`), `WARDEN-WP-0020`/`0021` (the worker)
- `wiki/OperatorAccessAssist.md` (the metadata-only audit principle)
- `wiki/AuditTrail.md`

View file

@ -0,0 +1,222 @@
---
id: WARDEN-WP-0023
type: workplan
title: "INTENT–SCOPE Alignment Closeout"
domain: infotech
repo: ops-warden
status: finished
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 23
created: "2026-07-01"
updated: "2026-07-01"
depends_on_workplans:
- WARDEN-WP-0022
state_hub_workstream_id: "7bad1ec4-a7c2-4980-b8f9-49a7f5408574"
---
# WARDEN-WP-0023 — INTENT–SCOPE Alignment Closeout
## Goal
Close the July 2026 INTENT↔SCOPE gaps that ops-warden can address directly: sync
aspirational docs with shipped capabilities, coordinate the remaining production
integration blockers (flex-auth flip, ops-bridge cutover), improve daily operator
UX for broker-backed signing, and establish a repeatable catalog promotion cadence.
Audit implementation stays in **WARDEN-WP-0022**; this workplan sequences and
surrounds it.
**Assessment:** `history/2026-07-01-intent-scope-gap-analysis.md`
## Boundary
- ops-warden does **not** deploy flex-auth, flip ops-bridge tunnels, or implement
the credential broker — it documents, coordinates, and routes.
- Production cutover evidence is captured here; execution remains with owning repos.
---
## Tasks
### T01 — Persist gap analysis
```task
id: WARDEN-WP-0023-T01
status: done
priority: high
state_hub_task_id: "52485c90-87fe-40b1-9db5-a51ebb957dd5"
```
Write and link `history/2026-07-01-intent-scope-gap-analysis.md` with success
criteria matrix, mission pillars, prioritized gaps, and workplan recommendation.
Acceptance:
- History file exists and is referenced from SCOPE and this workplan.
- State Hub progress note logged for the assessment.
**2026-07-01:** Assessment written at
`history/2026-07-01-intent-scope-gap-analysis.md`.
### T02 — Refresh INTENT.md
```task
id: WARDEN-WP-0023-T02
status: done
priority: high
state_hub_task_id: "9a9b3631-8948-45af-ace1-c19ee74ace4d"
```
Update `INTENT.md` so the aspirational doc reflects shipped reality without
becoming a second SCOPE:
- Mission pillar #2: assist layer (`warden access`) and owner-native exec routing
(secrets-engine, railiance-platform credential broker).
- NetKingdom literacy table: add secrets-engine and credential broker rows.
- Credential flow diagram: broker vs secrets-engine vs OpenBao proxy vs SSH issue.
- flex-auth: caller-side policy gate shipped; production flip external (FLEX-WP-0007).
- Workload posture stewardship and coordination worker as steward capabilities.
- Evolution notes pointer to July gap analysis.
Acceptance:
- INTENT still describes direction, not implementation inventory.
- No contradiction with SCOPE 2026-07-01 boundary (ops-warden does not mint tokens).
**2026-07-01:** INTENT.md updated.
### T03 — Production integration coordination pack
```task
id: WARDEN-WP-0023-T03
status: done
priority: high
state_hub_task_id: "26f23798-494b-45fc-baa8-af27bdffa038"
```
Prepare operator/coordination artifacts for the two P1 external gaps:
1. **flex-auth production flip** — checklist in `wiki/PolicyGatedSigning.md` or a
short playbook section: prerequisites, `policy.enabled: true` steps, rollback,
joint smoke with `credential-exec-ops-warden-smoke`, FLEX-WP-0007 cross-link.
2. **ops-bridge live cutover** — evidence template (non-secret): tunnel id, readiness
gate output, first warden-signed connection timestamp, pointer to
`wiki/playbooks/ops-bridge-tunnel-cert.md`.
Optionally post State Hub coordination messages to `flex-auth` and `ops-bridge`
agents with pointers only (no secrets).
Acceptance:
- A human operator can run the flip/cutover checklists without re-deriving steps.
- Evidence fields are defined; completion is recorded via State Hub progress when done.
**2026-07-01:** Rollback section added to `wiki/PolicyGatedSigning.md`; live cutover
evidence template added to `wiki/playbooks/ops-bridge-tunnel-cert.md`.
### T04 — `warden sign` broker hint when `VAULT_TOKEN` unset
```task
id: WARDEN-WP-0023-T04
status: done
priority: medium
state_hub_task_id: "85e324f9-273d-4740-a202-9c4e8fb122ae"
```
When `backend: vault` and `VAULT_TOKEN` (or configured `token_env`) is missing,
emit a structured hint pointing at `ops-warden-warden-sign-token` and the
`railiance-platform` `credential exec` command — not a generic error only.
Acceptance:
- Unit test covers the hint text (catalog id + exec shape, no secret placeholders).
- Manual `export VAULT_TOKEN` remains documented as fallback in playbooks.
**2026-07-01:** `src/warden/vault_hints.py` + `tests/test_vault.py`.
### T05 — Catalog draft-lane promotion checklist
```task
id: WARDEN-WP-0023-T05
status: done
priority: medium
state_hub_task_id: "82608692-2845-41e1-a498-90ed53780748"
```
Document the promotion criteria for `registry/routing/catalog.yaml` entries from
`draft` → `active` (concrete path, owner confirmation, `resolvable` or
`exec_owner` native exec, playbook with `#worker-checklist`, tests). Add to
`wiki/CredentialRouting.md` or a short `wiki/playbooks/catalog-lane-promotion.md`.
If any draft lane has owner-confirmed concrete paths during this WP, promote one
as a worked example (issue-core, OpenRouter, STS, or database — whichever is ready).
Acceptance:
- Checklist is reviewable by humans and agents.
- At least one promotion example or explicit “none ready yet” note in the workplan.
**2026-07-01:** `wiki/playbooks/catalog-lane-promotion.md` — worked example
`ops-warden-warden-sign-token`; four draft lanes explicitly not ready.
### T06 — SCOPE and workplan consistency
```task
id: WARDEN-WP-0023-T06
status: done
priority: medium
state_hub_task_id: "79ca7b9a-554e-4952-9393-a29b100f6190"
```
Fix SCOPE inconsistencies noted in the July assessment:
- “All workplans finished” → acknowledge WP-0022/0023 as active/ready.
- Latest gap analysis pointer → `history/2026-07-01-intent-scope-gap-analysis.md`.
- Link WP-0023 from Getting Oriented.
Acceptance:
- SCOPE and gap analysis cross-link correctly.
- Uncommitted SCOPE edits from 2026-07-01 broker routing are committed with this WP.
**2026-07-01:** SCOPE.md updated.
### T07 — Sequence WP-0022 audit implementation
```task
id: WARDEN-WP-0023-T07
status: done
priority: high
state_hub_task_id: "1f3b3b33-974e-49bf-be4a-9d50b702c2a4"
```
Promote `WARDEN-WP-0022` from `proposed` to `ready` (or `active` when T02–T06 allow
bandwidth). Ensure dependency is explicit; log State Hub note that WP-0022 is the
implementation vehicle for INTENT pillar 6 (observable gatekeeping).
Acceptance:
- WP-0022 frontmatter status updated.
- WP-0023 `depends_on_workplans` includes WP-0022.
- Hub consistency run syncs both workplans.
**2026-07-01:** WP-0022 implemented and both workplans marked `finished`.
---
## Exit criteria
- July gap analysis is the canonical reassessment (linked from SCOPE).
- INTENT.md no longer understates assist, posture, worker, or owner-native exec.
- Production integration checklists exist for flex-auth flip and ops-bridge cutover.
- `warden sign` surfaces the broker path when vault backend lacks a token.
- Catalog promotion cadence is documented; WP-0022 is queued for implementation.
## See also
- `history/2026-07-01-intent-scope-gap-analysis.md`
- `WARDEN-WP-0022-audit-trail-and-activity.md`
- `wiki/playbooks/ops-warden-warden-sign-token.md`
- `~/flex-auth/workplans/FLEX-WP-0007-ops-warden-policy-gate-production-deployment.md`

View file

@ -0,0 +1,269 @@
---
id: WARDEN-WP-0024
type: workplan
title: "Experiential Memory Across Worker, Agent Sessions, And OpenRouter"
domain: infotech
repo: ops-warden
status: finished
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 24
created: "2026-07-02"
updated: "2026-07-02"
state_hub_workstream_id: "5d9fafb3-f9b6-43bf-b259-5f5301daa2e9"
---
# WARDEN-WP-0024 — Experiential memory across worker, agent sessions, and OpenRouter
## Problem
`warden worker` (WARDEN-WP-0020) plans each inbox message in isolation. Coding
agent sessions (Claude Code, Codex, Grok, and future agents) invoke `warden
route` and `warden access` without continuity — every session rediscovers routing
from scratch. OpenRouter inference via llm-connect is invoked even when a
stabilized routing pattern already exists.
ops-warden needs **experiential memory** that is present in every runtime:
| Surface | Today | Target |
| --- | --- | --- |
| `warden worker` + OpenRouter | Stateless per message | Retrieve past outcomes before plan; record after execute |
| Coding agent session | Cold `warden route find` | Activate relevant memory at session start and after each warden call |
| Operator CLI | No learning loop | Same store; optional `--memory` context on advisory commands |
## Goal
Integrate phase-memory as ops-warden's shared experiential substrate so routing,
coordination, and inference improve from recorded outcomes — without ever
storing secret values or widening the guardrail allowlist.
## Non-Goals
- Hold or vend secrets (conduit-not-broker unchanged).
- Auto-commit routing catalog diffs (human review remains required).
- Own phase-memory schemas (PMEM-WP-0016 owns the profile and contract).
- Replace llm-connect or embed OpenRouter keys in ops-warden.
## Guardrails (unchanged — memory is untrusted context)
1. Retrieved memory is **context**, not instructions — fixed charter wins.
2. Guardrail allowlist enforced on every action regardless of memory content.
3. No secret values in memory writes, activation packs, or llm-connect prompts.
4. `propose_catalog_diff` stays human-reviewed even when memory is confident.
## Architecture
```mermaid
sequenceDiagram
participant Agent as Coding agent<br/>(claude/codex/grok)
participant Warden as ops-warden CLI
participant Memory as phase-memory store
participant LLM as llm-connect / OpenRouter
participant Hub as State Hub
Note over Agent,Hub: Agent session path
Agent->>Warden: warden route find "..."
Warden->>Memory: activate(session_kind=warden.agent.grok)
Memory-->>Warden: bounded routing context
Warden-->>Agent: route answer + memory digest
Warden->>Memory: record episode (metadata only)
Note over Warden,Hub: Worker tick path
Warden->>Hub: unread messages
Warden->>Memory: activate(session_kind=warden.worker)
Memory-->>Warden: stabilized + fluid context
alt stabilized match
Warden->>Warden: RuleBrain (skip LLM)
else ambiguous
Warden->>LLM: LlmConnectBrain + activated context
LLM-->>Warden: action plan
end
Warden->>Warden: guardrail pass
Warden->>Hub: execute / escalate
Warden->>Memory: record outcome
```
## T01 - Canonical memory store and discovery
```task
id: WARDEN-WP-0024-T01
status: done
priority: high
state_hub_task_id: "6305f1bc-c016-4298-adc2-a07d52b6aca5"
```
Establish the canonical phase-memory store path and discovery commands.
Acceptance:
- Default store at XDG location (e.g. `~/.local/share/warden/memory/`) with
override via `WARDEN_MEMORY_STORE`.
- `warden memory status` reports store path, schema version, episode counts by
`session_kind`, and last activation timestamp — no secret fields.
- Store initializes idempotently; missing phase-memory dependency fails with a
clear install pointer, not a traceback.
- Tests cover default path, override, and first-run initialization.
## T02 - Session recording hooks in CLI commands
```task
id: WARDEN-WP-0024-T02
status: done
priority: high
state_hub_task_id: "242a4d9a-5375-4df8-8d43-063b0491d202"
```
Record metadata-only episodes when `route`, `access`, and `sign` complete.
Acceptance:
- Each command writes a phase-memory event with `session_kind` derived from
environment: `WARDEN_AGENT_ID` (claude|codex|grok|...) when set, else
`warden.operator`.
- Recorded fields match `PMEM-WP-0016-T03` schema; secret patterns are rejected.
- Recording is opt-out via `WARDEN_MEMORY=0` for air-gapped/debug use.
- `warden activity` and phase-memory audit export remain consistent (no
duplicate secret-bearing logs).
## T03 - Memory-aware worker tick
```task
id: WARDEN-WP-0024-T03
status: done
priority: high
state_hub_task_id: "176fcae1-e4e5-481f-9a83-e9a7000fac1a"
```
Retrieve coordination memory before `Brain.plan` and record outcomes after execute.
Acceptance:
- `warden worker run` activates memory with `session_kind=warden.worker` before
planning each message.
- Activated context is passed to `LlmConnectBrain` as bounded, redacted context
— never replacing the fixed charter.
- Post-execute hook records: message id, proposed actions, guardrail outcome,
escalation reason, and route ids referenced.
- Worker tick with empty store degrades gracefully (current behavior).
## T04 - Agent session activation helper
```task
id: WARDEN-WP-0024-T04
status: done
priority: high
state_hub_task_id: "16501557-6cde-44ea-bc6f-1726cb7ec070"
```
Expose memory activation for coding agent sessions across Claude, Codex, Grok, and
future agents.
Acceptance:
- `warden memory activate [--agent <id>] [--json]` returns a bounded activation
package for session orientation.
- Agent instructions (AGENTS.md template in consuming repos) document setting
`WARDEN_AGENT_ID` and calling `warden memory activate` at session start.
- Activation works without OpenRouter (local retrieval only).
- Tests cover agent ids: `claude`, `codex`, `grok`, and an unknown future id.
## T05 - Cross-runtime continuity
```task
id: WARDEN-WP-0024-T05
status: done
priority: high
state_hub_task_id: "55ae679c-c08f-4afd-8646-9f5f3019f86e"
```
Ensure worker ticks see agent session episodes and vice versa.
Acceptance:
- Agent session routing outcomes appear in worker activation within the same
store without manual export/import.
- Worker escalation outcomes are visible to subsequent agent session activations.
- Continuity is verified by an integration test: agent session write → worker
read → agent session read round-trip.
- Episode retention follows the ops-warden profile compaction rules from
PMEM-WP-0016.
## T06 - OpenRouter efficiency layer
```task
id: WARDEN-WP-0024-T06
status: done
priority: medium
state_hub_task_id: "fc2dffcf-7184-4f3d-8653-d26dc18a9afc"
```
Skip or downgrade OpenRouter calls when stabilized memory provides a verified match.
Acceptance:
- When stabilized memory contains a verified route match for the message need,
`RuleBrain` handles the plan and llm-connect is not called.
- Ambiguous cases still use `LlmConnectBrain`; memory context is additive only.
- Efficiency metrics (llm_calls_avoided, rule_brain_resolution_rate) are
recorded for evaluation scenarios in PMEM-WP-0016.
- Dry-run mode reports whether LLM would have been skipped and why.
## T07 - Operator and agent documentation
```task
id: WARDEN-WP-0024-T07
status: done
priority: medium
state_hub_task_id: "ca2aaf23-833f-49a6-a49b-a0b659208f5f"
```
Document the memory workflow for operators and coding agents.
Acceptance:
- Wiki page covers: store location, session kinds, agent env vars, memory
activation at session start, and interaction with OpenRouter inference.
- ops-warden AGENTS.md and the state-hub agent template include memory
orientation steps for Claude, Codex, and Grok sessions.
- Credential routing doc cross-links PMEM-WP-0016 contract; anti-patterns
updated (no secret values in memory store).
- Scheduled worker playbook notes memory retention and evaluation gate checks.
## Acceptance Criteria
- phase-memory is present and useful in all three runtime surfaces (worker,
agent session, operator CLI) through one canonical store.
- OpenRouter inference cost decreases when stabilized routing memory matches.
- Cross-runtime continuity is tested and regression-gated.
- Security invariants (no-secret, allowlist, conduit-not-broker) are unchanged.
## Dependencies
- `PMEM-WP-0016` (phase-memory) — profile, event schema, activation pack,
evaluation scenarios. **Implement contract (T01–T03) before WARDEN T03–T05.**
- `WARDEN-WP-0020` — worker brain and guardrails (finished).
- `WARDEN-WP-0022` — audit trail for correlation (finished).
- llm-connect / OpenRouter — required only for T06 live efficiency measurement;
T01–T05 work offline.
## Suggested Implementation Order
1. PMEM-WP-0016 T01–T03 (profile + contract + event schema)
2. WARDEN-WP-0024 T01–T02 (store + CLI recording)
3. PMEM-WP-0016 T04 (activation pack)
4. WARDEN-WP-0024 T03–T05 (worker + agent activation + continuity)
5. PMEM-WP-0016 T05–T06 + WARDEN-WP-0024 T06–T07 (evaluation + docs)
## Closure Review
Integrated phase-memory across all ops-warden runtime surfaces:
- `warden memory status` and `warden memory activate` with canonical XDG store.
- CLI recording hooks on `route find`, `access`, and `sign` (opt-out via
`WARDEN_MEMORY=0`).
- Memory-aware worker planning with stabilized-route RuleBrain short-circuit
and LlmConnectBrain context injection.
- Cross-runtime continuity verified in tests (agent session → worker activation).
- `wiki/OpsWardenMemory.md` and AGENTS.md session orientation for Claude,
Codex, Grok, and future agents.

View file

@ -0,0 +1,118 @@
---
id: WARDEN-WP-0025
type: workplan
title: "Forgejo admin PAT OpenBao lane (CCR-2026-0006)"
domain: infotech
repo: ops-warden
status: finished
owner: grok
topic_slug: custodian
planning_priority: high
planning_order: 25
created: "2026-07-12"
updated: "2026-07-13"
state_hub_workstream_id: "70c11222-d8e7-5936-99f7-7d626a4a5deb"
---
# WARDEN-WP-0025 — Forgejo admin PAT OpenBao lane
**Trigger:** the-custodian CCR request (msg `54125f84`) — establish OpenBao custody
for the Forgejo site-admin PAT at `platform/workloads/forgejo/forgejo-admin`.
Drivers: `ACTIVITY-WP-0020` weekly package prune and railiance-apps/platform tools
still using `/tmp/forgejo-tegwick-api-token` or `FORGEJO_ADMIN_TOKEN`.
**Boundary:** ops-warden holds no PAT; workstation OIDC fetch mirrors
`railiance-backup-offsite-lane` (CCR-2026-0004). Distinct from `forgejo-mailer`
(SMTP via ESO). Phase 1: no cluster ExternalSecret.
**Depends on:** platform-operator approval of CCR-2026-0006; attended PAT mint.
---
## Tasks
### T1 — Draft CCR + policy metadata
```task
id: WARDEN-WP-0025-T01
status: done
priority: high
state_hub_task_id: "2c288bf0-b39c-5f5b-ad25-eed3da826dc3"
```
- [x] `CCR-2026-0006-forgejo-admin-api-token-lane.yaml` (`status: proposed`)
- [x] `openbao/policies/workload-kv-read-forgejo-admin.hcl`
- [x] `docs/workload-kv-access-lanes.md` section
### T2 — ops-warden catalog + playbook
```task
id: WARDEN-WP-0025-T02
status: done
priority: high
state_hub_task_id: "01b81595-f9e5-5746-b0dd-2075189cb00e"
```
- [x] Catalog entry `forgejo-admin-api-token` (`status: draft`)
- [x] `wiki/playbooks/forgejo-admin-api-token.md`
### T3 — Platform-operator approval + metadata apply
```task
id: WARDEN-WP-0025-T03
status: done
priority: high
state_hub_task_id: "279b74d7-3240-5ca0-897d-b1ddffd23c4e"
```
- [x] CCR approved by platform-operator (bernd.worsch, 2026-07-12)
- [x] `scripts/credential-change.py applier-dry-run CCR-2026-0006`
- [x] Policy `workload-kv-read-forgejo-admin` + OIDC role `forgejo-admin-workload-kv-read` applied on `bao.coulomb.social`
- [x] Non-secret `delegated_metadata_apply` evidence on CCR
### T4 — Attended PAT provision + verification
```task
id: WARDEN-WP-0025-T04
status: done
priority: high
state_hub_task_id: "4e21232c-62a1-5115-acce-edfbcfa84e48"
```
- [x] Mint PAT as Forgejo user `tegwick` (attended, 2026-07-12)
- [x] Stored at `platform/workloads/forgejo/forgejo-admin`, field `API_TOKEN`
(initial provision used field `Token`; re-stored as `API_TOKEN` 2026-07-13 to
match CCR/catalog/playbook `fetch_command`)
- [x] Positive fetch verified 2026-07-13 — `bao kv get -field=API_TOKEN …` returns
non-empty; PAT valid against `forgejo.coulomb.social` (`/api/v1/user` →
`login=tegwick`, `is_admin=true`)
- [x] Negative default-policy denial recorded on CCR
- [x] Promoted catalog `forgejo-admin-api-token` to `active` (`resolvable: true`)
### T5 — Notify downstream consumers
```task
id: WARDEN-WP-0025-T05
status: done
priority: medium
state_hub_task_id: "f8c7c70b-b9b6-5980-a25b-7f11033b81a2"
```
- [x] Ack the-custodian with CCR id + catalog id (no secret values) — msg 949e8ed1, 2026-07-13
- [x] Signal railiance-platform / activity-core / railiance-apps to wire `load_token()`
OpenBao paths — msgs 5be8e500 / 9ed1af98 / 2e47b6e5, 2026-07-13
---
## Acceptance
- CCR-2026-0006 approved, policy + OIDC role live, PAT in OpenBao
- `warden route find "forgejo admin pat"` → `forgejo-admin-api-token`
- No PAT in Git, State Hub, workplans, logs, or chat
- Workstation file drop retired as steady-state path after downstream wiring
## See also
- `railiance-platform/credential-change-requests/CCR-2026-0006-forgejo-admin-api-token-lane.yaml`
- `activity-core/workplans/ACTIVITY-WP-0020-weekly-forgejo-package-prune.md`
- Custodian message `54125f84-e9df-4fa0-9309-7370633a20d3`

View file

@ -0,0 +1,261 @@
---
id: WARDEN-WP-0026
type: workplan
title: "Credential disclosure hygiene + rotation guidance (Strand A)"
domain: infotech
repo: ops-warden
status: finished
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 26
created: "2026-07-16"
updated: "2026-07-16"
state_hub_workstream_id: "331c7620-bd34-5acd-9135-591985b568e5"
---
# Credential disclosure hygiene + rotation guidance (Strand A)
## Origin
Follow-up to a credential-disclosure incident on 2026-07-16 while verifying
`CCR-2026-0004` (railiance offsite backup lane). A negative policy test was run
as `BAO_TOKEN=$(bao token create -policy=default -field=token) bao kv get <path>`.
The `token create` was denied (workload role lacks it), `BAO_TOKEN` fell back to
the caller's privileged login token, and `bao kv get` printed all three field
values (`NC_WEBDAV_TOKEN`, `NC_WEBDAV_URL`, `AGE_PRIVATE_KEY`) into an agent
session transcript. Buildup mode — exposure accepted, learnings captured.
**Root causes:** (1) a deny-test that read the secret *data* path at all;
(2) a silent privileged-token fallback; (3) the read landed in a logged context.
This is **Strand A** (disclosure hygiene). Tamper-resistant policy governance and
one-command mass rotation/lockdown (Strand B) are deliberately **deferred** — see
"Out of scope" below.
## Goal
Make accidental secret disclosure structurally hard, and make ops-warden the
authoritative source for **how each secret is rotated or re-established** —
advisory knowledge held next to the routing catalog, not in OpenBao.
## Design guardrails (binding on acceptance)
- **Verification never reads secret data.** Use `bao token capabilities` (allow/deny)
instead of `kv get` for positive/negative lane tests.
- **Masking is defense-in-depth, not a boundary.** Any display filter is a wrapper
convenience; raw `bao kv get <path>` remains the documented anti-pattern.
- **Rotation guidance covers both `rotate` (provider re-mint) and `re-establish`
(regenerate from source, e.g. a new age keypair).**
- **Coverage gate:** every `active` (and newly promoted) catalog lane must carry
rotation guidance, enforced by a scorecard check.
## Out of scope (Strand B — deferred, not built here)
- Executable one-command rotation of all tainted secrets.
- Graded lockdown / break-glass seal + re-key with a designed trust-root.
- Policy time-travel / policy-as-code reconcile-to-past-commit. (Drift *detection*
may be revisited separately; the reconcile machinery is out.)
## Task: Capabilities-based lane verification
```task
id: WARDEN-WP-0026-T01
status: done
priority: high
state_hub_task_id: "1cb22a40-b7c6-560a-a805-7766a5786dcc"
```
Done 2026-07-16: canonical capabilities-safe verification pattern added to
`wiki/playbooks/catalog-lane-promotion.md` (fleet promotion checklist criterion 8
+ dedicated section), and applied to the `railiance-backup-offsite-lane` and
`forgejo-admin-api-token` playbook verify sections. Positive/negative proven via
`bao token capabilities` against the KV v2 data path — never `bao kv get`; the
denied `default` token-create is documented as a pass, not a fallback trigger.
Live CCR-2026-0004 re-verify carried under T07.
Replace secret-reading verify flows with capability checks. Positive test:
approved identity has `read` on the KV data path. Negative test: a `default`-only
identity is `deny`. Both via `bao token capabilities <token> <path>` (or the
self endpoint) — **never** `bao kv get`. Update
`wiki/playbooks/*lane*.md` verify sections and any lane-verify helper.
**Done when:** the documented and tooled verify path for any lane proves
allow/deny without reading a secret value, and the CCR-2026-0004 re-verify uses
it (see T07).
## Task: Safe access transport (no stdout values)
```task
id: WARDEN-WP-0026-T02
status: done
priority: high
state_hub_task_id: "bcb7da96-0a28-5484-bf3e-06e97acf5873"
```
Done 2026-07-16: sanctioned transports added to `warden access` so a value never
lands on stdout — `--out FILE` (mode-0600 file), `--exec` (child env, pre-existing),
and `--wrap` (single-use OpenBao response-wrapping token via `bao kv get -wrap-ttl`,
caller `bao unwrap`s in their own context). Raw `--fetch` to a non-TTY stdout is now
refused (exit 6) unless `--unsafe-stdout` is passed (interactive human only).
`proxy_fetch_to_file`/`proxy_fetch_wrapped`/`build_wrapped_fetch` in `proxy.py`; tests
in `tests/test_proxy.py`. Anti-pattern + transports documented fleet-wide in
`.claude/rules/credential-routing.md` and `wiki/OperatorAccessAssist.md` (G2).
`warden access` / fetch paths must emit values only into an env var, a file, or
a **response-wrapping token** (`bao … -wrap-ttl`), never a stdout table. Add a
wrapping-token transport for values that must move between processes. Record in
canon (`credential-routing` rules) that raw `bao kv get <path>` (full table) is
the anti-pattern; the sanctioned path is `warden access … --field <F>` into env.
**Done when:** the sanctioned fetch path cannot print a value to a terminal, and
the anti-pattern is documented fleet-wide.
## Task: Masking display filter (defense-in-depth)
```task
id: WARDEN-WP-0026-T03
status: done
priority: medium
state_hub_task_id: "d90b0628-fa1d-527d-99c3-28a7ed933e52"
```
Done 2026-07-16: `warden/mask.py` (`fingerprint`/`mask_value` — presence, length,
8-char sha256 prefix; never the value) + `proxy_fetch_fingerprint` and a
`warden access … --fingerprint` masked status view (bypasses the stdout guard
because it emits no value). Lets two parties compare sha256 prefixes to confirm a
shared value (e.g. rotation landed) without disclosure. Explicitly labelled
defense-in-depth — raw `bao kv get` bypasses it — in `wiki/OperatorAccessAssist.md`
and the module docstring. Tests in `tests/test_mask.py` + a CLI test in
`tests/test_proxy.py`.
In the warden wrapper, mask KV data values by default when any listing/status is
shown — display presence, length, and a short non-reversible hash instead of the
value. Explicitly labelled as defense-in-depth (raw bao bypasses it).
**Done when:** wrapper-mediated output never shows a raw KV value, with the
limitation documented.
## Task: Agent read-boundary on high-risk lanes
```task
id: WARDEN-WP-0026-T04
status: done
priority: high
state_hub_task_id: "827fa67d-5f69-5fac-bdce-9903b1b909fb"
```
Done 2026-07-16: Catalog `risk: high|standard` (default standard). High-risk:
`railiance-backup-offsite-lane`, `forgejo-admin-api-token`, `openrouter-llm-connect`.
OpenBao policy `agent-high-risk-boundary` (railiance-platform + live write) grants
metadata/capabilities only and **denies** data-read on those paths — verified with
minted agent token (data=deny, metadata=read). `warden access` with
`WARDEN_AGENT_ID` set refuses raw value stream on high-risk lanes (exit 7);
`--out`/`--exec`/`--wrap`/`--fingerprint` remain. Playbook:
`wiki/playbooks/agent-read-boundary.md`. Tests in `tests/test_routing.py` +
`tests/test_proxy.py`.
**Repo: railiance-platform (OpenBao policy/roles).** Agent identities receive
`capabilities`/metadata and wrapping tokens on high-risk lanes, not raw data
reads. Align with the existing credential-routing rule ("ops-warden proxies reads
as the caller and must not retain values"). Classify which lanes are high-risk
(recovery escrow like `AGE_PRIVATE_KEY`, upload tokens).
**Done when:** at least the high-risk lanes deny raw data reads to agent roles
while still allowing wrapped/proxied access, verified via capabilities checks.
## Task: EXPOSED taint convention
```task
id: WARDEN-WP-0026-T05
status: done
priority: medium
state_hub_task_id: "09ef8727-31da-59ac-aac7-2d47924569fe"
```
Done 2026-07-16: Convention documented in `wiki/playbooks/exposed-taint.md`
(`exposed_at`, `exposed_version`, `exposed_reason`, `exposed_ref` on KV v2
custom_metadata). First worked mark applied to
`platform/workloads/railiance/backup/offsite-lane` version 2 (disclosure
incident). `warden taint <id>` (+ `--json`) reports taint via metadata-only
`bao kv metadata get` — never secret data (`src/warden/taint.py`). Tests in
`tests/test_taint.py`.
**Repo: railiance-platform (OpenBao) + ops-warden surface.** Establish a KV v2
`custom_metadata` convention to mark a tainted secret: `exposed_at=<datetime>`
and the affected `version`. Identify semi-automatic candidates from the OpenBao
audit log (reads from agent/shared contexts). `warden` surfaces taint status for
a lane (advisory; no auto-rotation here).
**Done when:** a secret can be marked EXPOSED via a documented convention and
`warden` reports whether a lane is currently tainted.
## Task: Rotation / re-establishment guidance registry
```task
id: WARDEN-WP-0026-T06
status: done
priority: high
state_hub_task_id: "a2e1544e-e501-57eb-a40e-9a2147cef12a"
```
Done 2026-07-16: `rotation:` block (method rotate|re-establish, ordered steps,
owner, automatable) added to the routing model/parser (`RotationGuide`,
`RouteEntry.rotation`, `vends_secret`), screened for secret material in a prose-safe
mode. `warden rotate-guide <id>` (human + `--json`) surfaces the guidance; `warden
route show --json` carries `has_rotation` + `rotation`. Coverage enforced by the new
`catalog_rotation_coverage` scorecard check (every active secret-vending lane must
have a block) and promotion checklist criterion 9. Rotation blocks authored for all
7 active vending lanes + the draft railiance-backup lane (re-establish example: age
keypair regen + re-encrypt). Tests in `tests/test_routing.py`. Also fixed a
pre-existing keyword collision (bare `npm` on the forgejo-admin lane → `forgejo-npm`)
so "npm token" routes to the generic lane again.
Give every catalog lane **structured-but-advisory** renewal guidance, held in the
ops-warden registry (not in OpenBao). Add a `rotation:` block per catalog entry
capturing: `method` (rotate | re-establish), ordered `steps` (provider re-mint /
keygen / OpenBao write / re-encrypt-and-reupload where relevant), `owner`, and
`automatable` (bool, for future Strand-B). Surface via `warden rotate-guide <id>`
(and/or `warden route … --rotate`). Add a **scorecard coverage check**: every
`active` lane must have a `rotation:` block; flag any that don't.
**Done when:** `warden rotate-guide <id>` returns actionable renewal steps for
every active lane, and the scorecard fails if any active lane lacks guidance.
## Task: Incident lessons + first worked lane (CCR-2026-0004)
```task
id: WARDEN-WP-0026-T07
status: done
priority: medium
state_hub_task_id: "62d8286f-7954-52a8-bce6-6a16072e5246"
```
Done 2026-07-16: Lessons note present. Capabilities-safe live re-verify on
`bao.coulomb.social`: lane-policy token → `read` on data path; default + agent
boundary → `deny`; field keys present (no values printed). Catalog promoted
`draft`→`active`, `fetch_command` pinned to `NC_WEBDAV_TOKEN` (no placeholders)
so `resolvable: true`; `risk: high`; rotation guidance + EXPOSED taint on v2.
CCR-2026-0004 evidence + `access_frontdoor.resolvable: true` / `readiness: ready`.
Playbook + `wiki/CredentialRouting.md` updated. Operator may still rotate the
exposed values optionally (buildup) — not a promotion blocker.
Write a short lessons-learned note (buildup context; exposure accepted; the three
root causes). Apply T01 + T06 to `CCR-2026-0004` as the first worked lane:
re-verify it the capabilities-safe way so it can finally promote to
`resolvable: true` (unblocking `RAILIANCE-WP-0015`), and ensure its `rotation:`
block (rotate Nextcloud token; re-establish age keypair + re-encrypt artifacts)
is present. **Rotation of the exposed values is the operator's optional call, not
a blocker** (buildup).
**Done when:** the lessons note exists, CCR-2026-0004 has capabilities-based
verify + rotation guidance, and its promotion path is unblocked.
## References
- `CCR-2026-0004-railiance-backup-offsite-lane.yaml` (railiance-platform)
- `wiki/playbooks/railiance-backup-offsite-lane.md`
- `.claude/rules/credential-routing.md` (the-custodian, fleet-inlined)
- `RAILIANCE-WP-0015` (railiance-apps) — cnpg backup coverage, gated on CCR-2026-0004
- Strand B (deferred): tamper-resistant governance, one-command rotation/lockdown,
policy time-travel — capture separately if/when justified.

View file

@ -0,0 +1,303 @@
---
id: WARDEN-WP-0027
type: workplan
title: "Tamper-resistant credential governance + mass rotation/lockdown (Strand B)"
domain: infotech
repo: ops-warden
status: blocked
flavor: implementation
owner: codex
topic_slug: custodian
planning_priority: medium
planning_order: 27
created: "2026-07-16"
updated: "2026-10-03"
state_hub_workstream_id: "21528e8d-a049-523d-9ae1-da7a27cb8bbf"
---
# Tamper-resistant credential governance + mass rotation/lockdown (Strand B)
## Origin
Explicitly deferred from `WARDEN-WP-0026` (credential disclosure hygiene, Strand A).
WP-0026 "Out of scope" carves out the heavyweight governance machinery and directs
that it be "capture[d] separately if/when justified." This workplan is that capture.
Strand A makes accidental disclosure structurally hard and gives every lane
**advisory** rotation guidance. Strand B is the **executable, tamper-resistant**
layer: turning that advisory guidance into one-command action and hardening policy
governance against silent drift or malicious change.
## Status: blocked on T02 (reviewed 2026-09-28)
Activated by the operator on 2026-08-22 after the second activation gate became
concrete. `RAILIANCE-WP-0024-T03` now requires an approved recovery window,
fresh encrypted Raft snapshot evidence, provider-console access, named abort
authority, and the live **2-of-3 Shamir quorum** before a coordinated reboot.
That is fleet policy requiring a designed break-glass path, not speculative
heavyweight machinery.
Activation is deliberately narrow. No mass-disclosure incident triggers T01,
and no fleet policy currently mandates T03's signed policy-manifest reconcile.
Those tasks remain `cancel`; cancellation here continues to mean deferred, not
abandoned. T02 alone was activated; it now waits on a fresh attended drill.
## Activation gate (promote to `ready` only when ≥1 holds)
- A real disclosure incident requires rotating **more than a couple** of secrets at
once, making manual per-lane rotation (Strand A) too slow.
- Fleet policy for OpenBao mandates tamper-evident policy governance or a designed
break-glass path.
- Audit/compliance requires provable "reconcile policy to a known-good commit."
## Goal
Make credential response **executable and trustworthy at fleet scale**: one command
rotates or re-establishes a set of tainted secrets; policy changes are tamper-evident
and reconcilable to a known-good state; a graded lockdown / break-glass path exists
with an explicit trust-root.
## Scope boundary (unchanged from Strand A)
ops-warden still **custodies no secret values**. Strand B orchestrates the owner's
tools (OpenBao, provider re-mint, railiance-platform credential broker) as the
caller — it does not hold or vend secrets. Rotation execution runs the owner-native
path; ops-warden sequences and verifies it.
## Task: Executable mass rotation driver
```task
id: WARDEN-WP-0027-T01
status: cancel
priority: high
state_hub_task_id: "b5691939-9d84-5115-9618-0f8839010d14"
```
Turn Strand A's per-lane `rotation:` guidance (WP-0026 T06) into an executable
driver: `warden rotate <id>` (single lane) and `warden rotate --tainted` (all lanes
marked EXPOSED per WP-0026 T05). Each step runs the owner-native command
(provider re-mint, `bao kv put`, re-encrypt+reupload for re-establish lanes) as the
caller, verifies via capabilities (never reads the value), and clears the
`exposed_at` taint on success. Dry-run first; idempotent; per-lane failure isolates.
**Done when:** a tainted set of lanes can be rotated/re-established with one command,
each verified capabilities-safe, taint cleared only on success.
**Depends on:** WP-0026 T05 (taint convention), T06 (rotation registry).
## Task: Graded lockdown / break-glass with explicit trust-root
```task
id: WARDEN-WP-0027-T02
status: todo
decision_id: 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa
priority: medium
state_hub_task_id: "cae498ee-6307-5d32-9f1b-a471cfcc2536"
```
2026-10-11: requalified after founder decision D3 (trust root, build-mode default) resolved — see the-custodian docs/decisions/2026-10-11-security-unblock-decisions.md.
Design and document a graded lockdown: (a) soft — deny agent roles read on all
high-risk lanes; (b) hard — seal + re-key with a pre-designed trust-root and quorum.
Define the trust-root (who holds unseal shares, recovery keys), the break-glass
invocation, and the re-entry path. **Design + runbook first**; any executable seal
step is opt-in and attended.
**Done when:** a documented, rehearsed break-glass path exists with a named
trust-root and quorum, and soft-lockdown is executable via capabilities-based
policy toggles.
**Parked input — the warden-sign AppRole (2026-08-11).** secrets-engine holds a
validated dry-run for a `warden-sign` AppRole (policy + role, `update` on
`ssh/sign/{agt,adm,atm}-role` only). It was **parked** rather than withdrawn
specifically because it is an input to this task: today the credential broker is the
only *autonomous* path to a signing token, so if its issuer lapses, recovery is a
founder OIDC act. Whether a second autonomous path should exist — and whether it is
the AppRole or something this trust-root design supersedes — is a break-glass
question, not a routing one. Resolve it here. Context and the counter-argument
(AppRole is narrower in capability than placing the broker's issuer token on a remote
host) are in `workplans/ADHOC-2026-08-11.md` T03 (ad-hoc **finished** 2026-08-15;
question lives here now); secrets-engine was told to stop holding apply
readiness until this task or the ops-bridge cutover fires (msg `863c7b57`).
**Rebaselined 2026-08-22.** The July description predates the authoritative
OpenBao migration. The current barrier is a rotated **2-of-3**, not the
aspirational 3-of-5 value still present in ops-warden's legacy posture
descriptor. `RMASTER-WP-0020` records two attended restart/unseal cycles on
2026-08-03 with shares supplied through hidden prompts, matching inventory,
audit continuity, exact-path read, and sibling denial. That is valid rehearsal
evidence for re-entry, but it is not misreported as a current production
emergency-seal drill.
The soft half is also already live: `RAILIANCE-WP-0022` reports total concrete
high-risk path coverage and a dedicated coding-agent AppRole proving deny-wins
without reading a secret value. ops-warden consumes that owner control through
`scripts/check_agent_read_boundary.py`; it does not take ownership of the live
OpenBao policy.
The consumer contract and remaining acceptance gate are now documented in
`docs/credential-governance-break-glass.md`. One attended production emergency
seal/unseal drill remains. It must use railiance-platform's evidence template
and validator, have snapshot/quorum/console/driver/abort receipts before the
seal hold point, and be executed by the platform owner—not by a coding agent.
**Parked AppRole disposition:** do not unpark the standalone `warden-sign`
AppRole for T02 break-glass. The normal broker remains autonomous; an issuer
failure deliberately crosses into attended OIDC and, below that, the 2-of-3
platform trust-root. A standing AppRole placed outside the broker would weaken
that boundary and still would not recover a sealed OpenBao. A separately
approved ops-bridge unattended-signing design may re-evaluate the narrow
AppRole under its own workplan; that is service access, not recovery authority.
**Read-only readiness 2026-08-22.** The owner `node-reboot` preflight passed
every automated check without observing a secret value: node/k3s, platform-pg
and continuous archiving, a 16.37-hour successful backup, initialized/unsealed
OpenBao with `shares=3` and `threshold=2`, ESO stores/projections, and the
reviewed audit-core digest were healthy. `ready_for_live_execution` correctly
remained false because no approved window, current encrypted off-host snapshot
receipt, provider-console attestation, quorum attestation, owner-ack flag, or
named abort operator was supplied.
That preflight also exposed a Warden safety defect: the ceremony request matched
the generic `openbao-api-key` template and proposed paste-once provisioning.
`openbao-shamir-recovery-ceremony` now distinguishes the owner-operated approval
ceremony from secret retrieval. It is a non-value-bearing pointer and can never
offer `--fetch`, `--exec`, `--out`, `--wrap`, or paste-once share transport.
**Scenario established 2026-08-22.** The operator delegated preparation to the
agent and reserved their involvement for the final GO/NO-GO. The bounded,
non-secret scenario is
`docs/evidence/WARDEN-WP-0027-T02-drill-scenario-2026-08-22.md`: ops-warden
coordinates and enforces the hold point; railiance-platform is the proposed
OpenBao driver; railiance-infra is the proposed independent console/abort owner;
and railiance-master is asked only for a metadata-only 2-of-3 availability
attestation. All three owner receipts and a green fully parameterized preflight
are required before the final operator question.
The railiance-infra role is scoped by the authoritative review contract
`WARDEN-WP-0027-T02-DRILL-20260822-01-INFRA` in
`interfaces/reviews/WARDEN-WP-0027-T02-DRILL-20260822-01-railiance-infra.json`.
It binds the exact scenario artifact and expiry, requires explicit independent
provider-console and distinct-abort attestations, permits metadata-only evidence,
and states `authorizes_execution: false`.
**Preparation approved 2026-08-22.** Decision
`9da57559-712a-4521-b46e-a4c69729f9d2` authorizes preparation only and narrows
the possible live scope to one intentional OpenBao seal followed by the existing
2-of-3 unseal ceremony. It excludes a host reboot, re-key, restore, policy
change, PVC mutation, credential disclosure, and general workload restart.
Railiance-infra satisfied its direct contract with receipt
`01a02b4b-7295-7836-b288-f29407008524`. The revisioned, non-authorizing gate
matrix is in
`docs/evidence/WARDEN-WP-0027-T02-drill-preparation-checklist-2026-08-22.md`;
platform snapshot/driver and master quorum contracts remain required before the
fully parameterized read-only preflight.
**Live attempt terminal NO-GO 2026-08-23.** All owner receipts and the final
read-only preflight became green, and the operator opened the exact bounded
window with decision `449a697a-5303-4582-aa9e-b0bc8b35ab2d`. The platform
driver stopped before seal when attended OIDC succeeded but the read-only agent
home prevented token-helper persistence and the underlying client emitted the
short-lived credential into captured output despite `-no-print`. The credential
was immediately self-revoked. Independent metadata confirmed OpenBao remained
initialized and unsealed with zero unseal progress; no seal, unseal, reboot,
restore, policy, PVC, or workload mutation occurred. NO-GO decision
`85724c0c-e70f-4e2f-a8c6-a9cb1ea6331b` supersedes and consumes the GO; the
scenario and its receipts cannot be reused.
The direct remediation interface is `RAILIANCE-WP-0026-T01`. Ops-warden commit
`0fae0904ce8d8694338dd53a8a79abec5fec788d` replaces the persistent login-only
handoff with a contained login-plus-reviewed-command envelope. It proves a
private writable helper before OIDC, captures login/child/revocation stdout and
stderr, fails closed on any output or persistence defect, self-revokes, and
removes the helper. No live OIDC was used for verification. The value-safe
owner receipt is
`docs/evidence/RAILIANCE-WP-0026-T01-ops-warden-receipt.json`; a future drill
requires owner acceptance, fresh receipts, a new scenario id, and a new human
decision.
**Containment review status 2026-08-23.** `railiance-infra` independently
accepted the exact implementation revision at its commit `186b030` and State
Hub message `7b2846dd-4b7c-4933-b61f-921e8ccf9ff2`, after rerunning the 42
focused tests and lint. Direct platform review request
`9a5f8973-0e74-4df2-8089-5a5bdc42295b` now carries the exact revision, receipt,
test results, and infra acceptance. T02 remains `progress` until
`railiance-platform` accepts or requests changes. No human GO is relevant while
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.
2026-10-03: human gate routed to hub decision 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa (D3: Trust root and secret custody: unseal/recovery holders, break-glass, and the deferred rotation of exposed material) by CUST-WP-0075; resolving that decision raises C-40 here.
## Task: Tamper-evident policy governance + reconcile
```task
id: WARDEN-WP-0027-T03
status: cancel
priority: medium
state_hub_task_id: "7dbedcdc-dd5a-551c-bff1-0702fea0a9cf"
```
Policy-as-code for OpenBao policies/roles with tamper-evidence: a signed/hashed
manifest of the intended policy set, drift **detection** against live OpenBao, and a
reconcile-to-known-good-commit path. (Drift detection may land independently even if
full reconcile stays gated.) Coordinate ownership with railiance-platform (OpenBao
deployment) — ops-warden contributes the ops-access policy surface, not the cluster.
**Done when:** live OpenBao policy state is diffable against a signed known-good
manifest, and an attended reconcile can restore it.
**Cross-repo:** railiance-platform (OpenBao cluster + policy custody).
## References
- `WARDEN-WP-0026` — Strand A (disclosure hygiene, advisory rotation) — prerequisite
- `.claude/rules/credential-routing.md` — ops-warden custodies no secret values
- `railiance-platform` — OpenBao cluster, policy custody, credential broker
- `wiki/AccessRouting.md` — issue vs route vs assist boundary
- `workplans/ADHOC-2026-08-11.md` T03 — parked warden-sign AppRole (ad-hoc finished
2026-08-15); T02 resolves it as unsuitable for break-glass, while a separately
approved ops-bridge unattended-signing design may still re-evaluate it
cert_command cutover
- `secrets-engine` `SECRETS-WP-0004` — the parked AppRole apply/handoff
### 2026-09-28 loose-end review
T02 now waits and the workplan is blocked. Source containment acceptance is
already complete in railiance-platform's archived RPF-WP-0017; it is not a live
drill receipt. The terminal August scenario remains consumed. Completion still
requires a fresh platform-driven attended emergency seal/unseal scenario, fresh
platform/infra/master receipts and a new founder GO. The cancelled T01/T03 stay
cancelled. No ceremony, rotation or production mutation was performed.

View file

@ -0,0 +1,421 @@
---
id: WARDEN-WP-0028
type: workplan
title: "Tenant secret custody — NetKingdom pattern for client/tenant secrets"
domain: infotech
repo: ops-warden
status: finished
owner: grok
topic_slug: custodian
planning_priority: high
planning_order: 28
created: "2026-07-16"
updated: "2026-07-17"
state_hub_workstream_id: "6b66228a-199a-5b85-b5e2-a7afeaab903b"
---
# WARDEN-WP-0028 — Tenant secret custody (NetKingdom pattern)
## Origin
Founder establishing **binky-control** as the control-plane repo for a Coulomb
client/tenant (Binky-Hedgehog GmbH). Immediate need: store **tenant-specific**
secrets in OpenBao (e.g. company mailbox usernames/passwords for IMAP scan) and
consume them safely via email-connect / agents **without** putting values in
git, State Hub, chat, or workplans.
BINKY-WP-0003-T01 prepared a draft plan
(`binky-control/integrations/company-email-openbao.md`) that targeted
`secret/prod/binky/...` via secrets-engine. That draft is directionally right on
*workflow*, but it does not match a production-ready custody layout on
`bao.coulomb.social`. This workplan resolves the NetKingdom layout and makes
**tenant** secrets first-class — **separate from** platform workload lanes
(`platform/workloads/...`).
## Goal
Define and land a **repeatable, multi-tenant-safe** pattern for:
1. Where tenant secrets live in OpenBao (path + mount convention)
2. Who owns policy, CCR, catalog, and front door
3. How agents and workloads obtain values (sanctioned transports only)
4. First concrete lane: **binky company email IMAP** (unblocks real-world event
intake for binky-control)
## Architectural facts (as of 2026-07-16)
### Planes (ADR-0006)
| Plane | Role | Example |
| --- | --- | --- |
| Bootstrap | First trust / recovery | unseal, platform-root |
| Platform control | Shared identity, secrets, authz | OpenBao, key-cape, flex-auth, railiance-platform |
| Tenant | Scoped client/workload authority | coulomb products, **binky**, future clients |
**Binky is a tenant**, not platform-root. Tenant secrets must not require
platform-admin for day-to-day read, and tenant operators must not gain
platform-root grants.
### OpenBao mounts (live + planned)
| Mount | Type | Role |
| --- | --- | --- |
| **`platform/`** | KV v2 | **Platform control-plane** secrets: `platform/workloads/...` (fleet CCRs, ESO) and `platform/operators/...` — *not* client/tenant commercial secrets |
| **`secret/`** | KV v2 | secrets-engine stage / pilot paths (`secret/coulomb/...`) — not the tenant home |
| **`tenants/`** | KV v2 (**new**) | **Client/tenant commercial secrets** — explicit multi-tenant namespace |
Live under `platform/workloads/` today: `activity-core/`, `coulomb/`, `forgejo/`,
`issue-core/`, `railiance/`, `reuse/`. Those stay where they are; we do **not**
migrate them into `tenants/` in this workplan.
### Dual front-door systems (both real; don't invent a third)
| Layer | Owns | Entry |
| --- | --- | --- |
| **OpenBao** | Custody, ACL, audit | `bao` CLI / API |
| **railiance-platform CCR** | Approved metadata apply (policy + OIDC role + evidence) | `credential-change-requests/CCR-*.yaml` |
| **ops-warden catalog** | Routing + `warden access` proxy (no custody) | `registry/routing/catalog.yaml` |
| **secrets-engine catalog** | Workflow: decision → plan → provision → exec delivery | `secrets-engine/catalog/*.yaml` |
**Binding rule (ops-warden):** never vend secret values; only route/proxy as the
caller. **Binding rule (WP-0026):** capabilities-safe verify; agents on
`risk: high` use `--out` / `--exec` / `--wrap` only.
### Why not bury tenants under `platform/workloads/`
Earlier draft of this workplan used `platform/workloads/<tenant>/...`. Founder
prefer a **shallower, explicit** namespace. That is sound:
- **No conflict with Vault/OpenBao best practice.** Separate mounts (or
top-level prefixes) for different security *domains* are common and good.
`platform/workloads` is an *internal fleet convention* for platform services,
not an industry mandate for every secret.
- **Clearer mental model:** platform plane vs tenant plane (ADR-0006) maps to
mount/prefix names operators can see at a glance.
- **Isolation:** ACLs, list boundaries, and future audit queries stay simpler
when tenant material is not mixed under the same path tree as forgejo/ESO
lanes.
### Decision (2026-07-17) — use dedicated mount `tenants/`
```text
mount: tenants # KV v2, enable once (platform-admin)
logical path: <tenant_slug>/<workload>/<bundle>
CLI: tenants/<tenant_slug>/<workload>/<bundle>
API data path: tenants/data/<tenant_slug>/<workload>/<bundle>
```
**Rejected alternatives (kept for archaeology only):**
| Option | Why not |
| --- | --- |
| `secret/prod/binky/...` | `secret/prod/` does not exist; stage model not ready as sole production path |
| `platform/workloads/binky/...` | Too deep; conflates tenant clients with platform workloads |
| `platform/tenants/binky/...` | Acceptable fallback if enabling a new mount is blocked; prefer full `tenants/` mount |
### Tooling debt to clear (not a reason to keep the deep path)
`railiance-platform/scripts/credential-change.py` currently hard-fails unless:
- `openbao.mount == "platform"`
- `openbao.kv_path` starts with `platform/workloads/`
That guard must be **extended** to allow `mount: tenants` and
`kv_path` under `tenants/` (T03). It is an implementation constraint, not a
security reason to force the deep path.
## Recommended path convention (tenant secrets)
```text
tenants/<tenant_slug>/<workload>/<bundle>
```
| Segment | Rules | Binky email example |
| --- | --- | --- |
| `tenant_slug` | Stable kebab slug; company/client id | `binky` |
| `workload` | Capability or system using the secret | `company-email` |
| `bundle` | Single purpose unit (one CCR / one policy) | `imap` |
Full CLI path:
```text
tenants/binky/company-email/imap
```
Suggested fields (names only — never values in git):
| Field | Purpose |
| --- | --- |
| `IMAP_USERNAME` | mailbox login (often the address) |
| `IMAP_PASSWORD` | app password / mailbox password |
| `IMAP_HOST` | optional if not fixed in consumer config |
| `IMAP_PORT` | optional (default 993 in config) |
Non-secret connection facts (provider host if stable) may live in
`binky-control` config / email-connect yaml as **env names + host**, not
passwords.
### Future multi-mailbox / multi-tenant
```text
tenants/<tenant>/mailbox/<mailbox_id>
# e.g. tenants/binky/mailbox/founder-primary
# tenants/acme/mailbox/billing
```
One CCR + one least-privilege policy **per bundle** (or per mailbox). Do not
grant `tenants/binky/*` list/read to agents — exact-path policies only.
### Risk class
Mailbox credentials and similar client secrets are **`risk: high`** (WP-0026
T04): agent identities get metadata/capabilities only; raw stream refused when
`WARDEN_AGENT_ID` is set.
## Ownership split
| Concern | Owner repo | Artifact |
| --- | --- | --- |
| Tenant business need, IMAP host facts, scan config, queues | **binky-control** | `integrations/*`, mailmeta (metadata only), activity defs |
| OpenBao path, policy HCL, OIDC role, CCR lifecycle | **railiance-platform** | `CCR-YYYY-NNNN-…yaml`, `openbao/policies/…` |
| Routing front door + rotation guidance | **ops-warden** | catalog entry, playbook, `warden access` / `rotate-guide` |
| Exec-time delivery workflow (optional same path) | **secrets-engine** | catalog entry pointing at `tenants/...` (same path; no second copy) |
| Identity groups for tenant operators | **net-kingdom / key-cape** | group e.g. `tenant-binky-operators` (near-term may use `net-kingdom-admins` for founder-only) |
| Mailbox scan consumer | **email-connect** | config with `username_env` / `password_env` only |
## Auth model (near-term vs target)
**Near-term (founder dogfood):** OIDC `netkingdom` role bound to
`groups=net-kingdom-admins` (same pattern as backup/forgejo lanes). Acceptable
while binky is founder-operated only.
**Target (real multi-tenant):**
- IAM group `tenant-binky-operators` (and later per-tenant groups)
- OpenBao OIDC role `binky-company-email-imap-workload-kv-read` bound only to
that group
- flex-auth check `secret.read:binky-company-email` if pre-approval required
- Agents **never** hold the workload-kv-read policy; use operator wrap / exec
injection / AppRole for email-connect scanner only
## First worked lane (deliverable sketch)
| Item | Value |
| --- | --- |
| Catalog id | `binky-company-email-imap` |
| CCR | `CCR-2026-0007` (next free) — title: Binky company email IMAP |
| Mount | `tenants` |
| KV path | `tenants/binky/company-email/imap` |
| Policy | `workload-kv-read-binky-company-email-imap` |
| OIDC role | `binky-company-email-imap-workload-kv-read` |
| Consumer | email-connect `scan-mailbox` via env inject |
| Front door | `warden access binky-company-email-imap --out FILE` or `--exec -- …` |
| Provision | **Red lane, founder once** — value via `bao kv put … @file` or secrets-engine provision; never chat |
## Out of scope
- Mass rotation / lockdown machinery (WARDEN-WP-0027 Strand B)
- Sending mail / SMTP from company address (separate lane if needed)
- Migrating all `secret/` mount lanes onto `platform/` (separate secrets-engine
/ railiance work)
- Full key-cape tenant group productization (may be a net-kingdom follow-on)
## Tasks
### T01 — Canon note: tenant secret path + ownership
```task
id: WARDEN-WP-0028-T01
status: done
priority: high
state_hub_task_id: "9982a884-7a50-593e-861e-cc8d2343a0ba"
```
Done 2026-07-17: `wiki/playbooks/tenant-secret-onboarding.md` + CredentialRouting
tenant paragraph; catalog-lane-promotion draft table updated.
Land a short ops-warden wiki page (and one paragraph in
`wiki/CredentialRouting.md`) that freezes:
- mount **`tenants`** + path `tenants/<tenant>/<workload>/<bundle>`
- ownership table (binky-control / railiance-platform / ops-warden / secrets-engine)
- link to WP-0026 hygiene (capabilities verify, high-risk, taint)
- **do not** put new client/tenant commercial secrets under
`platform/workloads/` or invent `secret/prod/...` as the production home
**Done when:** wiki + CredentialRouting pointer exist; binky integration doc
updated to match (or superseded with link).
### T02 — Align binky-control integration plan to production path
```task
id: WARDEN-WP-0028-T02
status: done
priority: high
state_hub_task_id: "d7d7ee9d-2ecf-5492-8a13-0b747d899456"
```
Done 2026-07-17: `binky-control/integrations/company-email-openbao.md` rewritten
to `tenants/binky/company-email/imap` + checklist (host confirm + Red provision
still open).
**Cross-repo: binky-control.** Rewrite
`integrations/company-email-openbao.md` to use
`tenants/binky/company-email/imap`, CCR + ops-warden front door as primary,
secrets-engine as optional exec wrapper on the same path. Confirm non-secret
IMAP host/port with founder (Blue). Keep Red-lane value provision as the last
step.
**Done when:** binky doc matches this workplan; checklist items re-opened for
implementation (T01 in BINKY was "prepared only").
### T03 — Enable `tenants` mount + extend CCR tooling + policy/role
```task
id: WARDEN-WP-0028-T03
status: done
priority: high
state_hub_task_id: "e0b675ef-9c08-5f89-8f13-ef4249ca2364"
```
Done 2026-07-17: `tenants/` KV v2 mount live; CCR applier allowlist extended;
CCR-2026-0007 + policy + OIDC role applied; lane-policy `read` / default
`deny` / agent boundary on tenants path; `docs/workload-kv-access-lanes.md`
tenant section.
**Cross-repo: railiance-platform (+ OpenBao admin once).**
1. **Enable KV v2 mount** `tenants/` on `bao.coulomb.social` (platform-admin /
attended; record non-secret evidence). Versioning + max versions policy
aligned with `platform` if practical.
2. **Extend** `scripts/credential-change.py` allowlist: `mount: tenants` and
`kv_path` under `tenants/` (keep existing `platform/workloads/` rules
intact for fleet lanes). Update dry-run docs and tests.
3. Author `CCR-2026-0007` (or next id) for the binky IMAP path; policy HCL on
exact data/metadata paths under `tenants/…`; OIDC role (founder group
near-term). Dry-run; founder approves; apply metadata only.
4. Document fields without values; add a **tenant lanes** section to
`docs/workload-kv-access-lanes.md` (or sibling doc).
**Done when:** mount exists; CCR tool accepts tenant paths; CCR approved +
policy/role applied; capabilities-safe positive/negative evidence (no value
reads for verify).
### T04 — ops-warden catalog + playbook + rotation
```task
id: WARDEN-WP-0028-T04
status: done
priority: high
state_hub_task_id: "9405b13d-4045-519b-8e3f-79a891323397"
```
Done 2026-07-17: catalog draft `binky-company-email-imap` (`risk: high`,
rotation, path `tenants/binky/...`); playbooks
`binky-company-email-imap.md` + onboarding. Promote to active after T05.
Add `binky-company-email-imap` to `registry/routing/catalog.yaml`:
`status: draft` until verify, then promote; `risk: high`; `exec_capable: true`;
concrete `fetch_command` for primary field; `rotation:` block (re-establish or
rotate mailbox app-password). Playbook under `wiki/playbooks/`. Scorecard
rotation coverage satisfied on promote.
**Done when:** `warden route show binky-company-email-imap --json` shows
expected pointers; after T03+T05, `resolvable: true`.
### T05 — Founder provision (Red) + first scan evidence
```task
id: WARDEN-WP-0028-T05
status: done
priority: high
state_hub_task_id: "f17bba95-bc53-5c2a-8b44-7df9e42b2341"
```
Done 2026-07-17: Founder provisioned via OpenBao UI (KV version 2; not
placeholder). Capabilities-safe verify pass; catalog + CCR promoted
active/resolvable. Optional follow-up: first email-connect read-only scan into
`binky-control/mailmeta/` (OperatingRhythm), not a custody blocker.
**Human-only value path.** Founder provisions IMAP username/password into
OpenBao via approved tool (`bao kv put … @file` or secrets-engine provision).
Agents never see the value. Run email-connect read-only scan with
`warden access … --exec` or secrets-engine exec; store **metadata-only**
evidence under `binky-control/mailmeta/`.
**Done when:** one successful read-only scan evidence note exists; lane
promoted active/resolvable; CCR verification evidence complete.
### T06 — Generalize "tenant secret onboarding" playbook
```task
id: WARDEN-WP-0028-T06
status: done
priority: medium
state_hub_task_id: "76bd01a0-1d03-5ff9-8f59-a1b44763979d"
```
Done 2026-07-17 with T01: `wiki/playbooks/tenant-secret-onboarding.md` +
CredentialRouting link.
From the binky lane, write a reusable playbook:
`wiki/playbooks/tenant-secret-onboarding.md` — steps for any new tenant:
slug, CCR template fields, policy naming, catalog entry, agent boundary,
rotation block, promotion checklist. Intended for the next Coulomb client
without redesign.
**Done when:** playbook exists and is linked from CredentialRouting + first
session notes for tenant repos.
### T07 — secrets-engine alignment decision (record only)
```task
id: WARDEN-WP-0028-T07
status: done
priority: low
state_hub_task_id: "46c8f8a9-3bbe-568f-8a45-07b690874273"
```
Done 2026-07-17: **Decision** — tenant production lanes use `mount: tenants`
and the CCR path only; secrets-engine may wrap exec delivery against that same
path later but must not store a second copy under `secret/`. Until stage roles
gain an approved `tenants/` grant, production path is CCR + ops-warden +
caller `bao`.
Record a short decision: secrets-engine catalog entries for **tenant**
production lanes **must** use `mount: tenants` and the same path as the CCR
(no second copy under `secret/`). Stage roles may need a later extension to
touch `tenants/` under an approved plan — until then, ops-warden + CCR +
`bao` as caller are the production path.
**Done when:** decision note in this workplan or `POST /decisions/` + wiki
pointer; no dual-value storage for the IMAP password.
## Suggested implementation order
1. T01 canon (unblocks everyone)
2. T02 binky doc alignment
3. T03 mount + CCR tooling + CCR apply (metadata)
4. T04 catalog draft
5. T05 founder provision + verify + promote
6. T06 generalize playbook
7. T07 secrets-engine alignment (can parallel after T01)
## Acceptance
- [ ] Documented path convention `tenants/<tenant>/…` used for ≥1 live lane (`binky`)
- [ ] CCR applier accepts `tenants/` without weakening `platform/workloads/` rules
- [ ] No secret values in any git/State Hub artifact
- [ ] Lane is capabilities-verified and agent high-risk safe
- [ ] email-connect can scan with env injection without printing password
- [ ] Next tenant can copy the onboarding playbook without redesign
## References
- ADR-0006 recursive multi-tenant identity (`net-kingdom/docs/adr/…`)
- `net-kingdom/docs/secrets-engine-security-infrastructure-boundary.md`
- `railiance-platform/docs/workload-kv-access-lanes.md`
- `railiance-platform/docs/credential-change-approval.md`
- `binky-control/integrations/company-email-openbao.md` (draft to align)
- WARDEN-WP-0026 disclosure hygiene (capabilities, high-risk, taint, rotation)
- WARDEN-WP-0027 Strand B (out of scope here)

View file

@ -0,0 +1,159 @@
---
id: WARDEN-WP-0029
type: workplan
title: "Policy front door: posture-aware access planning + founder interaction surface"
domain: infotech
repo: ops-warden
status: finished
owner: codex
topic_slug: custodian
planning_priority: high
planning_order: 29
created: "2026-07-18"
updated: "2026-07-18"
state_hub_workstream_id: "bbb3d9ec-d88d-5088-b4c0-55bfba0a10cf"
---
# WARDEN-WP-0029 — Policy front door + founder interaction surface
## Origin
Founder directive 2026-07-18 (binky-control cutover prep): agents proposed
raw credential mechanics to the founder ("attach the deploy key in the
forgejo UI", "save the PAT to /tmp/...") although a catalogued lane
(`forgejo-admin-api-token`, WARDEN-WP-0025) already covered the need — the
installed CLI's catalog was stale, and nothing forced the ask-warden-first
step. Directive: **ops-warden is the service to ask what can and needs to be
done** per NetKingdom policy; the founder is bothered only when policy makes
it absolutely necessary, and then preferably via a purpose-built interaction
surface, not CLI/file handoffs. The organization is in **build phase** and
ops-warden must know that posture. INTENT.md principles 7 and 8 (added with
this workplan) capture the direction.
## Goal
1. `warden plan "<need>"` — a policy decision front door: given a need, answer
*autonomous / founder-act-required / unroutable*, with the exact commands
or the exact founder act, posture-stated.
2. Declared **organization posture** (`build`) as a **third axis** beside env
posture (dev/test/prod) and workload maturity (M0–M3).
3. A **founder interaction surface**: local web page for the rare founder
acts (approve, OIDC-login prompt, paste-once secret capture straight into
OpenBao) — no values through CLI history or files.
4. Catalog freshness + agent guidance so ask-warden-first is the enforced
default.
## Design constraints (optimized 2026-07-18)
- **Compose, do not fork:** `warden plan` must call the routing catalog +
`expand_handoff` / `resolvable`; it must not re-implement keyword matching
or invent a second catalog.
- **Org posture is a third axis:** do not overload env posture or maturity.
- **Desk MVP is build-phase only:** localhost, OS-session trust, stdlib HTTP
server (pattern: net-kingdom `security-bootstrap-console`). No core-hub /
whynot dependency for v1.
- **Reuse map (reuse.coulomb.social):** flex-auth (policy-evaluate), key-cape
(OIDC act), net-kingdom bootstrap console (localhost desk shape),
railiance-platform (OpenBao custody). Do not rebuild those owners.
## Delivery sequence
```text
T02 (org posture) ─┐
T05 (catalog freshness) ─┼─→ T01 (warden plan composes both)
T04 (playbook sweep) ───┘ (parallel once plan shape known)
T03 (desk) ← after T01 can emit founder_required with a typed act
```
T05 is high priority: catalog staleness was the incident root cause.
## Tasks
### T02 — Declared organization posture (build phase)
```task
id: WARDEN-WP-0029-T02
status: done
priority: high
state_hub_task_id: "6c213024-6601-5116-b52f-d6711dc0587d"
```
Added `organization_posture: build` as axis C in
`registry/policy/security-posture.yaml` (relaxations + graduation triggers).
Surfaced in `warden policy list/show`, scorecard, and `warden plan` output.
### T05 — Catalog freshness + agent guidance
```task
id: WARDEN-WP-0029-T05
status: done
priority: high
state_hub_task_id: "c82d8745-4af4-5b89-ab49-06d8a902e592"
```
`Catalog.freshness()` reports source (repo/bundled/override), content hash,
mtime, package version, stale entry count, and warnings for bundled fallback.
Human `warden route list` prints catalog line; plan JSON embeds `catalog`.
Scorecard check `catalog_freshness`. AGENTS.md + credential-routing rules
require `warden plan` before founder credential steps.
### T01 — `warden plan` decision front door
```task
id: WARDEN-WP-0029-T01
status: done
priority: high
state_hub_task_id: "34db38fa-cb99-5ced-9a12-85176a7f2b44"
```
`warden plan "<need>" [--actor] [--domain] [--json]` composes catalog find +
handoff + org posture + policy gate. Verdicts: `autonomous` /
`founder_required` (`oidc_login` | `approve` | `paste_once_provision`) /
`unroutable` (CCR stub). Metadata-only audit. Module: `src/warden/plan.py`.
### T04 — Retire file-drop patterns from playbooks
```task
id: WARDEN-WP-0029-T04
status: done
priority: medium
state_hub_task_id: "717f57da-fbc4-5a4d-9f8c-c1c3fa75e0ee"
```
`wiki/playbooks/forgejo-admin-api-token.md` rewritten: plan-first, sanctioned
transports (`--exec`/`--out`/`--wrap`), desk paste-once for provision; `/tmp`
file drops marked retired. Consumer follow-ups noted for railiance-platform
and binky-control docs.
### T03 — Founder interaction surface (local web approval page)
```task
id: WARDEN-WP-0029-T03
status: done
priority: medium
state_hub_task_id: "47c781d2-768b-5777-b971-b5227fe41f5c"
```
`warden desk` — loopback `ThreadingHTTPServer`, short-lived token URL, acts
approve / oidc_login / paste_once_provision (bao kv put via stdin, dry-run
supported). Metadata-only audit open/close. Module: `src/warden/desk.py`.
## Acceptance
- [x] `warden plan "forgejo deploy key for binky-control"` → `autonomous` /
`agent-harness-forgejo-deploy` with access commands
- [x] Provision-style needs → `founder_required` with typed founder act
- [x] Posture `build` in plan + policy + scorecard
- [x] Desk approve flow (unit) with zero secrets in audit
- [x] No in-repo playbook instructs founder file drop as steady state
- [x] Catalog freshness on `warden route list` / plan JSON
## See also
- INTENT.md §7 (founder escalated, never tasked) and §8 (build-phase posture)
- WARDEN-WP-0025 (forgejo admin token lane), WARDEN-WP-0026/0027 (disclosure
hygiene, governance lockdown)
- reuse.coulomb.social: `capability.authorization.policy-evaluate`,
`capability.iam.key-cape`, `capability.security.iam-tooling-suite`
- binky-control DEC-2026-003 (first consumer: cutover without founder
mechanics)

View file

@ -0,0 +1,270 @@
---
id: WARDEN-WP-0030
type: workplan
title: "Delegation register — make gap-covering interim, visible, and retirable"
domain: infotech
repo: ops-warden
status: finished
owner: grok
topic_slug: custodian
planning_priority: high
planning_order: 30
created: "2026-08-11"
updated: "2026-08-15"
state_hub_workstream_id: "da3367d5-890c-52c6-aa54-1bdd0f277342"
---
# WARDEN-WP-0030 — Delegation register
## Origin
Founder directive 2026-08-11: **ops-warden should work with, but never replace or
duplicate, secrets-engine, tenant-engine, user-engine and other NetKingdom
components.** It is acceptable for ops-warden to cover a gap where needed security
functionality is not yet systematically provided — *provided* the gap is kept in
mind, filled, and given proper governance, after which ops-warden delegates to the
improved component.
The directive is already half-lived and nowhere written. Survey of
`registry/routing/catalog.yaml` on 2026-08-11 (24 entries):
| Execution mode | Count | Meaning |
| --- | --- | --- |
| `warden_executes: true` | 1 | ops-warden's own lane (`ssh-cert-host-access`) |
| `exec_owner:` set | 2 | Delegated — route-primary, proxy-fallback |
| `exec_capable` proxy, no `exec_owner` | 11 | **ops-warden is the de facto front door** |
| route-only | 10 | Pointer, nothing to delegate |
The delegation primitive already exists and works: `exec_owner` / `exec_command` /
`pointer_command` (`whynot-design-npm-publish` → secrets-engine, WP-0019;
`ops-warden-warden-sign-token` → railiance-platform credential broker,
RAILIANCE-WP-0005 T08). It is used by 2 of 24 lanes.
Nothing distinguishes the other eleven — "ops-warden proxies because that is the
right end state" reads identically to "ops-warden proxies because no owner front
door was ever built." Supporting evidence of the doctrine gap:
- `wiki/AccessRouting.md` does not mention secrets-engine at all and has no section
on interim positions.
- `wiki/playbooks/catalog-lane-promotion.md` gates draft→active on the lane
*working*, never on whether ops-warden should be the one running it.
## Goal
Make every ops-warden execution position **explicitly interim or explicitly
permanent**, with the intended owner and blocking condition recorded in the
machine-readable layer — so gap-covering is a tracked, retirable state rather than
silent ownership drift.
Success is not removing proxies. Success is that no proxy exists without an answer
to *"who should own this front door, and what is missing?"*
## Non-goals
- Removing or degrading any working lane. Proxies keep working until the owner's
front door exists and is proven.
- Building the missing front doors. That work belongs to secrets-engine,
tenant-engine, user-engine, and railiance-platform — this workplan produces the
register they need, not their implementations.
- A second catalog or a parallel schema. `delegation:` extends the existing entry
shape; `warden route gaps` composes the existing loader.
## Design constraints
- **Interim is the default.** A lane without a `delegation:` block is treated as
`interim` with an unknown owner, not as settled. Absence must read as a question.
- **Founder classifies, agent drafts.** Which of the eleven are legitimately
permanent is an architecture judgement (`key-cape-oidc-login` plausibly is; the
tenant/workload secret lanes plausibly are not). T02 lands a *drafted*
classification for review; the founder's answer is authoritative.
- **No restating owner procedure.** The register names the intended owner and the
blocker; it does not describe how that owner will implement their front door.
Same pointer-layer discipline as the rest of the catalog.
## Tasks
### T01 — Interim custodianship doctrine
```task
id: WARDEN-WP-0030-T01
status: done
priority: high
state_hub_task_id: "6f88876e-434c-5718-9c8d-ec6bf64ae4aa"
```
Add a doctrine section to `wiki/AccessRouting.md` stating the boundary: the only
lane ops-warden executes with its own authority is SSH issuance; every other
execution position is interim, held because the owning component does not yet cover
the need, and retired to that owner once it does. Name secrets-engine,
tenant-engine, user-engine, railiance-platform and flex-auth as the delegation
targets. Cross-link INTENT.md §9.
### T02 — `delegation:` metadata + backfill
```task
id: WARDEN-WP-0030-T02
status: done
priority: high
state_hub_task_id: "b02e8da6-57ca-5f9f-9405-9b0624498e3a"
```
Extend the catalog entry schema with:
```yaml
delegation:
mode: native | interim | permanent # native = owner already fronts it
intended_owner: <repo> # required unless mode: permanent
blocked_on: <what is missing> # required when mode: interim
reviewed: "YYYY-MM-DD"
```
Backfill all 24 entries. `exec_owner` lanes become `mode: native`.
`ssh-cert-host-access` becomes `mode: permanent` (ops-warden's own lane). The
eleven undelegated proxies are classified per the founder review below — five
`interim` now, six held pending secrets-engine's answer.
**Landed 2026-08-15.** Catalog is now 27 entries. All 27 carry `delegation:`.
- `permanent` (1): `ssh-cert-host-access`
- `native` (10): both `exec_owner` lanes plus the route-only pointers
- `interim` (16): the five founder-classified now; the six held pending
secrets-engine (still unanswered as of 2026-08-15, msg `7d55d332`) recorded as
`interim` / `intended_owner: secrets-engine` / `blocked_on` the generic-vs-per-lane
question — **not** `permanent`; plus five new-since-survey lanes drafted the same
way (`email-connect-transactional` same held question; two AppRoles;
`coulomb-social-runtime-env`; draft `scaleway-bootstrap`)
The six are not guessed permanent. Interim is the default until secrets-engine
answers. Reclassify to `permanent` only if they confirm `exec --catalog` stays
per-lane.
### T03 — `warden route gaps` + conformance test
```task
id: WARDEN-WP-0030-T03
status: done
priority: medium
state_hub_task_id: "f5e0f5af-45d8-5c82-9de2-d640d7d0a1f7"
```
`warden route gaps [--json]` lists interim lanes with intended owner, blocker, and
age since review — the queryable register. Add a routing test asserting every
`exec_capable` non-`warden_executes` entry declares `delegation`, so a new proxy
cannot be added without answering the ownership question. Surface stale interim
entries in the existing drift/stale review cadence.
### T04 — Promotion gate
```task
id: WARDEN-WP-0030-T04
status: done
priority: medium
state_hub_task_id: "b808a749-e1d7-5708-aabf-91732dd76abd"
```
Update `wiki/playbooks/catalog-lane-promotion.md`: draft→active requires a
`delegation` block. If `mode: interim`, the promotion note must state the intended
owner and the retirement condition. Add the matching question to the lane-review
checklist.
### T05 — Publish the register to the owners
```task
id: WARDEN-WP-0030-T05
status: done
priority: medium
state_hub_task_id: "b0188ec4-4860-57c8-8030-45904a132190"
```
Once T02 is reviewed, send the interim register to secrets-engine, tenant-engine,
user-engine, railiance-platform and net-kingdom as a coordination message: here is
what ops-warden currently fronts on your behalf, here is what would let us step
back. This is the artefact that converts a private ops-warden position into a
fleet-visible capability gap.
**Landed 2026-08-15.** Register sent (no secret values):
| To | Message |
| --- | --- |
| secrets-engine | `9c1d753f` — 1 native + 7 interim pending generic-exec answer |
| tenant-engine | `17c851b1` — 2 Binky tenant lanes |
| user-engine | `38aeccd5` — confirm USER_ENGINE_PROXY_SECRET ownership |
| railiance-platform | `e75793e3` — 1 native + 4 interim |
| net-kingdom | `3fea09df` — object-storage-sts remains native/draft |
| key-cape | `28ded56c` — rapp-qonto-keycape-client (founder-classified interim) |
## Acceptance
- [x] `wiki/AccessRouting.md` states the interim-custodianship boundary and names
the delegation targets
- [x] All catalog entries carry `delegation`; `warden route gaps` returns the
interim set with owner + blocker (27 entries; 15 active interim)
- [x] Routing test fails when a proxy lane omits `delegation`
- [x] Promotion playbook gates draft→active on the ownership question
- [x] Founder has reviewed the interim/permanent classification of the eleven
(2026-08-11); the six held lanes stay interim pending secrets-engine, not
marked permanent
- [x] Register delivered to the named owner repos (T05)
## Classification of the eleven (founder review, 2026-08-11)
### The test
An initial draft sorted by *subsystem* (tenant lanes → tenant-engine, workload lanes →
secrets-engine). Inspecting the entries showed that is the wrong axis. Nine of the
eleven share one `auth_method` — "caller's own OpenBao token" (operator OIDC via
key-cape, or a `workload-kv-read-*` policy) — and one `fetch_command` shape,
`bao kv get -field=X <path>`. No owner procedure is duplicated there. Contrast
`whynot-design-npm-publish`, which needs npm config and token injection into a specific
tool; that is a *procedure*, which is why WP-0019 handed it to secrets-engine.
**Test: owner-specific procedure or lifecycle → `interim`. Generic KV read →
ops-warden's thin wrapper is arguably `permanent`.**
### Interim — classify now (5)
| Lane | `intended_owner` | `blocked_on` |
| --- | --- | --- |
| `rapp-qonto-keycape-client` | key-cape | `client_secret_basic` exchange is a key-cape protocol procedure, not a KV read; rotation already `automatable: true`, so key-cape could front it today |
| `binky-company-email-imap` | tenant-engine | Custody at `tenants/binky/...` but rotation owner is `binky-control` — split lifecycle, no front door reconciling it |
| `binky-qonto-api` | tenant-engine | Same split, same tenant |
| `railiance-backup-offsite-lane` | railiance-platform | Rotation is `re-establish`, a multi-step procedure ops-warden only describes |
| `agent-harness-forgejo-deploy` | railiance-platform / agent-harness | `re-establish` plus an alternative host-local key path; two ways in, neither owner-fronted |
### Held pending secrets-engine (6)
`openbao-api-key`, `key-cape-oidc-login`, `issue-core-ingestion-api-key`,
`reuse-surface-hub-write-token`, `openrouter-llm-connect`, `forgejo-admin-api-token`.
These pass the test as `permanent` **only if `secrets-engine exec` stays per-lane and
provisioned.** If secrets-engine intends `exec --catalog <id>` to generalize over
arbitrary OpenBao lanes, the thin-wrapper argument collapses and all six become
`interim` with `intended_owner: secrets-engine` — ops-warden would then be duplicating
a front door the owner provides.
Asked directly (msg `7d55d332`, 2026-08-11): generic or per-lane; if generic, is it
near-term enough to mark now; and are there lanes they would decline, so those can be
marked permanent with the owner's position on record rather than ops-warden's inference.
Supporting detail: for `issue-core-ingestion-api-key`, `reuse-surface-hub-write-token`
and `openrouter-llm-connect`, **production never touches the proxy** — External Secrets
syncs the value into the cluster and the proxy exists for operator verification and
debugging. That weakens the case that they represent a missing front door at all.
**Do not backfill these six until the answer arrives.** A lane wrongly marked
`permanent` bakes in exactly the ownership drift this register exists to catch.
### user-engine
No lane names **user-engine** as owner — it appears only as a consumer inside
`coulomb-social-runtime-env` (`USER_ENGINE_PROXY_SECRET`, rotated at
`user-engine/user-engine-runtime`). Whether user-engine should front that lane itself
is worth confirming.
## See also
- INTENT.md §9 (cover gaps, never silently own them)
- WARDEN-WP-0019 (route to secrets-engine — the pattern this generalizes)
- WARDEN-WP-0028 (tenant secret custody pattern; front door still ops-warden's proxy)
- `history/2026-08-11-delegation-surface-assessment.md`
- `registry/routing/catalog.yaml`, `wiki/playbooks/catalog-lane-promotion.md`

View file

@ -0,0 +1,170 @@
---
id: WARDEN-WP-0031
type: workplan
title: "Calling-side identity for flex-auth, so policy.enabled can flip"
domain: infotech
repo: ops-warden
status: finished
owner: ops-warden
topic_slug: netkingdom
planning_priority: P1
depends_on_workplans:
- WARDEN-WP-0007
related_workplans:
- WARDEN-WP-0009
created: "2026-08-19"
updated: "2026-08-19"
state_hub_workstream_id: "739bad25-2345-5f4f-aaa3-cc4cd8c71f6c"
---
# WARDEN-WP-0031 — Calling-side identity for flex-auth
flex-auth shipped `flex-auth-ops-warden` (FLEX-WP-0016 T01/T02): an
independently rollable in-cluster pin carrying ops-warden's production registry
and policy package, on digest `sha256:138aa347…`, at
`flex-auth-ops-warden.flex-auth.svc.cluster.local:8080`.
It runs `callerAuth.mode: warn`, and it says why in its own logs:
```
caller authentication warning: caller is not authenticated
```
`src/warden/policy.py` posted `/v1/check` with **no `Authorization` header**.
flex-auth authenticates the caller with a Kubernetes TokenReview and binds
`resource.system: ops-warden` to `system:serviceaccount:ops-warden:ops-warden`;
an unauthenticated caller can only be served in `warn`. So the pin cannot
enforce, and per ADHOC-2026-08-17-T01 — `policy.enabled` must not flip anywhere
while `/v1/check` still answers unauthenticated callers — `policy.enabled` stays
false. The gap is ours, not flex-auth's, and this workplan closes it.
Warn is also not A2 evidence: a request that succeeds because failures are
downgraded proves nothing about the enforcing path.
## Ownership
| Concern | Owner |
| --- | --- |
| The pin, its digest, `callerAuth.mode` | flex-auth |
| Sending a caller identity on `/v1/check` | **ops-warden** (this workplan) |
| Choosing the token source on a given host | ops-warden operator |
| `policy.enabled: true` in `warden.yaml` | ops-warden operator |
## Design note — fail closed on identity too
When a caller token is configured but cannot be obtained, `check_sign_policy`
raises under `fail_closed` rather than retrying unauthenticated. Falling back to
an anonymous call is precisely the behaviour that keeps the pin in `warn`; a
gate that silently degrades to the ungated path is not a gate (ADR-0004's choke
point argument, applied to ops-warden as a caller).
## Tasks
```task
id: WARDEN-WP-0031-T01
status: done
priority: high
state_hub_task_id: "d3b7c701-bcdd-53f9-aa72-6f289bf5909b"
```
**Caller identity on the outbound policy call.** `policy.caller_auth` in
`warden.yaml` (`mode: none | file | env | command`, `token_path`, `token_env`,
`command`, `audience`); `src/warden/caller_identity.py` resolves the token at
call time and never caches, logs, or echoes it (ADR-0002); both
`check_sign_policy` and `check_fetch_policy` attach `Authorization: Bearer …`.
Whitespace-bearing and empty tokens are rejected before the call, because
flex-auth rejects them outright.
Done 2026-08-19. `mode: none` remains the default, so behaviour is unchanged
until an operator opts in. Tests in `tests/test_policy.py`.
```task
id: WARDEN-WP-0031-T02
status: done
priority: high
state_hub_task_id: "b77b3c80-a168-564a-9b7f-3063aefc3c2e"
```
**Readiness gate.** `scripts/check_policy_caller_identity.py` — read-only:
config loads, mode is not `none`, a token is actually obtainable, and with
`--url` a live `/v1/check` against a port-forward of the warn pin. Prints the
token's length and a truncated SHA-256 fingerprint only, so its output is safe
to paste into a handoff. Exit 0 ready / 1 not ready / 2 bad input. Distinguishes
401 (token not accepted — audience or binding) from 403 (authenticated but not
allowed to represent `system: ops-warden`).
Done 2026-08-19.
```task
id: WARDEN-WP-0031-T03
status: done
priority: medium
state_hub_task_id: "4245155e-6c71-5425-b574-11f61e1d4461"
```
**Docs.** `examples/warden.production.example.yaml` gains the `caller_auth`
block with both realistic sources, and its `flex_auth_url` is corrected — the
example pointed at `flex-auth.flex-auth.svc.cluster.local`, a Service that does
not exist. `wiki/PolicyGatedSigning.md` gains the caller-identity section and
the flip sequence.
Done 2026-08-19.
```task
id: WARDEN-WP-0031-T04
status: done
priority: high
state_hub_task_id: "f3834af7-2a08-51dd-bf31-8ce8550de699"
```
**Pick the token source and prove it against the warn pin.** Operator work on
the real host: `kubectl create token` (workstation) or a projected token
(in-cluster PEP), then
`python scripts/check_policy_caller_identity.py --url http://127.0.0.1:19090`
against a port-forward. Expect `effect=allow` for `agt-state-hub-bridge` while
the warn log stops printing `caller authentication warning` — the absence of
that line, not the allow, is the evidence.
Done 2026-08-19. Source is `mode: command` — `kubectl create token ops-warden
-n ops-warden --audience flex-auth --duration 10m` against the railiance01
cluster (tunnel `k3s-api-railiance01`, local `16444`; `16443` was CoulombCore's
k3s, a different cluster, which is why a `system:masters` cert 401s there —
not a port collision, as first reported).
`deploy/kubernetes/caller-identity.yaml` creates the Namespace and
ServiceAccount the binding names — no RBAC, `automountServiceAccountToken:
false`; it exists only to be TokenReviewed. Gate exits 0 live:
`HTTP 200, effect=allow, decision:f3f7c88f9585582a`, and the pin's
`caller authentication warning` count held at 4 across two authenticated runs.
Evidence: `history/2026-08-19-flex-auth-caller-identity-evidence.md`.
```task
id: WARDEN-WP-0031-T05
status: cancel
priority: high
state_hub_task_id: "3f6dc609-89db-52eb-a6f9-d2fd271be821"
```
**Sequence the flip.** Only after T04: tell flex-auth to set
`callerAuth.mode: enforce` on `flex-auth-ops-warden` (their FLEX-WP-0016 T03),
re-run the gate against the enforcing pin, and only then set
`policy.enabled: true` with `fail_closed: true`. Flipping before enforce buys
nothing; flipping before T04 401s every `warden sign`.
**Deferred 2026-08-19 under `ADR-0006`** — not blocked, decided against for now.
flex-auth did enforce (FLEX-WP-0016 T03, Helm rev 2): the pin runs
`--caller-auth-mode enforce`, the gate exits 0 against it
(`HTTP 200, effect=allow, decision:f3f7c88f9585582a`), and an anonymous
`/v1/check` is 401. Everything needed to flip was in place.
It was not flipped. `policy.enabled` is a single repo-wide boolean, and with
`fail_closed: true` it makes flex-auth a hard dependency of every `warden sign`
— including the certs the ops-bridge tunnels depend on, one of which carries
the policy call itself. Uniform enforcement across an estate being actively
rebuilt would harden the access needed to perform the rebuild. Enforcement
belongs to a zone, not to the repo; that is `ADR-0006`, and the model is
`WARDEN-WP-0032`. This task resumes as WARDEN-WP-0032-T05.
Also shipped while proving the flip: the gate URL is now a managed ops-bridge
tunnel `flex-auth-ops-warden-railiance01` (`-L 19090:10.43.1.165:8080`) instead
of a hand-run `kubectl port-forward`.

View file

@ -0,0 +1,429 @@
---
id: WARDEN-WP-0032
type: workplan
title: "Adopt security zones as a consumer — retire the global policy.enabled"
domain: infotech
repo: ops-warden
status: finished
owner: ops-warden
topic_slug: netkingdom
planning_priority: P1
depends_on_workplans:
- WARDEN-WP-0031
created: "2026-08-19"
updated: "2026-08-22"
state_hub_workstream_id: "38c6a5f3-fb0d-5230-be85-f9e3ffc850f6"
quality_dod: DoD-Ok
quality_dod_at: "2026-08-22"
quality_dod_by: codex
quality_dod_note: "All tasks are done; the global switches and trust-zone source are retired, workload references are explicit, the owner policy is total, declarations validate, live caller identity is re-proven, and the full suite passes."
---
# WARDEN-WP-0032 — Adopt security zones as a consumer
`ADR-0006` defers `policy.enabled: true` until enforcement can be scoped to a
zone. **The zone model itself is no longer ops-warden's work.** It moved to
`zone-engine` as `ZONE-WP-0001` on 2026-08-19, where it belongs under `ADR-0005`
— ops-warden implements one lane narrowly and routes the rest, and an
estate-wide enforcement model is not a lane it should absorb.
What stays here is the consumer side: ops-warden was the repo whose deferred
flip exposed the gap, it holds the controls the model must be able to express,
and it is the first consumer the model has to satisfy.
## What ops-warden owes zone-engine
Inputs, not designs. `ZONE-WP-0001-T02` derives the model from the real estate,
and most of that estate is ops-warden's:
- **27 routing catalog lanes** (`registry/routing/catalog.yaml`) with `risk`,
`status`, and `delegation` already on each — the likeliest membership inputs.
- **The actor inventory** (`adm` / `agt` / `atm`) and its TTL policy.
- **The three posture axes already shipped** — environment and maturity
(WP-0015), `organization_posture` (WP-0029) — including the honest answer to
whether `organization_posture` should be folded into zones rather than run
beside them.
- **Three controls the model must be able to express**: the flex-auth pre-sign
gate (`policy.enabled` + `fail_closed`), the agent read-boundary on
`risk: high` lanes (`ADR-0004`), and the `warden plan` escalation verdicts.
- **The compiled-registry path** (`scripts/build_flex_auth_registry.py`) — how
membership can reach flex-auth without a lookup in a latency-critical decision
path.
## Tasks
```task
id: WARDEN-WP-0032-T01
status: done
priority: high
state_hub_task_id: "b03a5caa-0bb5-5cdd-bb99-32c694b0da29"
```
**Hand the estate inputs to `ZONE-WP-0001-T02`.** Not a design proposal — the
lanes, actors, axes, and controls above, with the exceptions ops-warden already
knows do not fit cleanly (the interim delegation lanes from WP-0030 are the
obvious candidates: a lane covered on someone else's behalf may not sit in the
same zone as one ops-warden owns outright).
Include the `organization_posture` fold-in question honestly, including the case
against keeping it.
**Answered by net-kingdom 2026-08-19** (canon owner of `tenancy-posture_v0.1`,
answering `ZONE-WP-0001-T01`): **do not fold it in, and do not put it in a
per-repo declaration under any key.** `organization_posture` is a fleet-wide,
time-varying scalar describing the *estate*, not a property of a declaring
service; a per-repo copy of a global goes stale in as many places as there are
repos. It stays what WP-0029 made it — an input to stance selection that the
zone model reads. Hand it over as an input, not as a candidate axis. Environment
posture and `M0`–`M3` are per-workload and remain genuinely composable; those two
are still open for `ZONE-WP-0001-T02`.
**Done 2026-08-21.** Every input listed above is now carried in `ZONE-WP-0001`,
and `T02` there is `done` — which is the acceptance condition for this task, since
what was owed was inputs rather than a design.
What actually reached them: the 27 graded lanes with `risk`/`status`/`delegation`
(T05), the `M0`–`M3` ladder in `registry/policy/security-posture.yaml` — which
`ZONE-WP-0001-T02` adopted as the maturity ladder rather than
`.repo-classification.yaml` `category`, on the evidence that the latter grades a
production SSH CA below a documentation repo — the three controls, and the
compiled-registry path including the dormant `trust_zone` constant at
`scripts/build_flex_auth_registry.py:77`.
Two inputs were handed over as corrections to ops-warden's own earlier claims,
which is the part worth recording. `organization_posture` was offered as a
candidate axis and net-kingdom refused it (above); and ops-warden asserted no
registry carried a workload join key, which was true of its own catalog and false
of the estate — `rapp-*/declarations/rapp.yaml` carries eight
`workload_identity` declarations. `scripts/report_workload_join.py` then measured
the join rather than asserting it: **1 of 27 lanes** matches a declared workload.
That number is `ZONE-WP-0001-T03`'s critical path, and it came out of correcting
this repo's own input rather than out of supplying a new one.
```task
id: WARDEN-WP-0032-T02
status: done
priority: high
state_hub_task_id: "b3f41c85-a293-58ad-ac27-9f8110c51266"
```
**Replace `policy.enabled` with a zone-aware control.** Waits on
`ZONE-WP-0001-T03` and `T05`. Reads the zone of the actor being signed for and
that zone's failure mode. Ship deprecation and migration in the same change —
leaving both is the second-source-of-truth failure `ADR-0001` exists to prevent.
Re-run `scripts/check_policy_caller_identity.py` before enabling anything: the
WP-0031 evidence (`decision:f3f7c88f9585582a`, 2026-08-19) will be stale, and
re-establishing it is cheap precisely so this is a re-check rather than a re-do.
This closes `WARDEN-WP-0031-T05`.
**Amended by flex-auth 2026-08-19, reviewing `ZONE-WP-0001` as the PDP.** Two
constraints that change what this task can build, both argued in full at
`ZONE-WP-0001-T03` and `T04`:
1. **The zone-aware control splits across the boundary, it does not move.**
flex-auth will read compiled zone *membership* from the registry and apply the
per-zone *stance* from its policy package, returning an effect plus an
advisory annotation. What stays on the ops-warden side is the axis flex-auth
structurally cannot carry: **`fail_closed` is not expressible by a PDP.**
Fail-open describes what `warden sign` does when flex-auth is *unreachable* —
no decision is rendered, so no compiled data and no policy rule can reach it.
So the replacement for `policy.enabled` is not one zone-derived boolean
either; it is (a) stance, which arrives *in the decision*, and (b) failure
mode, which stays a local ops-warden setting declared per zone. Plan for two,
or T02 will be built expecting flex-auth to answer something it cannot.
2. **The membership compiler is ops-warden's to change, and it has a name
collision to resolve first.** `scripts/build_flex_auth_registry.py:77` already
emits `"trust_zone": "platform"` as a hardcoded constant on every
ssh-certificate resource. It is a first-class field on flex-auth's `Resource`,
it is surfaced into rego input, and **no policy package reads it**. Before
compiling zone membership, either retire that constant or deliberately
repurpose it — do not add `security_zone` beside a dormant `trust_zone` and
leave the next reader to guess which is real. That is the `ADR-0001`
second-source-of-truth failure in miniature, inside a generated artifact.
Good news for T03's cost: **no flex-auth registry schema change is required.**
`metadata`, `labels` and `attributes` already flatten into the rego input, so the
compiler can emit membership today.
**Consumer implementation landed in the working tree 2026-08-22.** The config
loader rejects the retired `policy.enabled` and global `policy.fail_closed`
keys. `scripts/build_flex_auth_registry.py` now emits the normative
`workload_id`, `security_zone`, `security_zone_declared`,
`security_zone_admission`, `security_zone_reason`, and
`security_zone_revision` attributes; the dormant `trust_zone` field is gone.
The PEP reads compiled resource membership and applies its local per-zone
failure mode. Sign and audit records retain the zone, selected failure mode,
outcome, and decision id.
The legacy `--no-policy` proxy switch remains only as a rejected compatibility
flag. It can no longer bypass the gate: unresolved credential targets take the
explicit `unknown` profile and its configured failure mode.
**Done 2026-08-22.** flex-auth package v2 (commit `e521e7b`) supplies total
stance over every v0.1 zone plus `unknown`, preserves native enforcement for
`not-applicable`, and returns `audit_only` for advisory decisions. The required
live caller check passed through the existing tunnel with command-mode caller
identity and decision `decision:f3f7c88f9585582a`. The operator config was then
migrated from the two rejected global keys to `zone_registry_path`, and the
same live check passed against that real config. Full repo tests pass and
sign/audit evidence records zone, failure mode, outcome, and decision id.
```task
id: WARDEN-WP-0032-T03
status: done
priority: medium
state_hub_task_id: "d04a737b-ecdf-5747-ba25-20dadd99d3bc"
```
**Declare ops-warden's zones** in the format `ZONE-WP-0001-T05` settles,
alongside the existing posture descriptors.
**Amended by net-kingdom 2026-08-19 — the carrier file is already settled, only
its contents are open.** Canon Decision 5.6 (`tenancy-posture_v0.1` draft-9)
rules that zone membership is declared in **`tenancy.yaml` under a reserved
top-level `zones:` key**, sibling to `tenancy:` and `provider:` and never inside
`tenancy.current`. §5.4 makes that file the repo's single posture declaration
surface, and a second root file would be the second-source-of-truth failure
`ADR-0001` exists to prevent — in ops-warden's own idiom. The key is reserved and
deliberately unconstrained in `net-kingdom/canon/schemas/tenancy-posture_v0.1.schema.json`,
so a combined declaration validates today.
Note the consequence for this repo: **ops-warden does not currently have a
`tenancy.yaml`.** Declaring zones means writing one, which means declaring the
six-axis posture vector too. That is a real and probably overdue cost, not an
accident of this amendment — canon would rather ops-warden declare both
accurately than declare a zone with no posture beside it.
Note also *why* stance is not something this declaration may set: canon Decision
5.6 rules that a declarer must not be the party that sets the stance, or an
accurately declared `exempt` becomes conformant *and* exempt. ops-warden declares
which zone a lane or actor is in. The stance of the pre-sign gate in that zone is
flex-auth's policy package; the failure mode is ops-warden's own setting, per
flex-auth's T03 amendment. Per flex-auth's T05 amendment, this
declaration must also say whether a zone rides the **actor** (a flex-auth
subject) or the **lane** (a flex-auth per-actor resource) — in the compiled
registry an actor is both, and the compiler needs to be told which record
carries membership. Carry the conformance rule:
*accuracy, not altitude*. Declaring a stricter zone than can be evidenced is the
failure mode that looks like progress.
**Done 2026-08-22.** `tenancy.yaml` now declares ops-warden as an independently
governed operational execution unit with its Kubernetes service-account
binding, and admits it to `z1-operational` at `M1`, `medium`, `internal`.
`docs/evidence/security-zone-admission-2026-08-22.md` records why this is the
highest evidenced admission rather than an aspirational `M2`. The declaration
passes net-kingdom's current `tenancy-posture_v0.1` validator.
```task
id: WARDEN-WP-0032-T04
status: done
priority: medium
state_hub_task_id: "c7879127-3dba-55c0-853c-a10775736873"
```
**Amend `ADR-0006`.** Once zones exist and enforcement scoping is owned by
`zone-engine`, ADR-0006 must say that ops-warden *follows* the model rather than
owning it — a superseding record, never an in-place edit. Update `SCOPE.md`,
`wiki/WorkloadSecurityPosture.md`, and `wiki/PolicyGatedSigning.md` with it.
**Done 2026-08-22.** ADR-0006 is marked superseded without rewriting its
decision. ADR-0009 accepts `security-zones_v0.1` as a consumer, records the
PDP/PEP split and unknown handling, and is indexed as its successor. `SCOPE.md`,
`wiki/WorkloadSecurityPosture.md`, `wiki/PolicyGatedSigning.md`, configuration
guidance, access guidance, and affected playbooks now describe the zone-aware
control and do not instruct operators to use a global bypass.
```task
id: WARDEN-WP-0032-T05
status: done
priority: high
state_hub_task_id: "1d968627-83f4-59cd-84ca-0f9f35e435ff"
```
**Grade the five exposed lanes now — do not wait for the model.**
`RISK-F-0003`: `is_high_risk` is `risk == "high"` and `risk` is optional, so the
14 ungraded lanes never reach the agent read-boundary. Five are `exec_capable`
and can therefore stream a value to an agent session: `openbao-api-key`,
`whynot-design-npm-publish`, `key-cape-oidc-login`,
`issue-core-ingestion-api-key`, `reuse-surface-hub-write-token`.
The durable answer is a maturity-derived default (`ZONE-WP-0001-T03`), and it is
the right answer. It is also months away, and this is a live control gap in a
shipped ADR. Grade these five explicitly, then the remaining nine.
Grading is judgement, not backfill — each lane's grade should be justified in the
entry, and the operator should sanction the high/standard calls rather than
having them inferred. Verify separately whether OpenBao's
`agent-high-risk-boundary` policy covers these paths; `RISK-F-0003` deliberately
does not assume it does, because those paths were graded by the same omission.
**Done 2026-08-19, operator-sanctioned.** All 14 ungraded lanes graded on merit,
each with its justification in the entry: 17 `high`, 10 `standard`, **0
ungraded**. `warden access <lane> --fetch` with `WARDEN_AGENT_ID` set now exits 7
on lanes that were silently outside the control an hour earlier.
Graded on merit, not defensively. A first pass marked
`issue-core-ingestion-api-key` and `reuse-surface-hub-write-token` `high`; the
existing test `test_high_risk_lanes_classified` asserted the opposite and was
right — ordinary internal workload secrets are `standard`. Both were regraded
down. `high` means disclosure into a logged context is damaging beyond what
rotation recovers: provider keys with spend, admin PATs, tenant commercial data,
supply-chain publish rights. `inter-hub-bootstrap-ssh` is `high` **conservatively**
— ops-warden could not establish that no key material moves in the envelope, and
that is recorded in the entry so it is regraded with evidence rather than assumed
down.
The rule is now `ADR-0007`: build-stage permissiveness stops at credential
disclosure. Not yet verified: whether OpenBao's `agent-high-risk-boundary`
policy covers these paths (T06).
```task
id: WARDEN-WP-0032-T06
status: done
priority: medium
state_hub_task_id: "4294084c-bf3f-5aa6-b84d-5173121882ff"
```
**Make absence impossible, once the model says what absence means.** Waits on
`ZONE-WP-0001-T03`. Either invert the default (absent `risk` resolves through the
lane owner's maturity, per the operator direction) or require `risk` at catalog
load and in CI. Whichever lands, the failure mode to kill is the current one:
adding a lane without a grade silently places it outside a control, with nothing
at load or in CI noticing.
Feed back to `ZONE-WP-0001-T03` whether ops-warden can supply the join it needs —
today no lane references a workload or an environment, so the `M0`–`M3` ladder
has nothing to attach to from this side.
**Enforcement half done 2026-08-20.** It did not need the zone model: `ADR-0007`
already decided absence is a defect, which is enough to make the code fail safe
and to gate CI.
The real mechanism turned out to be sharper than `RISK-F-0003` described.
`is_high_risk` was `risk == "high"`, but `risk` was **not** absent at the model
layer — `RouteEntry.risk` carried a dataclass default of `"standard"`. So an
omitted grade was not unhandled; it was actively resolved to the permissive
value. Fail-open by construction, which is why nothing warned.
Now: the default is `"ungraded"`, and `is_high_risk` returns true for anything
not in an explicit low-risk vocabulary (`standard` / `low` / `accepted`). An
omitted grade **and** a grade from a newer catalog both resolve to high, so the
boundary fails safe in both directions. `is_graded` exposes the distinction, and
`test_every_repo_catalog_lane_is_explicitly_graded` is the CI gate that stops an
ungraded lane being committed. Four regression tests cover it.
`accepted` is in the low-risk vocabulary deliberately, ready for the
maturity-derived default: an experimental-context lane may be explicitly
accepted, which is a graded decision rather than an omission.
**Second layer checked 2026-08-20 — it does not cover them.** The OpenBao side
was compared statically (policy file vs catalog): `agent-high-risk-boundary`
denies 5 data paths covering **6** of the **17** high-risk lanes. Eight
high-risk lanes with concrete KV paths are not denied — and **four of those were
already graded `high` before the regrade**, so the divergence is pre-existing
rather than something the grading introduced. It had simply never been
comparable before.
This matters more than the ops-warden half: `warden access` exits 7 for all 17,
but that only protects the ops-warden path. The OpenBao policy is what protects a
direct `bao kv get`, which is the actual 2026-07-16 vector.
Routed to `risk-nexus` as **`RISK-F-0004`**, `fix_owner: railiance-platform` —
the policy is theirs, and ops-warden does not amend another repo's control.
**Live confirmation done 2026-08-21 — and the blocker was not real.** The
token was not expired: `bao token lookup` returned a valid `platform-admin`
token from an OIDC login, and `bao policy read agent-high-risk-boundary`
succeeded. No `bao login` was needed. Worth recording as a small instance of the
lesson `.claude/rules/finding-routing.md` already states — *re-read a blocker
before trusting it*. This one was a stale claim about the world, carried for a
day in both this workplan and `RISK-F-0009`.
The verification script also did not exist. It was described here as "ready",
and nothing was committed. `scripts/check_agent_read_boundary.py` now exists,
with tests, and is the invariant `RISK-F-0009` asked for rather than a one-off
audit: exit 1 when any high-risk lane has no corresponding deny. It prefers the
deployed policy and falls back to the file only with a loud warning, because
deployment drift is the thing it exists to catch. Capabilities-only by
construction — it reads the policy document and lane metadata, never a secret
value, and never mints a token.
Three results, one against ourselves:
1. **Coverage confirmed at 6 of 17** against the live policy — the headline was
right and is no longer inferred from a checkout.
2. **Six lanes uncovered, not eight.** `RISK-F-0009` counted `openbao-api-key`
(a `<domain>/<workload>/<bundle>` pattern) and `ops-warden-warden-sign-token`
(a broker grant, not KV) among the concrete uncovered paths, while its own
prose said the first was a pattern. Neither can be expressed as a deny.
Corrected: 6 covered, 6 uncovered, 5 with no address.
3. **The deployed policy has drifted from the file.** The file denies
`platform/workloads/core-hub/runtime`; the server does not. No ops-warden
lane maps there, so our numbers are unchanged — it matters as evidence, since
`RISK-F-0009` named exactly this divergence as its unconfirmed risk.
Still not established, and not ops-warden's to establish: whether any agent
token carries `agent-high-risk-boundary`, and whether any carries it together
with a `workload-kv-read-*` policy. Confirming that means minting or inspecting
tokens — a write against railiance-platform's OpenBao. Exposure stays theoretical
to the same degree as before.
**Platform half closed 2026-08-22.** `RAILIANCE-WP-0022` consumed the generated
high-risk path input and deployed the completed deny policy. The platform-owned
invariants report **19 high-risk lanes, 14 concrete entries, 0 uncovered**. A
dedicated `coding-agent-railiance-platform` AppRole then proved deny-wins with
exactly `agent-high-risk-boundary` plus one workload read policy: data access was
denied while metadata remained readable; its single-use test identity was
self-revoked and no test tokens remained. Decision `f0955252` records the
operational identity. No KV value was read.
The local invariant agrees against the platform policy file: 19 high-risk lanes,
14 concrete entries covered, 5 without a concrete address, 0 uncovered. This
session could not independently read the deployed policy, so live-state evidence
is the platform-owned readback above rather than a claim inferred from the local
file.
**Done 2026-08-22.** The settled model makes the two layers complementary:
catalog CI continues to require an explicit `risk` field so omission cannot
silently weaken the agent boundary, while `RouteEntry.risk_for_zone` implements
the normative maturity-derived fallback for consumers evaluating unresolved or
future inputs (`z0` + satisfied + synthetic-only → `standard`; satisfied `z3`
→ `critical`; everything else → `high`). An explicit catalog grade always wins.
The platform deny policy and its live proof above close the direct-OpenBao half.
```task
id: WARDEN-WP-0032-T07
status: done
priority: medium
state_hub_task_id: "6b4bbbed-2864-5fe9-82be-22ff9543f6f4"
```
**Adopt Repo Manager's workload-reference owner interface.** Accepted with one
documented amendment against repo-manager revision `890f3b0`: managed
deployables use the exact `(rapp_id, workload_identity.name)` pair and optional
deployable name; an independently governed operational execution unit may use
an exact local `tenancy.yaml` declaration. Native actions, actors, grants,
patterns, and non-workload resources are explicitly `not-applicable`; unresolved
workload-applicable references remain `unknown`. No path, owner name, or
repository-name inference is allowed.
Every one of the 27 catalog lanes now carries an explicit `workload_ref`: 3
resolved (2 exact managed RAPP references and ops-warden's direct operational
declaration), 17 unknown with reasons, and 7 not-applicable with reasons.
`scripts/report_workload_join.py` resolves only those explicit references,
Repo Manager validates the interface and resolves both managed tuples exactly,
and regression tests reject malformed or inferred joins. This incorporates
net-kingdom's draft-12 correction received 2026-08-22: local tenancy declaration
is not an escape hatch for a managed running deployable.
## Related
- `zone-engine` `ZONE-WP-0001` — the model, and where this work is led from
- `ADR-0006` — enforcement is zone-scoped, never a global flag
- `WARDEN-WP-0031` — the deferred flip and its readiness evidence
- `net-kingdom` `tenancy-posture_v0.1` draft-9 Decisions 5.6, 8.4.1, 8.4.2 — canon's
answer to `ZONE-WP-0001-T01`; enforcement stance is a sibling standard, not a
seventh axis, and the declaration surface is `tenancy.yaml`

View file

@ -0,0 +1,344 @@
---
id: WARDEN-WP-0033
type: workplan
title: "Native lane handoff — review secrets-engine's catalog admission, and fix what it exposed"
domain: infotech
repo: ops-warden
status: finished
owner: ops-warden
topic_slug: netkingdom
planning_priority: P1
depends_on_workplans:
- WARDEN-WP-0030
created: "2026-08-21"
updated: "2026-08-28"
state_hub_workstream_id: "4627d89b-4b00-562a-81e9-76e96f90fa7e"
---
# WARDEN-WP-0033 — Native lane handoff
On 2026-08-20 `secrets-engine` accepted five of ops-warden's seven interim
proxy lanes for catalog admission (`SECRETS-WP-0006`, decision
`ae676382-1826-4e04-aa4e-bb77990c7a0d`), rejected two with reasons ops-warden
agrees with, drafted the five entries itself rather than waiting for the offered
contribution, and asked for a line-by-line review of the non-secret metadata.
In the same hour `railiance-platform` closed the `RISK-F-0009` coverage gap and
asked ops-warden for two things back.
This workplan is the response to both, plus the defect the review turned up in
ops-warden's own grading model — which is the most consequential item here and
would not have been found without the second pair of eyes.
## Why a workplan and not an adhoc
Four counterparties are waiting, one deliverable is a **cross-repo interface**
another repo will consume on a schedule, and the review carries approval
semantics — `secrets-engine` holds interim proxy ownership open until each lane
has approved native verification. The convention reserves adhocs for low-risk
work completed directly; this is none of those.
## Tasks
```task
id: WARDEN-WP-0033-T01
status: done
priority: high
state_hub_task_id: "154f2f03-387d-5fe6-a0f5-1929c46a2bd8"
```
**Review the five drafted catalog entries and reply.**
`issue-core-ingestion-api-key`, `reuse-surface-hub-write-token`,
`openrouter-llm-connect`, `forgejo-admin-api-token`,
`email-connect-transactional` at `secrets-engine@784be97`.
Review the axes they asked for: owner-repo coordinates, field grouping, workload
consumers, rotation/deactivation owners, delivery intent. Verify claims against
the authoritative `railiance-platform` CCRs — **never against a secret read**;
`bao kv get` on any of these paths is the 2026-07-16 vector and three of the five
are `risk: high`.
Accept their two rejections. `openbao-api-key` is a routing template rather than
one lane and `key-cape-oidc-login` belongs to key-cape — that is `ADR-0005`
applied to ops-warden by someone else, correctly.
```task
id: WARDEN-WP-0033-T02
status: done
priority: high
state_hub_task_id: "6996d07f-63bb-5708-a171-68c4b1bbddde"
```
**Correct ops-warden's per-path risk grading — the defect T01 exposed.**
`secrets-engine` graded `issue-core-ingestion-api-key` **high**; ops-warden grades
it **standard**, and deliberately: WP-0032-T05 regraded it *down* on 2026-08-19,
operator-sanctioned, because `test_high_risk_lanes_classified` asserted standard
and was judged right — "ordinary internal workload secrets are standard".
That reasoning was incomplete, and CCR-2026-0002 says so explicitly: the path
carries **both** `ISSUE_CORE_API_KEY` **and** `GITEA_BACKEND_TOKEN`, a Forgejo
backend token, and the CCR records keeping both as a deliberate field-set
decision.
**The root cause is structural, not a single bad call.** ops-warden grades a
*lane* by its headline field — the catalog carries one `fetch_command` naming one
field and no `fields` list at all — but the disclosure unit is the **path**: a
`bao kv get` returns every field stored there. So a lane can be graded on its
least dangerous contents. `ADR-0007` says every lane carries an explicit grade;
it does not say the grade must cover everything a read of that path would
disclose, and it should.
Fix the grade, then fix the model that produced it: record `fields` per lane and
grade on the union. Check the other 25 lanes for the same shape.
**Done 2026-08-21 — and it was two lanes, not one.** While verifying
`reuse-surface-hub-write-token` I told secrets-engine their second field was
unevidenced and asked them to confirm it. It was evidenced: `CCR-2026-0005`'s
`kv_path` block lists both fields and its notes describe the HMAC's alignment
with Forgejo org webhook id=1. A truncated grep, and a retraction sent within
twenty minutes so they would not spend time on it. That lane was under-graded on
exactly the same reasoning, and both had been regraded *down* in the same T05
pass — which is what makes this a systematic flaw rather than one bad call.
Blast radius checked and bounded: of the 8 remaining `standard` lanes, 6 have no
KV path at all (SSH, policy check, tunnel, principals, issue-sink, key-cape
login) so nothing is disclosed by a read. Two do have paths and no CCR field
evidence — `rein-openweights-openrouter-approle` and `coulomb-social-runtime-env`
(a whole k8s env Secret, which by shape almost certainly holds several fields).
Deliberately **not** regraded: `ADR-0008` §3 says an unknown field set is stated
rather than assumed, and grading is operator-sanctioned judgement, not backfill.
They are the open item on this task.
Shipped: both regrades with their evidence and the superseded reasoning kept
inline, `fields` recorded with its CCR source, the test that had been holding the
wrong answer inverted with an explanation of why it was wrong to trust it, and
**`ADR-0008`** — a lane's grade covers every field its path discloses. That is a
new binding rule, so it is a record rather than a wiki note.
```task
id: WARDEN-WP-0033-T03
status: done
priority: high
state_hub_task_id: "a736f983-94da-5a4a-aaf9-5114485518a6"
```
**Emit the generated high-risk data-path artifact for `railiance-platform`.**
They asked for a versioned artifact of concrete high-risk data paths
(`id` + `data_path` + catalog revision) to consume instead of hand-maintaining
the deny list — the half of the `RISK-F-0009` fix ops-warden explicitly declined
to build *for* them. Emitting the artifact is not the same as amending their
policy: they still own what to deny. That boundary is the point of `ADR-0002`
and must survive this task.
Must be generated, never hand-edited, and must carry the catalog revision so a
consumer can tell what it was derived from. Depends on T02 — publishing the deny
set before fixing the grades would ship the wrong list to a consumer who will
apply it.
**Done 2026-08-21.** `scripts/emit_high_risk_paths.py` →
`registry/generated/high-risk-data-paths.yaml`: 19 high-risk lanes, 14 concrete
data paths, 5 with no single KV address listed separately so a consumer does not
read the absence as an omission. Carries `catalog_revision`, its date, and a
`catalog_dirty` flag — a revision that does not describe the file it came from is
worse than none.
The T02 dependency was not theoretical. The two regrades land in this artifact,
and `check_agent_read_boundary.py` now reports **2 uncovered** against a policy
railiance-platform closed to 0 yesterday. Emitting before regrading would have
handed them a list that confirmed a coverage claim that had just stopped being
true.
`fields` is emitted as `null` where no CCR declares the set, never as a
single-element guess — `ADR-0008` §3. Two CI tests: the artifact must be current,
and every high-risk lane must appear in it, so a lane graded high after the last
emit cannot silently fail to reach the consumer.
Boundary held: the header states this is an input and not a policy, and that
railiance-platform may deny more, deny less, or dispute a grade (`ADR-0002`).
```task
id: WARDEN-WP-0033-T04
status: done
priority: medium
state_hub_task_id: "5acac140-a586-5db3-b231-bbf236710786"
```
**Route the coding-agent issuance identity question.**
`RAILIANCE-WP-0017` is blocked on defining a distinct coding-agent issuance
identity and proving deny-wins when that identity is combined with workload read.
They asked ops-warden to route ownership.
Route it; do not absorb it (`ADR-0005`, `ADR-0003`). ops-warden owns actor
identity for `adm`/`agt`/`atm` **SSH certificates** and nothing else — a coding
agent's OpenBao issuance identity is an IAM question. The likely owner is
`key-cape`, with `user-engine` and `zone-engine` both plausibly involved. Say so
with reasoning rather than guessing, and record the answer either way.
Note the interaction with `ADR-0004`: the agent read-boundary already depends on
`WARDEN_AGENT_ID` being set, which is an honour-system marker on the ops-warden
side. A real issuance identity is what would make that boundary hold on the
OpenBao side too, so ops-warden is an interested consumer, not a bystander.
**Routed 2026-08-21 to `key-cape` (msg 903b2223); waiting on accept or refuse.**
Reasoning given: it is an identity and issuance question about a principal
authenticating to OpenBao, which is key-cape/Keycloak's. The precedent is an hour
old and runs the same direction — `secrets-engine` declined `key-cape-oidc-login`
as ops-warden's to hand them, on the grounds that login and identity-token
issuance stay with key-cape. Absorbing this would contradict agreeing with them.
Named the adjacent parties explicitly rather than leaving them to inference:
`zone-engine` has an interest (a coding-agent identity is a strong candidate zone
subject) and `user-engine` is **not** involved — this is a machine principal, not
an end-user account. Stated so nobody concludes it by elimination.
Asked for a refusal-with-pointer as an equally good answer. The failure mode to
avoid is the 2026-08-17 one recorded in `.claude/rules/finding-routing.md`:
ops-warden answered a question well and never routed it, and another repo ended
up filing it.
**Followed up 2026-08-23 after the immediate enforcement gap closed.**
`RAILIANCE-WP-0022` no longer waits for this ownership decision: the platform
owner deployed a dedicated coding-agent AppRole, proved deny-wins when it is
combined with workload read, and identified an exact-bound KeyCape JWT role as
the migration target. That makes the remaining question narrower and more
important rather than obsolete: who owns issuance of the durable
KeyCape/Keycloak-backed machine identity?
Direct follow-up `d25d4604-5713-42a8-8e3a-1ea31b5a5cc7` asks `key-cape` to
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
priority: medium
state_hub_task_id: "75051d17-399b-5129-860b-ae00dae91c47"
```
**Make blocker staleness a mechanism instead of an intention.**
Four stale blockers surfaced in twelve hours: an OpenBao token recorded expired
that was valid, a verification script recorded ready that had never been written,
a ten-day `secrets-engine` question answerable from their source, and
`FLEX-WP-0007` cited as blocking `policy.enabled` seven weeks after it read
`finished`. `.claude/rules/finding-routing.md` has said *re-read a blocker before
trusting it* since `RISK-F-0001`. Saying it has not worked.
`warden route gaps` had a `--stale-days` threshold defaulting to 90, which was
not loose but **inert** — the register was created 2026-08-15, so it could not
fire before November.
**Done 2026-08-21.** Two changes, and the second matters more:
1. **Split the cadences.** `DEFAULT_STALE_DAYS` (90) still governs pointer
freshness — "is this the right owner and page" genuinely is quarterly. New
`DEFAULT_BLOCKER_STALE_DAYS` (14) governs interim blockers, calibrated on the
cases that cost something: ten days for the secrets-engine lanes, one day for
`RISK-F-0001`, ~50 for `FLEX-WP-0007`. At ~15 lanes it surfaces about one a
day rather than a wall, and it fires on zero lanes on age today.
**Then scaled by risk, after risk-nexus answered.** They accepted the offer to
converge and published their convention: 14 days critical/high, 30 medium, 60
low, with fix state *read* from the owning repo rather than remembered. Their
framing — "point `warden route gaps` at those windows and the two will agree
without either of us building a shared mechanism" — is better than a joint
tool, so `blocker_stale_days()` now maps lane `risk` onto exactly those
windows. `ungraded` takes the *shortest*, not the longest: `ADR-0007` makes an
absent grade a defect, so its blocker is the least trustworthy of all.
2. **`verified:` distinguishes re-checking from re-editing.** `reviewed` records
when someone touched the entry; nothing recorded whether the claim was
re-established. `owner-confirmed` and `source-read` count;
**`asked-and-waiting` and `unverified` do not**, and a lane in those states is
stale regardless of its date. `key-cape-oidc-login` is the proof: asked today,
zero days old, correctly flagged.
Current state: 14 non-draft interim lanes — 5 `owner-confirmed`, 1
`asked-and-waiting`, 8 `unverified`. The 8 are honest; they were carried forward
this session without a check and now say so instead of hiding behind a fresh date.
`--fail-on-stale` exits 3 so a cron job or gate can act. **Deliberately not a CI
test on age**: a date-triggered failure breaks the build on a calendar day with
no code change, punishing whoever commits next rather than whoever owns the
blocker. The CI test is structural instead — every interim lane must record
*how* it was verified, which fails on the commit that introduces the omission.
```task
id: WARDEN-WP-0033-T06
status: done
priority: high
state_hub_task_id: "94f77f5a-f919-5328-832c-ba1d24c6431b"
```
**Correct first-time OpenBao administration routing.** `rapp-postgres` reported
on 2026-08-22 that `warden plan` mapped first-time
`database/config/platform-pg-2` administration to the generic
`openbao-api-key` template. It consequently proposed paste-once KV provisioning
and a workload OIDC role, neither of which can configure database connections,
policies, auth roles, or token roles. Their Desk session stopped without an
approval or secret action.
The authoritative platform runbook and rapp-postgres's live T04 evidence agree
on the missing distinction: this is one attended KeyCape-backed OpenBao identity
act at auth mount `netkingdom`, role `platform-admin`. It is not a credential
value handoff. Root stays offline break-glass authority and a workload role must
never be widened to make the operation pass.
Add an exact `openbao-platform-admin-login` lane, an operator playbook, and a
regression that makes the reported request resolve to `founder_required` with
`oidc_login` — never `paste_once_provision`. Verify the route, then return the
corrected non-secret command to rapp-postgres.
**Done 2026-08-22.** The new active lane resolves the exact reported request at
score 20, ahead of the generic KV template at 11, and returns one
`founder_required` act:
`bao login -no-print -method=oidc -path=netkingdom role=platform-admin`.
Planner output offers only `warden access openbao-platform-admin-login --fetch`
and the exact owner command; login lanes no longer inherit secret-value
transports (`--exec`, `--out`, `--wrap`). The lane is explicitly a high-risk,
non-workload human identity act, so the generated boundary artifact lists it as
having no KV address rather than inventing one.
Verification: 384 tests pass, Ruff passes, workload accounting resolves all 28
lanes (3 resolved, 17 unknown, 8 not-applicable), and the boundary invariant
reports 20 high-risk lanes, 14 concrete paths covered, 6 non-KV/pattern lanes,
0 uncovered. No login or credential action was performed.
## Related
- `secrets-engine` `SECRETS-WP-0006` — catalog admission, decision `ae676382`
- `RISK-F-0009` — closed by railiance-platform 2026-08-21; 0 uncovered
- `railiance-platform` `RAILIANCE-WP-0022` (boundary coverage), `RAILIANCE-WP-0017`
- `ADR-0002`, `ADR-0003`, `ADR-0004`, `ADR-0005`, `ADR-0007`
- `WARDEN-WP-0030` — the delegation register these five lanes retire from