ops-warden/workplans/WARDEN-WP-0044-security-case-follow-through.md
tegwick b593c87983
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
test: isolate ordinary unit runs from ambient credentials and provider I/O
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1468b-63fa-7710-85dc-8f2e16b3ebfa
2026-10-17 21:30:12 +02:00

22 KiB
Raw Blame History

id type title domain repo status flavor owner topic_slug created updated depends_on related_repos state_hub_workstream_id
WARDEN-WP-0044 workplan Follow through on KnownSecurityCases along their type's route infotech ops-warden active implementation claude-code netkingdom 2026-10-08 2026-10-11
net-kingdom
ops-mason
key-cape
railiance-platform
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

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).

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.
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.

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.

2026-10-17 safe unit-runner source candidate: make test now selects an existing interpreter and scripts/run_unit_tests.py, which constructs the environment and empty temporary HOME before pytest collection, denies unexpected process/socket use and ambient file opens, and guards the pinned BrowserInputs child too. Closed fixture exceptions cover the synthetic desk endpoint, metadata checkers, exact-byte contract doubles and fixed transport prints; they confer no provider authority. Explicit public declaration fixtures replace ambient HOME source lookups. See docs/development/safe-unit-tests.md and Custodian packet docs/changes/netkingdom-target-2026-10-17/warden-safe-unit-runner-r1. Synthetic token, ambient-path, forged-provider and nested-child regressions are retained alongside the initial failed isolation runs and corrected results. This is a source candidate for the existing safe-test handoff, not an OS sandbox or native case acceptance. T03 remains progress; contained sessions, authenticated owner provenance, materialization, exact type acknowledgment/pin and first native case remain open. No credential lookup, live investigation or rotation occurred.

Candidate validation: ordinary make test under synthetic ambient token/HOME controls passes 783 tests with four integration-marked tests deselected. Affected focused checks pass 117 tests; new runner code/regressions pass Ruff. Retained initial failures exposed fixture dependencies and were corrected, not suppressed.

2026-10-17 root follow-through: the original safe-runner source candidate was independently rejected for O_TRUNC open-write misclassification and unchecked public fixture projection hashes. Both counterexamples are retained. The minimal correction treats truncating/appending opens as writes and adds the closed projection-byte provenance regression. Root inspected the two exact corrections and ran ordinary make test on stable corrected source with only synthetic parent HOME/token/Python/pytest sentinels: 785 passed, four deselected. No real credential or native provider action occurred. Initial author failures and rejected review are preserved in the Custodian warden-safe-unit-runner-r1 and warden-safe-unit-runner-review-r1 packets, with root disposition/full result in warden-safe-unit-integration-r1. This completes the known trusted-unit-entry accident-prevention follow-through; direct pytest bypass, native/non-open/preopened file-descriptor limits remain explicit. No OS sandbox, isolated agent assignment, production grant or native T03 acceptance follows. T03 stays progress.