Repository navigation
v0.6.0 publish is blocked on six Trusted Publisher registrations — runbook #370
Description
The v0.6.0 publish path is proven green up to the npm authentication boundary and stops there.
This issue is the remaining runbook, written out because the next steps are not mine to take.
Why this matters more than a version bump
The published CLI is broken. v0.5.4's build:binary recipe did not bundle the sodium-native
addon, so the shipped binary hangs forever on tps mail send on macOS and exits 1 with
"Cannot find addon" on Linux. tps --version returns zero bytes with exit 0, which is why a
broken install looks healthy to anything checking it.
Measured on one machine, same minute, both binaries:
installed shim (published latest) mail send exit=124 21s nothing delivered
built v0.6.0 (run 35229055942) mail send exit=0 0s delivered, id verified on disk
53 commits are behind this release, ten of them mail fixes. Every installed CLI silently
loses mail until it ships.
What is already done
v0.6.0is tagged on the commit carrying the OIDC publish path.- All six packages are at
0.6.0with correct names, andpackages/clipins the four platform
packages at exactly0.6.0. The workflow's version gate will pass. - The first real run (35229055942) went green through preflight, smoke and all four binary
builds, then failed atENEEDAUTHexactly as designed. No release was created and nothing
was published —github-releasedeclaresneeds: [build-binaries, publish-packages], so it
skipped. Verified by status code (404), not by an empty response body.
What is blocked on a maintainer
Six Trusted Publisher registrations on npmjs.com, one per package. For each of:
@tpsdev-ai/cli
@tpsdev-ai/agent
@tpsdev-ai/cli-darwin-arm64
@tpsdev-ai/cli-darwin-x64
@tpsdev-ai/cli-linux-arm64
@tpsdev-ai/cli-linux-x64
set Trusted Publisher → GitHub Actions with:
- repository:
tpsdev-ai/cli - workflow filename:
release.yml - environment: leave empty
The empty environment is deliberate and is the weaker half of a trade already recorded in the
workflow comment: flair pins environment: release, which scopes its trust to that environment.
This job has none, so any run of this workflow on this repo can mint a publishing token.
Tightening it is a follow-up that needs the environment created first.
All six must be registered together. packages/cli pins the platform binaries at exact
versions, so a partially published set produces a CLI whose dependencies do not exist.
Order of operations
- Merge fix(release): diagnose npm stage failures by error code, and report skipped packages honestly #369 (the failure-path fixes from release.yml: correct the stage-2FA rationale and report skipped packages honestly in the Summary #368) — it changes
release.yml. - Re-cut
v0.6.0onto the resulting main tip, so the release carries the corrected error path.
Safe only while nothing is published at 0.6.0; verify against the registry first. - Register the six trusted publishers.
- The tag push runs the workflow; it stages all six under
--tag staged. - Approve each staged package in npm. This requires 2FA and cannot be done from CI.
latestdoes not move on approval. Approval publishes understaged; promoting is a
separate manualnpm dist-tag add @tpsdev-ai/<pkg>@0.6.0 latest. That gap is latest does not move on approval — the dist-tag promote is manual, unrecorded, and easy to forget #366.
Refs #366
Activity
tps-flint commentedon Sep 17, 2026
Status 2026-09-17 15:0xZ — the tag now carries the corrected failure path.
v0.6.0re-cut onto55b6bce8(the #369 merge). Preconditions re-verified before moving it:main settled green (11 checks, no non-success conclusions), all six packages and all four
optionalDependenciespins at0.6.0, and nothing published at0.6.0on npm.Run 35237223167 behaved exactly as
designed: preflight, smoke and all four binary builds green;
publish-packagesfailed at npmauth;
github-releaseskipped; release endpoint confirmed 404; nothing published.The failure message is now the corrected one, verified from the runtime output (not from the
script GitHub echoes before executing it — that echo is unexpanded source and is easy to mistake
for evidence):
Counted in that run: 0 "ALREADY STAGED" claims and 0 "PARTIAL STAGE" lines — the latter
correctly absent, because the failure was on the first package so nothing was pending.
Nothing further can happen without the six registrations in this issue. Once they exist,
re-running this tag stages all six for approval. Note the last step is still manual and separate:
approval publishes under
staged, andlatestmoves only vianpm dist-tag add(#366) — theSummary now prints that reminder even on a re-run where nothing new was staged.
tps-flint commentedon Sep 20, 2026
Done 2026-09-19. All six Trusted Publishers are registered and v0.6.0 is published.
Registered on
tpsdev-ai/cli/release.yml, environment blank,npm stage publishonly (the"Allow npm publish" box deliberately left unchecked, so CI can stage but nothing publishes directly —
2FA stays the real gate):
Re-ran
release.ymlon the existingv0.6.0tag (--failed, reusing the smoke-tested binaryartifacts rather than rebuilding). All six staged with signed provenance — sigstore transparency
log index 2893232779 — and were approved. First release we have ever shipped with provenance;
0.5.4has no attestations at all.Verified after publish rather than from the green job:
cli@0.6.0binis intact(
{"tps": "bin/tps.cjs"}— npm's"bin[tps] … invalid and removed"warning describes its ownnormalisation, not a removal), and
dist.attestationsis present withpredicateTypehttps://slsa.dev/provenance/v1.Not fully closed for users yet, and that is #366, not this issue:
lateststill points at0.5.4. Approval cannot move a dist-tag../scripts/promote-latest.sh 0.6.0must run frommain— not from the tag, which predates #371 — on an npm-authenticated machine.
Three findings worth carrying, filed or noted separately:
tpsdev-ci, a GitHub org that does not exist —an unclaimed namespace anyone could have registered to gain publish rights to the three packages
that ship the actual binaries. Caught by reading back
npm trust list, revoked, re-registered.npm validates neither the org nor the workflow filename at registration.
npm trust list/npm trust githubexist and are the better path than the web form on a currentnpm — but an older client cannot express stage-only and 400s on create (filed as ops-uxfo).
v0.6.0tag has been moved at least three times, so "the artifact built from v0.6.0" is not astable referent. Filed separately as ops-99ja.