Mark whynot lane applied pending verification

This commit is contained in:
2026-06-28 12:53:39 +02:00
parent 271aa94642
commit adf865611c
5 changed files with 29 additions and 17 deletions

View File

@@ -3,7 +3,7 @@ kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: whynot-design npm publish token lane
status: approved
status: applied
created: '2026-06-27'
updated: '2026-06-28'
requester:
@@ -73,8 +73,8 @@ access_frontdoor:
selector: npm publish token
command: warden access whynot-design-npm-publish --exec -- npm publish
resolvable: false
readiness: template
activation: draft-until-ccr-verified
readiness: applied-pending-verify
activation: pending-positive-and-negative-caller-verification
risk:
classification: high
notes:

View File

@@ -7,8 +7,8 @@ This is the next-session handoff for `CCR-2026-0001` and the
- CCR: `CCR-2026-0001`
- Decision: `e6381a56-6b04-4fd5-b2de-f3ef59cde888`
- Status: approved; non-secret OpenBao apply checks passed 2026-06-28
- Front door: `template`, `resolvable=false`
- Status: applied; non-secret OpenBao apply checks passed 2026-06-28
- Front door: `applied-pending-verify`, `resolvable=false`
- Catalog id: `whynot-design-npm-publish`
- Tenant/org: `coulomb`
- Workload/project: `whynot-design`
@@ -202,6 +202,6 @@ then `CCR-2026-0001` can move toward `active`, and ops-warden can mark
Until then, keep the front door as:
```text
readiness = template
readiness = applied-pending-verify
resolvable = false
```

View File

@@ -30,7 +30,7 @@ Ops-warden batch follow-up:
| KV mount | `platform` |
| OpenBao CLI path | `platform/workloads/coulomb/whynot-design/npm-publish` |
| Secret field | `NPM_AUTH_TOKEN` |
| Front-door readiness | `template`, `resolvable=false` until CCR verification |
| Front-door readiness | `applied-pending-verify`, `resolvable=false` until caller verification |
| Read policy | `workload-kv-read-whynot-design-npm-publish` |
| Policy file | `openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl` |
| OIDC auth mount | `netkingdom` |
@@ -205,6 +205,6 @@ flex-auth ref: secret.read:whynot-design, if tenant policy requires it
runbook: docs/workload-kv-access-lanes.md
```
Until live provisioning and verification are complete, ops-warden should keep
the catalog entry in `template`/`draft` or equivalent non-active state with
Until positive and negative caller verification are complete, ops-warden should
keep the catalog entry in `applied-pending-verify`/non-active state with
`resolvable=false`.

View File

@@ -34,6 +34,7 @@ ALLOWED_STATUSES = {
"cancelled",
}
APPLY_ALLOWED_STATUSES = {"approved"}
POST_APPLY_STATUSES = {"applied", "verified", "active"}
SECRET_MARKERS = [
"AGE-SECRET-KEY-1",
"-----BEGIN PRIVATE KEY-----",
@@ -435,8 +436,11 @@ def validate_or_exit(path: Path) -> tuple[dict[str, Any], list[str]]:
def apply_blockers(ccr: dict[str, Any]) -> list[str]:
blockers: list[str] = []
if ccr.get("status") not in APPLY_ALLOWED_STATUSES:
blockers.append(f"apply requires status approved, got {ccr.get('status')}")
status = ccr.get("status")
if status in POST_APPLY_STATUSES:
return blockers
if status not in APPLY_ALLOWED_STATUSES:
blockers.append(f"apply requires status approved, got {status}")
if ccr["openbao"]["auth"].get("bound_claims_confirmed") is not True:
blockers.append("apply requires confirmed OpenBao auth binding")
return blockers
@@ -467,7 +471,8 @@ def status_payload(ccr: dict[str, Any], warnings: list[str]) -> dict[str, Any]:
"title": ccr["title"],
"status": ccr["status"],
"request_type": ccr["request_type"],
"apply_allowed": not apply_blocked_by,
"apply_allowed": ccr.get("status") in APPLY_ALLOWED_STATUSES and not apply_blocked_by,
"apply_complete": ccr.get("status") in POST_APPLY_STATUSES,
"apply_blockers": apply_blocked_by,
"frontdoor_resolvable": not frontdoor_blocked_by,
"frontdoor_blockers": frontdoor_blocked_by,
@@ -504,6 +509,7 @@ def render_status(payload: dict[str, Any]) -> str:
f"Readiness: {payload['access_frontdoor']['readiness']}",
f"Resolvable: {payload['frontdoor_resolvable']}",
f"Apply allowed: {payload['apply_allowed']}",
f"Apply complete: {payload.get('apply_complete') is True}",
]
decision = payload.get("state_hub", {}).get("decision_api_url")
dashboard = payload.get("state_hub", {}).get("decision_dashboard_url")

View File

@@ -52,15 +52,17 @@ 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: template resolvable=False", rendered)
self.assertIn("readiness: applied-pending-verify resolvable=False", rendered)
self.assertIn("approve | deny | needs_changes", rendered)
def test_status_payload_marks_template_not_resolvable(self) -> None:
def test_status_payload_marks_applied_pending_verify_not_resolvable(self) -> None:
ccr, _errors, warnings = credential_change.validate_ccr(self.sample)
payload = credential_change.status_payload(ccr, warnings)
self.assertTrue(payload["apply_allowed"])
self.assertFalse(payload["apply_allowed"])
self.assertTrue(payload["apply_complete"])
self.assertFalse(payload["frontdoor_resolvable"])
self.assertEqual(payload["access_frontdoor"]["readiness"], "template")
self.assertEqual(payload["status"], "applied")
self.assertEqual(payload["access_frontdoor"]["readiness"], "applied-pending-verify")
self.assertEqual(payload["access_frontdoor"]["catalog_id"], "whynot-design-npm-publish")
self.assertEqual(payload["apply_blockers"], [])
self.assertEqual(payload["warnings"], [])
@@ -69,7 +71,11 @@ class CredentialChangeTests(unittest.TestCase):
"e6381a56-6b04-4fd5-b2de-f3ef59cde888",
)
self.assertIn(
"front door requires CCR status active, got approved",
"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"])