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 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 427672@bnt-lap001
Assistant-Session: a0a2367e-4697-440c-a4e5-9713c009f6d8
This commit is contained in:
tegwick 2026-10-10 10:24:51 +02:00
parent 919b9ab3e5
commit 0ae8a0e467
4 changed files with 82 additions and 3 deletions

View file

@ -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"

View file

@ -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/<client_id>"
exec_owner: railiance-platform
exec_command: "scripts/credential.py generate --grant keycape/client-secret-generate --client-id <client_id> --case-file <case.yaml> --case-ref <case_id>@sha256:<hex64> [--receipt <file>] [--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."

View file

@ -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",

View file

@ -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 <case.yaml>`.
2. Run the owner command from `~/railiance-platform` in your own terminal:
```bash
scripts/credential.py generate --grant keycape/client-secret-generate \
--client-id <client_id> --case-file <case.yaml> \
--case-ref <case_id>@sha256:<hex64> --receipt <file>
```
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/<client_id>`. 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.