246 lines
6.8 KiB
Markdown
246 lines
6.8 KiB
Markdown
# 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: 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
|
|
- Catalog id: `whynot-design-npm-publish`
|
|
- Tenant/org: `coulomb`
|
|
- Workload/project: `whynot-design`
|
|
- Bound IAM group: `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.
|
|
Using the temporary operator token only for non-secret infrastructure work, Codex
|
|
confirmed that the policy exists, the OIDC role exists with the whynot-design
|
|
binding and redirect URIs, the secret metadata has the expected catalog id, and
|
|
the `NPM_AUTH_TOKEN` field is present. No secret value was printed, recorded,
|
|
or copied into Git, State Hub, chat, or workplans.
|
|
|
|
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.
|
|
|
|
## 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",
|
|
"allowed_redirect_uris": [
|
|
"https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback",
|
|
"http://localhost:8250/oidc/callback",
|
|
"http://127.0.0.1:8250/oidc/callback"
|
|
],
|
|
"oidc_scopes": [
|
|
"openid",
|
|
"profile",
|
|
"email",
|
|
"groups"
|
|
],
|
|
"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 shell:
|
|
|
|
```bash
|
|
role_payload_file="$(mktemp)"
|
|
trap 'rm -f "$role_payload_file"' EXIT
|
|
cat >"$role_payload_file" <<'JSON'
|
|
{
|
|
"allowed_redirect_uris": [
|
|
"https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback",
|
|
"http://localhost:8250/oidc/callback",
|
|
"http://127.0.0.1:8250/oidc/callback"
|
|
],
|
|
"oidc_scopes": [
|
|
"openid",
|
|
"profile",
|
|
"email",
|
|
"groups"
|
|
],
|
|
"bound_claims": {
|
|
"groups": [
|
|
"whynot-design"
|
|
]
|
|
},
|
|
"groups_claim": "groups",
|
|
"policies": "workload-kv-read-whynot-design-npm-publish",
|
|
"role_type": "oidc",
|
|
"ttl": "15m",
|
|
"user_claim": "sub"
|
|
}
|
|
JSON
|
|
bao write auth/netkingdom/role/whynot-design-workload-kv-read @"$role_payload_file"
|
|
```
|
|
|
|
The OpenBao Browser CLI cannot run this shell block and may treat
|
|
`bound_claims={...}` as a string. When staying in the Web UI, open the API
|
|
Explorer and submit the role payload JSON above with:
|
|
|
|
```text
|
|
method: PUT
|
|
path: /v1/auth/netkingdom/role/whynot-design-workload-kv-read
|
|
```
|
|
|
|
If the API Explorer asks for a path without the API prefix, use
|
|
`auth/netkingdom/role/whynot-design-workload-kv-read`.
|
|
|
|
## 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.
|
|
|
|
Before retrying, confirm the account used for OIDC login is a member of the
|
|
`whynot-design` LLDAP group. If OpenBao reports:
|
|
|
|
```text
|
|
claim "groups" does not match any associated bound claim values
|
|
```
|
|
|
|
then the groups claim is present, but the account is not in `whynot-design` or
|
|
KeyCape did not emit that membership in the fresh login.
|
|
|
|
The positive verification passed on 2026-06-28. During that run, the CLI printed
|
|
the short-lived OpenBao login token; it was revoked immediately by accessor.
|
|
Prefer `bao login -no-print` for future attended verification if the installed
|
|
CLI accepts that flag.
|
|
|
|
Use an attended shell, keep tracing disabled, and suppress command output:
|
|
|
|
```bash
|
|
set +x
|
|
bao login -no-print -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"]` with approved
|
|
browser/local CLI callback URIs and `groups` OIDC scope;
|
|
- 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 = applied-pending-verify
|
|
resolvable = false
|
|
```
|