diff --git a/CLAUDE.md b/CLAUDE.md index d781c99f83..c4e888c23d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -108,9 +108,13 @@ npm's trusted publisher (npmjs.com → package Settings) must match this file ex `Org=nForma-AI · Repo=nForma · Workflow filename=publish.yml · Environment=npm-publish · Allowed=npm publish`. Requirements baked into the workflow: Node ≥ 22.14.0 and npm ≥ 11.5.1 (`npm i -g npm@latest`), `permissions: id-token: write`, **no** `NODE_AUTH_TOKEN` (its presence forces the token path and defeats OIDC). -**Aligning `@next` — current state (2026-08-08).** The long-standing explanation ("OIDC authorizes `npm publish` but not `npm dist-tag add`") is **incomplete, and was not the operative cause** of the drift everyone kept chasing. It may well be true — it has never been tested here, because the step never got far enough to find out. What was actually happening, in order: +**Aligning `@next` — current state (2026-08-08).** Two independent facts, long conflated: -1. **Wiring bug (fixed, #391).** The align step exported `NPM_TOKEN` as a bare `env:` var. npm does not read `NPM_TOKEN` — auth comes from `.npmrc` — so `dist-tag add` ran *unauthenticated* and 401'd every release, while the warning text blamed a token that was configured and healthy. The step now writes `//registry.npmjs.org/:_authToken=${NPM_TOKEN}` for its own duration (safe: it runs after the OIDC publish, so it cannot force publish onto the token path). Whether OIDC alone would suffice is still unverified — the step uses a token, so the question stays open and costs nothing. +**Fact 1 — OIDC does not cover `npm dist-tag`.** Per [npm's trusted-publishers docs](https://docs.npmjs.com/trusted-publishers): *"OIDC authentication supports the `npm publish` and `npm stage publish` commands"*, and *"Other npm commands such as `install`, `view`, or `access` still require traditional authentication methods."* The trusted-publisher config states the same scope in its own field: `Allowed = npm publish`. So the alignment step must use token auth **as of this writing** — re-check the docs before assuming that still holds, since npm may extend OIDC scope. (An earlier revision of this file called that explanation "wrong". It was not: it was right about *why* a token is needed, and merely silent about the bug in *how* the token was supplied.) + +**Fact 2 — the drift everyone kept chasing was a wiring bug, not the OIDC limit.** In order: + +1. **Wiring bug (fixed, #391).** The align step exported `NPM_TOKEN` as a bare `env:` var. npm does not read `NPM_TOKEN` — auth comes from `.npmrc` — so `dist-tag add` ran *unauthenticated* and 401'd every release, while the warning text blamed a token that was configured and healthy. The step now writes `//registry.npmjs.org/:_authToken=${NPM_TOKEN}` for its own duration (safe: it runs after the OIDC publish, so it cannot force publish onto the token path). 2. **The `NPM_TOKEN` secret is currently expired** (created 2026-02-21; CI returns `E401 — authentication token seems to be invalid`). Until it is replaced, **alignment is a manual step after every release** — an accepted trade-off, not an unknown. **Manual alignment.** Run it yourself in an interactive terminal: