@patchstack/connect 0.3.19 → 0.3.21

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
@@ -7,17 +7,17 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
7
7
  - 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.
8
8
  - It reads the project's **dependency list only** — from the lockfile (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`) or, on bun projects (`bun.lock`/`bun.lockb`), by enumerating the installed packages under `node_modules/` — and sends package names + versions to Patchstack for vulnerability matching. No source code, no env var values, no file paths, no git history. (`mark-build` additionally stamps built HTML with a coarse stack descriptor that may include hosting-related env variable *names* — e.g. `VERCEL`, `CF_PAGES` — never their values.)
9
9
  - **`scan` makes one source edit, and only after a successful post:** it adds (or updates) the disclosure widget's `<script>` tag in the project's root HTML shell — the first of `index.html`, `public/index.html`, or `src/app.html` that exists. It touches no other file, never edits on `--dry-run` or after a failed post, leaves any pre-existing manual widget tag untouched, and is disabled entirely by `"widget": false` in `.patchstackrc.json`. `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`.
10
- - **`setup` runs `scan`, then edits only `package.json` build scripts:** it preserves existing commands, adds `scan` before builds and `mark-build` after builds, and uses a direct build chain for Bun. It never runs the project build or `protect`. If the widget needs a framework-specific source edit, it prints the exact remaining step instead of rewriting framework code.
11
- - The package also bundles an **opt-in** `protect` command (runtime exploit guard; its templates live under `dist/protect/`). It runs **only** when explicitly invoked; `scan`, `setup`, `guide`, `status`, and `mark-build` never invoke it, and it writes only local files. It auto-wires known stacks — **TanStack Start + Supabase** (patches the Supabase client + `src/start.ts`), **Next.js** (scaffolds `middleware.ts`), **SvelteKit** (`src/hooks.server.ts`), **Astro** (`src/middleware.ts`), **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).
10
+ - **`setup` runs `scan`, then `protect`, then edits `package.json` scripts:** provisioning happens first so the runtime guard can bake the real site UUID. It verifies the resulting framework seam, preserves existing commands, adds `scan` after dependency installs and before builds, adds `mark-build` after builds, and uses a direct build chain for Bun. It never runs the project build. If the widget or runtime guard needs a framework-specific manual merge, it prints the exact remaining step instead of overwriting user code.
11
+ - 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`), **Next.js** (scaffolds `middleware.ts`), **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).
12
12
  - **`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.
13
13
  - **`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.
14
14
  - Patchstack is not WordPress-only. This connector monitors any JS/Node project — Vite, Next.js, plain vanilla JS, anything with a lockfile.
15
15
 
16
16
  ## Before you start — never install twice
17
17
 
18
- - `npx @patchstack/connect guide` prints a read-only live checklist showing which steps are already done in the current project (install, provisioning, build hooks, widget).
18
+ - `npx @patchstack/connect guide` prints a read-only live checklist showing which steps are already done in the current project (install, provisioning, build hooks, widget, runtime protection).
19
19
  - If `.patchstackrc.json` contains a `siteUuid` key, the project is already provisioned. Reuse that UUID; run `npx @patchstack/connect status` to re-print it and the dashboard URL. **Do not delete the file and provision a second site.** (A `.patchstackrc.json` with other keys — e.g. an `endpoint` override — but no `siteUuid` is *not* provisioned yet; scan normally.)
20
- - If `@patchstack/connect` is already in `devDependencies`, skip the install command.
20
+ - If `@patchstack/connect` is already in `dependencies`, skip the install command. If it is only in `devDependencies`, move it with the matching package manager so production runtimes that prune dev dependencies can load the generated guard.
21
21
  - If the widget script tag (`cdn.patchstack.com/patchstack-widget.js`) is already in the layout, don't add a second one — `scan` also respects an existing tag: it updates its own managed tag in place and leaves a manual one untouched.
22
22
 
23
23
  ## Automated setup
@@ -25,10 +25,10 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
25
25
  1. **Install** (skip if already present), matching the project's package manager:
26
26
 
27
27
  ```
28
- npm install --save-dev @patchstack/connect # package-lock.json
29
- pnpm add -D @patchstack/connect # pnpm-lock.yaml
30
- yarn add -D @patchstack/connect # yarn.lock
31
- bun add -d @patchstack/connect # bun.lock / bun-managed platforms
28
+ npm install --save @patchstack/connect # package-lock.json
29
+ pnpm add @patchstack/connect # pnpm-lock.yaml
30
+ yarn add @patchstack/connect # yarn.lock
31
+ bun add @patchstack/connect # bun.lock / bun-managed platforms
32
32
  ```
33
33
 
34
34
  2. **Run bounded setup:**
@@ -37,7 +37,9 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
37
37
  npx @patchstack/connect setup
38
38
  ```
39
39
 
40
- This provisions or reuses the site, manages the widget, wires the build scripts, prints a dashboard link, and finishes with the same status shown by `guide`. Re-running it reuses existing configuration, widget tags, and build commands rather than duplicating them.
40
+ This provisions or reuses the site, manages the widget, installs and verifies runtime protection, wires dependency-install and build scans, prints a dashboard link, and finishes with the same status shown by `guide`. Re-running it reuses existing configuration, widget tags, guards, and commands rather than duplicating them.
41
+
42
+ 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 should default to `production`. A client-only SPA has no server request path to guard; do not call it protected unless `protect --check` succeeds after a real server or edge seam is wired.
41
43
 
42
44
  ## Manual setup
43
45
 
@@ -54,13 +56,14 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
54
56
  ```jsonc
55
57
  {
56
58
  "scripts": {
57
- "prebuild": "patchstack-connect scan",
58
- "postbuild": "patchstack-connect mark-build"
59
+ "prebuild": "patchstack-connect scan",
60
+ "postbuild": "patchstack-connect mark-build",
61
+ "postinstall": "patchstack-connect scan"
59
62
  }
60
63
  }
61
64
  ```
62
65
 
63
- If a `prebuild`/`postbuild` hook already exists, chain instead of replacing it, e.g. `"prebuild": "existing-command && patchstack-connect scan"`.
66
+ If a lifecycle hook already exists, chain instead of replacing it, e.g. `"prebuild": "existing-command && patchstack-connect scan"`. The `postinstall` scan reports dependencies added during an iterative sandbox session and covers applications with no build command.
64
67
 
65
68
  **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"`.
66
69
 
@@ -72,20 +75,31 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
72
75
 
73
76
  Framework-specific placement patterns: https://cdn.patchstack.com/llm.html. The site UUID is public by design — it ships in client-side HTML and is not a secret. If the project must not carry the widget, persist `"widget": false` in `.patchstackrc.json`; otherwise the next scan re-adds it.
74
77
 
75
- 4. **Commit** `.patchstackrc.json`, the updated `package.json`, and the layout/HTML file carrying the widget tag, so every developer and CI run reports to the same site.
78
+ 4. **Install and verify runtime protection:**
79
+
80
+ ```
81
+ npx @patchstack/connect protect
82
+ npx @patchstack/connect protect --check
83
+ ```
84
+
85
+ `setup` performs both steps automatically. The explicit commands are for manual setup or repair. If verification reports a generic or existing framework seam, complete the printed source edit and re-run `--check`; do not report protection as active until it exits successfully.
86
+
87
+ 5. **Commit** `.patchstackrc.json`, the updated `package.json`, the guard/framework source changes, and the layout/HTML file carrying the widget tag, so every developer and CI run reports to the same site.
76
88
 
77
- 5. **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.
89
+ 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.
78
90
 
79
91
  ## Rules
80
92
 
81
93
  - Never invent or guess a UUID — the scan provisions it, the widget silently no-ops on a fake one.
82
94
  - The CLI never opens the dashboard link and never asks for Patchstack credentials.
95
+ - Label hosted workspace scans with `PATCHSTACK_ENVIRONMENT=sandbox` in that process only. Leave production builds unset (the default is `production`) and never commit a sandbox label into files shared with production.
83
96
  - If a step fails, stop and report it. Don't proceed with placeholders.
84
97
  - In CI where `.patchstackrc.json` can't be committed, set `PATCHSTACK_SITE_UUID` as an env var instead. Precedence: CLI flag → env var → `.patchstackrc.json`.
85
98
 
86
99
  ## Verifying the install
87
100
 
88
101
  - `npx @patchstack/connect status` re-prints the site UUID and dashboard URL.
102
+ - `npx @patchstack/connect protect --check` verifies the runtime guard is connected to the request path.
89
103
  - Load the site in a browser — the "Report a vulnerability" button should appear.
90
104
 
91
105
  ## Uninstalling
@@ -94,9 +108,10 @@ Remove only the pieces that are actually present — check for each first. If no
94
108
 
95
109
  1. **Read the site UUID from `.patchstackrc.json` before deleting anything.** It is the only local record of the provisioned site — report it to the user at the end so they can identify the site in their dashboard.
96
110
  2. **Remove the widget snippets** from the layout/template: the `<script src="https://cdn.patchstack.com/patchstack-widget.js">` tag and any `PatchstackWidget.init(...)` call (which may live in a separate client component/plugin/effect). Afterwards, grep the repo for `patchstack-widget` and `PatchstackWidget` to confirm nothing remains.
97
- 3. **Remove the hooks from `package.json` scripts.** If a hook was chained (e.g. `"postbuild": "existing-command && patchstack-connect mark-build"`), remove only the `patchstack-connect …` part and keep the rest; if removal leaves a script empty, delete the key.
98
- 4. **Uninstall the package** with the manager matching the lockfile: `npm uninstall` / `pnpm remove` / `yarn remove` / `bun remove` `@patchstack/connect`. Don't hand-edit `node_modules` or the lockfile.
99
- 5. **Delete `.patchstackrc.json`** and remove `PATCHSTACK_SITE_UUID` (and public-prefixed variants like `NEXT_PUBLIC_PATCHSTACK_SITE_UUID`) from env files and CI variables.
100
- 6. **Commit** the changes. Reporting stops immediately. The `window.__PATCHSTACK_PROD__` flag that `mark-build` injected lives only in build output, never in source — the next build simply won't contain it (rebuild if build output is committed).
111
+ 3. **Remove runtime protection before uninstalling the package.** Delete the connector-managed guard/rules files and remove only their managed imports, middleware registrations, tunnel code, and `#region patchstack…` blocks from the framework/server files. Preserve unrelated middleware and application code. Run `rg "patchstack|x-ps-target"` (or the available equivalent) afterwards and inspect every remaining source hit.
112
+ 4. **Remove the hooks from `package.json` scripts.** If a hook was chained (e.g. `"postbuild": "existing-command && patchstack-connect mark-build"`), remove only the `patchstack-connect …` part and keep the rest; if removal leaves a script empty, delete the key.
113
+ 5. **Uninstall the package** with the manager matching the lockfile: `npm uninstall` / `pnpm remove` / `yarn remove` / `bun remove` `@patchstack/connect`. Don't hand-edit `node_modules` or the lockfile.
114
+ 6. **Delete `.patchstackrc.json`** and remove `PATCHSTACK_SITE_UUID` (and public-prefixed variants like `NEXT_PUBLIC_PATCHSTACK_SITE_UUID`) from env files and CI variables.
115
+ 7. **Commit** the changes. Reporting stops immediately. The `window.__PATCHSTACK_PROD__` flag that `mark-build` injected lives only in build output, never in source — the next build simply won't contain it (rebuild if build output is committed).
101
116
 
102
117
  Local removal does not delete the site record on Patchstack's side. An unclaimed site is an anonymous record that stops receiving reports; a claimed site is removed by the user in their dashboard at https://app.patchstack.com. There is no CLI command for account-side deletion — do not invent one, and never attempt to authenticate or remove the site on the user's behalf.
package/README.md CHANGED
@@ -8,17 +8,19 @@ For how this repo fits with the wider Patchstack ecosystem (`saas`, `hub`, `patc
8
8
 
9
9
  Copy this request into a coding assistant, or run the same command yourself:
10
10
 
11
- > I have vetted `@patchstack/connect` and authorize its widget and production build hooks. Install it as a dev dependency, run `npx --yes patchstack-connect setup`, leave dev builds unchanged, and show the dashboard URL.
11
+ > 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.
12
12
 
13
- `setup` is state-aware and idempotent: it scans dependencies, provisions or reuses the site, manages the disclosure widget, wires the existing build command without replacing it, and prints the remaining setup status. It never runs the project build or the opt-in `protect` command. `guide` provides the same project-specific status without changing files.
13
+ `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.
14
14
 
15
15
  ## Quick start (zero configuration)
16
16
 
17
17
  ```bash
18
- npm install --save-dev @patchstack/connect && npx @patchstack/connect setup
18
+ npm install --save @patchstack/connect && npx @patchstack/connect setup
19
19
  ```
20
20
 
21
- > **Use your project's own package manager.** On Bun-managed projects (including many Lovable projects) install with `bun add -d @patchstack/connect` instead — running `npm install` there plants a `package-lock.json` that the platform's native dependency flow never updates again, leaving a stale lockfile next to the live one. The connector detects and works around that (see *Stale lockfiles* below), but not creating the fossil is better.
21
+ > **Use your project's own package manager.** On Bun-managed projects (including many Lovable projects) install with `bun add @patchstack/connect` instead — running `npm install` there plants a `package-lock.json` that the platform's native dependency flow never updates again, leaving a stale lockfile next to the live one. The connector detects and works around that (see *Stale lockfiles* below), but not creating the fossil is better. Protection imports `@patchstack/connect/protect` at runtime, so deployments that prune dev dependencies need the package in `dependencies`.
22
+
23
+ > **Hosted builders:** set `PATCHSTACK_ENVIRONMENT=sandbox` in the workspace process environment (or scope it to the setup command above), persist every file written by `setup`, and restart any already-running server so it loads the new middleware. Do not write `"environment": "sandbox"` to the committed `.patchstackrc.json`: the same project files reach production, where scans should inherit no override and default to `production`. TanStack Start + Supabase (the server shape emitted by Lovable) is auto-wired: browser Supabase traffic is tunneled through a same-origin guard, server-function arguments are inspected, and responses are screened. A client-only SPA has no server request path to protect; setup will leave a generic scaffold and `protect --check` will remain red until the host adds a server/edge seam. Set `PATCHSTACK_ROUTE_WAF=1` when the deployment should additionally screen every TanStack route request.
22
24
 
23
25
  That's it. `setup`:
24
26
 
@@ -27,15 +29,17 @@ That's it. `setup`:
27
29
  3. Patchstack provisions a fresh site and returns its UUID.
28
30
  4. The connector writes the UUID to `.patchstackrc.json` so the next `scan` targets the same site.
29
31
  5. The connector installs the disclosure widget's `<script>` tag into your root HTML shell (see *The disclosure widget* below) so the "Report a vulnerability" button shows up on the next preview reload.
30
- 6. Wires `scan` before builds and `mark-build` after builds, preserving existing commands and using direct build chaining for Bun.
31
- 7. Prints a dashboard link — open it in a browser to attach the new site to your Patchstack account. You can re-display it any time with `npx @patchstack/connect status`.
32
+ 6. Installs the runtime guard after provisioning, bakes the site UUID into it, and verifies the framework seam. Known server stacks are auto-wired; unmatched or conflicting layouts get a generic scaffold and exact manual checks.
33
+ 7. Adds `postinstall: patchstack-connect scan`, preserving any existing command, so dependencies added during a sandbox session and build-less production installs are reported immediately.
34
+ 8. Wires `scan` before builds and `mark-build` after builds, preserving existing commands and using direct build chaining for Bun.
35
+ 9. Prints a dashboard link — open it in a browser to attach the new site to your Patchstack account. You can re-display it any time with `npx @patchstack/connect status`.
32
36
 
33
37
  ## Quick start (existing site)
34
38
 
35
39
  If you already created an "Application" site in the Patchstack dashboard, pre-seed the UUID:
36
40
 
37
41
  ```bash
38
- npm install --save-dev @patchstack/connect
42
+ npm install --save @patchstack/connect
39
43
  npx @patchstack/connect init <your-site-uuid>
40
44
  npx @patchstack/connect setup
41
45
  ```
@@ -50,8 +54,8 @@ patchstack-connect scan [options] Scan the lockfile and POST to
50
54
  widget tag in the root HTML shell (opt out
51
55
  with "widget": false in .patchstackrc.json)
52
56
  patchstack-connect setup [options] Run scan, manage the widget, and idempotently
53
- wire package.json build scripts. Never runs
54
- the project build or protect
57
+ install + verify runtime protection and wire
58
+ dependency/build scans. Never runs the build
55
59
  patchstack-connect init <site-uuid> Optional: pre-seed .patchstackrc.json with
56
60
  an existing site UUID
57
61
  patchstack-connect status [options] Show current configuration
@@ -61,10 +65,10 @@ patchstack-connect mark-build [options] Stamp built HTML with a produ
61
65
  patchstack-connect guide Show this project's setup status (what's done,
62
66
  what's missing, with tailored commands), then
63
67
  print the full setup guide
64
- patchstack-connect protect Opt-in: install the always-on runtime exploit
68
+ patchstack-connect protect Install/reconcile the always-on runtime exploit
65
69
  guard. Auto-wires supported server stacks;
66
70
  use --check to verify or --demo for local rules.
67
- Never run by scan/setup/guide/mark-build.
71
+ Also run by setup; never run by scan/guide/mark-build.
68
72
  patchstack-connect demo node-serialize Production-backed walkthrough: require
69
73
  node-serialize@0.0.4, scan it, wait for live
70
74
  rule 18843, install + verify the runtime guard,
@@ -97,6 +101,7 @@ Environment variables:
97
101
  - `PATCHSTACK_SITE_UUID` — the site UUID from your Patchstack dashboard
98
102
  - `PATCHSTACK_ENDPOINT` — override the API endpoint (default `https://api.patchstack.com/monitor/pulse/manifest`)
99
103
  - `PATCHSTACK_TIMEOUT_MS` — request timeout in milliseconds (default `30000`)
104
+ - `PATCHSTACK_ENVIRONMENT` — manifest label: `production` (default) or `sandbox`
100
105
 
101
106
  `.patchstackrc.json` example:
102
107
 
@@ -111,6 +116,18 @@ Environment variables:
111
116
 
112
117
  The site UUID identifies the site; it is not a secret — the disclosure widget ships the same UUID in client-side HTML, and committing `.patchstackrc.json` is the intended workflow so every developer and CI run reports to the same site. Possession of the UUID lets someone submit dependency manifests for that site (noise, not data access). In CI setups where the file isn't committed, set `PATCHSTACK_SITE_UUID` instead.
113
118
 
119
+ ### Sandbox and production manifests
120
+
121
+ Every `scan` sends an environment label with its dependency manifest. The default is `production`; sandboxed builders should set `PATCHSTACK_ENVIRONMENT=sandbox` in the sandbox process only. Patchstack stores and deduplicates manifests per environment, so an iterative workspace scan does not replace the last production manifest.
122
+
123
+ Do not commit `"environment": "sandbox"` to `.patchstackrc.json` when the same files are deployed to production. Scope the variable to the sandbox command/process instead:
124
+
125
+ ```bash
126
+ PATCHSTACK_ENVIRONMENT=sandbox npx @patchstack/connect setup
127
+ ```
128
+
129
+ The generated `prebuild` scan deliberately carries no hard-coded environment. A production builder with no override reports `production`; a preview/sandbox builder must receive `PATCHSTACK_ENVIRONMENT=sandbox` from its host. Runtime protection itself is not environment-specific: `PATCHSTACK_ENVIRONMENT` labels manifests only. Use `PATCHSTACK_MODE=dry-run` when protection should observe rather than block.
130
+
114
131
  ## Production virtual-patch demo
115
132
 
116
133
  The `node-serialize` scenario demonstrates dependency detection and a live, version-scoped virtual patch against a throwaway Express application. Connect/provision the project first, deliberately add the known-vulnerable package, then run: