Skip to content

feat: publish to npm, over trusted publishing - #135

Merged
lex00 merged 1 commit into
mainfrom
feat/134-publish-to-npm
Aug 5, 2026
Merged

feat: publish to npm, over trusted publishing#135
lex00 merged 1 commit into
mainfrom
feat/134-publish-to-npm

Conversation

@lex00

@lex00 lex00 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Closes #134.

private: true meant "open your own project" started with "clone this repo and run it from the checkout". kubemicrovm-ops ships BEHOLD_DIR handling and a bespoke error message for exactly that, and every other consumer would invent its own.

The package

private removed. publishConfig sets access: public — a scoped package's first publish is restricted otherwise — and provenance: true.

Nothing else needed changing: bin, files: [bin, dist, web] and prepublishOnly were already right.

Trusted publishing, not a token

release.yml publishes over OIDC. npm mints a short-lived credential for this repository and this workflow filename, so there is no NPM_TOKEN to leak, rotate, or scope wrongly.

Two things have to line up outside this PR:

  1. On npmjs.com → the package → Settings → Trusted Publisher, naming this repo and release.yml. Until that exists the publish step fails rather than falling back to anything, which is the behaviour you want.
  2. id-token: write on the job — declared here. Neither alone is enough.

npm is upgraded explicitly: trusted publishing needs 11.5.1+, and while Node 24 ships an npm 11 the exact patch moves with the runner image. Pinning the floor beats discovering it on a tag.

What it refuses to publish

Typecheck, tests and build run first, then two release-specific gates:

  • The tarball must carry bin, dist and web. web is the SPA — a tarball missing it publishes a server with no UI, which looks fine in CI and breaks on install.
  • The tag must match package.json's version, so a mistyped tag cannot ship a version nobody asked for.

workflow_dispatch rehearses all of it and publishes nothing.

Verified against a real install, not just a dry run

$ npm pack && npm install ../behold/intentius-behold-0.2.0.tgz
$ ./node_modules/.bin/behold serve /tmp/kubemicrovm-ops --port 4699
installed behold serving on 4699
<title>behold</title>

That exercises the thing most likely to break on packaging: webRoot is dirname(module)/../web, which resolves from src/ in dev and from dist/ when installed, because files ships both at the package root. It served the SPA and a real project's graph.

npm run tsc clean, 433 tests passing.

One thing to settle first

There is no license field and no LICENSE file. npm will warn on publish, and a public package without one is ambiguous for anyone who installs it. Picking a license is not my call, so I have left it alone — but it is worth settling before the first publish rather than after.

Follow-up, not in this PR

Once published, kubemicrovm-ops's just view can drop its checkout-finding logic for npx @intentius/behold serve .. Deliberately held back: that change is wrong until the package actually exists.

Closes #134.

behold carried `private: true`, so "open your own project" started with
"clone this repo and run it from the checkout". kubemicrovm-ops ships
BEHOLD_DIR handling and a bespoke error message for exactly that, and
every other consumer would invent its own.

`private` goes, `publishConfig` sets `access: public` (a scoped package's
first publish is otherwise restricted) and `provenance: true`.

## Trusted publishing rather than a token

release.yml publishes over OIDC — npm mints a short-lived credential for
this repository and this workflow filename, so there is no NPM_TOKEN to
leak, rotate or scope wrongly. That needs `id-token: write`, which the job
declares, and a Trusted Publisher configured on npmjs.com naming this repo
and `release.yml`. Until that exists the publish step fails rather than
falling back to anything, which is the behaviour you want.

npm is upgraded explicitly: trusted publishing needs 11.5.1 or newer, and
while Node 24 ships an npm 11 the exact patch moves with the runner image.
Pinning the floor here beats discovering it on a tag.

## What the workflow refuses to publish

Everything that can say no runs first — typecheck, tests, build — then two
release-specific gates:

The tarball has to carry bin, dist and web. `files` includes web because
it is the SPA; a tarball missing it publishes a server with no UI, which
would look fine in CI and break on install.

The tag has to match package.json's version, so a mistyped tag cannot ship
a version nobody asked for.

workflow_dispatch rehearses all of it and publishes nothing.

## Verified against a real install

`npm pack`, installed into a scratch project, and run from
node_modules/.bin: the bin resolves dist/cli.js, the server resolves
web/ (it is dirname(module)/../web, which lands the same from src/ in dev
and dist/ when installed), and it served the SPA and a real project's
graph on a port.

Note: the package has no `license` field and the repo has no LICENSE file.
npm will warn on publish. Choosing one is not my call, so it is left as
is — worth settling before the first publish rather than after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TCV5kwB1jdnWH9if9ZbNXq
@lex00
lex00 force-pushed the feat/134-publish-to-npm branch from 54e440f to 9db546e Compare August 5, 2026 04:22
@lex00

lex00 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

Restacked onto main.

This branch carried #133's commit underneath the npm change, so my #139 (which closes the same issue, #131) put it in conflict. That was my doing — I implemented #131 without checking for an open PR on it first.

The npm work itself was never in conflict: 54e440f touches only .github/workflows/release.yml and package.json. The branch is now that commit alone on top of current main, so this PR is what its title says and nothing else.

The zoom-note work it was stacked on is handled separately — #139 landed the bulk, and #133's logicalDegraded partial-projection threshold is being ported as a follow-up, since that part is genuinely better than what I merged.

Original tip 54e440fb7252960cd324d22c4103c888543788b5 if anything needs recovering.

just check: 455 tests, tsc and build clean.

@lex00
lex00 merged commit 710bb05 into main Aug 5, 2026
1 check passed
@lex00
lex00 deleted the feat/134-publish-to-npm branch August 5, 2026 04:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

behold is private:true, so "open your own project" means "clone this repo first"

1 participant