ci: switch npm publish to Trusted Publishing (OIDC)#14
Conversation
Replaces the NPM_TOKEN secret with npm's OIDC-based trusted publisher auth so CI no longer trips over the 2FA OTP prompt that blocked recent publishes. Adds id-token: write to both the called workflow and the caller, bumps setup-node to v4 and Node to 22 (required for npm >= 11.5.1, which performs the OIDC exchange), and drops NODE_AUTH_TOKEN. Requires the @jam.dev/rimless package to have a trusted publisher configured on npmjs.com pointing at jamdotdev/rimless + npm-publish.yml before this merges.
| permissions: | ||
| id-token: write | ||
| contents: read |
There was a problem hiding this comment.
🔴 Workflow-level permissions caps id-token to none, blocking OIDC publishing via PR merge flow
The workflow-level permissions at .github/workflows/publish-release.yml:9-10 only specifies contents: write. Per GitHub Actions docs, when the permissions key is used, all unspecified permissions are set to none. This means id-token is none at the workflow level. Since workflow-level permissions act as a ceiling for all jobs, the publish-package job's permissions: id-token: write (line 95-96) cannot escalate beyond this — it remains none. Consequently, when npm-publish.yml is called via workflow_call, GitHub will not mint the OIDC token, and npm Trusted Publishing will fail with an authentication error. The fix is to add id-token: write to the top-level permissions block.
Prompt for agents
The workflow-level `permissions` block at line 9-10 of publish-release.yml only specifies `contents: write`, which causes all other permissions (including `id-token`) to default to `none`. Job-level permissions cannot escalate beyond the workflow-level ceiling.
To fix this, add `id-token: write` to the top-level permissions block at lines 9-10:
permissions:
contents: write
id-token: write
This ensures the `publish-package` job (and the called `npm-publish.yml` workflow) can actually receive the `id-token: write` permission needed for OIDC-based npm Trusted Publishing.
Was this helpful? React with 👍 or 👎 to provide feedback.
| - name: Publish package on NPM | ||
| run: npm publish |
There was a problem hiding this comment.
🚩 npm publish may need --provenance flag for OIDC authentication
The PR removes NODE_AUTH_TOKEN from the npm publish step (npm-publish.yml:36-37) but does not add --provenance to the npm publish command. The actions/setup-node action with registry-url creates an .npmrc containing //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}. Since NODE_AUTH_TOKEN is no longer set, the auth token will be empty.
npm Trusted Publishing historically requires npm publish --provenance to trigger the OIDC token exchange for authentication. Without this flag and without NODE_AUTH_TOKEN, there may be no valid authentication mechanism. However, npm's OIDC support has been evolving — newer npm versions (10.x+ with Node 22) may handle this differently. This should be verified against the current npm Trusted Publishing documentation and tested before merging.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Replaces the
NPM_TOKENsecret with npm's Trusted Publishing (OIDC) so CI no longer fails on the 2FA OTP prompt that blocked the last@jam.dev/rimless@0.6.4publish. Addsid-token: writeto bothnpm-publish.ymland thepublish-release.ymlcaller, bumpssetup-nodeto v4 and Node to 22 (needed for npm >= 11.5.1, which performs the OIDC exchange), and dropsNODE_AUTH_TOKEN.Prerequisite before merging
Configure a trusted publisher on npmjs.com for
@jam.dev/rimlesspointing at: orgjamdotdev, reporimless, workflow filenamenpm-publish.yml, actionnpm publish. Without this, the next publish will fail with an auth error. Once the publish path is verified working, theNPM_TOKENrepo secret can be deleted.Test plan
release:patchand confirmpublish-packagejob succeeds withoutNPM_TOKEN