diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index c0b2fce..fdc559d 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -1544,8 +1544,9 @@ entries: # probe passes. Then railiance-platform confirms and ops-warden activates. # 2026-10-10: issuer role bound (CCR-2026-0043) and T05 probe passed # (railiance-platform 21b8af3: generated v1, second run exit 3, grant token - # revoked, value_reads 0). Still draft at the owner's request until - # key-cape confirms the secret format. + # revoked, value_reads 0). Activated 2026-10-10 on railiance-platform's + # go-ahead (message 20973a9c) after key-cape confirmed the secret format + # (message 4e0213b3); RPF-WP-0054 T01, T03, T05 done. # How warden case run executes it is WARDEN-WP-0044-T03. risk: high workload_ref: @@ -1558,7 +1559,7 @@ entries: 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 + status: active delegation: mode: native intended_owner: railiance-platform diff --git a/tests/test_case_type.py b/tests/test_case_type.py index bec2ed6..488c7cf 100644 --- a/tests/test_case_type.py +++ b/tests/test_case_type.py @@ -120,8 +120,9 @@ def test_cli_exit_codes(tmp_path): @pytest.mark.skipif(not LIVE_TYPE.exists(), reason="net-kingdom checkout not present") def test_live_oidc_rp_type_schema_conforms(catalog): - """The revised 1.0 type meets R1-R3/R5-R7; only the two owner lanes are outstanding.""" + """The acknowledged 1.0 type is plannable: every lane it names is active (2026-10-10).""" report = check_follow_through(load_type(LIVE_TYPE), catalog) assert report.schema_ok, report.findings + assert report.plannable, report.findings assert report.attended_lanes == ["key-cape-oidc-login"] - assert {f.code for f in report.findings} <= {"LANE-MISSING", "LANE-UNREVIEWED"} + assert report.warden_steps == ["mint-secret"] diff --git a/tests/test_routing.py b/tests/test_routing.py index 1943aba..0161a38 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -137,6 +137,18 @@ def test_ops_warden_warden_sign_lane_has_native_exec(): assert e.resolvable is False # broker lane — owner exec, not warden access --fetch +def test_keycape_client_secret_generate_is_owner_native_and_never_proxied(): + """WARDEN-WP-0044 / RPF-WP-0054: generate-in-custody lane for SecurityCase mint-secret.""" + catalog = load_catalog(_repo_catalog()) + e = catalog.get("keycape-client-secret-generate") + assert e is not None and e.is_active and e.owner_repo == "railiance-platform" + assert e.has_native_exec is True and e.exec_owner == "railiance-platform" + assert "credential.py generate" in e.exec_command + assert "--case-ref" in e.exec_command and "--case-file" in e.exec_command + assert e.warden_executes is False and e.exec_capable is False + assert e.risk == "high" and e.rotation is not None + + def test_route_find_vault_token_ops_warden_prefers_broker_lane(): catalog = load_catalog(_repo_catalog()) matches = catalog.find("VAULT_TOKEN ops-warden warden sign", limit=3) diff --git a/wiki/CredentialRouting.md b/wiki/CredentialRouting.md index e741543..85e82d9 100644 --- a/wiki/CredentialRouting.md +++ b/wiki/CredentialRouting.md @@ -107,6 +107,7 @@ lists the interim set — WARDEN-WP-0030). | `binky-qonto-api` | "tenant Qonto API on `tenants/binky/qonto-api` (API_KEY+API_USER)" | `warden access binky-qonto-api --out FILE` (`risk: high`) | | `net-kingdom-lldap-bind-credential` | "railiance-platform custody for the LLDAP bind credential used by identity-provisioner and the privacyIDEA resolver" | Follow the owner-approved NetKingdom reconciliation runbook; lane is currently unresolved and never fetches a value | | `net-kingdom-privacyidea-admin-token` | "railiance-platform custody for the privacyIDEA administrative token used by attended resolver reconciliation" | Follow the owner-approved NetKingdom reconciliation runbook; lane is currently unresolved and never fetches a value | +| `keycape-client-secret-generate` | "railiance-platform's broker generates a KeyCape client secret inside custody for an accepted SecurityCase. The value is never returned" | `bao login` to role `credential-broker-keycape-client-secret-generate`, then `credential.py generate --case-file ... --case-ref ...` (see playbook). Agents are refused | Promotion criteria: `wiki/playbooks/catalog-lane-promotion.md`. High-risk / agent boundary: `wiki/playbooks/agent-read-boundary.md`. @@ -121,6 +122,7 @@ EXPOSED taint: `wiki/playbooks/exposed-taint.md` · `warden taint `. | --- | --- | --- | | `object-storage-sts` | NK-WP-0007 STS vending path | `wiki/playbooks/object-storage-sts.md` | | `database-dynamic-credentials` | OpenBao database secrets engine | `wiki/playbooks/database-dynamic-credentials.md` | +| `fluid-telegram-operator` | ops-mason attended OIDC lane for the Hall of Helix campaign (pending owner-run checks) | `wiki/playbooks/fluid-telegram-operator.md` | ops-warden answers *where + who + how*. The worker still acts on the owning system. When `warden access` proxies a non-SSH lane, it does so as the caller and stores no diff --git a/wiki/playbooks/keycape-client-secret-generate.md b/wiki/playbooks/keycape-client-secret-generate.md index e44daa4..225abe4 100644 --- a/wiki/playbooks/keycape-client-secret-generate.md +++ b/wiki/playbooks/keycape-client-secret-generate.md @@ -1,6 +1,6 @@ # Generate a KeyCape client secret in custody -Catalog: `keycape-client-secret-generate` (status `draft`, pointer only) +Catalog: `keycape-client-secret-generate` (status `active`, 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` @@ -36,8 +36,7 @@ This page is a pointer. ops-warden does not generate, read or hold the value. Refused for agent sessions (`WARDEN_AGENT_ID`), root, and callers without the issuer policy. -Status: draft. The issuer role is bound (CCR-2026-0043), and the RPF-WP-0054-T05 -disposable probe passed on 2026-10-10 (railiance-platform -`docs/evidence/2026-10-10-keycape-client-secret-generate-probe.json`). The lane -still waits for key-cape to confirm the secret format (length and alphabet). -railiance-platform then sends the go-ahead, and ops-warden activates the entry. +Status: active since 2026-10-10. The issuer role is bound (CCR-2026-0043), and +the RPF-WP-0054-T05 disposable probe passed (railiance-platform +`docs/evidence/2026-10-10-keycape-client-secret-generate-probe.json`). key-cape +confirmed the secret format the same day. diff --git a/workplans/WARDEN-WP-0044-security-case-follow-through.md b/workplans/WARDEN-WP-0044-security-case-follow-through.md index 31b7595..679e9e9 100644 --- a/workplans/WARDEN-WP-0044-security-case-follow-through.md +++ b/workplans/WARDEN-WP-0044-security-case-follow-through.md @@ -143,8 +143,8 @@ reaches the plan unrendered. ```task id: WARDEN-WP-0044-T03 status: wait -depends_on: [WARDEN-WP-0044-T02, MASON-WP-0010-T02] -blocking_reason: "The Forgejo case must be materialized (MASON-WP-0010-T02), and lane keycape-client-secret-generate needs railiance-platform's generate-in-custody entry point." +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" ``` @@ -188,6 +188,12 @@ activated: `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