secrets-engine corrected our claim (msg 15f0c0ca): `npm_token` is the KV field on the whynot-design publish lane; `NPM_AUTH_TOKEN` is the environment variable their publication-scope policy injects. Their doc lists the two as separate rows and we had copied the env var in as the field name, so our `fetch_command` named a field that does not exist -- `bao kv get -field=NPM_AUTH_TOKEN` could only ever have failed. This is ADR-0001's failure mode, not a typo: a pointer layer restating an owner's procedure and getting it wrong. Corrected from the owner's statement rather than re-derived here, and the catalog now records the distinction inline so the env var does not get copied back in. The path is a separate and still-open question. secrets-engine declined to resolve it unilaterally -- which location backs the lane for reads is railiance-platform's custody state -- so the path is unchanged and routed to them rather than moved on a coordination message. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C Assistant: claude-code Assistant-Model: opus Assistant-Process: 1276224@bnt-lap001 Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
110 lines
5.1 KiB
Markdown
110 lines
5.1 KiB
Markdown
# whynot-design npm publish token
|
|
|
|
Date: 2026-09-04
|
|
Catalog: `whynot-design-npm-publish` (status `active`, `resolvable: true`)
|
|
Owner: `railiance-platform` (OpenBao) · provisioning CCR-2026-0001 (commit 8f617fc)
|
|
|
|
> **Rotation required (2026-09-04).** The OIDC role and OpenBao read path are
|
|
> healthy, but the stored credential failed a real Forgejo publish. Version
|
|
> `@whynot/design@0.4.2` was published and integrity-verified through the
|
|
> plan-authorized Forgejo admin recovery lane. Treat this dedicated lane as
|
|
> unverified for writes until its package token is rotated and re-proven.
|
|
|
|
The npm publish token for `@whynot/design` on the coulomb Forgejo npm registry
|
|
(KV field `npm_token`; reaching the publish command as `NPM_AUTH_TOKEN`)
|
|
(`https://forgejo.coulomb.social/api/packages/coulomb/npm/`). ops-warden **does not hold
|
|
this token** — it is the access front door: `warden access` proxies the read from OpenBao
|
|
**as the caller** and never persists, caches, or logs the value.
|
|
|
|
---
|
|
|
|
## Owner-confirmed lane (no placeholders)
|
|
|
|
| Field | Value |
|
|
| --- | --- |
|
|
| OpenBao path | `platform/workloads/coulomb/whynot-design/npm-publish` |
|
|
| KV field | `npm_token` |
|
|
| Injected env var | `NPM_AUTH_TOKEN` (set by the publication-scope policy; not a KV key) |
|
|
| KV mount | `platform` |
|
|
| Read policy | `workload-kv-read-whynot-design-npm-publish` |
|
|
| OIDC login | `bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read` |
|
|
| Bound group | `whynot-design` |
|
|
| flex-auth ref | `secret.read:whynot-design` (if tenant policy requires pre-approval) |
|
|
| Runbook (owner) | `railiance-platform/docs/workload-kv-access-lanes.md` |
|
|
|
|
> The `platform/workloads/whynot-design/whynot-design/npm-publish` path from early in the
|
|
> provisioning thread is **superseded** — the live path is under the `coulomb` tenant.
|
|
|
|
---
|
|
|
|
## Worker checklist
|
|
|
|
1. **Authenticate as yourself** (you need your own identity; ops-warden adds none):
|
|
```bash
|
|
bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
|
```
|
|
Your token must carry the `whynot-design` group bound claim; a non-whynot identity is
|
|
denied by policy (verified negative case).
|
|
|
|
2. **Run via the owner-native front door (primary).** secrets-engine owns the secret-exec
|
|
for this lane (SECRETS-WP-0003, decision e6381a56); ops-warden routes to it:
|
|
```bash
|
|
secrets-engine route whynot-design-npm-publish --json # pointer / readiness
|
|
secrets-engine exec --catalog whynot-design-npm-publish -- \
|
|
npm view @whynot/design@<version> version \
|
|
--registry=https://forgejo.coulomb.social/api/packages/coulomb/npm/
|
|
secrets-engine exec --catalog whynot-design-npm-publish -- npm publish
|
|
```
|
|
|
|
**ops-warden transparent fallback** — same lane via the `warden access` proxy (fetches as
|
|
you, holds nothing). The project `.npmrc` must point both the `@whynot` scope and
|
|
token fragment at `forgejo.coulomb.social`:
|
|
```bash
|
|
# --exec needs the env-var name. The zone-aware policy gate always runs first.
|
|
warden access whynot-design-npm-publish --field npm_token \
|
|
--exec -- npm view @whynot/design@<version> version \
|
|
--registry=https://forgejo.coulomb.social/api/packages/coulomb/npm/
|
|
warden access whynot-design-npm-publish --field npm_token \
|
|
--exec -- npm publish
|
|
warden access whynot-design-npm-publish --field npm_token --fetch
|
|
```
|
|
On either path the value transits to you (or the child env) and never enters
|
|
ops-warden's memory, disk, or audit log.
|
|
|
|
3. **Readiness gate (for automated callers).** Before attempting `--fetch`, check the flag:
|
|
```bash
|
|
warden route show whynot-design-npm-publish --json | jq .resolvable # true
|
|
```
|
|
`resolvable: true` means the lane is concrete and `--fetch` will run; a template lane
|
|
reports `false`.
|
|
|
|
4. **Publish is outward-facing and immutable.** Before publishing, confirm that
|
|
`package.json#publishConfig.registry` is exactly the Forgejo URL above, verify the
|
|
intended version and `npm pack --dry-run` contents, and obtain explicit operator
|
|
approval. `npm publish` is irreversible; do not auto-run it from an agent.
|
|
|
|
5. **Record non-secret release evidence.** After the owner publishes, record only the
|
|
package coordinate (for example `@whynot/design@0.4.2`), registry URL, authenticated
|
|
install result, and release-content verification. Never record the token or npm
|
|
configuration generated for its delivery.
|
|
|
|
Forgejo advertises `npm view`, search, install, publish, unpublish, and dist-tag
|
|
support; it does not advertise `npm whoami`. Use the exact-version lookup above
|
|
rather than treating `npm whoami` failure as a credential failure.
|
|
|
|
---
|
|
|
|
## Scopes
|
|
|
|
This lane is the **publish** token only. A separate **read/install** token (for consumers
|
|
of `@whynot/design`) is a distinct need and would be its own catalog id
|
|
(`whynot-design-npm-read`) once railiance-platform provisions it — do not conflate them.
|
|
|
|
---
|
|
|
|
## See also
|
|
|
|
- `wiki/OperatorAccessAssist.md` — the `warden access` front door + guardrails
|
|
- `wiki/CredentialRouting.md` — routing model
|
|
- `railiance-platform/docs/workload-kv-access-lanes.md`,
|
|
`workplans/RAILIANCE-WP-0006-workload-kv-access-lanes.md`
|