Summary
npm-publish.yml currently authenticates to npm using a long-lived granular access token (NPM_TOKEN repo secret) with 2FA bypass. npm/GitHub are deprecating that bypass in two phases (see changelog):
- Phase 1 (early August 2026, already in effect): 2FA-bypass tokens can no longer create/delete tokens, change account/password/email/2FA settings, change package access/maintainers/trusted-publishing config, or manage org/team membership.
- Phase 2 (~January 2027): 2FA-bypass tokens lose direct publishing ability entirely — reduced to "reading private packages and staging a publish, where a package only becomes public after a human 2FA approval."
We already hit Phase 1 in practice: the very first CI publish of @textadventures/quest-viva-wasmplayer failed with npm error code EOTP because creating the package for the first time needed to establish maintainer/ownership (a Phase-1-restricted action even for a bypass-capable token). It was bootstrapped with a one-off manual npm publish from a local machine with real 2FA instead. Ordinary version-bump publishes from CI should be unaffected until Phase 2 lands, but Phase 2 will break them too.
What to do
Migrate npm-publish.yml to npm's trusted publishing (OIDC) instead of a long-lived token:
- On the package's npmjs.com settings page, add a Trusted Publisher: GitHub Actions, repo
textadventures/quest, workflow file npm-publish.yml (no environment).
- Update
.github/workflows/npm-publish.yml:
- Add
permissions: id-token: write (and contents: read) to the job.
- Drop the
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} env var from the "Publish to npm" step — npm's CLI auto-detects the GitHub Actions OIDC environment once a trusted publisher is configured, no token needed.
- Once confirmed working on a real release, remove the now-unused
NPM_TOKEN repo secret.
This sidesteps the whole 2FA-bypass-token question going forward and isn't affected by the Phase 2 deprecation.
Context
Summary
npm-publish.ymlcurrently authenticates to npm using a long-lived granular access token (NPM_TOKENrepo secret) with 2FA bypass. npm/GitHub are deprecating that bypass in two phases (see changelog):We already hit Phase 1 in practice: the very first CI publish of
@textadventures/quest-viva-wasmplayerfailed withnpm error code EOTPbecause creating the package for the first time needed to establish maintainer/ownership (a Phase-1-restricted action even for a bypass-capable token). It was bootstrapped with a one-off manualnpm publishfrom a local machine with real 2FA instead. Ordinary version-bump publishes from CI should be unaffected until Phase 2 lands, but Phase 2 will break them too.What to do
Migrate
npm-publish.ymlto npm's trusted publishing (OIDC) instead of a long-lived token:textadventures/quest, workflow filenpm-publish.yml(no environment)..github/workflows/npm-publish.yml:permissions: id-token: write(andcontents: read) to the job.NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}env var from the "Publish to npm" step — npm's CLI auto-detects the GitHub Actions OIDC environment once a trusted publisher is configured, no token needed.NPM_TOKENrepo secret.This sidesteps the whole 2FA-bypass-token question going forward and isn't affected by the Phase 2 deprecation.
Context
npm-publish.yml: feat(WasmPlayer): implement single-file, CDN-linked game export #2012--tag latestrequirement: fix(WasmPlayer): pass --tag latest to npm publish #2014