From 0ae8a0e46703719ab4d8d5ad264faddb9f05d641 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 10 Oct 2026 10:24:51 +0200 Subject: [PATCH] Catalog keycape-client-secret-generate as draft (RPF-WP-0054) Pointer to railiance-platform's credential.py generate for the mint-secret step of oidc-browser-relying-party 1.0. Draft until the issuer policy is bound to the operator OIDC role, key-cape confirms the secret format and the RPF-WP-0054-T05 probe passes. Workload-join not_applicable 17 -> 18. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 427672@bnt-lap001 Assistant-Session: a0a2367e-4697-440c-a4e5-9713c009f6d8 --- pep-stance.yaml | 4 +- registry/routing/catalog.yaml | 43 +++++++++++++++++++ tests/test_workload_join.py | 4 +- .../keycape-client-secret-generate.md | 34 +++++++++++++++ 4 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 wiki/playbooks/keycape-client-secret-generate.md diff --git a/pep-stance.yaml b/pep-stance.yaml index 370db6f..e5d0d54 100644 --- a/pep-stance.yaml +++ b/pep-stance.yaml @@ -98,7 +98,7 @@ on_apply: # 2026-10-08: platform-supplier-credentials added as a not-applicable path pattern, # so routing not_applicable rose 16 -> 17. classification_coverage: - measured: "2026-10-09" + measured: "2026-10-10" attribution: self-measured signing_targets: resolved: 0 @@ -107,7 +107,7 @@ classification_coverage: routing_lanes: resolved: 4 unknown: 22 - not_applicable: 17 + not_applicable: 18 verdict_caching: none input_claim_caching: "registry/flex-auth/production_registry_snapshot.json, rebuilt by scripts/build_flex_auth_registry.py" diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index e9d68ef..615cd66 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -1530,3 +1530,46 @@ entries: exec_capable: false resolvable: false lane: login + + - id: keycape-client-secret-generate + title: Generate a KeyCape client secret inside OpenBao custody (SecurityCase mint-secret) + # Pointer only, draft (WARDEN-WP-0044; railiance-platform RPF-WP-0054, + # message d951386f, 2026-10-09). Lane named by SecurityCaseType + # oidc-browser-relying-party 1.0, step mint-secret + # (value_handling: generated_in_custody). The broker generates the value + # in its own process, writes once with CAS 0, verifies by metadata only and + # returns a receipt with no value. Grant applied (CCR-2026-0040). Not live + # until: the issuer policy is bound to the operator OIDC role (founder), + # key-cape confirms the secret format, and the RPF-WP-0054-T05 disposable + # probe passes. Then railiance-platform confirms and ops-warden activates. + # How warden case run executes it is WARDEN-WP-0044-T03. + risk: high + workload_ref: + applicability: not-applicable + reason: "Per-case generation lane; each case's consuming service gets its own {consuming_service}-keycape-client entry." + need_keywords: [keycape client secret, generate client secret, mint-secret, client-secret-generate, oidc client secret, keycape/client-secret-generate, generated in custody, security case] + owner_repo: railiance-platform + subsystem: railiance-platform credential broker + OpenBao platform/workloads/keycape/ + warden_executes: false + wiki_ref: wiki/playbooks/keycape-client-secret-generate.md#worker-checklist + canon_ref: railiance-platform/workplans/RPF-WP-0054-keycape-client-secret-generate-lane.md + reviewed: "2026-10-10" + status: draft + delegation: + mode: native + intended_owner: railiance-platform + reviewed: "2026-10-10" + verified: owner-confirmed + auth_method: "caller's own OIDC session holding policy credential-broker-keycape-client-secret-generate-issuer; broker mints a 5m create-only grant token (keycape/client-secret-generate). Agents and root refused." + path_template: "platform/workloads/keycape/" + exec_owner: railiance-platform + exec_command: "scripts/credential.py generate --grant keycape/client-secret-generate --client-id --case-file --case-ref @sha256: [--receipt ] [--dry-run]" + exec_capable: false + resolvable: false + lane: secret + rotation: + method: rotate + owner: railiance-platform + automatable: false + steps: + - "This lane covers first generation only and refuses an existing path (exit 3). Rotation is a separate railiance-platform task that does not exist yet; route rotation needs to railiance-platform." diff --git a/tests/test_workload_join.py b/tests/test_workload_join.py index ecca720..e6363e8 100644 --- a/tests/test_workload_join.py +++ b/tests/test_workload_join.py @@ -26,7 +26,9 @@ def test_repo_catalog_uses_only_explicit_workload_references(): # supplier-account path pattern; concrete consumers keep their own lanes. # unknown 22 since 2026-10-09: fluid-telegram-operator (MASON-WP-0005-T06) # names fluid-telegram, which has published no workload declaration. - assert len(report["not_applicable"]) == 17 + # not_applicable 18 since 2026-10-10: keycape-client-secret-generate is a + # per-case generation lane; each case's consumer gets its own entry. + assert len(report["not_applicable"]) == 18 assert {row["lane"] for row in report["resolved"]} == { "ops-warden-warden-sign-token", "issue-core-ingestion-api-key", diff --git a/wiki/playbooks/keycape-client-secret-generate.md b/wiki/playbooks/keycape-client-secret-generate.md new file mode 100644 index 0000000..2d49e44 --- /dev/null +++ b/wiki/playbooks/keycape-client-secret-generate.md @@ -0,0 +1,34 @@ +# Generate a KeyCape client secret in custody + +Catalog: `keycape-client-secret-generate` (status `draft`, pointer only) +Owner: `railiance-platform` credential broker (RPF-WP-0054, grant applied by CCR-2026-0040) +Used by: SecurityCaseType `oidc-browser-relying-party` 1.0, step `mint-secret` + +## Worker checklist + +This page is a pointer. ops-warden does not generate, read or hold the value. + +1. The case must be `materialized`, `client_type: confidential`, with a + `case-ref` from `warden case plan `. +2. Run the owner command from `~/railiance-platform` in your own terminal: + + ```bash + scripts/credential.py generate --grant keycape/client-secret-generate \ + --client-id --case-file \ + --case-ref @sha256: --receipt + ``` + + The broker re-derives the case-ref, checks status, type and `client_id`, + proves the path is absent, and writes once with CAS 0 to + `platform/workloads/keycape/`. It prints nothing. +3. Exit codes: 0 generated (or dry-run ok), 2 precondition, 3 already present + (never overwritten), 4 token or write failure, 5 verify failure. +4. Verify from the receipt and metadata only (version 1). Never read the value. + +Refused for agent sessions (`WARDEN_AGENT_ID`), root, and callers without the +issuer policy. + +Status: draft. The lane is live only once the issuer policy is bound to the +operator OIDC role (founder), key-cape has confirmed the secret format, and the +RPF-WP-0054-T05 disposable probe has passed. railiance-platform confirms, and +ops-warden then activates the entry.