From 8f617fcbf4496fb8a3ba2883b40653234bdedaed Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 29 Jun 2026 00:13:09 +0200 Subject: [PATCH] Activate whynot npm credential lane --- ...R-2026-0001-whynot-design-npm-publish.yaml | 26 ++++++++++++---- docs/whynot-design-npm-publish-handoff.md | 30 ++++++++++++------- tests/test_credential_change.py | 24 +++++++-------- ...LIANCE-WP-0006-workload-kv-access-lanes.md | 12 +++++++- ...007-credential-change-approval-workflow.md | 6 ++++ 5 files changed, 67 insertions(+), 31 deletions(-) diff --git a/credential-change-requests/CCR-2026-0001-whynot-design-npm-publish.yaml b/credential-change-requests/CCR-2026-0001-whynot-design-npm-publish.yaml index 686046c..f3bfe69 100644 --- a/credential-change-requests/CCR-2026-0001-whynot-design-npm-publish.yaml +++ b/credential-change-requests/CCR-2026-0001-whynot-design-npm-publish.yaml @@ -3,9 +3,9 @@ kind: credential-change-request schema_version: 1 request_type: workload-kv-read title: whynot-design npm publish token lane -status: applied +status: active created: '2026-06-27' -updated: '2026-06-28' +updated: '2026-06-29' requester: agent: ops-warden message_id: fe5b1696-8956-4bd5-9d6f-dbde1901a076 @@ -78,9 +78,9 @@ access_frontdoor: catalog_id: whynot-design-npm-publish selector: npm publish token command: warden access whynot-design-npm-publish --exec -- npm publish - resolvable: false - readiness: applied-pending-verify - activation: pending-positive-and-negative-caller-verification + resolvable: true + readiness: ready + activation: verified-positive-and-negative-caller-verification risk: classification: high notes: @@ -137,6 +137,22 @@ verification: - The secret value was not printed or recorded. - A short-lived OpenBao client token was printed by the CLI login output and was revoked by accessor immediately after the report. - Negative denial verification is still pending; keep the front door non-resolvable until it passes. + - at: '2026-06-28T22:06:43+00:00' + actor: bernd.worsch + kind: negative_denial_verification + result: passed + details: + - platform-root was temporarily removed from the whynot-design LLDAP group for the attended negative check. + - OIDC login for auth/netkingdom/role/whynot-design-workload-kv-read failed with a groups bound-claim mismatch. + - No OpenBao client token was issued for the negative identity, and no NPM_AUTH_TOKEN value was printed or recorded. + - at: '2026-06-28T22:08:50+00:00' + actor: codex + kind: identity_group_restore + result: passed + details: + - Restored platform-root membership in the whynot-design LLDAP group after negative verification. + - Verified whynot-design membership contains platform-root and no unexpected additional users. + - Positive and negative verification gates are now complete; access_frontdoor is ready/resolvable. lifecycle: deactivate: Disable ops-warden catalog entry and remove or detach auth role policy. rotate: Replace NPM_AUTH_TOKEN value directly in OpenBao and record non-secret rotation diff --git a/docs/whynot-design-npm-publish-handoff.md b/docs/whynot-design-npm-publish-handoff.md index 6839fdb..9c62a8c 100644 --- a/docs/whynot-design-npm-publish-handoff.md +++ b/docs/whynot-design-npm-publish-handoff.md @@ -7,9 +7,10 @@ This is the next-session handoff for `CCR-2026-0001` and the - CCR: `CCR-2026-0001` - Decision: `e6381a56-6b04-4fd5-b2de-f3ef59cde888` -- Status: applied; non-secret OpenBao apply checks passed 2026-06-28 -- Front door: `applied-pending-verify`, `resolvable=false` -- Positive verification: passed 2026-06-28; negative verification pending +- Status: active; non-secret OpenBao apply and verification checks passed +- Front door: `ready`, `resolvable=true` +- Positive verification: passed 2026-06-28 +- Negative verification: passed 2026-06-28 - Catalog id: `whynot-design-npm-publish` - Tenant/org: `coulomb` - Workload/project: `whynot-design` @@ -30,8 +31,10 @@ On 2026-06-28, the attended positive OIDC login advanced from a missing `groups` claim to a bound-claim mismatch. That means the role now requests the `groups` scope correctly, but the authenticating identity is not a member of `whynot-design`. The `whynot-design` LLDAP group was created and verified. -The intended publisher/verifier identity was later added, and positive -verification passed. +The intended publisher/verifier identity was later added, positive +verification passed, then `platform-root` was temporarily removed for negative +verification. The negative check passed with a groups bound-claim mismatch, and +`platform-root` was restored to `whynot-design`. ## Safety Rules @@ -40,8 +43,8 @@ verification passed. - Do not run verification with shell tracing enabled. - Record only non-secret evidence: path, field name, metadata keys, policy name, role name, actor, timestamp, and pass/fail result. -- Do not mark the ops-warden catalog entry ready until positive and negative - verification are complete. +- Mark ops-warden catalog entries ready only after positive and negative + verification are complete. For this lane, both checks have passed. ## OpenBao Secret Check @@ -223,6 +226,11 @@ or store any token value. Record only the denial result and non-secret audit timestamp/request metadata. +The negative verification passed on 2026-06-28. `platform-root` was temporarily +removed from `whynot-design`; OpenBao rejected the OIDC login with a groups +bound-claim mismatch, so no OpenBao client token was issued and the secret was +not read. `platform-root` was then restored to `whynot-design`. + ## Activation Only after these are true: @@ -234,12 +242,12 @@ Only after these are true: - positive verification passed; - negative verification passed; -then `CCR-2026-0001` can move toward `active`, and ops-warden can mark +`CCR-2026-0001` is now `active`, and ops-warden can mark `whynot-design-npm-publish` `ready`/`resolvable=true`. -Until then, keep the front door as: +Current front door: ```text -readiness = applied-pending-verify -resolvable = false +readiness = ready +resolvable = true ``` diff --git a/tests/test_credential_change.py b/tests/test_credential_change.py index 2544654..bbe7ba3 100644 --- a/tests/test_credential_change.py +++ b/tests/test_credential_change.py @@ -52,33 +52,25 @@ class CredentialChangeTests(unittest.TestCase): self.assertIn("whynot-design npm publish token lane", rendered) self.assertIn("platform/workloads/coulomb/whynot-design/npm-publish", rendered) self.assertIn("whynot-design-npm-publish", rendered) - self.assertIn("readiness: applied-pending-verify resolvable=False", rendered) + self.assertIn("readiness: ready resolvable=True", rendered) self.assertIn("approve | deny | needs_changes", rendered) - def test_status_payload_marks_applied_pending_verify_not_resolvable(self) -> None: + def test_status_payload_marks_active_ready_resolvable(self) -> None: ccr, _errors, warnings = credential_change.validate_ccr(self.sample) payload = credential_change.status_payload(ccr, warnings) self.assertFalse(payload["apply_allowed"]) self.assertTrue(payload["apply_complete"]) - self.assertFalse(payload["frontdoor_resolvable"]) - self.assertEqual(payload["status"], "applied") - self.assertEqual(payload["access_frontdoor"]["readiness"], "applied-pending-verify") + self.assertTrue(payload["frontdoor_resolvable"]) + self.assertEqual(payload["status"], "active") + self.assertEqual(payload["access_frontdoor"]["readiness"], "ready") self.assertEqual(payload["access_frontdoor"]["catalog_id"], "whynot-design-npm-publish") self.assertEqual(payload["apply_blockers"], []) + self.assertEqual(payload["frontdoor_blockers"], []) self.assertEqual(payload["warnings"], []) self.assertEqual( payload["state_hub"]["decision_id"], "e6381a56-6b04-4fd5-b2de-f3ef59cde888", ) - self.assertIn( - "front door requires CCR status active, got applied", - payload["frontdoor_blockers"], - ) - self.assertIn( - "front door readiness must be ready, got applied-pending-verify", - payload["frontdoor_blockers"], - ) - self.assertIn("front door is marked resolvable=false", payload["frontdoor_blockers"]) def test_state_hub_rationale_prefix_maps_to_ccr_status(self) -> None: cases = { @@ -101,6 +93,10 @@ class CredentialChangeTests(unittest.TestCase): copied = Path(tmp) / self.sample.name shutil.copy2(self.sample, copied) copied_ccr = credential_change.load_yaml(copied) + copied_ccr["status"] = "proposed" + copied_ccr["access_frontdoor"]["readiness"] = "template" + copied_ccr["access_frontdoor"]["resolvable"] = False + copied_ccr["access_frontdoor"]["activation"] = "pending-review" copied_ccr.setdefault("state_hub", {})[ "decision_id" ] = "250669d0-8475-4527-9624-cd072249f9a9" diff --git a/workplans/RAILIANCE-WP-0006-workload-kv-access-lanes.md b/workplans/RAILIANCE-WP-0006-workload-kv-access-lanes.md index ec8ab69..a7c9661 100644 --- a/workplans/RAILIANCE-WP-0006-workload-kv-access-lanes.md +++ b/workplans/RAILIANCE-WP-0006-workload-kv-access-lanes.md @@ -233,7 +233,7 @@ chat, or workplans. ```task id: RAILIANCE-WP-0006-T05 -status: progress +status: done priority: high state_hub_task_id: "dc1f470b-e78a-48a9-9957-965aed47861f" ``` @@ -259,6 +259,11 @@ metadata, and field presence. Remaining verification is the attended whynot-design OIDC positive check and a non-whynot denial check, both without printing the token. +**2026-06-29:** Positive and negative caller verification passed without +printing the token value. The negative check failed OIDC login with the expected +groups bound-claim mismatch. `platform-root` was restored to the +`whynot-design` group after the temporary negative-test removal. + ## T06 - Coordinate ops-warden catalog activation ```task @@ -291,6 +296,11 @@ the check with explicit `--path` and `--field`, but the dedicated `whynot-design-npm-publish` route is not yet present in the ops-warden routing catalog. Keep activation pending until caller verification and catalog update. +**2026-06-29:** `CCR-2026-0001` is now active with +`access_frontdoor.readiness=ready` and `resolvable=true`. ops-warden still needs +to confirm that its dedicated `whynot-design-npm-publish` catalog selector +resolves through the caller-scoped lane. + ## T07 - Decide whether to batch sibling workload-KV requests ```task diff --git a/workplans/RAILIANCE-WP-0007-credential-change-approval-workflow.md b/workplans/RAILIANCE-WP-0007-credential-change-approval-workflow.md index e98e5ad..93c8fff 100644 --- a/workplans/RAILIANCE-WP-0007-credential-change-approval-workflow.md +++ b/workplans/RAILIANCE-WP-0007-credential-change-approval-workflow.md @@ -296,6 +296,12 @@ OpenBao read policy and OIDC role, confirmed metadata `catalog-id`, and confirme now records non-secret evidence for that apply check. Positive whynot-design and negative non-whynot caller verification still gate `active`/`ready`. +**2026-06-29:** The whynot-design pilot completed OpenBao verification. Positive +fetch succeeded with output suppressed, negative login failed with the expected +groups bound-claim mismatch, `platform-root` membership was restored afterward, +and `CCR-2026-0001` is now active/ready/resolvable. ops-warden catalog +confirmation remains the external closeout step. + ## T08 - Add deactivation, rotation, and compromise flows ```task