@patchstack/connect 0.5.9 → 0.5.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENT-INSTALL.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  This versioned reference ships inside `@patchstack/connect` and documents each setup command and its project changes.
4
4
 
5
+ ## Choose the project path first
6
+
7
+ Use the package setup flow below for an existing JS/Node application. Work in its package directory; a missing `package.json` can mean you are in a subdirectory or looking at generated HTML rather than the source project. A page containing HTML can still belong to a server-rendered application. Do not infer that runtime protection is unnecessary from the file extension alone.
8
+
9
+ ### Plain HTML sites
10
+
11
+ For a standalone site made of HTML, CSS, and browser JavaScript, with no package-managed application or server request handler, use the disclosure widget directly. Do not create `package.json`, install a framework, invent build hooks, or add a server just to run Connect. `setup` requires an existing `package.json`; it is not a standalone HTML installer.
12
+
13
+ 1. Use the public site UUID or widget snippet for the correct site in the Patchstack dashboard. An existing `.patchstackrc.json` can also supply `siteUuid`. If neither is available, ask the user for the site's public UUID or dashboard-provided snippet before editing the page. Never invent a UUID or use a claim token or API key as the widget identifier.
14
+ 2. Add one widget tag before `</body>` in the page or shared layout. Preserve an existing correct tag. For a page published directly without a build step, disable the widget's build-mode onboarding with `data-build-mode="false"`:
15
+
16
+ ```html
17
+ <script src="https://cdn.patchstack.com/patchstack-widget.js" data-site-uuid="YOUR_SITE_UUID" data-build-mode="false" defer></script>
18
+ ```
19
+
20
+ Replace `YOUR_SITE_UUID` with the real public site UUID before saving. Keep credentials out of the page. The [public widget reference](https://cdn.patchstack.com/llm.html) documents this embed and its options.
21
+ 3. Verify the saved tag uses the correct UUID. If a browser preview is available, reload it and check for the report button; otherwise tell the user that the browser check is pending. Do not submit a vulnerability report as an installation test. Save the HTML change and remind the user to publish it when ready; do not deploy it yourself.
22
+
23
+ Report this as **disclosure widget installed**, with any remaining preview or publishing step. This path does not inventory local JavaScript files or scripts loaded from a CDN, scan npm dependencies, or install runtime exploit protection. External APIs used by the page require their own server-side integration.
24
+
5
25
  ## Command reference
6
26
 
7
27
  Every command at a glance — what it does, whether it reads your source, what it writes, and what leaves your machine. Full behavior, flags, and edge cases follow in the sections below.
@@ -88,12 +108,72 @@ This is a request, not a mechanism: nothing in the install depends on it. Do it
88
108
 
89
109
  **If the request you were given includes a claim token**, pass it exactly as given: `npx @patchstack/connect setup --claim-token <token>`. The site is then created in the person's own Patchstack account and `setup` prints their dashboard link for it — there is no sign-in step to relay. The token comes only from the person's Patchstack dashboard; never invent one, never write it to a file, never print it back. If `setup` reports that the token had expired or was not recognised, the site is not connected: hand over the dashboard link it prints instead, and tell the person they can copy a fresh prompt from the dashboard.
90
110
 
91
- In a hosted builder, run setup with `PATCHSTACK_ENVIRONMENT=sandbox` scoped to the workspace process/command, ensure the CLI's on-disk edits are adopted into the platform's persisted project state, then restart any already-running preview/server process so it loads the guard. Do not persist `"environment": "sandbox"` in `.patchstackrc.json`: deployed builds use the same committed files and report `production` only when the build platform's own variables say so — its tier (Vercel, Netlify, Render, Railway, GitLab CI) or a branch named `main`, `master`, `production`, `prod`, `release` or `live` (Cloudflare Pages and Workers Builds, AWS Amplify, GitHub Actions, GitLab CI without a tier); a preview, pull request or other branch there reports `sandbox`, as does the Replit workspace, while a Replit Deployment reports `production`. A build in a project the builder generated and builds for itself (Lovable, Replit) reports `production` without an override, because the edit preview is a dev server and a build is the publish step — which is exactly why the sandbox label belongs in the workspace process and not in a file. A scan on a developer's machine, in a CI runner this does not know (`CI=true` alone), or on a platform with no such signal reports `local` on its own, and the dashboard shows that app as configured, not deployed. A client-only SPA or a static site generator has no server request path to guard: `setup` says runtime protection does not apply and installs nothing for it; never call such a project protected.
111
+ In a hosted builder, run setup with `PATCHSTACK_ENVIRONMENT=sandbox` scoped to the workspace process/command, ensure the CLI's on-disk edits are adopted into the platform's persisted project state, then restart any already-running preview/server process so it loads the guard. Do not persist `"environment": "sandbox"` in `.patchstackrc.json`: deployed builds use the same committed files and report `production` only when the build platform's own variables say so — its tier (Vercel, Netlify, Render, Railway, GitLab CI) or a branch named `main`, `master`, `production`, `prod`, `release` or `live` (Cloudflare Pages and Workers Builds, AWS Amplify, GitHub Actions, GitLab CI without a tier); a preview, pull request or other branch there reports `sandbox`, as does the Replit workspace, while a Replit Deployment reports `production`. A build in a project the builder generated and builds for itself (Lovable, Replit) reports `production` without an override, because the edit preview is a dev server and a build is the publish step — which is exactly why the sandbox label belongs in the workspace process and not in a file. A scan on a developer's machine, in a CI runner this does not know (`CI=true` alone), or on a platform with no such signal reports `local` on its own, and the dashboard shows that app as configured, not deployed. A positively identified static build reports runtime protection as not applicable. A bundler-only project, including plain Vite, can remain runtime unknown and receive a generic scaffold with incomplete wiring. Report that limitation; do not add an artificial server merely to make the check pass, and never describe a widget or an unwired scaffold as runtime protection.
92
112
 
93
113
  **Finish by telling the user to refresh their preview.** The widget's "Report a vulnerability" button loads with the page, so a preview that was already open still shows the HTML from before setup — the button is missing there until it reloads. Nothing in the CLI can reach the user's browser, so relaying this is your job. Phrase it as a check rather than a required step: a builder that hot reloads, or a preview server you restarted, may have refreshed it already.
94
114
 
95
115
  **Then tell them to deploy.** Setup changes source files, and the deployed site keeps serving its previous build until the next deploy — so visitors get no widget, and on a server-rendered root no production marker, until the user deploys (or hits Publish) again. Say it as a reminder; do not deploy anything yourself.
96
116
 
117
+ ## When your tool will not run this CLI
118
+
119
+ Some coding tools refuse to execute a third-party command until the person approves it. In Claude Code,
120
+ auto mode's classifier can decline `npx @patchstack/connect setup` and the installed `patchstack-connect`
121
+ binary on that ground instead of prompting. The command is not the problem; the approval is missing.
122
+ Handle it in this order:
123
+
124
+ 1. **Stop at the refused command.** Do not route around the refusal: do not call the Patchstack API
125
+ yourself, do not wrap the command in a `package.json` script so a later install runs it, and do not add
126
+ the `postinstall` / `prebuild` hooks first so the next install provisions the site. Each of those runs
127
+ the command the tool declined, with the person's decision taken away from them. Leave `package.json`
128
+ and the source tree as they were.
129
+
130
+ 2. **Hand the person the ways forward, with the exact text.** Say what the command does in plain words —
131
+ it registers the site with Patchstack, writes two small config files, adds the "Report a vulnerability"
132
+ line to the page, and adds the protection files and build steps described above — then give them:
133
+
134
+ - **Run it themselves, in this session.** In Claude Code a line that starts with `!` runs in their shell
135
+ and its output lands in the conversation: `! npx @patchstack/connect setup`. Other tools have a
136
+ terminal beside the chat; the command is the same without the `!`.
137
+ - **Approve it once.** In Claude Code, `/permissions` → **Recently denied** → `r` retries the command
138
+ with a manual approval; or `Shift+Tab` switches to Manual mode, and the tool prompts them when you
139
+ try again.
140
+ - **Allow it for good, then ask you to run it again.** For Claude Code these rules pre-approve every
141
+ `npx @patchstack/connect …` command and nothing else. They go in `.claude/settings.json` (shared with
142
+ the repository), `.claude/settings.local.json` (this person only), or through `/permissions`:
143
+
144
+ ```json
145
+ {
146
+ "permissions": {
147
+ "allow": [
148
+ "Bash(npx @patchstack/connect *)",
149
+ "Bash(npx --yes @patchstack/connect *)"
150
+ ]
151
+ }
152
+ }
153
+ ```
154
+
155
+ Other tools keep their own allowlists; the README section "If your coding tool blocks the command"
156
+ shows the Gemini CLI and OpenCode forms.
157
+
158
+ 3. **Write the command as `npx @patchstack/connect <command>`.** A rule matches the command text as
159
+ written. `./node_modules/.bin/patchstack-connect setup`, `PATCHSTACK_ENVIRONMENT=sandbox npx …` and
160
+ `npx --yes patchstack-connect setup` are different texts, and the rules above do not cover them. On a
161
+ developer's machine the sandbox label is not needed anyway: a scan there reports `local` on its own.
162
+
163
+ 4. **Resume from the output.** `setup` prints the same checklist, dashboard link and outcome block whoever
164
+ ran it, and re-running it changes nothing that is already done. If the person ran it, relay the
165
+ dashboard link and the outcome block from their output as they are. If your tool still will not run
166
+ `guide` or `status` for you, verify from the files instead of guessing: `siteUuid` in
167
+ `.patchstackrc.json` means the site is provisioned; `patchstack-connect scan` and
168
+ `patchstack-connect mark-build` in the `package.json` scripts mean the hooks are wired;
169
+ `patchstack-widget.js` in the root shell means the widget is in place; `.patchstackrc.local.json` in
170
+ `.gitignore` means the credential stays out of the commit. Never construct a dashboard link yourself —
171
+ it comes from `setup`, `status` or `claim` output.
172
+
173
+ 5. **`claim` and `login` are the same shape.** Both print a link the person opens. If your tool will not
174
+ run them, the person runs `npx @patchstack/connect claim` (or `login`) themselves and you relay the
175
+ link from their output.
176
+
97
177
  ## Manual setup
98
178
 
99
179
  1. **First scan** — provisions a Patchstack site automatically, writes the UUID to `.patchstackrc.json`, and installs the disclosure widget's `<script>` tag into the root HTML shell (`index.html`, `public/index.html`, or `src/app.html`) when one exists — or, when the root shell is JSX, the production marker instead. No signup, dashboard step, or UUID is needed up front:
@@ -120,7 +200,7 @@ This is a request, not a mechanism: nothing in the install depends on it. Do it
120
200
 
121
201
  **Bun-managed projects:** `bun run` does not execute npm-style `pre`/`post` scripts, so wire the build script directly instead: `"build": "patchstack-connect scan && <existing build command> && patchstack-connect mark-build"`.
122
202
 
123
- 3. **Verify the disclosure widget** — a floating "Report a vulnerability" button. `scan` installs it automatically into a plain HTML shell **or a JSX root** (Next, Remix, React Router, TanStack Start, Gatsby), and `mark-build` carries it into built HTML. Only when `scan` reported that it found no editable shell at all — a root whose head mechanism is not a plain script tag, e.g. Nuxt's `useHead` or an Astro layout — add the one-liner it printed to the root layout yourself, just before `</body>` (never a JS entry point), reading `siteUuid` from `.patchstackrc.json`. On those same roots the widget also needs the production marker above the tag — `scan` adds it automatically to a JSX root, and prints it to paste when it finds no anchor. A server-rendered site without the marker serves the build-mode claim flow to its visitors:
203
+ 3. **Verify the disclosure widget** — a floating control whose form follows the site's claim state: while the site is unclaimed it is a one-time "Connect this website" panel, and it becomes the public "Report a vulnerability" button once the site is claimed. Do not tell the user the report button will appear on a site that has not been connected to an account yet. `scan` installs it automatically into a plain HTML shell **or a JSX root** (Next, Remix, React Router, TanStack Start, Gatsby), and `mark-build` carries it into built HTML. Only when `scan` reported that it found no editable shell at all — a root whose head mechanism is not a plain script tag, e.g. Nuxt's `useHead` or an Astro layout — add the one-liner it printed to the root layout yourself, just before `</body>` (never a JS entry point), reading `siteUuid` from `.patchstackrc.json`. On those same roots the widget also needs the production marker above the tag — `scan` adds it automatically to a JSX root, and prints it to paste when it finds no anchor. A server-rendered site without the marker serves the build-mode claim flow to its visitors:
124
204
 
125
205
  ```html
126
206
  <script src="https://cdn.patchstack.com/patchstack-widget.js" data-site-uuid="<SITE_UUID>" defer></script>
@@ -188,7 +268,11 @@ It is server-only. Never put it in the widget tag, client bundles, or public env
188
268
 
189
269
  **Do not commit `.patchstackrc.local.json`.** That file holds the API key issued at provision; the scan writes it and adds it to `.gitignore`, and tells you if it could not. `.patchstackrc.json` holds only the site UUID and settings, and the UUID is public by design — it ships in the widget tag in served HTML.
190
270
 
191
- 6. **Open the dashboard link** from the scan in a browser and sign in. The site is monitored either way, but the vulnerability reports are only visible after connecting it to an account. The same connection flow is available from the widget's "Connect this website" prompt. On the published site, the owner reaches the widget login by appending `#patchstack` to the live URL.
271
+ 6. **Connect the site to a Patchstack account.** The site is monitored either way, but its vulnerability reports are only visible once it is attached to an account, and an unattached site stays claimable by anyone who loads the page — the site UUID ships in the HTML and claiming is first-come. Three routes reach the same place; tell the user all three and lead with the first, which needs no terminal and no copied URL:
272
+
273
+ 1. **The widget's "Connect this website" panel**, already on the preview. While the site is unclaimed the widget serves this panel *instead of* the report button, and signing in there attaches the site. On a published build it is hidden from visitors; the owner reveals it by appending `#patchstack` (or `?patchstack`) to the live URL.
274
+ 2. **The dashboard link** the scan printed — open it in a browser and sign in.
275
+ 3. **`npx @patchstack/connect claim`** from the terminal, which prints a link to sign in with and then attaches the site.
192
276
 
193
277
  ## Rules
194
278
 
@@ -197,6 +281,7 @@ It is server-only. Never put it in the widget tag, client bundles, or public env
197
281
  - The CLI never opens the dashboard link and never asks for Patchstack credentials.
198
282
  - Label hosted workspace scans with `PATCHSTACK_ENVIRONMENT=sandbox` in that process only. Leave production builds unset (a platform's own tier or production branch name, or the hosted builder the project belongs to, makes the build report `production`; a developer machine or a CI runner this does not know reports `local`) and never commit a sandbox label into files shared with production.
199
283
  - If a step fails, stop and report it. Don't proceed with placeholders.
284
+ - If your tool refuses to execute the CLI, stop and hand the command to the person — see "When your tool will not run this CLI". Never work around a permission refusal.
200
285
  - CI never has the credential in a file: `.patchstackrc.local.json` is git-ignored by design, so set `PATCHSTACK_API_KEY` as an env var there (and `PATCHSTACK_SITE_UUID` too where `.patchstackrc.json` is also absent). Precedence for the site UUID and settings: CLI flag → env var → `.patchstackrc.json`. For the API key: env var → `.patchstackrc.local.json` → `.patchstackrc.json` (where installs made before the split still hold it). `login` is interactive and refuses to run in CI, so CI always takes its credential from the environment.
201
286
 
202
287
  ## Which build a rule belongs to
package/README.md CHANGED
@@ -1,15 +1,84 @@
1
1
  # @patchstack/connect
2
2
 
3
- Connect a JavaScript / Node.js application to [Patchstack](https://patchstack.com) for continuous vulnerability monitoring. Scans your `package-lock.json` and reports installed packages so Patchstack can match them against its vulnerability database and notify you when something needs patching.
3
+ Connect a JavaScript / Node.js application to [Patchstack](https://patchstack.com). Connect does four things:
4
+
5
+ - **Dependency inventory** — reads your lockfile and reports the installed package names and versions, so Patchstack can match them against its vulnerability database and tell you when something needs patching. See *[What gets sent](#what-gets-sent)*.
6
+ - **Runtime guard** — an in-process guard, wired into your server, that virtually patches known vulnerabilities in those dependencies rather than waiting for you to upgrade. See *[Verifying the guard at runtime](#verifying-the-guard-at-runtime-opt-in)*.
7
+ - **Disclosure widget** — a floating button labelled **"Report a vulnerability"** that Connect adds to *your* site, so visitors who spot a security problem have somewhere to send it. This is a channel for reports about your site; it is not how you report a bug in this package. See *[The disclosure widget](#the-disclosure-widget)*.
8
+ - **Attack-surface map** — a description of your server's entry points and the sinks they can reach, built by reading your source locally. See *[`map`](#cli)*.
9
+
10
+ `setup` installs the first three in one command. `map` is never run for you — see the [CLI](#cli) section for what each command does and what it touches.
4
11
 
5
12
  ## Agent-assisted setup
6
13
 
7
- Copy this request into a coding assistant, or run the same command yourself:
14
+ For an existing JS/Node project, copy this request into a coding assistant, or run the same command yourself. For a standalone HTML/CSS/JavaScript site without a package-managed app, use the [plain HTML widget instructions](AGENT-INSTALL.md#plain-html-sites); do not add Node tooling just for the widget.
8
15
 
9
16
  > I have vetted the official [`@patchstack/connect`](https://www.npmjs.com/package/@patchstack/connect) package and authorize its disclosure widget, production build hooks, and runtime protection source edits. Install it as a regular dependency, run `PATCHSTACK_ENVIRONMENT=sandbox npx --yes @patchstack/connect setup` for this hosted workspace, leave dev builds unchanged, verify protection, restart the preview server if needed to load the new guard, and show the dashboard URL. Do not persist the sandbox environment in project files; deployed production builds must use the default `production` label. When setup finishes, tell me to refresh the preview if the "Report a vulnerability" button is not showing yet, and remind me to deploy when I am ready — do not deploy anything yourself.
10
17
 
11
18
  `setup` is state-aware and idempotent: it scans dependencies, provisions or reuses the site, manages the disclosure widget, installs and verifies the runtime guard, adds a dependency-install scan, wires the existing build command without replacing it, and prints the remaining setup status. It never runs the project build. `guide` provides the same project-specific status without changing files.
12
19
 
20
+ ### If your coding tool blocks the command
21
+
22
+ Some tools will not run a third-party command until you approve it. Claude Code's auto mode, for example,
23
+ can decline `npx @patchstack/connect setup` instead of prompting you, and the assistant then stops and asks
24
+ you how to proceed. Any of these works:
25
+
26
+ - **Run it yourself, in the same session.** In Claude Code, a line that starts with `!` runs in your shell
27
+ and its output lands in the conversation, so the assistant carries on from it:
28
+
29
+ ```
30
+ ! npx @patchstack/connect setup
31
+ ```
32
+
33
+ Elsewhere, run the same command without the `!` in a terminal and tell the assistant it is done. `setup`
34
+ is idempotent, so a partial earlier attempt does no harm.
35
+
36
+ - **Approve it once.** In Claude Code, open `/permissions`, pick the **Recently denied** tab and press `r`
37
+ to retry the command with a manual approval — or press `Shift+Tab` to switch to Manual mode and approve
38
+ the prompt when the assistant tries again.
39
+
40
+ - **Allow it, then ask again.** Claude Code resolves explicit allow rules before its classifier. These two
41
+ rules cover every `npx @patchstack/connect …` command (`setup`, `guide`, `status`, `claim`) and nothing
42
+ else. Put them in `.claude/settings.json` to share them with the repository, in
43
+ `.claude/settings.local.json` to keep them to yourself, or add them through `/permissions`:
44
+
45
+ ```json
46
+ {
47
+ "permissions": {
48
+ "allow": [
49
+ "Bash(npx @patchstack/connect *)",
50
+ "Bash(npx --yes @patchstack/connect *)"
51
+ ]
52
+ }
53
+ }
54
+ ```
55
+
56
+ A rule matches the command text as written, so use the plain `npx @patchstack/connect …` form: a leading
57
+ `PATCHSTACK_ENVIRONMENT=sandbox`, a path such as `./node_modules/.bin/patchstack-connect`, or the bare
58
+ `patchstack-connect` binary name is a different text and is not covered. On your own machine the sandbox
59
+ label is not needed — a scan there reports `local` by itself. Rules in a project's `.claude/settings.json`
60
+ apply once you have accepted that folder's trust dialog. If auto mode still declines the command with the
61
+ rules in place, use one of the first two options.
62
+
63
+ Other tools keep their own allowlists. Gemini CLI reads policy files from `~/.gemini/policies/`:
64
+
65
+ ```toml
66
+ [[rule]]
67
+ toolName = "run_shell_command"
68
+ commandPrefix = "npx @patchstack/connect"
69
+ decision = "allow"
70
+ priority = 100
71
+ ```
72
+
73
+ OpenCode takes the pattern in `opencode.json` (project root, or `~/.config/opencode/opencode.json`):
74
+
75
+ ```json
76
+ { "permission": { "bash": { "npx @patchstack/connect *": "allow" } } }
77
+ ```
78
+
79
+ Codex CLI asks according to `approval_policy` in `~/.codex/config.toml`: approve the command when it
80
+ asks, or run it yourself.
81
+
13
82
  ## Quick start (zero configuration)
14
83
 
15
84
  ```bash
@@ -384,55 +453,27 @@ Every scanned source is validated against `package.json`: if the chosen lockfile
384
453
  ## Development
385
454
 
386
455
  ```bash
387
- npm install
456
+ npm ci
388
457
  npm run typecheck
458
+ npm run build # before the tests: several only run once dist/ exists, and skip silently without it
389
459
  npm test
390
- npm run build
391
- ```
392
-
393
- ### Manifest endpoint testing
394
-
395
- To post the current lockfile manifest to a local Patchstack API endpoint and provision a new site:
396
-
397
- ```bash
398
- bun run test:manifest -- --endpoint http://localhost:8000/monitor/pulse/manifest
399
- ```
400
-
401
- The response should include the new site UUID. To re-test an existing site, pass that UUID explicitly:
402
-
403
- ```bash
404
- bun run test:manifest -- --endpoint http://localhost:8000/monitor/pulse/manifest --site-uuid YOUR_REAL_UUID
405
460
  ```
406
461
 
407
- Use `--dry-run` to preview the payload without posting.
462
+ `CONTRIBUTING.md` covers the rest — the Node versions this needs, the packaging checks, and what to run before opening a pull request. Changing onboarding, the install prompt or the setup guide? Read `MAINTAINING.md` first.
408
463
 
409
464
  ## Release process
410
465
 
411
466
  Pull requests run typecheck, tests, build, package verification, and a production dependency audit in GitHub Actions.
412
467
 
413
- Publishing runs when a GitHub Release is published. The release tag must match the package version in `package.json` with a leading `v`. For example, `package.json` version `0.2.0` must be released with tag `v0.2.0`; otherwise the workflow fails before publishing.
414
-
415
- To publish a release:
468
+ Releases are cut by the `Release` workflow, which works out the next version, tags it, and hands off to `Publish`:
416
469
 
417
- 1. Bump the package version, for example `npm version 0.2.0 --no-git-tag-version`.
418
- 2. Commit `package.json` and `package-lock.json`.
419
- 3. Merge the version bump to `main`.
420
- 4. Create and publish a GitHub Release tagged `v0.2.0`.
421
- 5. The `Publish` workflow verifies the package, then runs `npm publish --provenance --access public`.
422
-
423
- Before the first release, configure npm trusted publishing for this package:
470
+ ```bash
471
+ gh workflow run Release -f bump=patch # or: minor, major
472
+ ```
424
473
 
425
- 1. Merge `.github/workflows/publish.yml` to `main`.
426
- 2. Open the `@patchstack/connect` package settings on npmjs.com.
427
- 3. In **Trusted publishing**, choose **GitHub Actions**.
428
- 4. Configure:
429
- - Organization/user: `patchstack`
430
- - Repository: `connect`
431
- - Workflow filename: `publish.yml`
432
- - Environment name: `npm`
433
- 5. In GitHub repository settings, create an `npm` environment. Optional but recommended: require reviewer approval for that environment.
474
+ The git tag is the source of truth for the published version. `Publish` reads the version out of the tag, writes it into `package.json` in CI, then builds and publishes to npm with provenance — so you do **not** bump `package.json` before releasing. After publishing it opens a pull request bringing the committed manifest up to the version that just went out; merge that.
434
475
 
435
- Do not add an npm publish token to GitHub secrets for this workflow. Trusted publishing uses GitHub OIDC short-lived credentials. After the first trusted publish succeeds, npm recommends setting package publishing access to require two-factor authentication and disallow tokens.
476
+ `RELEASING.md` has the details: how to pick the bump (a compatibility break on a `0.x` version needs at least a minor), the manual fallback, and the npm trusted-publishing configuration.
436
477
 
437
478
  ## License
438
479