From 1b36e147e3e5525e1719af117f176e175348fb33 Mon Sep 17 00:00:00 2001 From: codex Date: Fri, 9 Oct 2026 11:47:09 +0200 Subject: [PATCH] RPF-WP-0035-T02: record founder approval and delegated apply of CCR-2026-0038 Service-JWT login lane (mount keycape-services, role secrets-engine-openbao, policy secrets-engine-login-self) applied 2026-10-08T22:42Z with matching readback. T02 now waits only on the live login proof (SECRETS-WP-0012-T03). Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 469992@bnt-lap001 Assistant-Session: e4b8e420-df0a-441d-83ae-7f19130594d9 --- WORK-RECORDS.md | 4 +- ...0038-secrets-engine-service-jwt-login.yaml | 86 ++++++++++++------- tests/test_service_jwt_lane.py | 13 ++- ...-WP-0035-credential-lane-implementation.md | 2 +- 4 files changed, 69 insertions(+), 36 deletions(-) diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 16ef156..77e0895 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -125,8 +125,8 @@ | task | RPF-WP-0053-T02 | wait | — | workplans/RPF-WP-0053-coulomb-paired-backup-admission.md | | task | RPF-WP-0053-T03 | wait | — | workplans/RPF-WP-0053-coulomb-paired-backup-admission.md | | task | RPF-WP-0053-T04 | todo | — | workplans/RPF-WP-0053-coulomb-paired-backup-admission.md | -| task | RPF-WP-0053-T05 | wait | — | workplans/RPF-WP-0053-coulomb-paired-backup-admission.md | -| task | RPF-WP-0053-T06 | progress | — | workplans/RPF-WP-0053-coulomb-paired-backup-admission.md | +| task | RPF-WP-0053-T05 | progress | — | workplans/RPF-WP-0053-coulomb-paired-backup-admission.md | +| task | RPF-WP-0053-T06 | done | — | workplans/RPF-WP-0053-coulomb-paired-backup-admission.md | | intake | RPF-IN-0001 | closed | — | intakes/intakes.md | | intake | RPF-IN-0002 | open | — | intakes/intakes.md | | intake | RPF-IN-0003 | open | — | intakes/intakes.md | diff --git a/credential-change-requests/CCR-2026-0038-secrets-engine-service-jwt-login.yaml b/credential-change-requests/CCR-2026-0038-secrets-engine-service-jwt-login.yaml index 5a020cb..b36e1bc 100644 --- a/credential-change-requests/CCR-2026-0038-secrets-engine-service-jwt-login.yaml +++ b/credential-change-requests/CCR-2026-0038-secrets-engine-service-jwt-login.yaml @@ -2,30 +2,45 @@ id: CCR-2026-0038 kind: credential-change-request schema_version: 1 request_type: service-jwt-login -title: secrets-engine-openbao KeyCape service-JWT login (isolated mount, login-only policy) -status: proposed +title: secrets-engine-openbao KeyCape service-JWT login (isolated mount, login-only + policy) +status: applied created: '2026-10-09' -updated: '2026-10-09' +updated: '2026-10-08' requester: agent: railiance-platform reason: RPF-WP-0035-T02. KEY-WP-0037 finished 2026-10-07 (registration live, issuance - verified 10/10, key-cape e0b5fae); CCR-2026-0033/0034 applied. Design - docs/credential-lane-designs/secrets-engine-service-jwt.md; source bundle prepared - 2026-09-27. ops-mason MASON-WP-0009-T05 waits on this lane to recheck invariant (ii). + verified 10/10, key-cape e0b5fae); CCR-2026-0033/0034 applied. Design docs/credential-lane-designs/secrets-engine-service-jwt.md; + source bundle prepared 2026-09-27. ops-mason MASON-WP-0009-T05 waits on this lane + to recheck invariant (ii). review: required: true required_approvers: - platform-owner - key-cape-owner - secrets-engine-owner - comments: [] + comments: + - at: '2026-10-08T22:42:07+00:00' + reviewer: platform-owner, key-cape-owner, secrets-engine-owner (founder Bernd + Worsch) + decision: approved + comment: 'Approve service-JWT login lane: mount keycape-services, role secrets-engine-openbao, + policy secrets-engine-login-self (self endpoints + deny on the client-secret + path).' + - at: '2026-10-08T22:42:07+00:00' + reviewer: founder + decision: binding_confirmed + comment: 'Bound claims match KeyCape registration: aud secrets-engine-openbao, + sub service:secrets-engine, principal_type service, tenant tenant:platform, + roles secrets-engine, scope openbao:login; issuer https://kc.coulomb.social + RS256.' target: domain: infotech tenant: platform workload: secrets-engine environment: production - purpose: Let secrets-engine log in to OpenBao with a KeyCape-issued service JWT and - receive a 5-minute, 8-use token that can only inspect and revoke itself. + purpose: Let secrets-engine log in to OpenBao with a KeyCape-issued service JWT + and receive a 5-minute, 8-use token that can only inspect and revoke itself. openbao: policy_name: secrets-engine-login-self policy_file: openbao/policies/secrets-engine-login-self.hcl @@ -38,16 +53,15 @@ openbao: config_file: openbao/auth/keycape-services-config.json role: secrets-engine-openbao role_file: openbao/auth/secrets-engine-jwt-role.json - bound_claims_confirmed: false + bound_claims_confirmed: true founder_confirmation_items: -- bound_claims_confirmed stays false until the founder confirms the binding against the - KeyCape registration (aud secrets-engine-openbao, sub service:secrets-engine, - principal_type service, tenant tenant:platform, roles secrets-engine, scope - openbao:login; issuer https://kc.coulomb.social, RS256). applier-dry-run refuses - until then. +- bound_claims_confirmed stays false until the founder confirms the binding against + the KeyCape registration (aud secrets-engine-openbao, sub service:secrets-engine, + principal_type service, tenant tenant:platform, roles secrets-engine, scope openbao:login; + issuer https://kc.coulomb.social, RS256). applier-dry-run refuses until then. - The isolated mount keycape-services is new (ops-mason survey 2026-10-07 found no - auth/jwt or keycape-services mount). The applier refuses if the path exists with a - type other than jwt. + auth/jwt or keycape-services mount). The applier refuses if the path exists with + a type other than jwt. access_frontdoor: type: none catalog_id: none @@ -64,27 +78,41 @@ risk: plus explicit deny on the client-secret data and metadata paths (MASON-WP-0009 invariant (ii)); no KV read, policy/auth write, SecretID or child token. - A JWT may be replayed while valid (15m); residual access is bounded by the 5m/8-use - OpenBao token. In an incident, delete the role, revoke issued tokens; do not disable a - shared mount. + OpenBao token. In an incident, delete the role, revoke issued tokens; do not disable + a shared mount. verification: positive: - - Readback after apply matches source for the policy text, mount type jwt, config and - role (done by applier-apply; prints nothing). - - A secrets-engine --auth service-jwt run (SECRETS-WP-0012-T03 probe-openbao) logs in; - the token's policies are exactly [secrets-engine-login-self]; revoke-self succeeds. + - Readback after apply matches source for the policy text, mount type jwt, config + and role (done by applier-apply; prints nothing). + - A secrets-engine --auth service-jwt run (SECRETS-WP-0012-T03 probe-openbao) logs + in; the token's policies are exactly [secrets-engine-login-self]; revoke-self + succeeds. negative: - - sys/capabilities-self for the service token returns deny on both guarded paths and - on sys/policies/acl/*, auth/*/role/*, auth/token/create. - - Wrong audience, subject, tenant, principal_type, role or scope, a coding-agent JWT - and an expired JWT are refused. + - sys/capabilities-self for the service token returns deny on both guarded paths + and on sys/policies/acl/*, auth/*/role/*, auth/token/create. + - Wrong audience, subject, tenant, principal_type, role or scope, a coding-agent + JWT and an expired JWT are refused. - A failed login never falls back to bootstrap/env providers. activation_conditions: - Founder approval of this CCR (three reviews) and bound_claims_confirmed true. - evidence: [] + evidence: + - at: '2026-10-08T22:42:13+00:00' + actor: founder + kind: delegated_metadata_apply + result: passed + details: + - Delegated metadata applier ran as founder using local bao CLI ambient authority. + - 'Policy metadata write: sys/policies/acl/secrets-engine-login-self' + - 'JWT auth mount ensured: sys/auth/keycape-services (type jwt)' + - 'Auth config write: auth/keycape-services/config' + - 'Auth role metadata write: auth/keycape-services/role/secrets-engine-openbao' + - Readback matched source for policy, mount type, config and role. + - No secret values were read, written, printed, or accepted in argv. lifecycle: deactivate: Delete auth/keycape-services/role/secrets-engine-openbao, then the policy; removing the exclusively owned empty mount is a later review. - rotate: Not applicable; the client secret rotates through the CCR-2026-0033 custody child. + rotate: Not applicable; the client secret rotates through the CCR-2026-0033 custody + child. compromised: KeyCape disables the registration; platform deletes the role and revokes issued tokens; tokens are 5m/8-use and self-revoked. state_hub: diff --git a/tests/test_service_jwt_lane.py b/tests/test_service_jwt_lane.py index ec53c60..803aac7 100644 --- a/tests/test_service_jwt_lane.py +++ b/tests/test_service_jwt_lane.py @@ -52,12 +52,17 @@ elif args[0] == "read": class ServiceJwtLaneTests(unittest.TestCase): - def test_ccr_validates_and_is_not_yet_applicable(self): + def test_ccr_validates_and_records_the_delegated_apply(self): _ccr, errors, _w = cc.validate_ccr(CCR_PATH) self.assertEqual(errors, []) - blockers = cc.applier_readiness_blockers(_ccr) - self.assertIn("applier requires confirmed OpenBao auth binding", blockers) - self.assertTrue(any("got proposed" in b for b in blockers)) + self.assertEqual(_ccr["status"], "applied") + self.assertTrue(_ccr["openbao"]["auth"]["bound_claims_confirmed"]) + evidence = _ccr["verification"]["evidence"] + self.assertTrue( + any(e["kind"] == "delegated_metadata_apply" and e["result"] == "passed" + for e in evidence), + evidence, + ) def test_invariant_ii_policy_has_no_capability_on_the_client_secret_path(self): policy = (ROOT / "openbao/policies/secrets-engine-login-self.hcl").read_text() diff --git a/workplans/RPF-WP-0035-credential-lane-implementation.md b/workplans/RPF-WP-0035-credential-lane-implementation.md index 908c5cd..4afbeeb 100644 --- a/workplans/RPF-WP-0035-credential-lane-implementation.md +++ b/workplans/RPF-WP-0035-credential-lane-implementation.md @@ -47,7 +47,7 @@ status: wait needs_human: true decision_id: 62aa95e4-3ccc-4867-8806-5e3db005b483 depends_on: [KEY-WP-0037-T02, KEY-WP-0037-T03, KEY-WP-0037-T04] -blocking_reason: "Source ready (CCR-2026-0038, service-jwt-login applier type). Waits on founder approval + binding confirmation + delegated apply (one command, see 2026-10-09 note), then the login proof via a real KeyCape service JWT (SECRETS-WP-0012-T03 probe-openbao)." +blocking_reason: "CCR-2026-0038 approved, binding confirmed and applied by the founder 2026-10-08T22:42Z (readback matched; evidence in the CCR). Waits only on the login proof with a real KeyCape service JWT (SECRETS-WP-0012-T03 probe-openbao) and the negative checks listed in the CCR." priority: high state_hub_task_id: "e0c82ea9-05a5-537e-8fbf-67534263572e" ```