diff --git a/docs/whynot-design-npm-publish-handoff.md b/docs/whynot-design-npm-publish-handoff.md new file mode 100644 index 0000000..7068a1e --- /dev/null +++ b/docs/whynot-design-npm-publish-handoff.md @@ -0,0 +1,174 @@ +# whynot-design npm Publish Token Handoff + +This is the next-session handoff for `CCR-2026-0001` and the +`whynot-design-npm-publish` access lane. + +## Current State + +- CCR: `CCR-2026-0001` +- Decision: `e6381a56-6b04-4fd5-b2de-f3ef59cde888` +- Status: approved +- Front door: `template`, `resolvable=false` +- Catalog id: `whynot-design-npm-publish` +- Tenant/org: `coulomb` +- Workload/project: `whynot-design` +- Secret path: `platform/workloads/coulomb/whynot-design/npm-publish` +- Field: `NPM_AUTH_TOKEN` +- Token source: Gitea package token for + `https://gitea.coulomb.social/api/packages/coulomb/npm/` + +The operator reported that the Gitea token was generated and stored in OpenBao. +Codex could not verify the metadata from the current token-helper identity: +metadata lookup, policy read, and auth-role read all returned `403 permission +denied`. No secret value was read or printed. + +## Safety Rules + +- Do not paste `NPM_AUTH_TOKEN` into Git, State Hub, chat, shell history, logs, + workplans, or screenshots. +- 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. + +## OpenBao Secret Check + +In the OpenBao UI, confirm the secret exists under the `platform` KV engine: + +```text +workloads/coulomb/whynot-design/npm-publish +``` + +Expected field: + +```text +NPM_AUTH_TOKEN +``` + +Expected custom metadata: + +```text +catalog-id = whynot-design-npm-publish +``` + +Do not reveal the value during review. + +## Policy + +Create or update ACL policy: + +```text +workload-kv-read-whynot-design-npm-publish +``` + +Policy body: + +```hcl +path "platform/data/workloads/coulomb/whynot-design/npm-publish" { + capabilities = ["read"] +} + +path "platform/metadata/workloads/coulomb/whynot-design/npm-publish" { + capabilities = ["read"] +} +``` + +Equivalent CLI command from an approved OpenBao operator context: + +```bash +bao policy write workload-kv-read-whynot-design-npm-publish \ + openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl +``` + +## OIDC Role + +Create or update: + +```text +auth/netkingdom/role/whynot-design-workload-kv-read +``` + +Role payload: + +```json +{ + "role_type": "oidc", + "user_claim": "sub", + "groups_claim": "groups", + "bound_claims": { + "groups": ["whynot-design"] + }, + "policies": "workload-kv-read-whynot-design-npm-publish", + "ttl": "15m" +} +``` + +Equivalent CLI command from an approved OpenBao operator context: + +```bash +bao write auth/netkingdom/role/whynot-design-workload-kv-read \ + 'bound_claims={"groups":["whynot-design"]}' \ + groups_claim=groups \ + policies=workload-kv-read-whynot-design-npm-publish \ + role_type=oidc \ + ttl=15m \ + user_claim=sub +``` + +## Non-Secret Reads + +These commands should succeed from an operator-capable identity and do not print +the token value: + +```bash +bao kv metadata get platform/workloads/coulomb/whynot-design/npm-publish +bao policy read workload-kv-read-whynot-design-npm-publish +bao read auth/netkingdom/role/whynot-design-workload-kv-read +``` + +## Positive Verification + +Positive verification proves the approved whynot-design identity can fetch the +field without exposing it in logs. + +Use an attended shell, keep tracing disabled, and suppress command output: + +```bash +set +x +bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read +bao kv get -format=json platform/workloads/coulomb/whynot-design/npm-publish \ + | jq -e '.data.data.NPM_AUTH_TOKEN | type == "string" and length > 0' \ + >/dev/null +``` + +Record only that the check passed. + +## Negative Verification + +Negative verification proves a non-whynot identity cannot read the same field. + +Use a non-whynot identity or role and confirm the read is denied. Do not print +or store any token value. + +Record only the denial result and non-secret audit timestamp/request metadata. + +## Activation + +Only after these are true: + +- secret metadata confirmed; +- policy exists and is scoped to the corrected `coulomb/whynot-design` path; +- OIDC role exists and binds only `groups=["whynot-design"]`; +- positive verification passed; +- negative verification passed; + +then `CCR-2026-0001` can move toward `active`, and ops-warden can mark +`whynot-design-npm-publish` `ready`/`resolvable=true`. + +Until then, keep the front door as: + +```text +readiness = template +resolvable = false +``` diff --git a/workplans/RAILIANCE-WP-0007-credential-change-approval-workflow.md b/workplans/RAILIANCE-WP-0007-credential-change-approval-workflow.md index c7a9ff3..89c8843 100644 --- a/workplans/RAILIANCE-WP-0007-credential-change-approval-workflow.md +++ b/workplans/RAILIANCE-WP-0007-credential-change-approval-workflow.md @@ -275,6 +275,17 @@ remains `readiness: template` and `resolvable: false`. Added guarded reviewed non-secret policy and auth-role commands without hand-writing them; secret value provisioning and verification remain under approved custody. +**2026-06-28:** After correcting the tenant/org to `coulomb`, the corrected +approval was synced from State Hub decision +`e6381a56-6b04-4fd5-b2de-f3ef59cde888`; `CCR-2026-0001` is approved and +`apply_allowed: true` for +`platform/workloads/coulomb/whynot-design/npm-publish`. The operator reported +secret provisioning likely completed, but Codex metadata-only verification still +received `403 permission denied`. Prepared +`docs/whynot-design-npm-publish-handoff.md` as the next-session checklist for +policy, auth-role, metadata verification, positive verification, negative +verification, and activation without printing the token. + ## T08 - Add deactivation, rotation, and compromise flows ```task