LearnNewsExamplesServices
Frontmatter
id12970
titlenpm-publish.yml never engages the configured Trusted Publisher (missing id-token grant; expired token shadows OIDC)
stateClosed
labels
bugaibuild
assigneesneo-fable
createdAtJun 12, 2026, 10:11 AM
updatedAtJun 12, 2026, 3:20 PM
githubUrlhttps://github.com/neomjs/neo/issues/12970
authorneo-fable
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 12, 2026, 3:10 PM

npm-publish.yml never engages the configured Trusted Publisher (missing id-token grant; expired token shadows OIDC)

neo-fable
neo-fable commented on Jun 12, 2026, 10:11 AM

Context

The v13.0.0 npm publish failed (masked E404 on PUT registry.npmjs.org/neo.mjs, run 2026-06-12T06:07Z) although the operator had ALREADY configured npm Trusted Publishing for neo.mjs (npmjs.com: trusted publisher neomjs/neo / npm-publish.yml / permissions: npm publish). The registry still serves 12.1.0; the morning cloud-trial anchor and the pages update are blocked on it.

Release classification: release-completion-blocking (the cut's distribution leg).

The Problem

.github/workflows/npm-publish.yml predates the trusted-publisher setup and defeats it twice:

  1. No permissions: id-token: write on the job — GitHub never mints the OIDC token, so the npm CLI cannot perform the trusted-publishing exchange at all.
  2. NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} is still passed — token auth takes precedence over OIDC when present, and that token expired 2026-03-27 (operator-confirmed). The publish therefore attempted token auth with a dead token → npm's masked 404-on-PUT.

The Architectural Reality

  • .github/workflows/npm-publish.ymlrelease: published trigger, ubuntu-latest (hosted runner ✓ OIDC-compatible), node 24 (npm ≥11.5.1 ✓ trusted-publishing-capable), npm ci + npm publish with the token env.
  • npmjs.com side: trusted publisher pinned to this exact workflow filename — already correct, nothing to change there.
  • Re-trigger constraint: re-running the failed run executes the workflow as committed at the original ref — the fix can't reach it. A workflow_dispatch trigger lets the operator re-publish 13.0.0 from dev tip (whose package.json already carries the bump).

The Fix

One workflow edit: add permissions: {id-token: write, contents: read}; remove the NODE_AUTH_TOKEN env (the NPM_TOKEN secret can be deleted afterward — trusted-publisher-only posture); add workflow_dispatch for the re-trigger (and future manual re-publishes).

Acceptance Criteria

  • Workflow grants id-token: write and carries no token env.
  • workflow_dispatch trigger present (the re-publish path from dev tip).
  • In-file comments document the OIDC engagement and the token-precedence trap.

Post-Merge Verification (operator-executed)

Tracked on PR #12971's Post-Merge Validation checklist + the #12696 publish runbook — reclassified from ACs in cycle 2 per the Resolves-mandate shape (operator rule #12367: a ticket's close-gating ACs are what the PR delivers; operator-credentialed runtime outcomes are post-merge verification):

  • Operator dispatch on dev → npm view neo.mjs version returns 13.0.0.
  • Provenance attestation visible on the npm package page (free under OIDC publishing).

Out of Scope

  • The KB-zip 404-at-publish ordering quirk (noted on #12969's trail).
  • Deleting the dead NPM_TOKEN secret (operator housekeeping, post-success).

Related

#12696 (the cut), #12965/PR #12966 (the cut's first unblock — same release).

Origin Session ID: e605ce21-3668-445c-bc00-45896aa9a092

Retrieval Hint: "npm publish OIDC trusted publisher id-token write expired NPM_TOKEN E404"

tobiu referenced in commit f333303 - "fix(ci): engage npm Trusted Publishing — id-token grant, drop expired token, add dispatch (#12970) (#12971) on Jun 12, 2026, 3:10 PM
tobiu closed this issue on Jun 12, 2026, 3:10 PM