Correct whynot credential tenant path
This commit is contained in:
parent
ad47a136f7
commit
eb24e04b71
10 changed files with 67 additions and 48 deletions
|
|
@ -3,9 +3,9 @@ kind: credential-change-request
|
||||||
schema_version: 1
|
schema_version: 1
|
||||||
request_type: workload-kv-read
|
request_type: workload-kv-read
|
||||||
title: whynot-design npm publish token lane
|
title: whynot-design npm publish token lane
|
||||||
status: approved
|
status: proposed
|
||||||
created: '2026-06-27'
|
created: '2026-06-27'
|
||||||
updated: '2026-06-27'
|
updated: '2026-06-28'
|
||||||
requester:
|
requester:
|
||||||
agent: ops-warden
|
agent: ops-warden
|
||||||
message_id: fe5b1696-8956-4bd5-9d6f-dbde1901a076
|
message_id: fe5b1696-8956-4bd5-9d6f-dbde1901a076
|
||||||
|
|
@ -26,15 +26,22 @@ review:
|
||||||
decision: approved
|
decision: approved
|
||||||
comment: 'State Hub decision 250669d0-8475-4527-9624-cd072249f9a9: APPROVE: scoped
|
comment: 'State Hub decision 250669d0-8475-4527-9624-cd072249f9a9: APPROVE: scoped
|
||||||
path and confirmed binding are acceptable'
|
path and confirmed binding are acceptable'
|
||||||
|
- at: '2026-06-27T22:54:20+00:00'
|
||||||
|
reviewer: bernd.worsch
|
||||||
|
decision: scope_corrected_requires_review
|
||||||
|
comment: Corrected tenant from whynot-design to coulomb per operator clarification.
|
||||||
|
The previous approval covered platform/workloads/whynot-design/whynot-design/npm-publish
|
||||||
|
and must not be reused for the corrected platform/workloads/coulomb/whynot-design/npm-publish
|
||||||
|
scope.
|
||||||
target:
|
target:
|
||||||
domain: financials
|
domain: financials
|
||||||
tenant: whynot-design
|
tenant: coulomb
|
||||||
workload: whynot-design
|
workload: whynot-design
|
||||||
environment: production
|
environment: production
|
||||||
purpose: npm package publishing through ops-warden caller-scoped fetch/exec
|
purpose: npm package publishing through ops-warden caller-scoped fetch/exec
|
||||||
openbao:
|
openbao:
|
||||||
mount: platform
|
mount: platform
|
||||||
kv_path: platform/workloads/whynot-design/whynot-design/npm-publish
|
kv_path: platform/workloads/coulomb/whynot-design/npm-publish
|
||||||
fields:
|
fields:
|
||||||
- NPM_AUTH_TOKEN
|
- NPM_AUTH_TOKEN
|
||||||
policy_name: workload-kv-read-whynot-design-npm-publish
|
policy_name: workload-kv-read-whynot-design-npm-publish
|
||||||
|
|
@ -90,7 +97,6 @@ state_hub:
|
||||||
related_workplan_id: RAILIANCE-WP-0006
|
related_workplan_id: RAILIANCE-WP-0006
|
||||||
ops_warden_reply_message_id: b175c561-7858-43f5-a309-949b0dede1b4
|
ops_warden_reply_message_id: b175c561-7858-43f5-a309-949b0dede1b4
|
||||||
ops_warden_batch_message_id: fe5b1696-8956-4bd5-9d6f-dbde1901a076
|
ops_warden_batch_message_id: fe5b1696-8956-4bd5-9d6f-dbde1901a076
|
||||||
decision_id: 250669d0-8475-4527-9624-cd072249f9a9
|
superseded_decision_id: 250669d0-8475-4527-9624-cd072249f9a9
|
||||||
decision_api_url: http://127.0.0.1:8000/decisions/250669d0-8475-4527-9624-cd072249f9a9
|
superseded_decision_resolved_at: '2026-06-27T22:04:32.956077Z'
|
||||||
decision_dashboard_url: http://127.0.0.1:3000/decisions
|
superseded_decision_reason: tenant/workload scope corrected before secret provisioning
|
||||||
decision_resolved_at: '2026-06-27T22:04:32.956077Z'
|
|
||||||
|
|
|
||||||
|
|
@ -137,12 +137,16 @@ Default pattern:
|
||||||
workload namespace.
|
workload namespace.
|
||||||
3. Reference that Kubernetes Secret from the Deployment, Job, or CronJob.
|
3. Reference that Kubernetes Secret from the Deployment, Job, or CronJob.
|
||||||
|
|
||||||
Path convention:
|
Path convention for workload credential custody:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
platform/workloads/<namespace>/<service-account>/<secret-name>
|
platform/workloads/<tenant-or-org>/<workload>/<secret-purpose>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Kubernetes namespace and service-account bounds belong in the OpenBao auth role
|
||||||
|
or External Secrets binding, not in the tenant segment unless the namespace is
|
||||||
|
itself the approved workload identity.
|
||||||
|
|
||||||
Use CSI-mounted files only for workloads that need file references, sharper
|
Use CSI-mounted files only for workloads that need file references, sharper
|
||||||
mount boundaries, or refresh behavior that should not rewrite application
|
mount boundaries, or refresh behavior that should not rewrite application
|
||||||
manifests. Do not use the OpenBao injector in the current deployment.
|
manifests. Do not use the OpenBao injector in the current deployment.
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ A reviewer should see a concise rendered proposal:
|
||||||
Request: whynot-design npm publish token lane
|
Request: whynot-design npm publish token lane
|
||||||
Type: workload-kv-read
|
Type: workload-kv-read
|
||||||
Mount/path/field:
|
Mount/path/field:
|
||||||
platform/workloads/whynot-design/whynot-design/npm-publish
|
platform/workloads/coulomb/whynot-design/npm-publish
|
||||||
NPM_AUTH_TOKEN
|
NPM_AUTH_TOKEN
|
||||||
Policy:
|
Policy:
|
||||||
workload-kv-read-whynot-design-npm-publish
|
workload-kv-read-whynot-design-npm-publish
|
||||||
|
|
|
||||||
|
|
@ -395,7 +395,7 @@ tenant contract):
|
||||||
Path convention:
|
Path convention:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
platform/workloads/<namespace>/<service-account>/<secret-name>
|
platform/workloads/<tenant-or-org>/<workload>/<secret-purpose>
|
||||||
platform/object-storage/<consumer>
|
platform/object-storage/<consumer>
|
||||||
platform/databases/<consumer>
|
platform/databases/<consumer>
|
||||||
platform/operators/<purpose>
|
platform/operators/<purpose>
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,10 @@ Ops-warden batch follow-up:
|
||||||
| Item | Value |
|
| Item | Value |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| ops-warden catalog id | `whynot-design-npm-publish` |
|
| ops-warden catalog id | `whynot-design-npm-publish` |
|
||||||
|
| Tenant/org | `coulomb` |
|
||||||
|
| Workload/project | `whynot-design` |
|
||||||
| KV mount | `platform` |
|
| KV mount | `platform` |
|
||||||
| OpenBao CLI path | `platform/workloads/whynot-design/whynot-design/npm-publish` |
|
| OpenBao CLI path | `platform/workloads/coulomb/whynot-design/npm-publish` |
|
||||||
| Secret field | `NPM_AUTH_TOKEN` |
|
| Secret field | `NPM_AUTH_TOKEN` |
|
||||||
| Front-door readiness | `template`, `resolvable=false` until CCR verification |
|
| Front-door readiness | `template`, `resolvable=false` until CCR verification |
|
||||||
| Read policy | `workload-kv-read-whynot-design-npm-publish` |
|
| Read policy | `workload-kv-read-whynot-design-npm-publish` |
|
||||||
|
|
@ -45,7 +47,7 @@ bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
||||||
Expected OpenBao fetch shape:
|
Expected OpenBao fetch shape:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bao kv get -field=NPM_AUTH_TOKEN platform/workloads/whynot-design/whynot-design/npm-publish
|
bao kv get -field=NPM_AUTH_TOKEN platform/workloads/coulomb/whynot-design/npm-publish
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected ops-warden exec shape after activation:
|
Expected ops-warden exec shape after activation:
|
||||||
|
|
@ -63,8 +65,8 @@ logging it.
|
||||||
The source policy grants only:
|
The source policy grants only:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
read platform/data/workloads/whynot-design/whynot-design/npm-publish
|
read platform/data/workloads/coulomb/whynot-design/npm-publish
|
||||||
read platform/metadata/workloads/whynot-design/whynot-design/npm-publish
|
read platform/metadata/workloads/coulomb/whynot-design/npm-publish
|
||||||
```
|
```
|
||||||
|
|
||||||
It does not grant write, delete, patch, sudo, auth, sibling workload, or parent
|
It does not grant write, delete, patch, sudo, auth, sibling workload, or parent
|
||||||
|
|
@ -121,7 +123,7 @@ and service account.
|
||||||
An approved operator must create or confirm the secret with:
|
An approved operator must create or confirm the secret with:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
path: platform/workloads/whynot-design/whynot-design/npm-publish
|
path: platform/workloads/coulomb/whynot-design/npm-publish
|
||||||
field: NPM_AUTH_TOKEN
|
field: NPM_AUTH_TOKEN
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -129,14 +131,14 @@ In the OpenBao UI, open the `platform` KV engine and create or edit the secret
|
||||||
at:
|
at:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
workloads/whynot-design/whynot-design/npm-publish
|
workloads/coulomb/whynot-design/npm-publish
|
||||||
```
|
```
|
||||||
|
|
||||||
For policies and API checks, the same KV-v2 secret is addressed as:
|
For policies and API checks, the same KV-v2 secret is addressed as:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
platform/data/workloads/whynot-design/whynot-design/npm-publish
|
platform/data/workloads/coulomb/whynot-design/npm-publish
|
||||||
platform/metadata/workloads/whynot-design/whynot-design/npm-publish
|
platform/metadata/workloads/coulomb/whynot-design/npm-publish
|
||||||
```
|
```
|
||||||
|
|
||||||
The OpenBao UI path does not include the `data/` or `metadata/` segment. Those
|
The OpenBao UI path does not include the `data/` or `metadata/` segment. Those
|
||||||
|
|
@ -169,7 +171,7 @@ Send ops-warden only these pointers:
|
||||||
```text
|
```text
|
||||||
catalog id: whynot-design-npm-publish
|
catalog id: whynot-design-npm-publish
|
||||||
mount: platform
|
mount: platform
|
||||||
path: platform/workloads/whynot-design/whynot-design/npm-publish
|
path: platform/workloads/coulomb/whynot-design/npm-publish
|
||||||
field: NPM_AUTH_TOKEN
|
field: NPM_AUTH_TOKEN
|
||||||
oidc login: bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
oidc login: bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
||||||
policy: workload-kv-read-whynot-design-npm-publish
|
policy: workload-kv-read-whynot-design-npm-publish
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@
|
||||||
# path used by ops-warden's caller-scoped access lane. It does not grant list
|
# path used by ops-warden's caller-scoped access lane. It does not grant list
|
||||||
# access to sibling workloads or mutation capabilities.
|
# access to sibling workloads or mutation capabilities.
|
||||||
|
|
||||||
path "platform/data/workloads/whynot-design/whynot-design/npm-publish" {
|
path "platform/data/workloads/coulomb/whynot-design/npm-publish" {
|
||||||
capabilities = ["read"]
|
capabilities = ["read"]
|
||||||
}
|
}
|
||||||
|
|
||||||
path "platform/metadata/workloads/whynot-design/whynot-design/npm-publish" {
|
path "platform/metadata/workloads/coulomb/whynot-design/npm-publish" {
|
||||||
capabilities = ["read"]
|
capabilities = ["read"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ Applies source-owned OpenBao workload KV read-lane policies.
|
||||||
|
|
||||||
Current lane:
|
Current lane:
|
||||||
- policy: workload-kv-read-whynot-design-npm-publish
|
- policy: workload-kv-read-whynot-design-npm-publish
|
||||||
- path: platform/workloads/whynot-design/whynot-design/npm-publish
|
- path: platform/workloads/coulomb/whynot-design/npm-publish
|
||||||
- field: NPM_AUTH_TOKEN
|
- field: NPM_AUTH_TOKEN
|
||||||
|
|
||||||
The script reads an OpenBao operator token from OPENBAO_TOKEN_FILE or an
|
The script reads an OpenBao operator token from OPENBAO_TOKEN_FILE or an
|
||||||
|
|
@ -131,7 +131,7 @@ Remaining live steps:
|
||||||
1. Confirm the whynot-design KeyCape/NetKingdom bound claim or service account.
|
1. Confirm the whynot-design KeyCape/NetKingdom bound claim or service account.
|
||||||
2. Create auth/netkingdom/role/whynot-design-workload-kv-read with only the
|
2. Create auth/netkingdom/role/whynot-design-workload-kv-read with only the
|
||||||
workload-kv-read-whynot-design-npm-publish policy.
|
workload-kv-read-whynot-design-npm-publish policy.
|
||||||
3. Provision platform/workloads/whynot-design/whynot-design/npm-publish with
|
3. Provision platform/workloads/coulomb/whynot-design/npm-publish with
|
||||||
field NPM_AUTH_TOKEN through approved OpenBao/operator custody.
|
field NPM_AUTH_TOKEN through approved OpenBao/operator custody.
|
||||||
4. Run positive and negative fetch verification without printing the token.
|
4. Run positive and negative fetch verification without printing the token.
|
||||||
NEXT
|
NEXT
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ class CredentialChangeTests(unittest.TestCase):
|
||||||
ccr, _errors, warnings = credential_change.validate_ccr(self.sample)
|
ccr, _errors, warnings = credential_change.validate_ccr(self.sample)
|
||||||
rendered = credential_change.render_summary(ccr, warnings)
|
rendered = credential_change.render_summary(ccr, warnings)
|
||||||
self.assertIn("whynot-design npm publish token lane", rendered)
|
self.assertIn("whynot-design npm publish token lane", rendered)
|
||||||
self.assertIn("platform/workloads/whynot-design/whynot-design/npm-publish", rendered)
|
self.assertIn("platform/workloads/coulomb/whynot-design/npm-publish", rendered)
|
||||||
self.assertIn("whynot-design-npm-publish", rendered)
|
self.assertIn("whynot-design-npm-publish", rendered)
|
||||||
self.assertIn("readiness: template resolvable=False", rendered)
|
self.assertIn("readiness: template resolvable=False", rendered)
|
||||||
self.assertIn("approve | deny | needs_changes", rendered)
|
self.assertIn("approve | deny | needs_changes", rendered)
|
||||||
|
|
@ -58,18 +58,15 @@ class CredentialChangeTests(unittest.TestCase):
|
||||||
def test_status_payload_marks_template_not_resolvable(self) -> None:
|
def test_status_payload_marks_template_not_resolvable(self) -> None:
|
||||||
ccr, _errors, warnings = credential_change.validate_ccr(self.sample)
|
ccr, _errors, warnings = credential_change.validate_ccr(self.sample)
|
||||||
payload = credential_change.status_payload(ccr, warnings)
|
payload = credential_change.status_payload(ccr, warnings)
|
||||||
self.assertTrue(payload["apply_allowed"])
|
self.assertFalse(payload["apply_allowed"])
|
||||||
self.assertFalse(payload["frontdoor_resolvable"])
|
self.assertFalse(payload["frontdoor_resolvable"])
|
||||||
self.assertEqual(payload["access_frontdoor"]["readiness"], "template")
|
self.assertEqual(payload["access_frontdoor"]["readiness"], "template")
|
||||||
self.assertEqual(payload["access_frontdoor"]["catalog_id"], "whynot-design-npm-publish")
|
self.assertEqual(payload["access_frontdoor"]["catalog_id"], "whynot-design-npm-publish")
|
||||||
self.assertEqual(payload["apply_blockers"], [])
|
self.assertEqual(payload["apply_blockers"], ["apply requires status approved, got proposed"])
|
||||||
self.assertEqual(payload["warnings"], [])
|
self.assertEqual(payload["warnings"], [])
|
||||||
self.assertEqual(
|
self.assertIsNone(payload["state_hub"]["decision_id"])
|
||||||
payload["state_hub"]["decision_id"],
|
|
||||||
"250669d0-8475-4527-9624-cd072249f9a9",
|
|
||||||
)
|
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"front door requires CCR status active, got approved",
|
"front door requires CCR status active, got proposed",
|
||||||
payload["frontdoor_blockers"],
|
payload["frontdoor_blockers"],
|
||||||
)
|
)
|
||||||
self.assertIn("front door is marked resolvable=false", payload["frontdoor_blockers"])
|
self.assertIn("front door is marked resolvable=false", payload["frontdoor_blockers"])
|
||||||
|
|
@ -94,6 +91,11 @@ class CredentialChangeTests(unittest.TestCase):
|
||||||
with tempfile.TemporaryDirectory() as tmp:
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
copied = Path(tmp) / self.sample.name
|
copied = Path(tmp) / self.sample.name
|
||||||
shutil.copy2(self.sample, copied)
|
shutil.copy2(self.sample, copied)
|
||||||
|
copied_ccr = credential_change.load_yaml(copied)
|
||||||
|
copied_ccr.setdefault("state_hub", {})[
|
||||||
|
"decision_id"
|
||||||
|
] = "250669d0-8475-4527-9624-cd072249f9a9"
|
||||||
|
credential_change.dump_yaml(copied, copied_ccr)
|
||||||
original = credential_change.state_hub_decision_status
|
original = credential_change.state_hub_decision_status
|
||||||
try:
|
try:
|
||||||
credential_change.state_hub_decision_status = lambda _ccr, _url: {
|
credential_change.state_hub_decision_status = lambda _ccr, _url: {
|
||||||
|
|
@ -144,7 +146,7 @@ class CredentialChangeTests(unittest.TestCase):
|
||||||
rendered,
|
rendered,
|
||||||
)
|
)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"# bao kv put platform/workloads/whynot-design/whynot-design/npm-publish",
|
"# bao kv put platform/workloads/coulomb/whynot-design/npm-publish",
|
||||||
rendered,
|
rendered,
|
||||||
)
|
)
|
||||||
self.assertIn("NPM_AUTH_TOKEN=<enter-through-approved-custody>", rendered)
|
self.assertIn("NPM_AUTH_TOKEN=<enter-through-approved-custody>", rendered)
|
||||||
|
|
@ -199,7 +201,7 @@ class CredentialChangeTests(unittest.TestCase):
|
||||||
def test_generated_policy_is_narrow(self) -> None:
|
def test_generated_policy_is_narrow(self) -> None:
|
||||||
ccr, _errors, _warnings = credential_change.validate_ccr(self.sample)
|
ccr, _errors, _warnings = credential_change.validate_ccr(self.sample)
|
||||||
policy = credential_change.generated_policy_hcl(ccr)
|
policy = credential_change.generated_policy_hcl(ccr)
|
||||||
self.assertIn('path "platform/data/workloads/whynot-design/whynot-design/npm-publish"', policy)
|
self.assertIn('path "platform/data/workloads/coulomb/whynot-design/npm-publish"', policy)
|
||||||
self.assertNotIn("*", policy)
|
self.assertNotIn("*", policy)
|
||||||
self.assertNotIn("delete", policy)
|
self.assertNotIn("delete", policy)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,12 +123,16 @@ Kubernetes workloads, use External Secrets Operator to materialize OpenBao
|
||||||
values as Kubernetes Secrets. Do not use the OpenBao injector in the current
|
values as Kubernetes Secrets. Do not use the OpenBao injector in the current
|
||||||
deployment.
|
deployment.
|
||||||
|
|
||||||
Runtime path convention:
|
Runtime path convention for workload credential custody:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
platform/workloads/<namespace>/<service-account>/<secret-name>
|
platform/workloads/<tenant-or-org>/<workload>/<secret-purpose>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Kubernetes namespace and service-account bounds belong in the auth role or
|
||||||
|
External Secrets binding unless the namespace is itself the approved workload
|
||||||
|
identity.
|
||||||
|
|
||||||
ArgoCD repository credentials are operator credentials, not workload secrets,
|
ArgoCD repository credentials are operator credentials, not workload secrets,
|
||||||
and should live under:
|
and should live under:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,11 +52,10 @@ whynot-design.
|
||||||
|
|
||||||
## Proposed Contract
|
## Proposed Contract
|
||||||
|
|
||||||
Use the existing workload convention documented in `docs/openbao.md` and
|
Use the workload credential convention documented in `docs/openbao.md`:
|
||||||
`docs/argocd-gitops.md`:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
platform/workloads/<namespace>/<service-account>/<secret-name>
|
platform/workloads/<tenant-or-org>/<workload>/<secret-purpose>
|
||||||
```
|
```
|
||||||
|
|
||||||
For this lane, the proposed non-secret contract is:
|
For this lane, the proposed non-secret contract is:
|
||||||
|
|
@ -64,9 +63,11 @@ For this lane, the proposed non-secret contract is:
|
||||||
| Item | Proposed value |
|
| Item | Proposed value |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| KV mount | `platform` |
|
| KV mount | `platform` |
|
||||||
| CLI path | `platform/workloads/whynot-design/whynot-design/npm-publish` |
|
| Tenant/org | `coulomb` |
|
||||||
| KV-v2 policy data path | `platform/data/workloads/whynot-design/whynot-design/npm-publish` |
|
| Workload/project | `whynot-design` |
|
||||||
| KV-v2 policy metadata path | `platform/metadata/workloads/whynot-design/whynot-design/npm-publish` |
|
| CLI path | `platform/workloads/coulomb/whynot-design/npm-publish` |
|
||||||
|
| KV-v2 policy data path | `platform/data/workloads/coulomb/whynot-design/npm-publish` |
|
||||||
|
| KV-v2 policy metadata path | `platform/metadata/workloads/coulomb/whynot-design/npm-publish` |
|
||||||
| Secret field | `NPM_AUTH_TOKEN` |
|
| Secret field | `NPM_AUTH_TOKEN` |
|
||||||
| OpenBao read policy | `workload-kv-read-whynot-design-npm-publish` |
|
| OpenBao read policy | `workload-kv-read-whynot-design-npm-publish` |
|
||||||
| OIDC auth mount | `netkingdom` unless KeyCape compatibility requires `keycape` |
|
| OIDC auth mount | `netkingdom` unless KeyCape compatibility requires `keycape` |
|
||||||
|
|
@ -78,7 +79,7 @@ The expected caller-facing read shape is:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
||||||
bao kv get -field=NPM_AUTH_TOKEN platform/workloads/whynot-design/whynot-design/npm-publish
|
bao kv get -field=NPM_AUTH_TOKEN platform/workloads/coulomb/whynot-design/npm-publish
|
||||||
```
|
```
|
||||||
|
|
||||||
The command shape is illustrative only. Verification must avoid printing the
|
The command shape is illustrative only. Verification must avoid printing the
|
||||||
|
|
@ -109,7 +110,7 @@ Acceptance:
|
||||||
ops-warden signing smoke.
|
ops-warden signing smoke.
|
||||||
|
|
||||||
**2026-06-27:** Reviewed the unread ops-warden request and existing
|
**2026-06-27:** Reviewed the unread ops-warden request and existing
|
||||||
`platform/workloads/<namespace>/<service-account>/<secret-name>` convention.
|
`platform/workloads/<tenant-or-org>/<workload>/<secret-purpose>` convention.
|
||||||
Captured the proposed `whynot-design` npm publish lane above with no secret
|
Captured the proposed `whynot-design` npm publish lane above with no secret
|
||||||
values.
|
values.
|
||||||
|
|
||||||
|
|
@ -129,7 +130,7 @@ the selected `npm-publish` path.
|
||||||
Acceptance:
|
Acceptance:
|
||||||
|
|
||||||
- A policy file under `openbao/policies/` defines read access to the exact
|
- A policy file under `openbao/policies/` defines read access to the exact
|
||||||
`platform/data/workloads/whynot-design/whynot-design/npm-publish` path.
|
`platform/data/workloads/coulomb/whynot-design/npm-publish` path.
|
||||||
- Metadata/list capabilities are only as broad as needed for the caller and
|
- Metadata/list capabilities are only as broad as needed for the caller and
|
||||||
ops-warden fetch UX.
|
ops-warden fetch UX.
|
||||||
- The policy grants no write, delete, patch, sudo, auth, or unrelated workload
|
- The policy grants no write, delete, patch, sudo, auth, or unrelated workload
|
||||||
|
|
@ -140,7 +141,7 @@ Acceptance:
|
||||||
**2026-06-27:** Added the concrete policy artifact at
|
**2026-06-27:** Added the concrete policy artifact at
|
||||||
`openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl`. It grants
|
`openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl`. It grants
|
||||||
only `read` on the exact KV-v2 data and metadata paths for
|
only `read` on the exact KV-v2 data and metadata paths for
|
||||||
`platform/workloads/whynot-design/whynot-design/npm-publish`; it does not grant
|
`platform/workloads/coulomb/whynot-design/npm-publish`; it does not grant
|
||||||
write/delete/list/sudo/auth or sibling workload access. Added
|
write/delete/list/sudo/auth or sibling workload access. Added
|
||||||
`scripts/openbao-apply-workload-kv-lanes.sh`,
|
`scripts/openbao-apply-workload-kv-lanes.sh`,
|
||||||
`make openbao-workload-kv-lanes-dry-run`, and
|
`make openbao-workload-kv-lanes-dry-run`, and
|
||||||
|
|
@ -195,7 +196,7 @@ publish token.
|
||||||
Acceptance:
|
Acceptance:
|
||||||
|
|
||||||
- The path exists at
|
- The path exists at
|
||||||
`platform/workloads/whynot-design/whynot-design/npm-publish`.
|
`platform/workloads/coulomb/whynot-design/npm-publish`.
|
||||||
- The field is named exactly `NPM_AUTH_TOKEN`.
|
- The field is named exactly `NPM_AUTH_TOKEN`.
|
||||||
- The token value is entered through an approved operator/OpenBao path and is
|
- The token value is entered through an approved operator/OpenBao path and is
|
||||||
never written to Git, State Hub, chat, prompts, shell history, or workplan
|
never written to Git, State Hub, chat, prompts, shell history, or workplan
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue