From 985048f2a0d5298382d67c4f54433e06d51d68a5 Mon Sep 17 00:00:00 2001 From: Mario Tarosso Date: Fri, 25 Sep 2026 10:55:06 +0100 Subject: [PATCH] Call the widget the Patchstack Connector The CLI, the install prompt and the shipped docs called the site widget the "disclosure widget", but its public report form is off until the site is claimed, so the name described something most new installs never show. Everything now calls it the Patchstack Connector, and "the connector" where it meant this package now says "Connect" so the two names never collide. Co-Authored-By: Claude Opus 5.5 --- AGENT-INSTALL.md | 22 +++++++++++----------- GETTING-STARTED.md | 6 +++--- MAINTAINING.md | 2 +- README.md | 36 ++++++++++++++++++------------------ field-test/prompt.txt | 2 +- src/architecture.ts | 2 +- src/build-hook.ts | 2 +- src/checksum.ts | 2 +- src/cli.ts | 6 +++--- src/client.ts | 4 ++-- src/config.ts | 2 +- src/demo.ts | 2 +- src/guide.ts | 14 +++++++------- src/protect/install/util.ts | 2 +- src/stack.ts | 4 ++-- src/types.ts | 2 +- src/widget.ts | 8 ++++---- tests/claim-token.test.ts | 2 +- tests/guide.test.ts | 2 +- 19 files changed, 61 insertions(+), 61 deletions(-) diff --git a/AGENT-INSTALL.md b/AGENT-INSTALL.md index 57c6c9b6..dc40cdbc 100644 --- a/AGENT-INSTALL.md +++ b/AGENT-INSTALL.md @@ -8,7 +8,7 @@ Use the package setup flow below for an existing JS/Node application. Work in it ### Plain HTML sites -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. +For a standalone site made of HTML, CSS, and browser JavaScript, with no package-managed application or server request handler, use the Patchstack Connector 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. 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. 2. Add one widget tag before `` 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"`: @@ -18,9 +18,9 @@ For a standalone site made of HTML, CSS, and browser JavaScript, with no package ``` 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. -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. +3. Verify the saved tag uses the correct UUID. If a browser preview is available, reload it and check that the Patchstack Connector appears (a "Connect this website" panel until the site is claimed); 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. -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. +Report this as **Patchstack Connector 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. ### JS/Node applications — the usual path @@ -65,7 +65,7 @@ Only `map` analyses your source, and only `map --upload` sends anything derived - **The address is the one your visitors use, and, apart from the tool's own `PATCHSTACK_*` settings, it is the only env var value read.** A site provisioned by a scan from a developer machine has no address, so the dashboard shows a placeholder and Patchstack cannot check that the published page still carries what was scanned. `scan` therefore sends `url` when — and only when — it can know it: `url` in `.patchstackrc.json` or `PATCHSTACK_SITE_URL` if you set one, otherwise the single variable a host publishes to name its own **production** URL (`VERCEL_PROJECT_PRODUCTION_URL` on a Vercel production deployment, Netlify's `URL` in the production context, `RENDER_EXTERNAL_URL`, `RAILWAY_PUBLIC_DOMAIN` in a production environment). Preview and branch deployments are excluded, as are hosts that publish no production signal. An address that is not how the public reaches a website is dropped: any IP address (in either family, however it is written), any single-label host such as `localhost` or `production`, and the reserved suffixes (`.local`, `.internal`, `.test`, `.invalid`, `.home.arpa`, …). A `url` you set explicitly that fails those checks is refused with an error rather than replaced by a guess. When nothing qualifies, `url` is omitted from the payload rather than guessed. Patchstack only ever applies it to a site that still has no address; it never re-points a site whose address is already real. - **The name is read from your project, never from the host environment.** `name` in `.patchstackrc.json` (or `PATCHSTACK_SITE_NAME`) if you set one; otherwise the `` of the project's root `index.html` (`public/index.html` if there is no root one), read from the file as text — a title your app sets from script is not seen; otherwise the `name` in `package.json`, unless it is a template placeholder such as `vite_react_shadcn_ts`. It is omitted when nothing qualifies, and it only ever fills in a site that has no name yet — a name set in the dashboard is never replaced. - **Only `map` analyses source files.** It parses your server source to report your app's attack surface. It runs only when you invoke it and prints to stdout. It transmits nothing unless you explicitly pass `--upload`, which sends that description of your app's structure to your own site's Patchstack endpoint — never source code, and never without that flag. A `prebuild` scan reads the scaffolded guard and rules JSON only to identify and clear the reserved map stamp; it does not analyse them or transmit their contents. -- **`scan` makes up to three source edits:** the disclosure widget'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. +- **`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. - 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. - 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`. - **`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. @@ -74,7 +74,7 @@ Only `map` analyses your source, and only `map --upload` sends anything derived - **`map` is local unless you pass `--upload`.** It walks the project's server source (skipping `node_modules`, build output and dot-directories; it does not follow symlinks out of the project unless you pass `--follow-symlinks`), parses it with the project's **own** `typescript`, and prints JSON describing the attack surface: entry points, the inputs each reads, the sinks they can reach (database / file system / process / outbound HTTP) with the npm package behind each, and evidence-backed input→sink flows, each labelled with how the link was established — from an exact read at the sink's own call site, through a transformed or cross-module link, down to the two being present together with no proven link. Static analysis is best-effort, so the output reports the *detected* surface with coverage counters — not a completeness guarantee. Without `--upload` it writes nothing except the file named by `--out`, and it is never invoked by `scan`, `setup`, `guide`, `protect`, or `mark-build`. - **`map --upload` is the only command that sends a description of your source.** (The runtime guard can also report rule detections, which carry route paths and parameter names — see "Runtime guard reporting" below.) It POSTs the same JSON document to `monitor/pulse/input-map/<your site uuid>` so Patchstack can pin protection rules to your app's own parameter names instead of guessing them. During a pre-bundle build hook it hashes the policy-relevant document (all fields except analyser timing and memory observations), writes the SHA-256 value as `_patchstack.build_id` in the existing rules file imported by the scaffolded guard, and sends the same value as `build_id`. Outside that lifecycle it sends no identity and changes no file, so any generated scoped rule remains detect-only. **No source code, no file contents, no environment variable values.** A map with no recognised entry points is still uploaded because its import inventory and coverage limits are evidence; a failure to reach Patchstack is reported and ignored rather than failing your build. Omit the flag and the command stays entirely local. - **`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. -- Patchstack is not WordPress-only. This connector monitors any JS/Node project — Vite, Next.js, plain vanilla JS, anything with a lockfile. +- Patchstack is not WordPress-only. Connect monitors any JS/Node project — Vite, Next.js, plain vanilla JS, anything with a lockfile. ## Before you start — never install twice @@ -135,7 +135,7 @@ This is a request, not a mechanism: nothing in the install depends on it. Do it **A step the checklist still lists is yours to finish, not a result to report.** `setup` applies what it can apply safely and prints the exact edit for anything it would have had to overwrite user code to do. They are: moving `@patchstack/connect` out of `devDependencies`, the widget tag in a root layout `setup` could not edit, the production marker on a server-rendered root, and wiring a generic guard into the server entry. The last three are steps 3 and 4 of "Manual setup" below; after the guard one, `npx @patchstack/connect protect --check` must exit 0. - **A tick is "nothing owed here", not "this part is on".** The checklist marks steps this project still owes, so a part it cannot carry — or one that is switched off — is green with nothing outstanding. `No build script to integrate`, `Disclosure widget disabled by config` and `Runtime protection: not applicable` all read that way. So report what the project ended up with by name — dependency scans, the disclosure widget, the build hooks, runtime protection — and say which of them are not active and why, rather than reporting an empty checklist as a finished install. Of those, the widget is the one that can be off by setting rather than by the shape of the project: if `.patchstackrc.json` carries `"widget": false` and the person did not ask for that, tell them it is off and ask whether they want it on. + **A tick is "nothing owed here", not "this part is on".** The checklist marks steps this project still owes, so a part it cannot carry — or one that is switched off — is green with nothing outstanding. `No build script to integrate`, `Patchstack Connector disabled by config` and `Runtime protection: not applicable` all read that way. So report what the project ended up with by name — dependency scans, the Patchstack Connector, the build hooks, runtime protection — and say which of them are not active and why, rather than reporting an empty checklist as a finished install. Of those, the widget is the one that can be off by setting rather than by the shape of the project: if `.patchstackrc.json` carries `"widget": false` and the person did not ask for that, tell them it is off and ask whether they want it on. **Finish by telling the user to refresh their preview.** The widget loads with the page, so a preview that was already open still shows the HTML from before setup — the widget is missing there until it reloads. Tell them what to expect after the refresh: a site that is not yet connected to an account shows the "Connect this website" panel, and the "Report a vulnerability" button takes its place once the site is claimed. A freshly set up site is unclaimed unless setup ran with a claim token. 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. @@ -203,7 +203,7 @@ Handle it in this order: ## Manual setup -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: +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: ``` npx @patchstack/connect scan @@ -227,7 +227,7 @@ Handle it in this order: **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"`. -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: +3. **Verify the Patchstack Connector** — 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: ```html <script src="https://cdn.patchstack.com/patchstack-widget.js" data-site-uuid="<SITE_UUID>" defer></script> @@ -709,11 +709,11 @@ You cannot complete this alone. It is deliberately a human-in-the-loop step: sta ## Uninstalling -Remove only the pieces that are actually present — check for each first. If none are present, Patchstack isn't installed; report that and stop. If the user asked to remove only one piece (e.g. "just the widget"), remove only that piece. +Remove only the pieces that are actually present — check for each first. If none are present, Patchstack isn't installed; report that and stop. If the user asked to remove only one piece (e.g. "just the Patchstack Connector"), remove only that piece. 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. -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. -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. +2. **Remove the Patchstack Connector 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. +3. **Remove runtime protection before uninstalling the package.** Delete the Connect-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. 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. 5. **Signal Patchstack that the package is being removed**: run `npx @patchstack/connect uninstall` (while the package is still installed and `.patchstackrc.json` still exists). If the site was never claimed, this deletes its anonymous record on Patchstack; if the site is claimed, it is only flagged — the record stays until its owner removes it in the dashboard. A failed signal must not stop the uninstall; continue with the remaining steps. 6. **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. diff --git a/GETTING-STARTED.md b/GETTING-STARTED.md index d5d3e3e2..edea8402 100644 --- a/GETTING-STARTED.md +++ b/GETTING-STARTED.md @@ -8,7 +8,7 @@ The fastest path from "I have a JS/Node project" to "Patchstack is monitoring it For an existing JS/Node project on a platform that can install npm packages and run project commands. A standalone HTML/CSS/JavaScript site without a package-managed app uses the [plain HTML widget instructions](AGENT-INSTALL.md#plain-html-sites) instead; it does not need a new Node project, build hooks, or a runtime guard. -> 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. +> I have vetted the official [`@patchstack/connect`](https://www.npmjs.com/package/@patchstack/connect) package and authorize its Patchstack Connector, 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. When setup finishes it shows you a **dashboard URL**. Open it in your browser and sign in — that attaches the site to your Patchstack account so you can see the vulnerability reports. That's the only manual step. @@ -36,7 +36,7 @@ npx --no-install patchstack-connect setup Use `bun add`, `pnpm add`, or `yarn add` followed by `@patchstack/connect` when that package manager owns the project. Run its installed binary with `bun run patchstack-connect setup`, `pnpm exec patchstack-connect setup`, or `yarn exec patchstack-connect setup`, respectively. Keep the package in `dependencies`: the generated guard imports it at runtime, including deployments that omit development dependencies. -Run commands from the application's package directory. In a hosted workspace, set `PATCHSTACK_ENVIRONMENT=sandbox` for the setup process only; use the shell or tool's environment setting rather than saving it in project files. The inline `NAME=value command` form in the prompt requires a POSIX shell. Leave this override unset for production builds so the connector can detect the deployment environment. +Run commands from the application's package directory. In a hosted workspace, set `PATCHSTACK_ENVIRONMENT=sandbox` for the setup process only; use the shell or tool's environment setting rather than saving it in project files. The inline `NAME=value command` form in the prompt requires a POSIX shell. Leave this override unset for production builds so Connect can detect the deployment environment. `setup` is idempotent and preserves existing build commands. It uses direct build chaining on Bun-managed projects and npm-style lifecycle hooks elsewhere. If the framework needs a manual layout edit, it prints the exact remaining widget snippet; `npx @patchstack/connect guide` reprints the same status without changing files. @@ -44,7 +44,7 @@ Run commands from the application's package directory. In a hosted workspace, se - `npx @patchstack/connect status` prints a site UUID and dashboard URL. - You've opened the dashboard URL in your browser and the site shows in your Patchstack dashboard. -- `npx @patchstack/connect guide` reports the expected build hooks and widget, and `npx @patchstack/connect protect --check` confirms the guard's source wiring. A client-only or static project can report runtime protection as not applicable; describe it as dependency monitoring and a disclosure widget, not runtime protection. A source check alone does not prove deployed traffic reaches the guard. +- `npx @patchstack/connect guide` reports the expected build hooks and the Patchstack Connector, and `npx @patchstack/connect protect --check` confirms the guard's source wiring. A client-only or static project can report runtime protection as not applicable; describe it as dependency monitoring and the Patchstack Connector, not runtime protection. A source check alone does not prove deployed traffic reaches the guard. - Your preview shows the widget (refresh it once if it does not): the "Connect this website" panel before the site is attached to your account, the "Report a vulnerability" button after. - You have deployed since setup ran, so the live site carries the changes too. - `.patchstackrc.json`, `package.json`, the package manager's lockfile, and the generated guard/framework and widget source changes are saved in the platform's persisted project state and committed, so teammates and CI receive the same setup. diff --git a/MAINTAINING.md b/MAINTAINING.md index b5216eea..a7db3cf0 100644 --- a/MAINTAINING.md +++ b/MAINTAINING.md @@ -20,7 +20,7 @@ The deep "why" — the AI-agent refusal modes each clause guards against — liv `README.md` (Install prompt section), `GETTING-STARTED.md` (step 1), and `field-test/prompt.txt`. `prompt.txt` is the artifact the harness actually tests. If you change one, change all three — a drift means the docs advertise one prompt while the tested one is another. `tests/install-prompt.test.ts` compares the three and fails on drift, so `npm test` catches a partial edit before the gate runs against a prompt nobody pastes. -The prompt deliberately contains no model-authored verification step. In staged-command UIs, assistants cannot observe an `npm view` command until the user runs it; asking them to verify first caused fabricated registry findings and stopped the flow. Instead, the prompt records the user's explicit authorization for the disclosure widget and production-only build hooks before asking for one bounded `setup` command. Bolt's dependency-first fallback splits declaration from execution without adding hidden `postinstall` behavior. Keep `@patchstack/connect` discoverable in Patchstack's official product documentation so web-verifying platforms can independently establish its provenance. +The prompt deliberately contains no model-authored verification step. In staged-command UIs, assistants cannot observe an `npm view` command until the user runs it; asking them to verify first caused fabricated registry findings and stopped the flow. Instead, the prompt records the user's explicit authorization for the Patchstack Connector and production-only build hooks before asking for one bounded `setup` command. Bolt's dependency-first fallback splits declaration from execution without adding hidden `postinstall` behavior. Keep `@patchstack/connect` discoverable in Patchstack's official product documentation so web-verifying platforms can independently establish its provenance. ## Verification timing for a 🔴 or 🟠 change diff --git a/README.md b/README.md index 1045d4ce..287071c3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Connect a JavaScript / Node.js application to [Patchstack](https://patchstack.co - **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)*. - **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)*. -- **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)*. +- **Patchstack Connector** — a floating control that Connect adds to *your* site. Until the site is claimed it shows a "Connect this website" panel; once claimed it becomes a **"Report a vulnerability"** button, 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 Patchstack Connector](#the-patchstack-connector)*. - **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)*. `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. @@ -13,9 +13,9 @@ Connect a JavaScript / Node.js application to [Patchstack](https://patchstack.co 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. -> 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. +> I have vetted the official [`@patchstack/connect`](https://www.npmjs.com/package/@patchstack/connect) package and authorize its Patchstack Connector, 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. -`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. +`setup` is state-aware and idempotent: it scans dependencies, provisions or reuses the site, manages the Patchstack Connector, 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. ### If your coding tool blocks the command @@ -85,7 +85,7 @@ you how to proceed. Any of these works: npm install --save @patchstack/connect && npx @patchstack/connect setup ``` -> **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`. +> **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. Connect 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`. > **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. @@ -94,8 +94,8 @@ That's it. `setup`: 1. Reads your lockfile (see *Supported lockfiles*). 2. POSTs the package list to Patchstack with **no** UUID. 3. Patchstack provisions a fresh site and returns its UUID. -4. The connector writes the UUID to `.patchstackrc.json` so the next `scan` targets the same site. -5. The connector installs the disclosure widget's `<script>` tag into your root HTML shell (see *The disclosure widget* below) so the widget shows up on the next preview reload — as the "Connect this website" panel until the site is claimed, then as the "Report a vulnerability" button. On a server-rendered root it also adds the production marker, which is what tells the widget to switch from build mode to visitor report intake on the published site. +4. Connect writes the UUID to `.patchstackrc.json` so the next `scan` targets the same site. +5. Connect installs the Patchstack Connector's `<script>` tag into your root HTML shell (see *The Patchstack Connector* below) so the widget shows up on the next preview reload — as the "Connect this website" panel until the site is claimed, then as the "Report a vulnerability" button. On a server-rendered root it also adds the production marker, which is what tells the widget to switch from build mode to visitor report intake on the published site. 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. 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. 8. Wires `scan` before builds and `mark-build` after builds, preserving existing commands and using direct build chaining for Bun. @@ -120,9 +120,9 @@ npx @patchstack/connect setup ``` patchstack-connect scan [options] Scan the lockfile and POST to Patchstack. If no UUID is configured the server provisions - one and the connector persists it. After a - successful post, adds/updates the disclosure - widget tag in the root HTML shell. Also adds the + one and Connect persists it. After a + successful post, adds/updates the Patchstack + Connector tag in the root HTML shell. Also adds the production marker to a JSX root shell, before the post (opt out of both with "widget": false in .patchstackrc.json) @@ -300,11 +300,11 @@ Two files, because one value is public and the other is not. } ``` -`"widget"` is optional and defaults to `true`; set it to `false` to stop the connector from managing the disclosure-widget tag (see *The disclosure widget*). +`"widget"` is optional and defaults to `true`; set it to `false` to stop Connect from managing the Patchstack Connector tag (see *The Patchstack Connector*). -**You do not write `apiKey` yourself.** The first `scan` provisions the site and the connector saves it, so setup needs no manual step. +**You do not write `apiKey` yourself.** The first `scan` provisions the site and Connect saves it, so setup needs no manual step. -The site UUID identifies the site and is **not** a secret — the disclosure widget ships the same UUID in client-side HTML. +The site UUID identifies the site and is **not** a secret — the Patchstack Connector ships the same UUID in client-side HTML. `apiKey` **is** a secret. One credential authenticates both paths: Pulse ingest (manifest, attack-surface map, package removal), where it is exchanged for a short-lived token rather than sent directly, and block-log reporting. Keep it out of the widget tag, client bundles and public env vars (`NEXT_PUBLIC_*`), and out of the committed config — `.patchstackrc.local.json` is git-ignored for that reason. For deploys, prefer `PATCHSTACK_API_KEY` in the platform's secret store. @@ -366,9 +366,9 @@ The guide inspects the Host-created site configuration and lockfile, explains th Use `--url http://localhost:PORT/api/tasks` when the app does not use the default `http://localhost:3000/api/tasks`. Remove the deliberately vulnerable dependency after the walkthrough. -## The disclosure widget +## The Patchstack Connector -The widget is a floating "Report a vulnerability" button — a disclosure channel for anyone who spots a bug on the site. The connector manages its install so the UUID never has to be copied by hand: +The Patchstack Connector is a floating control whose form follows the site's claim state: a "Connect this website" panel while the site is unclaimed, then a "Report a vulnerability" button — a disclosure channel for anyone who spots a bug on the site. Connect manages its install so the UUID never has to be copied by hand: - **`scan`** (after a successful post) adds this managed tag to the first root HTML shell it finds — `index.html`, `public/index.html`, or `src/app.html` — immediately before `</body>`: @@ -379,9 +379,9 @@ The widget is a floating "Report a vulnerability" button — a disclosure channe - **`scan`** installs the widget tag into a plain HTML shell, and — where there is none — into a JSX root (`src/routes/__root.tsx`, `app/layout.tsx`, …), just before `</body>`. The same tag serves both: JSX reads `defer` as a boolean attribute and passes `data-*` through. A server-rendered app has no HTML shell at all, so without this its published site carries no widget and Patchstack never hears from the live page. - **`scan`** also adds the production marker when the root shell is JSX rather than HTML (`src/routes/__root.tsx`, `app/layout.tsx`, …), above the widget tag and guarded by the framework's production expression. A server-rendered app emits no built HTML for `mark-build` to stamp, so without it the widget reads the published site as build mode and shows the claim flow to visitors instead of the report form. - Re-runs update the tag in place (the `data-patchstack-connect-widget` attribute marks it as connector-managed); a pre-existing manual widget tag is left untouched. `--dry-run` never edits anything; a failed post still skips the widget tag (it needs the site UUID) but the production marker may already have been written, since it runs before the post. Projects whose root layout is code rather than HTML (Next.js, Nuxt, Astro, …) get the exact snippet and target file printed instead — `guide` shows framework-specific placement. + Re-runs update the tag in place (the `data-patchstack-connect-widget` attribute marks it as managed by Connect); a pre-existing manual widget tag is left untouched. `--dry-run` never edits anything; a failed post still skips the widget tag (it needs the site UUID) but the production marker may already have been written, since it runs before the post. Projects whose root layout is code rather than HTML (Next.js, Nuxt, Astro, …) get the exact snippet and target file printed instead — `guide` shows framework-specific placement. -- **`mark-build`** ensures the same tag in built HTML output, covering builds whose source shell the connector couldn't edit, and stamps `window.__PATCHSTACK_PROD__` so the widget hides the claim/login UI on the published site (owners reach it by appending `#patchstack` to the live URL). It then reports what it did — `stamped`, `withheld`, `no-pages` for a server-rendered build, or `no-output` — alongside the same manifest `scan` sent before the bundler ran, so the dashboard can say why a published app is or is not reporting its build. That report is the second half of one build, not a second build: Patchstack keeps one copy of the manifest and reads the two together. It is sent only for a site that is already registered, and never carries the site's address or name, which `mark-build` does not resolve. The marker says the page is the live site, so **only a production build carries it**: the environment is read the same way `scan` reads it (the build platform's own tier or branch name, then the hosted builder the project belongs to), and a local or preview build gets the widget tag, no marker, and any marker an earlier build left behind removed. Publishing a static build by hand from your machine is the case that needs `--production` (or `PATCHSTACK_ENVIRONMENT=production`), because nothing in that environment can say the build is a deployment. +- **`mark-build`** ensures the same tag in built HTML output, covering builds whose source shell Connect couldn't edit, and stamps `window.__PATCHSTACK_PROD__` so the widget hides the claim/login UI on the published site (owners reach it by appending `#patchstack` to the live URL). It then reports what it did — `stamped`, `withheld`, `no-pages` for a server-rendered build, or `no-output` — alongside the same manifest `scan` sent before the bundler ran, so the dashboard can say why a published app is or is not reporting its build. That report is the second half of one build, not a second build: Patchstack keeps one copy of the manifest and reads the two together. It is sent only for a site that is already registered, and never carries the site's address or name, which `mark-build` does not resolve. The marker says the page is the live site, so **only a production build carries it**: the environment is read the same way `scan` reads it (the build platform's own tier or branch name, then the hosted builder the project belongs to), and a local or preview build gets the widget tag, no marker, and any marker an earlier build left behind removed. Publishing a static build by hand from your machine is the case that needs `--production` (or `PATCHSTACK_ENVIRONMENT=production`), because nothing in that environment can say the build is a deployment. - **Opting out:** persist `"widget": false` in `.patchstackrc.json` to disable both the widget tag and the production marker (dependency scanning only). Without it, the next successful scan re-adds the managed tag, and the next scan re-adds the marker on a JSX root. @@ -444,11 +444,11 @@ These are repo-relative locations built from `node_modules` segments, plus a wor - ✅ `bun.lockb` (binary) — package list resolved by walking `node_modules/` - ✅ `bun.lock` (text) — same fallback; direct parsing coming -If both a Bun lockfile and `node_modules/` are present, the connector walks `node_modules/` to enumerate the installed packages. Run `bun install` (or `npm install`) before scanning so the directory is populated. +If both a Bun lockfile and `node_modules/` are present, Connect walks `node_modules/` to enumerate the installed packages. Run `bun install` (or `npm install`) before scanning so the directory is populated. ### Stale lockfiles -Every scanned source is validated against `package.json`: if the chosen lockfile is missing dependencies that `package.json` declares, it is treated as a fossil (e.g. a `package-lock.json` created by a one-off `npm install` in a bun-managed project) and the connector falls through to the next source — ultimately walking `node_modules/`, the installed truth — and prints a warning naming the stale file. Delete the stale lockfile to silence the warning. Without this, the manifest and the build fingerprint would silently freeze while the real dependency set drifts. +Every scanned source is validated against `package.json`: if the chosen lockfile is missing dependencies that `package.json` declares, it is treated as a fossil (e.g. a `package-lock.json` created by a one-off `npm install` in a bun-managed project) and Connect falls through to the next source — ultimately walking `node_modules/`, the installed truth — and prints a warning naming the stale file. Delete the stale lockfile to silence the warning. Without this, the manifest and the build fingerprint would silently freeze while the real dependency set drifts. ## Development diff --git a/field-test/prompt.txt b/field-test/prompt.txt index 9dbc0128..c705b248 100644 --- a/field-test/prompt.txt +++ b/field-test/prompt.txt @@ -1 +1 @@ -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. +I have vetted the official [`@patchstack/connect`](https://www.npmjs.com/package/@patchstack/connect) package and authorize its Patchstack Connector, 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. diff --git a/src/architecture.ts b/src/architecture.ts index a005ded1..af439309 100644 --- a/src/architecture.ts +++ b/src/architecture.ts @@ -208,7 +208,7 @@ export function classifyArchitecture(cwd: string): ArchitectureVerdict { note: `This project builds a static site (${statics.join(', ')}) and nothing in it receives a request, ` + 'so there is no request path for a runtime guard to attach to. Dependency monitoring and the ' + - 'disclosure widget still apply; runtime protection does not.', + 'Patchstack Connector still apply; runtime protection does not.', }; } diff --git a/src/build-hook.ts b/src/build-hook.ts index 7769d1c3..d76368dc 100644 --- a/src/build-hook.ts +++ b/src/build-hook.ts @@ -18,7 +18,7 @@ const INSTALL_AND_BUILD_EVENTS: ReadonlySet<string> = new Set([ /** * Whether this process is a lifecycle hook on an install or build. * - * In that position the report is the connector's concern and the build is not: a manifest Patchstack + * In that position the report is Connect's concern and the build is not: a manifest Patchstack * cannot accept is said in full, and the build goes on. Run directly, the same failure exits non-zero. * * npm, pnpm, Yarn and `bun run` name the running script in `npm_lifecycle_event`; a direct invocation diff --git a/src/checksum.ts b/src/checksum.ts index 2d74b85e..9a6a349d 100644 --- a/src/checksum.ts +++ b/src/checksum.ts @@ -18,7 +18,7 @@ import type { WirePackage } from './normalize.js'; * and PHP `json_encode` produce identical bytes (no unicode escaping, and * neither escapes `/`, so scoped names like `@babel/core` match). * - * Injected into built HTML by `mark-build` and reported by the disclosure widget + * Injected into built HTML by `mark-build` and reported by the Patchstack Connector * so Patchstack can compare the live build against the last reported manifest. */ export function computeManifestChecksum(packages: WirePackage[]): string { diff --git a/src/cli.ts b/src/cli.ts index 0d890219..7597996f 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -93,7 +93,7 @@ Usage: If no UUID is configured, the server provisions one and we persist it. After a successful post it also adds/updates the - disclosure-widget <script> tag in the root + Patchstack Connector <script> tag in the root HTML shell (index.html, public/index.html, or src/app.html) — opt out with "widget": false in .patchstackrc.json. @@ -802,7 +802,7 @@ async function runScan( const connected = response.claim?.state === 'claimed' || response.claim?.state === 'owned-by-you'; // With a UUID in hand (existing or freshly provisioned), ensure the - // disclosure widget's managed tag in the source HTML shell so the very next + // Patchstack Connector's managed tag in the source HTML shell so the very next // preview reload shows the "Report a vulnerability" button. Best-effort and // opt-out-able; a failed post never reaches this point, and --dry-run // returned above. @@ -877,7 +877,7 @@ function reportSourceWidget(siteUuid: string, framework: string | null): void { const result = ensureSourceWidget(process.cwd(), siteUuid, jsxShell); switch (result.action) { case 'added': - console.log(`Widget: added the disclosure widget tag to ${result.shell}. Reload your preview to see it.`); + console.log(`Widget: added the Patchstack Connector tag to ${result.shell}. Reload your preview to see it.`); console.log(' Unclaimed, it shows a "Connect this website" panel; the "Report a vulnerability" button replaces it once the site is claimed.'); break; case 'updated': diff --git a/src/client.ts b/src/client.ts index 4961f70c..22559ef1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -125,7 +125,7 @@ export function buildRulesUrl(manifestEndpoint: string, siteUuid: string): strin * the API endpoint, at `/monitor/claim?site=<uuid>`. Using the API endpoint's * origin (rather than a hard-coded https://api.patchstack.com) means staging, * ngrok tunnels and local dev environments all produce a claim URL on the same - * host the connector is already talking to. + * host Connect is already talking to. */ export function buildClaimUrl(endpoint: string, siteUuid: string): string { const origin = new URL(endpoint).origin; @@ -476,7 +476,7 @@ export interface ManifestPostResult { /** * Post the manifest, falling back from `local` to `sandbox` for a server that does not know `local`. * - * Keeps the connector publishable ahead of the server change: the honest label is tried first, and the + * Keeps Connect publishable ahead of the server change: the honest label is tried first, and the * older server's nearest label is used only when it refuses, never silently on a server that accepts. */ export async function postManifestWithEnvironmentFallback( diff --git a/src/config.ts b/src/config.ts index 45354763..b4dc511d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -437,7 +437,7 @@ export async function persistTimeout(cwd: string, timeoutMs: number): Promise<st /** * Persist the WP-format api_key issued at provision. Authenticates both the Pulse endpoints and connector - * log reporting. Never embed it in the public disclosure widget. + * log reporting. Never embed it in the public Patchstack Connector. * * Written to the credential file, which setup adds to the project's ignore list — the public config is * meant to be committed, so a credential in it is a credential in the repository. diff --git a/src/demo.ts b/src/demo.ts index 60ceaf07..fa4024c7 100644 --- a/src/demo.ts +++ b/src/demo.ts @@ -185,7 +185,7 @@ export function renderDemoGuide(state: DemoGuideState): string { `Patchstack demo guide — ${scenario.name}`, '', 'Goal: prove that a live Patchstack virtual patch blocks the vulnerable payload while normal traffic still succeeds.', - 'Deployment required: no. Keep the app running locally; the connector and generated guard contact Patchstack’s production API.', + 'Deployment required: no. Keep the app running locally; Connect and the generated guard contact Patchstack’s production API.', '', `1. ${siteReady ? '✓' : '○'} Connect this project from Bolt’s Host account dropdown`, siteReady diff --git a/src/guide.ts b/src/guide.ts index ef2d24af..859f50f5 100644 --- a/src/guide.ts +++ b/src/guide.ts @@ -458,7 +458,7 @@ export function renderGuideChecklist(state: GuideState, useColor: boolean): stri if (!state.hasPackageJson) { lines.push(todo('No package.json found in this directory.')); lines.push(detail('For a JS/Node app, run the guide from its package directory; check that package.json is readable and valid.')); - lines.push(detail('For a standalone HTML/CSS/browser-JavaScript site, use the disclosure widget directly.')); + lines.push(detail('For a standalone HTML/CSS/browser-JavaScript site, use the Patchstack Connector directly.')); lines.push(detail('Do not create a Node project, build hooks, or a server just to install the widget.')); lines.push(detail('Use the correct site UUID or widget snippet from the Patchstack dashboard; never invent one.')); lines.push(detail('See "Plain HTML sites" in AGENT-INSTALL.md. Widget-only setup provides no dependency scan or runtime protection.')); @@ -546,21 +546,21 @@ export function renderGuideChecklist(state: GuideState, useColor: boolean): stri } } - // 5. Disclosure widget + // 5. Patchstack Connector const widgetOk = state.widgetInstalled && state.widgetTokenMatches !== false; if (state.widgetOptOut && !widgetOk) { - lines.push(done('Disclosure widget disabled by config ("widget": false in .patchstackrc.json)')); + lines.push(done('Patchstack Connector disabled by config ("widget": false in .patchstackrc.json)')); } else if (widgetOk) { - lines.push(done('Disclosure widget installed')); + lines.push(done('Patchstack Connector installed')); } else if (state.widgetInstalled) { - lines.push(todo("Fix the disclosure widget yourself — its site UUID doesn't match this project's")); + lines.push(todo("Fix the Patchstack Connector yourself — its site UUID doesn't match this project's")); lines.push(detail(`Edit the widget tag → set data-site-uuid (or userToken) to '${state.siteUuid}' (a wrong UUID makes the widget silently no-op)`)); } else if (state.siteUuid === null) { - lines.push(todo('Add the "Report a vulnerability" widget — the first scan does this for you')); + lines.push(todo('Add the Patchstack Connector — the first scan does this for you')); lines.push(detail('Run → npx @patchstack/connect scan (provisions the site and adds the widget tag')); lines.push(detail(' to the root HTML shell: index.html / public/index.html / src/app.html)')); } else { - lines.push(todo('Add the "Report a vulnerability" widget yourself — this root is code, not a plain HTML shell')); + lines.push(todo('Add the Patchstack Connector yourself — this root is code, not a plain HTML shell')); lines.push(detail('Note → a normal `scan` adds this tag to a plain HTML shell automatically; add it by hand here:')); const placement = state.widgetFileHint !== null diff --git a/src/protect/install/util.ts b/src/protect/install/util.ts index 10017a14..4db03679 100644 --- a/src/protect/install/util.ts +++ b/src/protect/install/util.ts @@ -65,7 +65,7 @@ export function isSiteUuid(value: unknown): value is string { /** * Bake the site UUID written by `scan` into a managed runtime-guard template. * - * The UUID is public project configuration (the disclosure widget exposes the + * The UUID is public project configuration (the Patchstack Connector exposes the * same value). Keeping the environment-variable fallback in the template lets * unscanned projects remain inert and lets deployments override it explicitly. */ diff --git a/src/stack.ts b/src/stack.ts index 287d3ef0..d3daa16b 100644 --- a/src/stack.ts +++ b/src/stack.ts @@ -4,7 +4,7 @@ import type { WirePackage } from './normalize.js'; * A best-effort description of the stack a build was produced with, derived * entirely from the lockfile (ground truth) plus the build-time environment. * - * The disclosure widget reads this from `window.__PATCHSTACK_STACK__` (injected + * The Patchstack Connector reads this from `window.__PATCHSTACK_STACK__` (injected * by `mark-build`) and reports it to Patchstack, so we learn how the sites we * protect are actually built and hosted — across every "vibe" platform — without * shipping a runtime probe onto the host server. Every field is a coarse label @@ -39,7 +39,7 @@ interface StackRule { /** * Package → stack-label registry. First match per category wins, so order * within a category is priority order (most specific first). Add a row to teach - * the connector a new framework, bundler, or vibe platform. + * Connect a new framework, bundler, or vibe platform. */ const STACK_RULES: readonly StackRule[] = [ // Meta-frameworks (most specific first). diff --git a/src/types.ts b/src/types.ts index 7b86a7f4..5bf98397 100644 --- a/src/types.ts +++ b/src/types.ts @@ -104,7 +104,7 @@ export interface Config { */ environmentSource?: EnvironmentSource | null; /** - * Whether the connector manages the disclosure-widget tag (source shell on + * Whether Connect manages the Patchstack Connector tag (source shell on * `scan`, built HTML on `mark-build`). Defaults to true; persist * `"widget": false` in .patchstackrc.json for dependency-scanning only. */ diff --git a/src/widget.ts b/src/widget.ts index d2473852..31011875 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -1,6 +1,6 @@ -// Managed disclosure-widget tag — the connector installs the widget for you. +// Managed Patchstack Connector tag — Connect installs it for you. // -// After a successful scan the connector ensures the site's root HTML shell +// After a successful scan Connect ensures the site's root HTML shell // carries the widget's one-liner CDN tag (the canonical install form from the // widget docs: a single <script> with `data-site-uuid`, auto-initialising on // DOMContentLoaded). The tag carries an ownership attribute so re-runs update @@ -14,14 +14,14 @@ import { writeProjectFileSync } from './safe-file.js'; export const WIDGET_SCRIPT_URL = 'https://cdn.patchstack.com/patchstack-widget.js'; -/** Attribute that tags the connector-managed widget tag so re-runs update it. */ +/** Attribute that tags the Connect-managed widget tag so re-runs update it. */ export const WIDGET_MARKER_ATTR = 'data-patchstack-connect-widget'; /** Substring that marks any widget install (managed or manual) in HTML. */ const WIDGET_NEEDLE = 'patchstack-widget'; /** - * Root HTML shells the connector is willing to edit, in priority order: + * Root HTML shells Connect is willing to edit, in priority order: * Vite/plain SPA, CRA-style, SvelteKit. A framework whose root is code rather * than HTML has no entry here; a JSX one is handled by `ensureSourceWidget`'s * fallback below, and the rest get the snippet printed by `guide`. diff --git a/tests/claim-token.test.ts b/tests/claim-token.test.ts index 55462b3e..eabc7716 100644 --- a/tests/claim-token.test.ts +++ b/tests/claim-token.test.ts @@ -56,7 +56,7 @@ describe('the claim token in configuration', () => { expect((await resolveConfig({ cwd, cliClaimToken: '' })).claimToken).toBeNull(); }); - it('is never written to the project, whichever file the connector persists', async () => { + it('is never written to the project, whichever file Connect persists', async () => { process.env.PATCHSTACK_CLAIM_TOKEN = 'from-env'; await resolveConfig({ cwd, cliClaimToken: 'from-flag' }); diff --git a/tests/guide.test.ts b/tests/guide.test.ts index 7129f332..453f249b 100644 --- a/tests/guide.test.ts +++ b/tests/guide.test.ts @@ -335,7 +335,7 @@ describe('guide', () => { expect(countRemainingSteps(state)).toBe(0); const output = renderGuideChecklist(state, false); - expect(output).toContain('Disclosure widget disabled by config'); + expect(output).toContain('Patchstack Connector disabled by config'); expect(output).not.toContain('✖'); });