@patchstack/connect 0.5.8 → 0.5.10

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
@@ -17,7 +17,7 @@ Every command at a glance — what it does, whether it reads your source, what i
17
17
  | `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. | No | Nothing | Nothing |
18
18
  | `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 |
19
19
  | `init <site-uuid>` | Optional: pre-seed `.patchstackrc.json` with an existing UUID. | No | `.patchstackrc.json` only | Nothing |
20
- | `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 | Nothing |
20
+ | `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 |
21
21
  | `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 |
22
22
  | `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 |
23
23
  | `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 |
@@ -94,6 +94,66 @@ This is a request, not a mechanism: nothing in the install depends on it. Do it
94
94
 
95
95
  **Then tell them to deploy.** Setup changes source files, and the deployed site keeps serving its previous build until the next deploy — so visitors get no widget, and on a server-rendered root no production marker, until the user deploys (or hits Publish) again. Say it as a reminder; do not deploy anything yourself.
96
96
 
97
+ ## When your tool will not run this CLI
98
+
99
+ Some coding tools refuse to execute a third-party command until the person approves it. In Claude Code,
100
+ auto mode's classifier can decline `npx @patchstack/connect setup` and the installed `patchstack-connect`
101
+ binary on that ground instead of prompting. The command is not the problem; the approval is missing.
102
+ Handle it in this order:
103
+
104
+ 1. **Stop at the refused command.** Do not route around the refusal: do not call the Patchstack API
105
+ yourself, do not wrap the command in a `package.json` script so a later install runs it, and do not add
106
+ the `postinstall` / `prebuild` hooks first so the next install provisions the site. Each of those runs
107
+ the command the tool declined, with the person's decision taken away from them. Leave `package.json`
108
+ and the source tree as they were.
109
+
110
+ 2. **Hand the person the ways forward, with the exact text.** Say what the command does in plain words —
111
+ it registers the site with Patchstack, writes two small config files, adds the "Report a vulnerability"
112
+ line to the page, and adds the protection files and build steps described above — then give them:
113
+
114
+ - **Run it themselves, in this session.** In Claude Code a line that starts with `!` runs in their shell
115
+ and its output lands in the conversation: `! npx @patchstack/connect setup`. Other tools have a
116
+ terminal beside the chat; the command is the same without the `!`.
117
+ - **Approve it once.** In Claude Code, `/permissions` → **Recently denied** → `r` retries the command
118
+ with a manual approval; or `Shift+Tab` switches to Manual mode, and the tool prompts them when you
119
+ try again.
120
+ - **Allow it for good, then ask you to run it again.** For Claude Code these rules pre-approve every
121
+ `npx @patchstack/connect …` command and nothing else. They go in `.claude/settings.json` (shared with
122
+ the repository), `.claude/settings.local.json` (this person only), or through `/permissions`:
123
+
124
+ ```json
125
+ {
126
+ "permissions": {
127
+ "allow": [
128
+ "Bash(npx @patchstack/connect *)",
129
+ "Bash(npx --yes @patchstack/connect *)"
130
+ ]
131
+ }
132
+ }
133
+ ```
134
+
135
+ Other tools keep their own allowlists; the README section "If your coding tool blocks the command"
136
+ shows the Gemini CLI and OpenCode forms.
137
+
138
+ 3. **Write the command as `npx @patchstack/connect <command>`.** A rule matches the command text as
139
+ written. `./node_modules/.bin/patchstack-connect setup`, `PATCHSTACK_ENVIRONMENT=sandbox npx …` and
140
+ `npx --yes patchstack-connect setup` are different texts, and the rules above do not cover them. On a
141
+ developer's machine the sandbox label is not needed anyway: a scan there reports `local` on its own.
142
+
143
+ 4. **Resume from the output.** `setup` prints the same checklist, dashboard link and outcome block whoever
144
+ ran it, and re-running it changes nothing that is already done. If the person ran it, relay the
145
+ dashboard link and the outcome block from their output as they are. If your tool still will not run
146
+ `guide` or `status` for you, verify from the files instead of guessing: `siteUuid` in
147
+ `.patchstackrc.json` means the site is provisioned; `patchstack-connect scan` and
148
+ `patchstack-connect mark-build` in the `package.json` scripts mean the hooks are wired;
149
+ `patchstack-widget.js` in the root shell means the widget is in place; `.patchstackrc.local.json` in
150
+ `.gitignore` means the credential stays out of the commit. Never construct a dashboard link yourself —
151
+ it comes from `setup`, `status` or `claim` output.
152
+
153
+ 5. **`claim` and `login` are the same shape.** Both print a link the person opens. If your tool will not
154
+ run them, the person runs `npx @patchstack/connect claim` (or `login`) themselves and you relay the
155
+ link from their output.
156
+
97
157
  ## Manual setup
98
158
 
99
159
  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:
@@ -181,7 +241,8 @@ It is server-only. Never put it in the widget tag, client bundles, or public env
181
241
  rules were delivered, that the deployed app is wired, or that ordinary traffic is blocked.
182
242
 
183
243
  Nothing else runs the application. `protect`, `protect --check`, `setup`, `guide`, `scan`, `status`
184
- and `mark-build` only read and write files.
244
+ and `mark-build` only read and write files; `scan` and `mark-build` also report the dependency
245
+ manifest they read.
185
246
 
186
247
  5. **Commit** `.patchstackrc.json`, the updated `package.json`, the guard/framework source changes, and the layout/HTML file carrying the widget tag (and the production marker, when `scan` wrote one into a JSX root), so every developer and CI run reports to the same site.
187
248
 
@@ -196,6 +257,7 @@ It is server-only. Never put it in the widget tag, client bundles, or public env
196
257
  - The CLI never opens the dashboard link and never asks for Patchstack credentials.
197
258
  - 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.
198
259
  - If a step fails, stop and report it. Don't proceed with placeholders.
260
+ - 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.
199
261
  - 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.
200
262
 
201
263
  ## Which build a rule belongs to
package/README.md CHANGED
@@ -10,6 +10,68 @@ Copy this request into a coding assistant, or run the same command yourself:
10
10
 
11
11
  `setup` is state-aware and idempotent: it scans dependencies, provisions or reuses the site, manages the disclosure widget, installs and verifies the runtime guard, adds a dependency-install scan, wires the existing build command without replacing it, and prints the remaining setup status. It never runs the project build. `guide` provides the same project-specific status without changing files.
12
12
 
13
+ ### If your coding tool blocks the command
14
+
15
+ Some tools will not run a third-party command until you approve it. Claude Code's auto mode, for example,
16
+ can decline `npx @patchstack/connect setup` instead of prompting you, and the assistant then stops and asks
17
+ you how to proceed. Any of these works:
18
+
19
+ - **Run it yourself, in the same session.** In Claude Code, a line that starts with `!` runs in your shell
20
+ and its output lands in the conversation, so the assistant carries on from it:
21
+
22
+ ```
23
+ ! npx @patchstack/connect setup
24
+ ```
25
+
26
+ Elsewhere, run the same command without the `!` in a terminal and tell the assistant it is done. `setup`
27
+ is idempotent, so a partial earlier attempt does no harm.
28
+
29
+ - **Approve it once.** In Claude Code, open `/permissions`, pick the **Recently denied** tab and press `r`
30
+ to retry the command with a manual approval — or press `Shift+Tab` to switch to Manual mode and approve
31
+ the prompt when the assistant tries again.
32
+
33
+ - **Allow it, then ask again.** Claude Code resolves explicit allow rules before its classifier. These two
34
+ rules cover every `npx @patchstack/connect …` command (`setup`, `guide`, `status`, `claim`) and nothing
35
+ else. Put them in `.claude/settings.json` to share them with the repository, in
36
+ `.claude/settings.local.json` to keep them to yourself, or add them through `/permissions`:
37
+
38
+ ```json
39
+ {
40
+ "permissions": {
41
+ "allow": [
42
+ "Bash(npx @patchstack/connect *)",
43
+ "Bash(npx --yes @patchstack/connect *)"
44
+ ]
45
+ }
46
+ }
47
+ ```
48
+
49
+ A rule matches the command text as written, so use the plain `npx @patchstack/connect …` form: a leading
50
+ `PATCHSTACK_ENVIRONMENT=sandbox`, a path such as `./node_modules/.bin/patchstack-connect`, or the bare
51
+ `patchstack-connect` binary name is a different text and is not covered. On your own machine the sandbox
52
+ label is not needed — a scan there reports `local` by itself. Rules in a project's `.claude/settings.json`
53
+ apply once you have accepted that folder's trust dialog. If auto mode still declines the command with the
54
+ rules in place, use one of the first two options.
55
+
56
+ Other tools keep their own allowlists. Gemini CLI reads policy files from `~/.gemini/policies/`:
57
+
58
+ ```toml
59
+ [[rule]]
60
+ toolName = "run_shell_command"
61
+ commandPrefix = "npx @patchstack/connect"
62
+ decision = "allow"
63
+ priority = 100
64
+ ```
65
+
66
+ OpenCode takes the pattern in `opencode.json` (project root, or `~/.config/opencode/opencode.json`):
67
+
68
+ ```json
69
+ { "permission": { "bash": { "npx @patchstack/connect *": "allow" } } }
70
+ ```
71
+
72
+ Codex CLI asks according to `approval_policy` in `~/.codex/config.toml`: approve the command when it
73
+ asks, or run it yourself.
74
+
13
75
  ## Quick start (zero configuration)
14
76
 
15
77
  ```bash
@@ -192,7 +254,8 @@ Windows reports exit `2` without starting anything: the cleanup this relies on i
192
254
  group, and a verification that can leave a server running is worse than an unanswered question.
193
255
 
194
256
  No other command runs your application. `protect`, `protect --check`, `setup`, `guide`, `scan`,
195
- `status` and `mark-build` only read and write files.
257
+ `status` and `mark-build` only read and write files, and — for `scan` and `mark-build` — report the
258
+ dependency manifest they read.
196
259
 
197
260
  ## Configuration
198
261
 
@@ -311,7 +374,7 @@ The widget is a floating "Report a vulnerability" button — a disclosure channe
311
374
 
312
375
  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.
313
376
 
314
- - **`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). 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.
377
+ - **`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.
315
378
 
316
379
  - **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.
317
380
 
@@ -292,4 +292,4 @@ export {
292
292
  canonicalBuildId,
293
293
  readBuildStamp
294
294
  };
295
- //# sourceMappingURL=chunk-4OHAYSV2.js.map
295
+ //# sourceMappingURL=chunk-YG5C7HYB.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":";AAKO,SAAS,aAAa,OAAO;AAClC,MAAI;AACF,UAAM,IAAI,IAAI,IAAI,KAAK;AACvB,QAAI,EAAE,aAAa,SAAU,QAAO;AACpC,WAAO,EAAE,aAAa,YAAY,EAAE,aAAa,eAAe,EAAE,aAAa,eAAe,EAAE,aAAa,WAAW,EAAE,aAAa;AAAA,EACzI,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,YAAY,WAAW,UAAU,OAAO;AACtD,MAAI,OAAO,cAAc,YAAY,cAAc,GAAI,QAAO;AAC9D,MAAI,aAAa,SAAS,EAAG,QAAO;AACpC,WAAS,OAAO,gCAAgC,KAAK,cAAc,SAAS,qDAAqD;AACjI,SAAO;AACT;AAEA,IAAM,SAAS,oBAAI,IAAI;AACvB,SAAS,SAAS,KAAK,SAAS;AAC9B,MAAI,OAAO,IAAI,GAAG,EAAG;AACrB,SAAO,IAAI,GAAG;AAEd,UAAQ,KAAK,OAAO;AACtB;;;ACiGO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAQzC,YACE,SACgB,MAYA,OAChB;AACA,UAAM,OAAO;AAdG;AAYA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EAhBkB;AAAA,EAYA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAhBX,SAA4B,CAAC;AAqBtC;;;ACxJO,SAAS,0BAA0B,QAAgB,SAAS,OAAO,UAAgB;AACxF,MAAI,OAAO,oBAAoB,OAAO;AACpC,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,cAAc,OAAO,QAAQ,MAAM,MAAM;AAC3C,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,qBAAiB,IAAI,IAAI,OAAO,QAAQ,EAAE;AAC1C,mBAAe,IAAI,IAAI,MAAM,EAAE;AAAA,EACjC,SAAS,OAAO;AACd,UAAM,IAAI,gBAAgB,0DAA0D,kBAAkB,KAAK;AAAA,EAC7G;AACA,MAAI,cAAc,MAAM,MAAM,QAAQ,iBAAiB,gBAAgB;AACrE,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAGO,SAAS,cAAc,OAA+B;AAC3D,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,KAAO,QAAO;AACpF,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,KAAK;AAC5B,QAAI,CAAC,aAAa,OAAO,SAAS,CAAC,KAAK,OAAO,aAAa,MAAM,OAAO,aAAa,GAAI,QAAO;AACjG,WAAO,OAAO,SAAS;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,kBAAkB,OAAgB,YAAY,KAAoB;AAChF,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,QAAQ,MACX,QAAQ,kEAAkE,EAAE,EAC5E,QAAQ,iCAAiC,GAAG,EAC5C,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACR,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MAAM,MAAM,GAAG,SAAS;AACjC;AAEO,SAAS,gBAAgB,OAAiC;AAC/D,SACE,OAAO,UAAU,YACjB,kEAAkE,KAAK,KAAK;AAEhF;AAEO,SAAS,aAAa,OAAiC;AAC5D,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,KAAO,QAAO;AACpF,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,UAAM,OAAO,MAAM,WAAW,CAAC;AAC/B,QAAI,OAAO,MAAQ,OAAO,IAAM,QAAO;AAAA,EACzC;AACA,QAAM,YAAY,MAAM,YAAY,GAAG;AACvC,SAAO,YAAY,KAAK,YAAY,MAAM,SAAS,KAAK,QAAQ,KAAK,MAAM,MAAM,YAAY,CAAC,CAAC;AACjG;AAEO,SAAS,cAAc,OAAgB,YAAY,MAAwB;AAChF,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,UAAW,QAAO;AACxF,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,UAAM,OAAO,MAAM,WAAW,CAAC;AAC/B,QAAI,OAAO,MAAQ,OAAO,IAAM,QAAO;AAAA,EACzC;AACA,SAAO;AACT;;;AClFO,IAAM,6BAA6B,MAAM;AAGhD,eAAsB,gBACpB,UACA,WAAW,4BACM;AACjB,QAAM,SAAS,OAAO,SAAS,SAAS,MAAM,gBAAgB,CAAC;AAC/D,MAAI,OAAO,SAAS,MAAM,KAAK,SAAS,UAAU;AAChD,SAAK,SAAS,MAAM,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC3C,UAAM,IAAI,MAAM,oBAAoB,QAAQ,QAAQ;AAAA,EACtD;AAEA,QAAM,SAAS,SAAS;AACxB,MAAI,WAAW,QAAQ,OAAO,OAAO,cAAc,YAAY;AAC7D,QAAI,WAAW,EAAG,QAAO;AACzB,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,SAAS,OAAO,UAAU;AAChC,QAAM,SAAuB,CAAC;AAC9B,MAAI,QAAQ;AACZ,MAAI;AACF,eAAS;AACP,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,eAAS,MAAM;AACf,UAAI,QAAQ,UAAU;AACpB,aAAK,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AACnC,cAAM,IAAI,MAAM,oBAAoB,QAAQ,QAAQ;AAAA,MACtD;AACA,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AAEA,QAAM,QAAQ,IAAI,WAAW,KAAK;AAClC,MAAI,SAAS;AACb,aAAW,SAAS,QAAQ;AAC1B,UAAM,IAAI,OAAO,MAAM;AACvB,cAAU,MAAM;AAAA,EAClB;AACA,SAAO,IAAI,YAAY,EAAE,OAAO,KAAK;AACvC;AAEA,eAAsB,gBACpB,UACA,WAAW,4BACO;AAClB,QAAM,OAAO,MAAM,gBAAgB,UAAU,QAAQ;AACrD,SAAO,KAAK,MAAM,IAAI;AACxB;;;ACvCA,IAAM,gBAAgB;AAGf,SAAS,cAAc,kBAAkC;AAC9D,QAAM,MAAM,IAAI,IAAI,gBAAgB;AACpC,QAAM,OAAO,IAAI,SAAS,QAAQ,OAAO,EAAE;AAC3C,MAAI,WAAW,KAAK,SAAS,WAAW,IACpC,GAAG,KAAK,MAAM,GAAG,CAAC,YAAY,MAAM,CAAC,WACrC;AACJ,MAAI,SAAS;AACb,MAAI,OAAO;AACX,SAAO,IAAI,SAAS;AACtB;AAGO,SAAS,eAAe,YAAuE;AACpG,QAAM,QAAQ,WAAW,YAAY,GAAG;AACxC,MAAI,SAAS,KAAK,UAAU,WAAW,SAAS,EAAG,QAAO;AAE1D,QAAM,WAAW,WAAW,MAAM,QAAQ,CAAC;AAC3C,MAAI,CAAC,QAAQ,KAAK,QAAQ,EAAG,QAAO;AAEpC,SAAO,EAAE,UAAU,cAAc,WAAW,MAAM,GAAG,KAAK,EAAE;AAC9D;AAEA,IAAM,SAAS,oBAAI,IAAkD;AACrE,IAAM,WAAW,oBAAI,IAAoC;AAEzD,SAAS,SAAS,UAAkB,YAA4B;AAC9D,SAAO,GAAG,QAAQ;AAAA,EAAK,UAAU;AACnC;AAGO,SAAS,gBAAgB,QAAuB;AACrD,MAAI,CAAC,UAAU,OAAO,OAAO,cAAc,UAAU;AACnD,WAAO,MAAM;AACb,aAAS,MAAM;AACf;AAAA,EACF;AAEA,MAAI;AACF,UAAM,MAAM,SAAS,cAAc,OAAO,QAAQ,GAAG,OAAO,SAAS;AACrE,WAAO,OAAO,GAAG;AACjB,aAAS,OAAO,GAAG;AAAA,EACrB,QAAQ;AAAA,EAER;AACF;AAWA,eAAsB,cACpB,QACA,YAA0B,OACF;AAGxB,MAAI,OAAO,OAAO,cAAc,YAAY,OAAO,UAAU,WAAW,EAAG,QAAO;AAClF,MAAI,OAAO,oBAAoB,MAAO,QAAO;AAE7C,MAAI;AACJ,MAAI;AACF,eAAW,cAAc,OAAO,QAAQ;AAAA,EAC1C,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,CAAC,aAAa,QAAQ,EAAG,QAAO;AAEpC,QAAM,MAAM,SAAS,UAAU,OAAO,SAAS;AAC/C,QAAM,WAAW,OAAO,IAAI,GAAG;AAE/B,MAAI,aAAa,UAAa,KAAK,IAAI,IAAI,SAAS,YAAY,eAAe;AAC7E,WAAO,SAAS;AAAA,EAClB;AACA,QAAM,UAAU,SAAS,IAAI,GAAG;AAChC,MAAI,YAAY,OAAW,QAAO;AAElC,QAAM,cAAc,eAAe,OAAO,SAAS;AACnD,MAAI,gBAAgB,KAAM,QAAO;AAEjC,MAAI;AACJ,cAAY,YAAY;AACtB,QAAI;AACF,YAAM,WAAW,MAAM,UAAU,UAAU;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,QAAQ;AAAA,UACR,cAAc;AAAA,QAChB;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,YAAY;AAAA,UACZ,WAAW,YAAY;AAAA,UACvB,eAAe,YAAY;AAAA,QAC7B,CAAC;AAAA,QACD,QAAQ,YAAY,QAAQ,OAAO,SAAS;AAAA,MAC9C,CAAC;AAED,UAAI,CAAC,SAAS,GAAI,QAAO;AAEzB,YAAM,OAAQ,MAAM,gBAAgB,QAAQ;AAC5C,UAAI,CAAC,cAAc,KAAK,YAAY,EAAG,QAAO;AAE9C,YAAM,YAAY,OAAO,KAAK,UAAU;AACxC,YAAM,QAAQ,OAAO,SAAS,SAAS,KAAK,YAAY,IAAI,YAAY,MAAO;AAC/E,aAAO,IAAI,KAAK,EAAE,OAAO,KAAK,cAAc,WAAW,KAAK,IAAI,IAAI,MAAM,CAAC;AAE3E,aAAO,KAAK;AAAA,IACd,QAAQ;AACN,aAAO;AAAA,IACT,UAAE;AACA,UAAI,SAAS,IAAI,GAAG,MAAM,SAAU,UAAS,OAAO,GAAG;AAAA,IACzD;AAAA,EACF,GAAG;AACH,WAAS,IAAI,KAAK,QAAQ;AAE1B,SAAO;AACT;AAMA,eAAsB,gBACpB,QACA,YAA0B,OACO;AACjC,QAAM,QAAQ,MAAM,cAAc,QAAQ,SAAS;AACnD,SAAO,UAAU,OAAO,CAAC,IAAI,EAAE,eAAe,UAAU,KAAK,GAAG;AAClE;AAcA,eAAsB,WACpB,QACA,KACA,MACA,YAA0B,OACP;AACnB,4BAA0B,QAAQ,GAAG;AAErC,QAAM,OAAO,YAAY;AACvB,UAAM,OAAO,MAAM,gBAAgB,QAAQ,SAAS;AACpD,UAAM,WAAW,MAAM,UAAU,KAAK;AAAA,MACpC,GAAG;AAAA,MACH,SAAS,EAAE,GAAI,KAAK,SAAgD,GAAG,KAAK;AAAA,IAC9E,CAAC;AAED,WAAO,EAAE,UAAU,eAAe,KAAK,kBAAkB,OAAU;AAAA,EACrE;AAEA,QAAM,QAAQ,MAAM,KAAK;AAIzB,MAAI,MAAM,SAAS,WAAW,OAAO,MAAM,eAAe;AACxD,oBAAgB,MAAM;AAEtB,YAAQ,MAAM,KAAK,GAAG;AAAA,EACxB;AAEA,SAAO,MAAM;AACf;;;AC/KA,IAAM,WAAW;AAWV,SAAS,iBAAiB,OAA+B;AAC9D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAE3B,SAAO,SAAS,KAAK,OAAO,IAAI,QAAQ,YAAY,IAAI;AAC1D;AASO,IAAM,kBAAkB;AASxB,SAAS,eAAe,QAAgC;AAC7D,MAAI,WAAW,QAAQ,OAAO,WAAW,SAAU,QAAO;AAC1D,QAAM,YAAa,OAAmC,eAAe;AACrE,MAAI,cAAc,QAAQ,OAAO,cAAc,SAAU,QAAO;AAEhE,SAAO,iBAAkB,UAAsC,QAAQ;AACzE;","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
@@ -1790,11 +1790,18 @@ async function fetchSiteStatus(config) {
1790
1790
  return "unknown";
1791
1791
  }
1792
1792
  }
1793
- function buildManifestBody(config, payload, env = process.env) {
1793
+ function buildManifestBody(config, payload, env = process.env, marker = null) {
1794
1794
  const hosting = config.environment === "local" ? null : detectHostingPlatform(env);
1795
1795
  return {
1796
1796
  ...payload,
1797
1797
  environment: config.environment,
1798
+ // What the label rests on, sent with the label itself: a `production` claim decided by an
1799
+ // assumption about the project is worth less than one the platform declared, and only the
1800
+ // report can say which this was.
1801
+ ...config.environmentSource != null ? { environment_source: config.environmentSource } : {},
1802
+ // Present only on the report from a finished build, which is also what tells the two reports
1803
+ // of one build apart.
1804
+ ...marker !== null ? { marker } : {},
1798
1805
  ...typeof config.siteUrl === "string" && config.siteUrl !== "" ? { url: config.siteUrl } : {},
1799
1806
  ...typeof config.siteName === "string" && config.siteName !== "" ? { name: config.siteName } : {},
1800
1807
  ...hosting !== null && hosting.platform !== null ? { hosting } : {}
@@ -1848,16 +1855,19 @@ function environmentRejected(err) {
1848
1855
  function canRetryManifestPost(config) {
1849
1856
  return config.siteUuid !== null;
1850
1857
  }
1851
- async function postManifestWithEnvironmentFallback(config, payload) {
1858
+ async function postManifestWithEnvironmentFallback(config, payload, marker = null) {
1852
1859
  try {
1853
- return { response: await postManifest(config, payload), environmentUsed: config.environment };
1860
+ return {
1861
+ response: await postManifest(config, payload, marker),
1862
+ environmentUsed: config.environment
1863
+ };
1854
1864
  } catch (err) {
1855
1865
  if (config.environment !== "local" || !environmentRejected(err)) throw err;
1856
1866
  const fallback = { ...config, environment: "sandbox" };
1857
- return { response: await postManifest(fallback, payload), environmentUsed: "sandbox" };
1867
+ return { response: await postManifest(fallback, payload, marker), environmentUsed: "sandbox" };
1858
1868
  }
1859
1869
  }
1860
- async function postManifest(config, payload) {
1870
+ async function postManifest(config, payload, marker = null) {
1861
1871
  const url = buildEndpointUrl(config.endpoint, config.siteUuid);
1862
1872
  const timeoutMs = config.timeoutMs;
1863
1873
  assertConnectableEndpoint(config, url);
@@ -1871,7 +1881,7 @@ async function postManifest(config, payload) {
1871
1881
  "User-Agent": "@patchstack/connect",
1872
1882
  ...claimTokenHeader(config)
1873
1883
  },
1874
- body: JSON.stringify(buildManifestBody(config, payload)),
1884
+ body: JSON.stringify(buildManifestBody(config, payload, process.env, marker)),
1875
1885
  signal: AbortSignal.timeout(timeoutMs)
1876
1886
  });
1877
1887
  } catch (cause) {
@@ -2287,16 +2297,21 @@ function inferEnvironment(env = process.env, builder = null) {
2287
2297
  for (const discriminator of DISCRIMINATORS) {
2288
2298
  const verdict = discriminator.read(env);
2289
2299
  if (verdict !== null) {
2290
- return { environment: verdict.environment, evidence: [`${discriminator.platform}: ${verdict.evidence}`] };
2300
+ return {
2301
+ environment: verdict.environment,
2302
+ evidence: [`${discriminator.platform}: ${verdict.evidence}`],
2303
+ source: "platform"
2304
+ };
2291
2305
  }
2292
2306
  }
2293
2307
  if (builder !== null) {
2294
2308
  return {
2295
2309
  environment: "production",
2296
- evidence: [`${builder}: a build in a ${builder} project is its publish step`]
2310
+ evidence: [`${builder}: a build in a ${builder} project is its publish step`],
2311
+ source: "builder"
2297
2312
  };
2298
2313
  }
2299
- return { environment: "local", evidence: [] };
2314
+ return { environment: "local", evidence: [], source: null };
2300
2315
  }
2301
2316
 
2302
2317
  // src/site-url.ts
@@ -2515,6 +2530,7 @@ async function resolveConfig(options) {
2515
2530
  const inferred = environmentRaw === void 0 ? inferEnvironment(process.env, detectHostedBuilder(options.cwd)) : null;
2516
2531
  const environment = environmentRaw ?? inferred.environment;
2517
2532
  const environmentEvidence = inferred?.evidence ?? [];
2533
+ const environmentSource = environmentRaw !== void 0 ? "override" : inferred.source;
2518
2534
  if (siteUuid !== null && siteUuid.length > 0 && !isCanonicalUuid(siteUuid)) {
2519
2535
  throw new PatchstackError(
2520
2536
  `Site UUID "${siteUuid}" does not look like a valid UUID.`,
@@ -2542,6 +2558,7 @@ async function resolveConfig(options) {
2542
2558
  timeoutMs,
2543
2559
  environment,
2544
2560
  environmentEvidence,
2561
+ environmentSource,
2545
2562
  widget: fromFile.widget !== false,
2546
2563
  claimToken
2547
2564
  };
@@ -5838,6 +5855,8 @@ function renderGuideChecklist(state, useColor) {
5838
5855
  lines.push(detail("Run \u2192 npx @patchstack/connect scan"));
5839
5856
  lines.push(detail("Reads the lockfile, registers the project, writes .patchstackrc.json,"));
5840
5857
  lines.push(detail("and prints a dashboard link. The CLI prints the link but never opens it."));
5858
+ lines.push(detail("If your tool refuses to run this command, hand it to the person instead of working"));
5859
+ lines.push(detail('around it \u2014 see "When your tool will not run this CLI" in the reference guide.'));
5841
5860
  }
5842
5861
  if (state.installScanWired) {
5843
5862
  lines.push(done("Dependency-install scan wired (postinstall)"));
@@ -10041,17 +10060,36 @@ function readBuildScript(cwd) {
10041
10060
  return void 0;
10042
10061
  }
10043
10062
  }
10063
+ var REPORT_TIMEOUT_MS = 1e4;
10064
+ async function reportBuildStamp(config, payload, marker) {
10065
+ if (config === null || payload === null || config.siteUuid === null || config.siteUuid === "") {
10066
+ return;
10067
+ }
10068
+ try {
10069
+ const bounded = {
10070
+ ...config,
10071
+ timeoutMs: Math.min(config.timeoutMs, REPORT_TIMEOUT_MS)
10072
+ };
10073
+ await postManifestWithEnvironmentFallback(bounded, payload, marker);
10074
+ } catch (err) {
10075
+ console.warn(
10076
+ `mark-build: this build was not reported to Patchstack (${err.message}). The pages were still marked as described above.`
10077
+ );
10078
+ }
10079
+ }
10044
10080
  async function runMarkBuild(args) {
10045
10081
  const cwd = process.cwd();
10046
10082
  const startedAt = Date.now();
10047
10083
  let checksum = null;
10048
10084
  let stack = null;
10085
+ let wirePayload = null;
10049
10086
  try {
10050
10087
  const manifest = await scanLockfile(cwd);
10051
10088
  for (const warning of manifest.warnings ?? []) {
10052
10089
  console.warn(`mark-build: ${warning}`);
10053
10090
  }
10054
10091
  const { payload } = buildWirePayload(manifest);
10092
+ wirePayload = payload;
10055
10093
  checksum = computeManifestChecksum(payload.packages);
10056
10094
  stack = detectStack(payload.packages);
10057
10095
  } catch (err) {
@@ -10059,11 +10097,12 @@ async function runMarkBuild(args) {
10059
10097
  `mark-build: could not compute the build fingerprint (${err.message}). Stamping the production flag only.`
10060
10098
  );
10061
10099
  }
10100
+ let config = null;
10062
10101
  let widgetUuid = null;
10063
10102
  let environment = "local";
10064
10103
  let environmentEvidence = [];
10065
10104
  try {
10066
- const config = await resolveConfig({
10105
+ config = await resolveConfig({
10067
10106
  cwd,
10068
10107
  cliSiteUuid: getStringFlag(args.flags, "site-uuid")
10069
10108
  });
@@ -10079,6 +10118,7 @@ async function runMarkBuild(args) {
10079
10118
  }
10080
10119
  const forcedProduction = args.flags.get("production") === true;
10081
10120
  const published = forcedProduction || marksPublishedBuild(environment);
10121
+ const reported = config !== null && forcedProduction && config.environment !== "production" ? { ...config, environment: "production", environmentSource: "override" } : config;
10082
10122
  const buildDirOptions = { framework: stack?.framework ?? null, buildScript: readBuildScript(cwd) };
10083
10123
  const dir = resolveBuildDir(cwd, getStringFlag(args.flags, "dir"), buildDirOptions);
10084
10124
  if (dir === null) {
@@ -10089,6 +10129,7 @@ async function runMarkBuild(args) {
10089
10129
  console.warn(
10090
10130
  'mark-build: if the build writes elsewhere, set it once in package.json \u2192 "postbuild": "patchstack-connect mark-build --dir <path>".'
10091
10131
  );
10132
+ await reportBuildStamp(reported, wirePayload, "no-output");
10092
10133
  return 0;
10093
10134
  }
10094
10135
  const files = findHtmlFiles(dir);
@@ -10100,6 +10141,7 @@ async function runMarkBuild(args) {
10100
10141
  console.warn(
10101
10142
  "mark-build: add the marker to your root shell instead \u2014 run `patchstack-connect guide` for the snippet."
10102
10143
  );
10144
+ await reportBuildStamp(reported, wirePayload, "no-pages");
10103
10145
  return 0;
10104
10146
  }
10105
10147
  const staleBy = staleBuildAge(files, startedAt);
@@ -10134,6 +10176,7 @@ async function runMarkBuild(args) {
10134
10176
  console.log(
10135
10177
  `mark-build: marked ${marked} HTML file(s) in ${dir}${checksum !== null ? ` (build ${checksum})` : ""}${widgetTouched > 0 ? `, widget tag ensured in ${widgetTouched}` : ""}${stackSummary !== null ? ` [${stackSummary}]` : ""}.`
10136
10178
  );
10179
+ await reportBuildStamp(reported, wirePayload, "stamped");
10137
10180
  return 0;
10138
10181
  }
10139
10182
  const because = environmentEvidence.length > 0 ? ` (${environmentEvidence.join("; ")})` : "";
@@ -10146,6 +10189,7 @@ async function runMarkBuild(args) {
10146
10189
  console.log(
10147
10190
  "mark-build: publishing this directory by hand? Re-run with --production (or set PATCHSTACK_ENVIRONMENT=production) so the deployed pages carry it."
10148
10191
  );
10192
+ await reportBuildStamp(reported, wirePayload, "withheld");
10149
10193
  return 0;
10150
10194
  }
10151
10195
  function packageVersion() {