Skip to content

v0.6.0 publish is blocked on six Trusted Publisher registrations — runbook #370

Closed

Description

@tps-flint

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.0 is tagged on the commit carrying the OIDC publish path.
  • All six packages are at 0.6.0 with correct names, and packages/cli pins the four platform
    packages at exactly 0.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 at ENEEDAUTH exactly as designed. No release was created and nothing
    was published
    — github-release declares needs: [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

  1. 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.
  2. Re-cut v0.6.0 onto 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.
  3. Register the six trusted publishers.
  4. The tag push runs the workflow; it stages all six under --tag staged.
  5. Approve each staged package in npm. This requires 2FA and cannot be done from CI.
  6. latest does not move on approval. Approval publishes under staged; promoting is a
    separate manual npm 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

  1. tps-flint commented on Sep 17, 2026

    @tps-flint
    ContributorAuthor

    Status 2026-09-17 15:0xZ — the tag now carries the corrected failure path.

    v0.6.0 re-cut onto 55b6bce8 (the #369 merge). Preconditions re-verified before moving it:
    main settled green (11 checks, no non-success conclusions), all six packages and all four
    optionalDependencies pins at 0.6.0, and nothing published at 0.6.0 on npm.

    Run 35237223167 behaved exactly as
    designed: preflight, smoke and all four binary builds green; publish-packages failed at npm
    auth; github-release skipped; 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):

    stage publish failed for @tpsdev-ai/cli-darwin-arm64@0.6.0 and it is not published.
    npm reported an authentication failure (ENEEDAUTH) — OIDC did not authenticate
    for this package.
    Check, for THIS exact package name (@tpsdev-ai/cli-darwin-arm64):
      - a Trusted Publisher registration exists for @tpsdev-ai/cli-darwin-arm64 on npmjs.com,
        with repository + workflow filename matching this job (trust is
        per package, so a missing registration affects only @tpsdev-ai/cli-darwin-arm64)
      ...
    Fix the registration or the OIDC claim, then re-run this tag.
    

    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, and latest moves only via npm dist-tag add (#366) — the
    Summary now prints that reminder even on a re-run where nothing new was staged.

  2. tps-flint commented on Sep 20, 2026

    @tps-flint
    ContributorAuthor

    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 publish only (the
    "Allow npm publish" box deliberately left unchecked, so CI can stage but nothing publishes directly —
    2FA stays the real gate):

    @tpsdev-ai/cli · agent · cli-darwin-arm64 · cli-darwin-x64 · cli-linux-arm64 · cli-linux-x64
    

    Re-ran release.yml on the existing v0.6.0 tag (--failed, reusing the smoke-tested binary
    artifacts 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.4 has no attestations at all.

    Verified after publish rather than from the green job: cli@0.6.0 bin is intact
    ({"tps": "bin/tps.cjs"} — npm's "bin[tps] … invalid and removed" warning describes its own
    normalisation, not a removal), and dist.attestations is present with predicateType
    https://slsa.dev/provenance/v1.

    Not fully closed for users yet, and that is #366, not this issue: latest still points at
    0.5.4. Approval cannot move a dist-tag. ./scripts/promote-latest.sh 0.6.0 must run from main
    — not from the tag, which predates #371 — on an npm-authenticated machine.

    Three findings worth carrying, filed or noted separately:

    • Three of the six were first registered against 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 github exist and are the better path than the web form on a current
      npm — but an older client cannot express stage-only and 400s on create (filed as ops-uxfo).
    • The v0.6.0 tag has been moved at least three times, so "the artifact built from v0.6.0" is not a
      stable referent. Filed separately as ops-99ja.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions