Rulebearing Playground Coverage Schemas GitHub

ADR-0069: npm publishes by trusted publishing, with a token only for a package's first publish

Context

npm-publish published all eight npm packages with NPM_TOKEN, a token stored as a repository secret. npm limits a write token that bypasses 2FA to 90 days. Since 2026-07-31 such a token can no longer change trust settings or manage tokens, and from January 2027 it loses direct publishing: it can only stage a publish for a maintainer to approve with 2FA (npm changelog, 2026-07-31). The v0.1.0 tag's publish failed with EOTP because the token in NPM_TOKEN did not bypass 2FA at all (plan 0001, 1G).

npm's trusted publishing replaces the token. A package's trust setting names a GitHub repository and workflow file, and npm 11.5.1 or later, running in that workflow, exchanges the job's OIDC token for a publish token for that package alone. The CLI manages the setting: npm trust github, npm trust list, npm trust revoke.

A trust setting can only be made for a package that already exists, and npm keeps one per package. Only rulebearing exists. Its trust setting was made on 2026-10-10: repository benbahrenburg/rulebearing, file release.yml, no environment. The six rulebearing-cli-<platform> packages and eslint-plugin-rulebearing are created by the first release. CLAUDE.md rules out publishing placeholders to create them earlier.

Decision

npm-publish installs npm 11.21.0 and keeps both credentials. npm uses the OIDC exchange for every package with a matching trust setting. It falls back to NODE_AUTH_TOKEN, set from NPM_TOKEN, for a package with none, which is a package the release creates. --provenance stays and signs with the same OIDC token.

After the first release, all eight packages get the trust setting, and the secret is deleted. The maintainer runs npm trust github for the seven new names, as the loop in docs/release.md ยง The npm wrapper shows. Then NPM_TOKEN is deleted and the token revoked. From then on the workflow publishes with no stored npm credential. The fallback stays in the workflow for a package added later, whose first publish needs a token created for that package alone.

A dry run proves the trust setting. On a manual run, npm-credentials republishes the rulebearing 0.0.1 tarball with no token configured and provenance off. The registry answers "previously published" only if npm exchanged the OIDC token. Without a matching trust setting npm has no credential and fails with ENEEDAUTH, so the job fails and nothing new is published. When NPM_TOKEN is set, the job also checks it with npm whoami.

Consequences

Alternatives considered