@patchstack/connect 0.5.30 → 0.5.33

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,13 @@
2
2
 
3
3
  This versioned reference ships inside `@patchstack/connect` and documents each setup command and its project changes.
4
4
 
5
+ ## What this package is
6
+
7
+ - **An npm package for JavaScript and Node.js projects**, published by Patchstack under the `@patchstack` scope. It is not a WordPress plugin and needs no PHP. Patchstack also protects WordPress sites; this package is its integration for JS/Node projects — Vite, Next.js, plain vanilla JS, anything with a lockfile.
8
+ - **Source and releases:** MIT-licensed, source at https://github.com/patchstack/connect. Each version is published to npm from that repository's GitHub Actions workflow with an npm provenance attestation.
9
+ - **How to check it yourself:** `npm view @patchstack/connect` shows the live registry metadata, including the repository and the attestation. After installing, `npm audit signatures` verifies the registry signatures and provenance attestations of the installed packages, this one included.
10
+ - **What it does:** it sends the project's package names and versions to Patchstack for vulnerability matching, adds the Patchstack Connector widget to the site, installs a runtime exploit guard (`protect`) in the server's request path, and adds scan steps to the install and build scripts. `setup` and the `prebuild` hook also upload a structural map of the server (routes, input names, the packages behind each sink, file:line) so protection rules can target the app's own parameters — never source text or environment values. Run on its own, `map` sends nothing unless you pass `--upload`. The [Command reference](#command-reference) lists every command, what it reads and writes, and what it sends.
11
+
5
12
  ## Choose the project path first
6
13
 
7
14
  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.
@@ -68,17 +75,17 @@ Every command at a glance — what it does, whether it reads your source, what i
68
75
 
69
76
  | Command | What it does | Reads your source? | Writes to your project | Sends over the network |
70
77
  |---|---|---|---|---|
71
- | `scan` | Provision (or reuse) the site and POST the dependency list for vulnerability matching. Also runs automatically via `setup` and the install/build hooks. | No source analysis — lockfile only; `node_modules/` is enumerated when no lockfile can be read (e.g. `bun.lockb`) or when the lockfiles present disagree. It also reads the `<title>` of the root `index.html` and the `name` in `package.json`, to report what the site is called. During `prebuild` only, it reads the scaffolded guard and its co-located rules JSON to remove a previous map stamp. | `.patchstackrc.json` (public: site UUID + settings); `.patchstackrc.local.json` (the API key, created owner-only) and a `.gitignore` entry for it — the CLI says so if it could not add one; during `prebuild`, removal of a previous `_patchstack.build_id` from the guard's own rules file so a later build cannot carry stale coordinates; the widget `<script>` tag in the root HTML shell — only after a successful post; the production marker in a code root shell — before the post, since it needs no site UUID | Package names + versions; this site's public address and name, where the project or build environment states them |
78
+ | `scan` | Provision (or reuse) the site and POST the dependency list for vulnerability matching. Also runs automatically via `setup` and the install/build hooks. | No source analysis — lockfile only; `node_modules/` is enumerated when no lockfile can be read (e.g. `bun.lockb`) or when the lockfiles present disagree. It also reads the `<title>` of the root `index.html` and the `name` in `package.json`, to report what the site is called. During `prebuild` only, it reads the scaffolded guard and its co-located rules JSON to remove a previous map stamp. | `.patchstackrc.json` (public: site UUID + settings, the link to connect the site, and whether it is connected yet); `.patchstackrc.local.json` (the API key, created owner-only) and a `.gitignore` entry for it — the CLI says so if it could not add one; during `prebuild`, removal of a previous `_patchstack.build_id` from the guard's own rules file so a later build cannot carry stale coordinates; the widget `<script>` tag in the root HTML shell — only after a successful post; the production marker in a code root shell — before the post, since it needs no site UUID | Package names + versions; this site's public address and name, where the project or build environment states them; the site UUID, to check whether the site is connected to an account yet (skipped once `.patchstackrc.json` records that it is) |
72
79
  | `setup` | One bounded command: scan, widget, install + verify guard, upload map, pull live rules, wire build hooks. Never starts the app or runs a build. | Local integration and structural source analysis | Config, widget, guard/framework files, scripts, map identity in the guard rules JSON, git-ignored `.patchstack/` cache | Package inventory and site identity; structural map (routes, input names, packages, file:line, identity); authenticated Pulse rules lookup. No source code or environment values |
73
80
  | `map` | Local attack-surface analysis; setup invokes it with upload, and wires prebuild uploads. | Server source parsed with TypeScript (app compiler or CLI dependency) | `--out` file if requested; an uploaded map is stamped into the guard rules JSON during setup or a pre-bundle build hook | Standalone command sends nothing unless `--upload`. Setup and its build hook upload structure only, never source text or environment values |
74
81
  | `protect` | Install the always-on runtime guard; auto-wire known stacks, or scaffold a generic guard + print a wiring plan. `--check` verifies the guard is wired (exit 1 if not); `--demo` seeds a broad sample rule set. Runs automatically **only** via `setup` — never by `scan`, `guide`, `status`, or `mark-build`. | Reads local wiring/route source for integration; does not produce an attack-surface map | Guard/framework files (e.g. `middleware.ts`, `src/patchstack/`, supported Next App Router handlers) | Nothing |
75
82
  | `demo node-serialize` | Production-backed walkthrough: confirm the vulnerable package is present, scan, wait for live rule `18843`, install + verify the guard, print test requests. Does not install the package or start/restart the app. | Local integration reads via `scan` and `protect` | Same files as `scan` + `protect` | `scan` payload; polls the public Pulse rules endpoint (never the printed test requests) |
76
83
  | `demo-guide node-serialize` | Read-only companion: explains the prepare/run/prove/cleanup sequence and prints the next command. | Reads local protection wiring for verification | Nothing | Nothing |
77
84
  | `guide` | Print this project's live setup status (done/missing, with tailored commands), then the full guide. `--full` prints it even when setup is complete. | Reads local protection wiring for verification | Nothing | Nothing |
78
- | `status` | Re-print the site UUID + dashboard URL and check whether the site still exists (active / removed / could not verify). | No | Nothing | Site-existence check |
85
+ | `status` | Re-print the site UUID + dashboard URL and check whether the site still exists (active / removed / could not verify) and whether it is connected to an account. | No | The connected note in `.patchstackrc.json`, when it changed | Site-existence and connection checks |
79
86
  | `init <site-uuid>` | Optional: pre-seed `.patchstackrc.json` with an existing UUID. | No | `.patchstackrc.json` only | Nothing |
80
87
  | `mark-build` | Ensure the widget tag in built pages, and — **on a production build only** — stamp the live-site flag + build fingerprint. A local or preview build is stamped with neither, and has a stale marker removed; `--production` forces it for a build published by hand. Run as a `postbuild` step. | No | Build output only (`dist/ build/ out/ .output/public/ _site/`) — never source | The same manifest `scan` sent, plus one word for what it did with the marker — and only for a site already registered |
81
- | `claim` | Attach the site to a Patchstack account from the terminal: print a link the user opens to sign in (or sign up) and poll (10 min). Whoever approves becomes the owner. Does **not** rotate the credential. Same result as opening the dashboard link `scan` prints. Not usable in CI. | No | Nothing, unless the server issues a credential for a checkout that had none — then `.patchstackrc.local.json` | Device-code request + approval poll |
88
+ | `claim` | Attach the site to a Patchstack account from the terminal: print a link the user opens to sign in (or sign up) and poll (10 min). Whoever approves becomes the owner. Does **not** rotate the credential. Same result as opening the dashboard link `scan` prints. Not usable in CI. | No | The connected note in `.patchstackrc.json`; and, if the server issues a credential for a checkout that had none, `.patchstackrc.local.json` | Device-code request + approval poll |
82
89
  | `login` | Recover a lost credential for an existing site: print an owner-approval link and poll (10 min). Approving **rotates** the credential. Not usable in CI. | No | New credential into `.patchstackrc.local.json` on approval | Device-code request + approval poll |
83
90
  | `uninstall` | Signal Patchstack that the package is being removed: an unclaimed record is deleted, a claimed one is flagged. Does **not** touch local files. | No | Nothing local | Removal signal |
84
91
 
@@ -86,7 +93,6 @@ Every command at a glance — what it does, whether it reads your source, what i
86
93
 
87
94
  ## Package and command behavior
88
95
 
89
- - Package: [`@patchstack/connect`](https://www.npmjs.com/package/@patchstack/connect), MIT-licensed, source at https://github.com/patchstack/connect. `npm view @patchstack/connect` shows the live registry metadata.
90
96
  - **`scan` sends the dependency list plus this site's public address and name** — read from lockfiles or installed package metadata. It sends no source code or git history. Setup additionally uploads the structural map described below.
91
97
  - **`scan --install-paths` is the one exception, and it is opt-in.** It adds where each package sits in the dependency tree — repo-relative paths made of `node_modules` segments, plus a workspace directory name when a workspace pins its own copy. They are read from the lockfile's own keys or from the `node_modules` walk, **never from your source tree**: no path to a file you wrote is sent by either form of `scan`.
92
98
  - Why it exists: the same package is routinely installed twice at different versions, and without the locations an advisory affecting only one of them cannot be matched to the copy your code actually loads. Node resolves an import by walking up from the importing file, so the location is what distinguishes "you are running the vulnerable copy" from "the vulnerable copy is installed but nothing reaches it". Absent them, every installed version has to be treated as if the app used it — warnings about code you never call, and protection rules pinned to routes that run the safe copy.
@@ -97,14 +103,13 @@ Every command at a glance — what it does, whether it reads your source, what i
97
103
  - **Mapping is automatic in `setup`, and in its prebuild hook.** It parses server source and sends structure, not source text. A standalone `map` command prints locally and uploads only with `--upload`. `protect`, `scan`, `guide`, `status` and `mark-build` do not invoke mapping.
98
104
  - **`scan` makes up to three source edits:** the Patchstack Connector's `<script>` tag, the production marker, and — during `prebuild` only — removal of a previous `_patchstack.build_id` from the existing guard rules file. None runs on `--dry-run`; all are idempotent. `"widget": false` disables the first two, while stale-stamp removal is independent because it prevents old coordinates being attributed to a new build.
99
105
  - The **widget tag** goes in the root HTML shell — the first of `index.html`, `public/index.html`, or `src/app.html` that exists — and only after a successful post, because it carries the site UUID.
100
- - The **production marker** goes in a root shell that is JSX rather than HTML (e.g. `src/routes/__root.tsx`, `app/layout.tsx`), inside a `{/* #region patchstack */}` block placed above the widget tag. It is written *before* the post: it carries no site UUID and needs no network, and build scripts commonly chain `patchstack-connect scan || true`, where waiting on the server would mean an offline build silently ships without the flag. The marker is guarded by the framework's own production expression (`import.meta.env.PROD`, or `process.env.NODE_ENV === 'production'`), so it is inert in dev and preview builds. Without it a server-rendered site has no built HTML for `mark-build` to stamp, and the widget treats the published site as build mode. `mark-build` writes to build output only (`dist/`, `build/`, `out/`, `.output/public`), never to source. `guide`, `status`, and `init` write nothing except `init`'s own `.patchstackrc.json`.
106
+ - The **production marker** goes in a root shell that is JSX rather than HTML (e.g. `src/routes/__root.tsx`, `app/layout.tsx`), inside a `{/* #region patchstack */}` block placed above the widget tag. It is written *before* the post: it carries no site UUID and needs no network, and build scripts commonly chain `patchstack-connect scan || true`, where waiting on the server would mean an offline build silently ships without the flag. The marker is guarded by the framework's own production expression (`import.meta.env.PROD`, or `process.env.NODE_ENV === 'production'`), so it is inert in dev and preview builds. Without it a server-rendered site has no built HTML for `mark-build` to stamp, and the widget treats the published site as build mode. `mark-build` writes to build output only (`dist/`, `build/`, `out/`, `.output/public/`, `_site/`), never to source. `guide` writes nothing, `init` writes only its own `.patchstackrc.json`, and `status` writes only the connected note in `.patchstackrc.json`. `guide` sends nothing either: it reports a site as connected from that note, which `scan`, `status` and `claim` keep current.
101
107
  - **`setup` runs `scan` → `protect` → map upload → live-rule lookup**, then reports the outcome. Provisioning precedes guard installation. The map is stamped into the guard source for the NEXT startup/build; restart an already-running preview/server to load it. The rule lookup uses the runtime validator and source-scoped local cache without creating a running guard or installing global hooks. A successful empty policy is reported as zero assigned rules, not proof of protection. Failed uploads/pulls appear under Missing and can be retried by rerunning setup. It also wires install scans, prebuild scans + map uploads, and postbuild marking (explicit build chains for Yarn, pnpm and Bun), preserving existing commands. It never starts, builds or deploys the app. Ambiguous/custom integration code still requires review rather than being overwritten.
102
108
  - The package also exposes **`protect`** directly (runtime exploit guard; its templates live under `dist/protect/`). `setup` invokes it automatically; `scan`, `guide`, `status`, and `mark-build` do not. It writes only local files and auto-wires known stacks — **TanStack Start + Supabase** (patches the Supabase client + `src/start.ts`), **TanStack Start** (documented server Fetch entry without requiring Supabase), **Next.js** (scaffolds or composes middleware/proxy and adds request/response checks to supported App Router handlers), **SvelteKit** (`src/hooks.server.ts`), **Astro** (`src/middleware.ts`), **Nuxt** (`server/middleware/`), **NestJS** (`app.use(patchstackMiddleware)` in the bootstrap), **Fastify** (`app.register(patchstackFastify)`), and **Express** (`app.use(patchstackMiddleware)`). On **any other stack** it scaffolds a framework-agnostic guard under `src/patchstack/` and prints a wiring plan — then you finish the install by importing that guard into your server entry (`protectFetch(handler)` for a Web-Fetch server, or `app.use(patchstackMiddleware)` for Node/Express) and running `patchstack-connect protect --check` to confirm it is wired (exit 1 until it is). Passing `--demo` seeds a broad sample rule set (for demonstrations, not production).
103
109
  - **`demo node-serialize` is an explicit production-backed walkthrough.** It requires `node-serialize@0.0.4` to already be present in the lockfile; it does not install the vulnerable dependency. It runs the same production `scan`, polls the configured site's public Pulse rules endpoint until rule `18843` is served, runs `protect`, verifies the generated guard, and prints exploit/benign test requests. It writes the same manifest/widget and guard files as those underlying commands. It does not start/restart the app and does not send the printed requests.
104
110
  - **Standalone `map` is local unless you pass `--upload`.** It skips dependencies, build output and hidden directories and does not follow external symlinks by default. It reports detected entry points, inputs, sinks, dependency calls and evidence tiers with coverage limitations. Static analysis is best-effort, not a completeness guarantee. `setup` runs this analysis after guard integration and uploads it automatically.
105
111
  - **`map --upload` and `setup` send structural analysis** to `monitor/pulse/input-map/<your site uuid>`. The upload includes no source code, file contents or environment variable values. Setup and pre-bundle uploads derive `_patchstack.build_id` from the policy map and write it into the existing guard rules file. A standalone upload outside a build remains unbound and changes no guard file. No recognized routes still means useful import/coverage evidence and is uploaded. API failures are reported without failing a production build. Setup then retrieves Pulse rules, including delivered response-phase policies, using the same build identity. Only a matching server verdict permits scoped enforcement. The local cache is not a client bundle or a replacement for runtime rule refresh; filesystem-less deployments fetch at runtime and need server-side credentials.
106
112
  - **`demo-guide node-serialize` is the read-only companion.** It checks the Host-created site configuration and vulnerable lockfile entry, explains the complete local prepare/run/restart/prove/cleanup sequence, and prints the next exact command. It does not require a deployment and does not change files or contact Patchstack.
107
- - Patchstack is not WordPress-only. Connect monitors any JS/Node project — Vite, Next.js, plain vanilla JS, anything with a lockfile.
108
113
 
109
114
  ## Before you start — never install twice
110
115
 
@@ -278,6 +283,45 @@ Handle it in this order:
278
283
  run them, the person runs `npx @patchstack/connect claim` (or `login`) themselves and you relay the
279
284
  link from their output.
280
285
 
286
+ ### When the platform blocks the CLI outright
287
+
288
+ Some hosted builders refuse any third-party CLI that contacts an outside service, and offer the person
289
+ neither a terminal nor a way to approve it. Then none of the options above exists in that workspace, and
290
+ running the command again, under any spelling, gets the same answer. Step 1 still applies: do not route
291
+ around the block, and leave `package.json` and the source tree as they were.
292
+
293
+ That includes rebuilding by hand what `setup` would have done. Do not write a build plugin or script that
294
+ imitates a Patchstack step, do not set `window.__PATCHSTACK_PROD__` or `window.__PATCHSTACK_ENV__`
295
+ yourself, and do not call the Patchstack API in place of the CLI. A hosted builder can serve the same build
296
+ at its preview address and at the published one, so a marker decided at build time cannot be right for
297
+ both. A hand-set live-site flag tells the widget that the builder's preview is the live site, and the
298
+ person loses the "Connect this website" panel in the one place they would look for it.
299
+
300
+ Tell the person in plain words that this platform will not run Patchstack's setup, then give them these
301
+ choices and wait for theirs:
302
+
303
+ - **Run setup on a copy of the project outside the builder.** Offer this only when the builder can export
304
+ the project or sync it with a git repository; if you do not know whether it can, say so. In that copy,
305
+ the person runs `npx @patchstack/connect setup` — without `PATCHSTACK_ENVIRONMENT=sandbox`, which is for
306
+ a hosted workspace; on their own machine a scan reports `local` by itself. They then bring the changes
307
+ back the same way. `.patchstackrc.local.json` stays behind: it holds the API key and is git-ignored. If
308
+ the builder's own install or build cannot reach Patchstack, the scan steps `setup` added print the error
309
+ and let it continue, so the app still builds and only that build's report is missing. The exception is a
310
+ builder that installs with `bun install`: there the `postinstall` scan fails the install, so remove that
311
+ one script before bringing the changes back.
312
+ - **Add only the Patchstack Connector.** The person creates an "Application" site in the Patchstack
313
+ dashboard and gives you its site ID or widget snippet, and you add the tag as in steps 2 and 3 of
314
+ "Plain HTML sites", in the app's root HTML shell or layout. Add the tag only, with no production marker
315
+ and no build step: the widget then works out from the page's address whether it is on a preview or the
316
+ live site. This adds the widget and nothing else: no check of the app's packages, no build steps, no
317
+ runtime protection. Say that when you offer it.
318
+ - **Stop here.** Nothing else changes.
319
+
320
+ If you installed `@patchstack/connect` for this attempt, it stays in `dependencies` with nothing wired to
321
+ run it. Keep it for the first choice; for the other two, offer to remove it with the project's package
322
+ manager. Report the result as **Patchstack setup did not run on this platform**, with the choice the person
323
+ made, not as an installation.
324
+
281
325
  ## Manual setup
282
326
 
283
327
  1. **First scan** — provisions a Patchstack site automatically, writes the UUID to `.patchstackrc.json`, and installs the Patchstack Connector'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:
@@ -293,7 +337,7 @@ Handle it in this order:
293
337
  ```jsonc
294
338
  {
295
339
  "scripts": {
296
- "prebuild": "patchstack-connect scan && patchstack-connect map --upload",
340
+ "prebuild": "patchstack-connect scan && patchstack-connect map --upload",
297
341
  "postbuild": "patchstack-connect mark-build",
298
342
  "postinstall": "patchstack-connect scan"
299
343
  }
@@ -507,7 +551,7 @@ AI model. A framework or hosting upgrade requires this review again.
507
551
  - The CLI never opens the dashboard link and never asks for Patchstack credentials.
508
552
  - 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.
509
553
  - If a step fails, stop and report it. Don't proceed with placeholders.
510
- - 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.
554
+ - 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", and "When the platform blocks the CLI outright" when nobody can approve it there. Never work around a permission refusal, and never stand in for the CLI with a build step, a production marker or API calls of your own.
511
555
  - 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.
512
556
 
513
557
  ## Which build a rule belongs to
@@ -791,11 +835,15 @@ When more than one guard in a process has `egress: true`, an outbound call is ch
791
835
  refused if any one refuses it. A host listed in one guard's `allowHosts` is still refused when another guard
792
836
  refuses it.
793
837
 
794
- Two more endpoints the package can call, for completeness:
838
+ Three more endpoints the package can call, for completeness:
795
839
 
796
840
  - `GET monitor/widget/settings/<your site uuid>` — how `status` tells "this site was deleted on
797
841
  Patchstack" apart from "still active". It sends no credential and nothing about your project; the site
798
842
  UUID in the path is the whole request.
843
+ - `GET monitor/claim/preview?site=<your site uuid>` — how `scan` and `status` tell whether the site is
844
+ connected to an account yet, the same lookup the claim link's page makes. It sends no credential and
845
+ nothing about your project; the site UUID is the whole request. `scan` stops asking once
846
+ `.patchstackrc.json` records `"claimed": true`.
799
847
  - `GET api/get-rules/3` — the older rules path, used only when the guard is configured with a `token`
800
848
  instead of a site UUID. The zero-configuration flow provisions a site UUID and uses
801
849
  `monitor/pulse/rules/<uuid>` instead, so this is unreachable unless you pass `token` yourself.
@@ -806,7 +854,7 @@ Two more endpoints the package can call, for completeness:
806
854
  - `npx @patchstack/connect protect --check` verifies from the source that the runtime guard is connected to the request path. It does not run the app.
807
855
  - `npx @patchstack/connect protect --check --runtime` additionally **starts the app** on a loopback port and sends it one request, to establish that a request reaches the guard seam. Opt-in, and the only command that runs the application; exit `0`/`1`/`2` as described in step 4.
808
856
  - Load the site in a browser — the widget should appear, as the "Connect this website" panel while the site is unclaimed. Refresh a page that was already open before the tag was added: the widget only loads with the page.
809
- - On the deployed site, the button appears only after a deploy that includes these source changes.
857
+ - On the deployed site, the widget appears only after a deploy that includes these source changes.
810
858
 
811
859
  ## Answering "is Patchstack installed?" / "is Patchstack removed?"
812
860
 
@@ -916,7 +964,7 @@ You cannot complete this alone. It is deliberately a human-in-the-loop step: sta
916
964
  | Situation | What happens | What to do |
917
965
  |---|---|---|
918
966
  | Site was never claimed | `409` — no owner exists to approve | Ask the user to claim the site in the dashboard first, or, if the site is disposable, delete `.patchstackrc.json` **and** `.patchstackrc.local.json` and `scan` to provision a fresh one — leaving the old credential behind means the next scan starts out holding one that belongs to a different site |
919
- | Running in CI | Refuses to start | CI takes its credential from `PATCHSTACK_PULSE_AUTH`; `login` is for a developer machine |
967
+ | Running in CI | Refuses to start | CI takes its credential from `PATCHSTACK_API_KEY`; `login` is for a developer machine |
920
968
  | No `siteUuid` configured | Refuses to start | There is no site to recover — run `scan` |
921
969
  | Code expired | `--wait` ends after 10 minutes | Start again from step 1 for a new code |
922
970
  | `--wait` with nothing pending | "No login is waiting for approval" | Run step 1 first; `--wait` resumes a request, it does not start one |
package/README.md CHANGED
@@ -374,6 +374,8 @@ Two files, because one value is public and the other is not.
374
374
 
375
375
  `"widget"` is optional and defaults to `true`; set it to `false` to stop Connect from managing the Patchstack Connector tag (see *The Patchstack Connector*).
376
376
 
377
+ Connect also keeps two fields there itself. `"claimUrl"` is the link that connects the site to your Patchstack account, saved when the site is created so it is not lost with the terminal output. Once `scan`, `status` or `claim` sees the site connected, the link is removed and `"claimed": true` takes its place, which is how `guide` knows without asking Patchstack.
378
+
377
379
  **You do not write `apiKey` yourself.** The first `scan` provisions the site and Connect saves it, so setup needs no manual step.
378
380
 
379
381
  The site UUID identifies the site and is **not** a secret — the Patchstack Connector ships the same UUID in client-side HTML.
@@ -292,4 +292,4 @@ export {
292
292
  canonicalBuildId,
293
293
  readBuildStamp
294
294
  };
295
- //# sourceMappingURL=chunk-52IV7LN7.js.map
295
+ //# sourceMappingURL=chunk-RQTKVXBB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protect/safe-origin.js","../src/types.ts","../src/endpoint-policy.ts","../src/bounded-response.ts","../src/pulse-token.ts","../src/build-id.ts"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/protect/safe-origin.js","../src/types.ts","../src/endpoint-policy.ts","../src/bounded-response.ts","../src/pulse-token.ts","../src/build-id.ts"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -1816,6 +1816,30 @@ async function fetchSiteStatus(config) {
1816
1816
  return "unknown";
1817
1817
  }
1818
1818
  }
1819
+ async function fetchClaimState(config) {
1820
+ if (config.siteUuid === null) return "unknown";
1821
+ const url = new URL("/monitor/claim/preview", new URL(config.endpoint).origin);
1822
+ url.searchParams.set("site", config.siteUuid);
1823
+ try {
1824
+ assertConnectableEndpoint(config, url.toString());
1825
+ const response = await fetch(url.toString(), {
1826
+ method: "GET",
1827
+ headers: {
1828
+ Accept: "application/json",
1829
+ "Cache-Control": "no-cache",
1830
+ "User-Agent": "@patchstack/connect"
1831
+ },
1832
+ signal: AbortSignal.timeout(config.timeoutMs)
1833
+ });
1834
+ if (!response.ok) return "unknown";
1835
+ const body = await readBoundedJson(response);
1836
+ if (body?.state === "claimable") return "unclaimed";
1837
+ if (body?.state === "owned-by-other" || body?.state === "owned-by-you") return "claimed";
1838
+ return "unknown";
1839
+ } catch {
1840
+ return "unknown";
1841
+ }
1842
+ }
1819
1843
  function buildManifestBody(config, payload, env = process.env, marker = null) {
1820
1844
  const hosting = config.environment === "local" ? null : detectHostingPlatform(env);
1821
1845
  return {
@@ -2676,6 +2700,7 @@ async function resolveConfig(options) {
2676
2700
  environmentSource,
2677
2701
  ignoredFileEnvironment,
2678
2702
  widget: fromFile.widget !== false,
2703
+ claimed: fromFile.claimed === true,
2679
2704
  claimToken
2680
2705
  };
2681
2706
  }
@@ -2785,9 +2810,28 @@ function ignoresEntry(contents, entry) {
2785
2810
  }
2786
2811
  return ignored;
2787
2812
  }
2788
- async function persistSiteUuid(cwd, siteUuid) {
2813
+ async function persistSiteUuid(cwd, siteUuid, claimUrl) {
2789
2814
  const existing = await readConfigFile(cwd);
2790
- return writeConfigFile(cwd, { ...existing, siteUuid });
2815
+ return writeConfigFile(cwd, {
2816
+ ...existing,
2817
+ siteUuid,
2818
+ ...typeof claimUrl === "string" && claimUrl !== "" ? { claimUrl } : {}
2819
+ });
2820
+ }
2821
+ async function persistClaimState(cwd, claimed, claimUrl) {
2822
+ const existing = await readConfigFile(cwd);
2823
+ if (typeof existing.siteUuid !== "string" || existing.siteUuid === "") return false;
2824
+ const next = { ...existing };
2825
+ if (claimed) {
2826
+ next.claimed = true;
2827
+ delete next.claimUrl;
2828
+ } else {
2829
+ delete next.claimed;
2830
+ if (typeof claimUrl === "string" && claimUrl !== "") next.claimUrl = claimUrl;
2831
+ }
2832
+ if (JSON.stringify(next) === JSON.stringify(existing)) return false;
2833
+ await writeConfigFile(cwd, next);
2834
+ return true;
2791
2835
  }
2792
2836
  async function persistTimeout(cwd, timeoutMs) {
2793
2837
  const existing = await readConfigFile(cwd);
@@ -6877,6 +6921,7 @@ async function collectGuideState(cwd) {
6877
6921
  }
6878
6922
  let siteUuid = null;
6879
6923
  let claimUrl = null;
6924
+ let claimed = false;
6880
6925
  let endpointOverride = null;
6881
6926
  let widgetOptOut = false;
6882
6927
  let environment = null;
@@ -6886,6 +6931,7 @@ async function collectGuideState(cwd) {
6886
6931
  environment = config.environment;
6887
6932
  environmentSource = config.environmentSource ?? null;
6888
6933
  siteUuid = config.siteUuid;
6934
+ claimed = siteUuid !== null && config.claimed === true;
6889
6935
  if (siteUuid !== null && config.endpointTrusted !== false) {
6890
6936
  claimUrl = buildClaimUrl(config.endpoint, siteUuid);
6891
6937
  }
@@ -6910,6 +6956,7 @@ async function collectGuideState(cwd) {
6910
6956
  installed,
6911
6957
  siteUuid,
6912
6958
  claimUrl,
6959
+ claimed,
6913
6960
  endpointOverride,
6914
6961
  environment,
6915
6962
  environmentSource,
@@ -6959,9 +7006,9 @@ function countRemainingSteps(state) {
6959
7006
  function guideProgress(state, known = {}) {
6960
7007
  return {
6961
7008
  installed: state.installed !== null,
6962
- // Claim state lives on the server and nothing on disk records it, so only a caller that has just
6963
- // heard from the server (a scan's claim outcome) can mark it done.
6964
- connected: false,
7009
+ // Claim state lives on the server. The working tree has only the note a scan, status or claim left
7010
+ // in `.patchstackrc.json`; a caller that has just heard from the server overrides it.
7011
+ connected: state.claimed,
6965
7012
  // `.patchstackrc.json` only gains a site UUID from a manifest the server stored.
6966
7013
  synced: state.siteUuid !== null,
6967
7014
  // Only the dashboard can see the live site, so nothing the CLI runs marks this done.
@@ -7057,7 +7104,7 @@ function guideMissing(state, known = {}) {
7057
7104
  }
7058
7105
  );
7059
7106
  }
7060
- if (known.connected !== true) missing.push(notConnectedItem());
7107
+ if ((known.connected ?? state.claimed) !== true) missing.push(notConnectedItem());
7061
7108
  return missing;
7062
7109
  }
7063
7110
  function renderGuideChecklist(state, useColor2, known = {}, options = {}) {
@@ -10660,7 +10707,7 @@ function canonicalText(value) {
10660
10707
  if (Array.isArray(value)) return `[${value.map(canonicalText).join(",")}]`;
10661
10708
  if (value !== null && typeof value === "object") {
10662
10709
  const record = value;
10663
- const keys = Object.keys(record).sort();
10710
+ const keys = Object.keys(record).filter((key) => record[key] !== void 0).sort();
10664
10711
  return `{${keys.map((key) => `${canonicalString(key)}:${canonicalText(record[key])}`).join(",")}}`;
10665
10712
  }
10666
10713
  throw new NonCanonicalInputMap(`the input map contains a value with no JSON form (${typeof value})`);
@@ -10751,9 +10798,20 @@ async function runMapDetailed(flags, options = {}) {
10751
10798
  });
10752
10799
  let buildId = null;
10753
10800
  if (options.setup || isPreBundleBuildHook()) {
10754
- const candidate = inputMapBuildId(map);
10755
- const stamp = applyBuildStamp(cwd, candidate);
10756
- if (stamp.kind === "stamped" || stamp.kind === "unchanged") {
10801
+ let candidate = null;
10802
+ let identityError = null;
10803
+ try {
10804
+ candidate = inputMapBuildId(map);
10805
+ } catch (err) {
10806
+ if (!(err instanceof NonCanonicalInputMap)) throw err;
10807
+ identityError = err.message;
10808
+ }
10809
+ const stamp = candidate === null ? null : applyBuildStamp(cwd, candidate);
10810
+ if (candidate === null || stamp === null) {
10811
+ log2(
10812
+ `patchstack: could not bind this map to the runtime guard \u2014 ${identityError}. Rules generated from these coordinates will detect only, not block.`
10813
+ );
10814
+ } else if (stamp.kind === "stamped" || stamp.kind === "unchanged") {
10757
10815
  buildId = candidate;
10758
10816
  log2(`patchstack: bound this map to ${stamp.file} (${candidate.slice(0, 12)}).`);
10759
10817
  } else {
@@ -12980,6 +13038,7 @@ async function runClaim(args) {
12980
13038
  return 1;
12981
13039
  }
12982
13040
  const settled = async (result2) => {
13041
+ await recordClaimState(config, siteUuid, true);
12983
13042
  console.log(
12984
13043
  `
12985
13044
  \u2713 Site claimed${result2.account !== void 0 ? ` by ${result2.account}` : ""}.`
@@ -13031,6 +13090,7 @@ async function runClaim(args) {
13031
13090
  const started = await startClaim(config);
13032
13091
  if (started.status !== "started" || started.pending === void 0) {
13033
13092
  if (started.status === "already-claimed") {
13093
+ await recordClaimState(config, siteUuid, true);
13034
13094
  console.log(`
13035
13095
  ${started.message ?? "This site is already claimed."}
13036
13096
  `);
@@ -13051,6 +13111,7 @@ async function runClaim(args) {
13051
13111
  });
13052
13112
  if (result.status === "claimed") return await settled(result);
13053
13113
  if (result.status === "already-claimed") {
13114
+ await recordClaimState(config, siteUuid, true);
13054
13115
  console.log(`
13055
13116
  ${result.message ?? "This site is already claimed."}
13056
13117
  `);
@@ -13063,7 +13124,7 @@ async function runClaim(args) {
13063
13124
  }
13064
13125
  async function runLogin(args) {
13065
13126
  if (runningInCi()) {
13066
- console.error("`login` is interactive and cannot run in CI. Set PATCHSTACK_PULSE_AUTH instead.");
13127
+ console.error("`login` is interactive and cannot run in CI. Set PATCHSTACK_API_KEY instead.");
13067
13128
  return 1;
13068
13129
  }
13069
13130
  const config = await resolveCliConfig(args);
@@ -13272,9 +13333,10 @@ async function runScan(args, options = {}) {
13272
13333
  });
13273
13334
  }
13274
13335
  if (provisioning && response.uuid !== void 0 && response.uuid.length > 0) {
13275
- const target = await persistSiteUuid(process.cwd(), response.uuid);
13336
+ const claimUrl = config.endpointTrusted !== false ? buildClaimUrl(config.endpoint, response.uuid) : null;
13337
+ const target = await persistSiteUuid(process.cwd(), response.uuid, claimUrl);
13276
13338
  report.done.push("Added this project to Patchstack");
13277
- say(`Created site ${response.uuid}. Saved to ${target}.`);
13339
+ say(`Created site ${response.uuid}. Saved it${claimUrl !== null ? " and the link to connect it" : ""} to ${target}.`);
13278
13340
  }
13279
13341
  if (typeof response.api_key === "string" && response.api_key.length > 0) {
13280
13342
  const hadCredentialInConfig = await credentialInCommittedConfig(process.cwd());
@@ -13304,11 +13366,12 @@ async function runScan(args, options = {}) {
13304
13366
  } else if (claim3 !== null) {
13305
13367
  report.missing.push(notConnectedItem([`${claim3.summary}.`, ...claim3.hint]));
13306
13368
  }
13307
- const connected = response.claim?.state === "claimed" || response.claim?.state === "owned-by-you";
13369
+ const tokenConnected = response.claim?.state === "claimed" || response.claim?.state === "owned-by-you";
13308
13370
  const effectiveUuid = config.siteUuid ?? response.uuid ?? null;
13309
13371
  if (config.widget && effectiveUuid !== null && effectiveUuid.length > 0) {
13310
13372
  reportSourceWidget(effectiveUuid, shellFramework, report);
13311
13373
  }
13374
+ const connected = await resolveConnected(config, effectiveUuid, tokenConnected);
13312
13375
  const synced = effectiveUuid !== null && effectiveUuid.length > 0 && (response.stored || response.reason === "duplicate" || response.reason === "build-reported");
13313
13376
  const outcome = {
13314
13377
  connected,
@@ -13325,6 +13388,20 @@ async function runScan(args, options = {}) {
13325
13388
  }
13326
13389
  return 0;
13327
13390
  }
13391
+ async function resolveConnected(config, siteUuid, tokenConnected) {
13392
+ if (siteUuid === null || siteUuid.length === 0) return false;
13393
+ if (!tokenConnected && config.claimed === true) return true;
13394
+ const state = tokenConnected ? "claimed" : await fetchClaimState({ ...config, siteUuid });
13395
+ if (state !== "unknown") await recordClaimState(config, siteUuid, state === "claimed");
13396
+ return state === "claimed";
13397
+ }
13398
+ async function recordClaimState(config, siteUuid, claimed) {
13399
+ const claimUrl = config.endpointTrusted !== false ? buildClaimUrl(config.endpoint, siteUuid) : null;
13400
+ try {
13401
+ await persistClaimState(process.cwd(), claimed, claimUrl);
13402
+ } catch {
13403
+ }
13404
+ }
13328
13405
  function mergeMissing(...lists) {
13329
13406
  const merged = [];
13330
13407
  for (const item of lists.flat()) {
@@ -13696,7 +13773,15 @@ async function runStatus(args) {
13696
13773
  console.log(`Environment: ${config.environment}`);
13697
13774
  if (config.siteUuid !== null) {
13698
13775
  console.log(`Dashboard URL: ${buildClaimUrl(config.endpoint, config.siteUuid)}`);
13699
- console.log(" Not connected yet? Open the link above or run `npx @patchstack/connect claim`.");
13776
+ const claimState = await fetchClaimState(config);
13777
+ if (claimState !== "unknown") await recordClaimState(config, config.siteUuid, claimState === "claimed");
13778
+ if (claimState === "claimed") {
13779
+ console.log("Connected: yes, to a Patchstack account");
13780
+ } else if (claimState === "unclaimed") {
13781
+ console.log("Connected: not yet. Open the link above or run `npx @patchstack/connect claim`.");
13782
+ } else {
13783
+ console.log("Connected: could not be verified. Not connected yet? Open the link above.");
13784
+ }
13700
13785
  switch (await fetchSiteStatus(config)) {
13701
13786
  case "active":
13702
13787
  console.log("Site status: active on Patchstack");