Files
railiance-platform/docs/whynot-design-npm-publish-handoff.md

7.3 KiB

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: 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
  • 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, 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

  • 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.
  • Mark ops-warden catalog entries ready only after positive and negative verification are complete. For this lane, both checks have passed.

OpenBao Secret Check

In the OpenBao UI, confirm the secret exists under the platform KV engine:

workloads/coulomb/whynot-design/npm-publish

Expected field:

NPM_AUTH_TOKEN

Expected custom metadata:

catalog-id = whynot-design-npm-publish

Do not reveal the value during review.

Policy

Create or update ACL policy:

workload-kv-read-whynot-design-npm-publish

Policy body:

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:

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:

auth/netkingdom/role/whynot-design-workload-kv-read

Role payload:

{
  "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:

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:

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:

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:

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:

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.

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:

  • 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;

CCR-2026-0001 is now active, and ops-warden can mark whynot-design-npm-publish ready/resolvable=true.

Current front door:

readiness = ready
resolvable = true