[AAASM-4017] 🔧 (ci): Migrate npm publish to OIDC Trusted Publishing#223
Conversation
Authenticate the release-node publish steps via npm OIDC trusted publishing instead of a long-lived NPM_TOKEN: - Add `environment: npm` to the publish job (protected environment gate). - Upgrade npm to >= 11.5.1 (npm install -g npm@latest) so the OIDC token-exchange path exists on Node 22's bundled older npm. - Switch the two publish steps from `pnpm publish` to `npm publish --provenance` and drop `NODE_AUTH_TOKEN`; npm mints a short-lived publish-scoped credential from the workflow OIDC identity. - Keep NPM_CONFIG_PROVENANCE for SLSA provenance. - Retain a token only on `npm dist-tag add` (OIDC covers `npm publish` only — npm/cli#8547), documented for future removal. Requires manual admin setup before it works: create the `npm` GitHub Environment and configure the package's trusted publisher on npmjs.com. Refs AAASM-4017 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MvjnG3ysnqTY6Gu1wQ2h73
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
|
🤖 Claude Code review — approve AAASM-4017 npm OIDC. Publish job migrated to npm Trusted Publishing ( |
|
🤖 Claude Code — deep review: APPROVE (conditional on documented manual setup) CI: green (25/25). Scope: matches ticket — publish migrated to npm OIDC Trusted Publishing ( Side-effects (regression check): the main breakage risk —
|



What
Migrates the
release-node.ymlnpm publish job from a long-livedNPM_TOKENto npm OIDC Trusted Publishing for the package publish itself.environment: npmto thepublishjob.>= 11.5.1(npm install -g npm@latest) — OIDC trusted publishing is GA only in npm 11.5.1+, and Node 22 bundles an older npm.Publish 4 runtime sub-packages,Publish main @agent-assembly/sdk) frompnpm publishtonpm publish --provenance, and removesNODE_AUTH_TOKEN— npm mints a short-lived, publish-scoped credential from the workflow's OIDC identity.NPM_CONFIG_PROVENANCE: "true"so SLSA provenance still attaches.workflow_dispatchtrigger, dry-run gating, dist-tag logic, SBOM, and GitHub Release steps unchanged.Job-level
id-token: write(+contents: writefor the git tag/release) was already present.Why
AAASM-4017 [MED]: the workflow set
id-token: write+NPM_CONFIG_PROVENANCE: truebut still authenticated the publish with a stored, long-livedsecrets.NPM_TOKENand had noenvironment:gate — unlike python-sdk, which uses PyPI Trusted Publishing (OIDC, no stored token) behindenvironment: pypi. This brings node-sdk to parity: the package contents now publish tokenlessly via OIDC + provenance.Known limitation (one token remains, intentionally)
npm OIDC Trusted Publishing currently authenticates only the
npm publishcommand (npm/cli#8547). TheUpdate latest dist-tagstep runsnpm dist-tag add, a non-publish registry write OIDC does not cover, so it still needs a token. Blast radius is much smaller: it no longer publishes package contents, only moves a dist-tag pointer. It should be a granular automation token scoped to@agent-assembly/*dist-tag management. Once npm extends OIDC to dist-tag, that token can be dropped entirely.This code change alone will NOT publish successfully until a repo/npm admin completes both of the following. Until then, a dispatched release will fail auth at the publish step.
npmin this repo (Settings → Environments → New environment). Add required reviewers (Pioneer team) so publishes gate on human approval. No secrets need to live in the environment for the OIDC publish itself.@agent-assembly/sdk,@agent-assembly/runtime-linux-x64,@agent-assembly/runtime-linux-arm64,@agent-assembly/runtime-darwin-x64,@agent-assembly/runtime-darwin-arm64): Package Settings → Trusted Publisher → add a GitHub Actions publisher with:ai-agent-assembly/node-sdkrelease-node.ymlnpmNPM_TOKENsecret — keep a secret namedNPM_TOKENavailable to the workflow, but downgrade it to a granular automation token scoped only to dist-tag management for@agent-assembly/*(it no longer needs publish scope). Required only by theUpdate latest dist-tagstep (see "Known limitation").How to verify
actionlint .github/workflows/release-node.ymlpasses; YAML parses.release-nodewithdry-run=true(skips registry writes) to confirm the job wiring, then a real pre-release publish to confirm OIDC auth + provenance.Refs AAASM-4017
🤖 Generated with Claude Code
https://claude.ai/code/session_01MvjnG3ysnqTY6Gu1wQ2h73