ops-warden/workplans/WARDEN-WP-0044-security-case-follow-through.md
tegwick 64142527a7 Activate keycape-client-secret-generate (RPF-WP-0054 done)
railiance-platform's go-ahead (message 20973a9c) after key-cape confirmed the
secret format and the T05 probe passed. Promotion checklist: owner confirmed,
playbook, owner-native exec, probe evidence, rotation and delegation present;
routing test added. The live oidc-browser-relying-party type is now plannable.
CredentialRouting lists the lane and adds fluid-telegram-operator to drafts.
WP-0044-T03 now waits only on the Forgejo case materializing (MASON-WP-0010-T03).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 427672@bnt-lap001
Assistant-Session: a0a2367e-4697-440c-a4e5-9713c009f6d8
2026-10-10 13:16:48 +02:00

211 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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-09"
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: wait
depends_on: [WARDEN-WP-0044-T02, MASON-WP-0010-T03]
blocking_reason: "The Forgejo case must be materialized (MASON-WP-0010-T03) before a run can be built and proven against it."
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.
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).
```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.