@patchstack/connect 0.5.10 → 0.5.12

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/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/cli.ts
4
4
  import { readFileSync as readFileSync19 } from "fs";
5
- import path17 from "path";
5
+ import path16 from "path";
6
6
  import { createRequire as createRequire2 } from "module";
7
7
 
8
8
  // src/safe-file.ts
@@ -25,9 +25,9 @@ import { dirname, isAbsolute, join, relative, resolve, sep } from "path";
25
25
  function pathError(message) {
26
26
  return Object.assign(new Error(message), { code: "EINVAL" });
27
27
  }
28
- function existingEntry(path18) {
28
+ function existingEntry(path17) {
29
29
  try {
30
- return lstatSync(path18);
30
+ return lstatSync(path17);
31
31
  } catch (error) {
32
32
  if (error.code === "ENOENT") return null;
33
33
  throw error;
@@ -1488,8 +1488,8 @@ async function readBoundedJson(response, maxBytes = MAX_CONTROL_RESPONSE_BYTES)
1488
1488
  var TOKEN_SKEW_MS = 6e4;
1489
1489
  function buildTokenUrl(manifestEndpoint) {
1490
1490
  const url = new URL(manifestEndpoint);
1491
- const path18 = url.pathname.replace(/\/$/, "");
1492
- url.pathname = path18.endsWith("/manifest") ? `${path18.slice(0, -"/manifest".length)}/token` : "/monitor/pulse/token";
1491
+ const path17 = url.pathname.replace(/\/$/, "");
1492
+ url.pathname = path17.endsWith("/manifest") ? `${path17.slice(0, -"/manifest".length)}/token` : "/monitor/pulse/token";
1493
1493
  url.search = "";
1494
1494
  url.hash = "";
1495
1495
  return url.toString();
@@ -1657,8 +1657,8 @@ function authFailureMessage(status, config) {
1657
1657
  }
1658
1658
  function buildRulesUrl(manifestEndpoint, siteUuid) {
1659
1659
  const url = new URL(manifestEndpoint);
1660
- const path18 = url.pathname.replace(/\/$/, "");
1661
- url.pathname = path18.endsWith("/manifest") ? `${path18.slice(0, -"/manifest".length)}/rules/${encodeURIComponent(siteUuid)}` : `/monitor/pulse/rules/${encodeURIComponent(siteUuid)}`;
1660
+ const path17 = url.pathname.replace(/\/$/, "");
1661
+ url.pathname = path17.endsWith("/manifest") ? `${path17.slice(0, -"/manifest".length)}/rules/${encodeURIComponent(siteUuid)}` : `/monitor/pulse/rules/${encodeURIComponent(siteUuid)}`;
1662
1662
  url.search = "";
1663
1663
  url.hash = "";
1664
1664
  return url.toString();
@@ -1673,16 +1673,16 @@ function buildSettingsUrl(endpoint, siteUuid) {
1673
1673
  }
1674
1674
  function buildPackageRemovedUrl(manifestEndpoint, siteUuid) {
1675
1675
  const url = new URL(manifestEndpoint);
1676
- const path18 = url.pathname.replace(/\/$/, "");
1677
- url.pathname = path18.endsWith("/manifest") ? `${path18.slice(0, -"/manifest".length)}/package-removed/${encodeURIComponent(siteUuid)}` : `/monitor/pulse/package-removed/${encodeURIComponent(siteUuid)}`;
1676
+ const path17 = url.pathname.replace(/\/$/, "");
1677
+ url.pathname = path17.endsWith("/manifest") ? `${path17.slice(0, -"/manifest".length)}/package-removed/${encodeURIComponent(siteUuid)}` : `/monitor/pulse/package-removed/${encodeURIComponent(siteUuid)}`;
1678
1678
  url.search = "";
1679
1679
  url.hash = "";
1680
1680
  return url.toString();
1681
1681
  }
1682
1682
  function buildInputMapUrl(manifestEndpoint, siteUuid) {
1683
1683
  const url = new URL(manifestEndpoint);
1684
- const path18 = url.pathname.replace(/\/$/, "");
1685
- url.pathname = path18.endsWith("/manifest") ? `${path18.slice(0, -"/manifest".length)}/input-map/${encodeURIComponent(siteUuid)}` : `/monitor/pulse/input-map/${encodeURIComponent(siteUuid)}`;
1684
+ const path17 = url.pathname.replace(/\/$/, "");
1685
+ url.pathname = path17.endsWith("/manifest") ? `${path17.slice(0, -"/manifest".length)}/input-map/${encodeURIComponent(siteUuid)}` : `/monitor/pulse/input-map/${encodeURIComponent(siteUuid)}`;
1686
1686
  url.search = "";
1687
1687
  url.hash = "";
1688
1688
  return url.toString();
@@ -2336,6 +2336,7 @@ function isUnpublishableHost(hostname) {
2336
2336
  if (!host.includes(".")) return true;
2337
2337
  return RESERVED_SUFFIXES.some((suffix) => host.endsWith(suffix));
2338
2338
  }
2339
+ var URL_MAX_LENGTH = 191;
2339
2340
  function normaliseSiteUrl(value) {
2340
2341
  const trimmed = (value ?? "").trim();
2341
2342
  if (trimmed === "") return null;
@@ -2349,7 +2350,7 @@ function normaliseSiteUrl(value) {
2349
2350
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
2350
2351
  if (parsed.hostname === "" || isUnpublishableHost(parsed.hostname)) return null;
2351
2352
  const origin = `${parsed.protocol}//${parsed.host}`;
2352
- return origin.length <= 191 ? origin : null;
2353
+ return origin.length <= URL_MAX_LENGTH ? origin : null;
2353
2354
  }
2354
2355
  var PRODUCTION_URL_SOURCES = [
2355
2356
  {
@@ -2678,10 +2679,10 @@ async function persistTimeout(cwd, timeoutMs) {
2678
2679
  return writeConfigFile(cwd, { ...existing, timeoutMs });
2679
2680
  }
2680
2681
  async function persistApiKey(cwd, apiKey) {
2681
- const { apiKey: _movedKey, pulseAuth: _movedPulse, ...publicConfig } = await readConfigFile(cwd);
2682
+ const { apiKey: movedKey, pulseAuth: movedPulse, ...publicConfig } = await readConfigFile(cwd);
2682
2683
  const existingSecrets = await readSecretFile(cwd);
2683
2684
  const target = await writeSecretFile(cwd, { ...existingSecrets, apiKey, pulseAuth: void 0 });
2684
- if (_movedKey !== void 0 || _movedPulse !== void 0) {
2685
+ if (movedKey !== void 0 || movedPulse !== void 0) {
2685
2686
  await writeConfigFile(cwd, publicConfig);
2686
2687
  }
2687
2688
  return target;
@@ -3082,7 +3083,7 @@ function ensureSourceMarker(cwd, shell, framework, checksum = null) {
3082
3083
  }
3083
3084
 
3084
3085
  // src/guide.ts
3085
- import { existsSync as existsSync13, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
3086
+ import { existsSync as existsSync12, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
3086
3087
  import path12 from "path";
3087
3088
 
3088
3089
  // src/architecture.ts
@@ -3460,10 +3461,10 @@ function detectDeploymentShapes(cwd, opts = {}) {
3460
3461
  boundary = realpathSync3(boundary);
3461
3462
  } catch {
3462
3463
  }
3463
- const inProject = (path18) => {
3464
+ const inProject = (path17) => {
3464
3465
  if (opts.followOutside) return true;
3465
3466
  try {
3466
- return isInside(realpathSync3(path18), boundary);
3467
+ return isInside(realpathSync3(path17), boundary);
3467
3468
  } catch {
3468
3469
  return false;
3469
3470
  }
@@ -4100,14 +4101,6 @@ var tanstackSupabaseAdapter = {
4100
4101
  // src/protect/install/adapters/next.ts
4101
4102
  import { existsSync as existsSync5 } from "fs";
4102
4103
  import { join as join7 } from "path";
4103
- function hasNextDep(cwd) {
4104
- try {
4105
- const pkg = JSON.parse(read(join7(cwd, "package.json")));
4106
- return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }.next);
4107
- } catch {
4108
- return false;
4109
- }
4110
- }
4111
4104
  function middlewareInfo(cwd) {
4112
4105
  const candidates = ["middleware.ts", "middleware.js", "src/middleware.ts", "src/middleware.js"];
4113
4106
  for (const rel of candidates) {
@@ -4117,7 +4110,7 @@ function middlewareInfo(cwd) {
4117
4110
  return { relDir: useSrc ? "src" : ".", relFile: useSrc ? "src/middleware.ts" : "middleware.ts", exists: false };
4118
4111
  }
4119
4112
  function detect2(cwd) {
4120
- return hasNextDep(cwd);
4113
+ return hasDependency(cwd, "next");
4121
4114
  }
4122
4115
  function rulesFile(relDir) {
4123
4116
  return relDir === "." ? "patchstack.rules.json" : `${relDir}/patchstack.rules.json`;
@@ -4171,9 +4164,6 @@ var nextAdapter = {
4171
4164
  verify: verify2
4172
4165
  };
4173
4166
 
4174
- // src/protect/install/adapters/sveltekit.ts
4175
- import { join as join9 } from "path";
4176
-
4177
4167
  // src/protect/install/seam.ts
4178
4168
  import { existsSync as existsSync6 } from "fs";
4179
4169
  import { join as join8, dirname as dirname3 } from "path";
@@ -4231,12 +4221,7 @@ var SPEC = {
4231
4221
  seamLabel: "SvelteKit server hook"
4232
4222
  };
4233
4223
  function detect3(cwd) {
4234
- try {
4235
- const pkg = JSON.parse(read(join9(cwd, "package.json")));
4236
- return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }["@sveltejs/kit"]);
4237
- } catch {
4238
- return false;
4239
- }
4224
+ return hasDependency(cwd, "@sveltejs/kit");
4240
4225
  }
4241
4226
  function wire3(cwd, opts) {
4242
4227
  return wireSeam(cwd, opts, SPEC);
@@ -4253,7 +4238,6 @@ var sveltekitAdapter = {
4253
4238
  };
4254
4239
 
4255
4240
  // src/protect/install/adapters/astro.ts
4256
- import { join as join10 } from "path";
4257
4241
  var SPEC2 = {
4258
4242
  templateName: "astro-middleware.ts",
4259
4243
  candidates: ["src/middleware.ts", "src/middleware.js", "src/middleware/index.ts", "src/middleware/index.js"],
@@ -4263,12 +4247,7 @@ var SPEC2 = {
4263
4247
  seamLabel: "Astro middleware"
4264
4248
  };
4265
4249
  function detect4(cwd) {
4266
- try {
4267
- const pkg = JSON.parse(read(join10(cwd, "package.json")));
4268
- return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }.astro);
4269
- } catch {
4270
- return false;
4271
- }
4250
+ return hasDependency(cwd, "astro");
4272
4251
  }
4273
4252
  function wire4(cwd, opts) {
4274
4253
  return wireSeam(cwd, opts, SPEC2);
@@ -4311,8 +4290,8 @@ var nuxtAdapter = {
4311
4290
  };
4312
4291
 
4313
4292
  // src/protect/install/find-app.ts
4314
- import { readFileSync as readFileSync8, existsSync as existsSync7, readdirSync as readdirSync3, lstatSync as lstatSync2 } from "fs";
4315
- import { join as join11, relative as relative3, dirname as dirname4 } from "path";
4293
+ import { readFileSync as readFileSync8, readdirSync as readdirSync3, lstatSync as lstatSync2 } from "fs";
4294
+ import { join as join9, relative as relative3, dirname as dirname4 } from "path";
4316
4295
  var SKIP_DIRS2 = /* @__PURE__ */ new Set([
4317
4296
  "node_modules",
4318
4297
  "patchstack",
@@ -4333,7 +4312,6 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
4333
4312
  ]);
4334
4313
  var MAX_DEPTH = 8;
4335
4314
  function findAppInstance(cwd, re) {
4336
- const root = existsSync7(join11(cwd, "src")) ? join11(cwd, "src") : cwd;
4337
4315
  const found = [];
4338
4316
  const walk2 = (dir, depth) => {
4339
4317
  if (depth > MAX_DEPTH) return;
@@ -4345,7 +4323,7 @@ function findAppInstance(cwd, re) {
4345
4323
  }
4346
4324
  for (const name of entries) {
4347
4325
  if (SKIP_DIRS2.has(name) || name.startsWith(".")) continue;
4348
- const p = join11(dir, name);
4326
+ const p = join9(dir, name);
4349
4327
  let st;
4350
4328
  try {
4351
4329
  st = lstatSync2(p);
@@ -4372,7 +4350,7 @@ function findAppInstance(cwd, re) {
4372
4350
  }
4373
4351
  }
4374
4352
  };
4375
- walk2(root, 0);
4353
+ walk2(cwd, 0);
4376
4354
  if (found.length === 0) return null;
4377
4355
  const declared = declaredEntries(cwd);
4378
4356
  const chosen = found.slice().sort((a, b) => rankEntry({ ...a, declared: declared.has(a.relPath) }, { ...b, declared: declared.has(b.relPath) }))[0];
@@ -4404,7 +4382,7 @@ function declaredEntries(cwd) {
4404
4382
  const paths = /* @__PURE__ */ new Set();
4405
4383
  let pkg;
4406
4384
  try {
4407
- pkg = JSON.parse(readFileSync8(join11(cwd, "package.json"), "utf8"));
4385
+ pkg = JSON.parse(readFileSync8(join9(cwd, "package.json"), "utf8"));
4408
4386
  } catch {
4409
4387
  return paths;
4410
4388
  }
@@ -4430,17 +4408,17 @@ function importSpecifier(fromRel, toRel, preserveExtension = false) {
4430
4408
  }
4431
4409
 
4432
4410
  // src/protect/install/register.ts
4433
- import { existsSync as existsSync10 } from "fs";
4434
- import { join as join14, resolve as resolve3 } from "path";
4411
+ import { existsSync as existsSync9 } from "fs";
4412
+ import { join as join12, resolve as resolve3 } from "path";
4435
4413
 
4436
4414
  // src/protect/install/generic.ts
4437
- import { readFileSync as readFileSync9, existsSync as existsSync9, readdirSync as readdirSync4, lstatSync as lstatSync3 } from "fs";
4438
- import { join as join13, dirname as dirname6 } from "path";
4415
+ import { readFileSync as readFileSync9, existsSync as existsSync8, readdirSync as readdirSync4, lstatSync as lstatSync3 } from "fs";
4416
+ import { join as join11, dirname as dirname6 } from "path";
4439
4417
 
4440
4418
  // src/protect/install/source-scope.ts
4441
4419
  import { execFileSync } from "child_process";
4442
- import { existsSync as existsSync8 } from "fs";
4443
- import { dirname as dirname5, join as join12, resolve as resolve2 } from "path";
4420
+ import { existsSync as existsSync7 } from "fs";
4421
+ import { dirname as dirname5, join as join10, resolve as resolve2 } from "path";
4444
4422
 
4445
4423
  // src/protect/install/node-flags.ts
4446
4424
  var flagName = (token) => token.split("=")[0];
@@ -4730,8 +4708,8 @@ function moduleKindOf(filePath, packageIsModule) {
4730
4708
  }
4731
4709
  function resolvesToGuardModule(specifier, query) {
4732
4710
  const resolved = resolve2(dirname5(query.fromFile), specifier);
4733
- if (withoutModuleExtension(resolved) !== join12(query.guardDir, "guard")) return false;
4734
- const existing = GUARD_FILENAMES.filter((name) => existsSync8(join12(query.guardDir, name)));
4711
+ if (withoutModuleExtension(resolved) !== join10(query.guardDir, "guard")) return false;
4712
+ const existing = GUARD_FILENAMES.filter((name) => existsSync7(join10(query.guardDir, name)));
4735
4713
  if (existing.length === 0) return false;
4736
4714
  const extension = /(\.[A-Za-z0-9]+)$/.exec(specifier)?.[1] ?? "";
4737
4715
  if (!query.strictExtensions) return true;
@@ -4740,7 +4718,7 @@ function resolvesToGuardModule(specifier, query) {
4740
4718
  if (query.kind === "cjs") return existing.includes("guard.js");
4741
4719
  return true;
4742
4720
  }
4743
- if (existsSync8(resolved)) return true;
4721
+ if (existsSync7(resolved)) return true;
4744
4722
  return query.kind === "ts" && extension === ".js" && existing.includes("guard.ts");
4745
4723
  }
4746
4724
  function withoutModuleExtension(filePath) {
@@ -4750,16 +4728,16 @@ function withoutModuleExtension(filePath) {
4750
4728
  // src/protect/install/generic.ts
4751
4729
  function packageIsEsm(cwd) {
4752
4730
  try {
4753
- return JSON.parse(read(join13(cwd, "package.json"))).type === "module";
4731
+ return JSON.parse(read(join11(cwd, "package.json"))).type === "module";
4754
4732
  } catch {
4755
4733
  return false;
4756
4734
  }
4757
4735
  }
4758
4736
  function genericDir(cwd) {
4759
- return existsSync9(join13(cwd, "src")) ? "src/patchstack" : "patchstack";
4737
+ return existsSync8(join11(cwd, "src")) ? "src/patchstack" : "patchstack";
4760
4738
  }
4761
4739
  function hasTypeScript(cwd) {
4762
- return existsSync9(join13(cwd, "tsconfig.json")) || candidateEntries(cwd).some((entry) => /\.tsx?$/.test(entry));
4740
+ return existsSync8(join11(cwd, "tsconfig.json")) || candidateEntries(cwd).some((entry) => /\.tsx?$/.test(entry));
4763
4741
  }
4764
4742
  function genericGuardTarget(cwd) {
4765
4743
  if (hasTypeScript(cwd)) {
@@ -4773,7 +4751,7 @@ function genericGuardTarget(cwd) {
4773
4751
  function genericScaffoldFiles(cwd) {
4774
4752
  const dir = genericDir(cwd);
4775
4753
  const candidates = ["guard.ts", "guard.js", "guard.cjs", "rules.json"];
4776
- return candidates.map((file) => `${dir}/${file}`).filter((relative8) => existsSync9(join13(cwd, relative8)));
4754
+ return candidates.map((file) => `${dir}/${file}`).filter((relative8) => existsSync8(join11(cwd, relative8)));
4777
4755
  }
4778
4756
  function scaffoldGeneric(cwd, opts, guardTemplate, guardFile) {
4779
4757
  const target = genericGuardTarget(cwd);
@@ -4781,15 +4759,15 @@ function scaffoldGeneric(cwd, opts, guardTemplate, guardFile) {
4781
4759
  guardFile ??= target.file;
4782
4760
  const templates = templatesDir();
4783
4761
  const dir = genericDir(cwd);
4784
- const dst = join13(cwd, dir);
4762
+ const dst = join11(cwd, dir);
4785
4763
  ensureProjectDirectorySync(cwd, dst);
4786
- copyProjectFileSync(cwd, join13(templates, guardTemplate), join13(dst, guardFile));
4764
+ copyProjectFileSync(cwd, join11(templates, guardTemplate), join11(dst, guardFile));
4787
4765
  const guardRel = `${dir}/${guardFile}`;
4788
4766
  const changed = [guardRel];
4789
4767
  if (!opts.demo) bakeSiteUuid(cwd, guardRel);
4790
- const rulesDst = join13(dst, "rules.json");
4791
- if (opts.demo || !existsSync9(rulesDst)) {
4792
- copyProjectFileSync(cwd, join13(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
4768
+ const rulesDst = join11(dst, "rules.json");
4769
+ if (opts.demo || !existsSync8(rulesDst)) {
4770
+ copyProjectFileSync(cwd, join11(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
4793
4771
  changed.push(`${dir}/rules.json`);
4794
4772
  }
4795
4773
  return { changed, dir };
@@ -4810,25 +4788,17 @@ function candidateEntries(cwd) {
4810
4788
  "app.ts",
4811
4789
  "app.js"
4812
4790
  ];
4813
- const hits = names.filter((n) => existsSync9(join13(cwd, n)));
4791
+ const hits = names.filter((n) => existsSync8(join11(cwd, n)));
4814
4792
  try {
4815
- const pkg = JSON.parse(read(join13(cwd, "package.json")));
4816
- if (typeof pkg.main === "string" && existsSync9(join13(cwd, pkg.main))) hits.push(pkg.main);
4793
+ const pkg = JSON.parse(read(join11(cwd, "package.json")));
4794
+ if (typeof pkg.main === "string" && existsSync8(join11(cwd, pkg.main))) hits.push(pkg.main);
4817
4795
  } catch {
4818
4796
  }
4819
4797
  return [...new Set(hits)];
4820
4798
  }
4821
- function usesExpress(cwd) {
4822
- try {
4823
- const pkg = JSON.parse(read(join13(cwd, "package.json")));
4824
- return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }.express);
4825
- } catch {
4826
- return false;
4827
- }
4828
- }
4829
4799
  function wiringPlan(cwd, dir) {
4830
4800
  const entries = candidateEntries(cwd);
4831
- const express = usesExpress(cwd);
4801
+ const express = hasDependency(cwd, "express");
4832
4802
  const target = genericGuardTarget(cwd);
4833
4803
  const lines = [
4834
4804
  `no built-in adapter matched this stack \u2014 scaffolded a generic guard at ${dir}/${target.file} + ${dir}/rules.json.`,
@@ -4924,9 +4894,9 @@ function escapeForRegExp(value) {
4924
4894
  function genericVerify(cwd) {
4925
4895
  const dir = genericDir(cwd);
4926
4896
  const target = genericGuardTarget(cwd);
4927
- const present2 = GUARD_FILENAMES.find((name) => existsSync9(join13(cwd, dir, name)));
4897
+ const present2 = GUARD_FILENAMES.find((name) => existsSync8(join11(cwd, dir, name)));
4928
4898
  const scaffolded = present2 !== void 0;
4929
- const imported = scaffolded && guardIsImported(cwd, join13(cwd, dir, present2));
4899
+ const imported = scaffolded && guardIsImported(cwd, join11(cwd, dir, present2));
4930
4900
  return {
4931
4901
  wired: scaffolded && imported,
4932
4902
  checks: [
@@ -4962,7 +4932,7 @@ var NON_RUNTIME_DIRS = /* @__PURE__ */ new Set([
4962
4932
  function guardIsImported(cwd, guardPath) {
4963
4933
  const guardDir = dirname6(guardPath);
4964
4934
  const packageIsModule = packageIsEsm(cwd);
4965
- const root = existsSync9(join13(cwd, "src")) ? join13(cwd, "src") : cwd;
4935
+ const root = existsSync8(join11(cwd, "src")) ? join11(cwd, "src") : cwd;
4966
4936
  let found = false;
4967
4937
  const walk2 = (d, depth) => {
4968
4938
  if (found || depth > 8) return;
@@ -4975,7 +4945,7 @@ function guardIsImported(cwd, guardPath) {
4975
4945
  for (const name of entries) {
4976
4946
  if (found) return;
4977
4947
  if (NON_RUNTIME_DIRS.has(name) || name.startsWith(".")) continue;
4978
- const p = join13(d, name);
4948
+ const p = join11(d, name);
4979
4949
  let st;
4980
4950
  try {
4981
4951
  st = lstatSync3(p);
@@ -5034,7 +5004,7 @@ function guardTarget(cwd, entryRel, spec) {
5034
5004
  }
5035
5005
  function packageType(cwd) {
5036
5006
  try {
5037
- return JSON.parse(read(join14(cwd, "package.json"))).type;
5007
+ return JSON.parse(read(join12(cwd, "package.json"))).type;
5038
5008
  } catch {
5039
5009
  return void 0;
5040
5010
  }
@@ -5070,8 +5040,8 @@ function bindsGuard(line, maskedLine, importName, call, fileRel, guard) {
5070
5040
  }
5071
5041
  function namesGuardModule(specifier, fileRel, guard) {
5072
5042
  return resolvesToGuardModule(specifier, {
5073
- fromFile: join14(guard.cwd, fileRel),
5074
- guardDir: resolve3(join14(guard.cwd, guard.guardDir)),
5043
+ fromFile: join12(guard.cwd, fileRel),
5044
+ guardDir: resolve3(join12(guard.cwd, guard.guardDir)),
5075
5045
  kind: moduleKindOf(fileRel, packageType(guard.cwd) === "module"),
5076
5046
  strictExtensions: true
5077
5047
  });
@@ -5090,7 +5060,7 @@ function wireRegister(cwd, opts, spec) {
5090
5060
  }
5091
5061
  const target = guardTarget(cwd, entry.relPath, spec);
5092
5062
  const { changed, dir } = scaffoldGeneric(cwd, opts, target.template, target.file);
5093
- const p = join14(cwd, entry.relPath);
5063
+ const p = join12(cwd, entry.relPath);
5094
5064
  const s = read(p);
5095
5065
  const state = wiringState(s, spec, entry.appVar, entry.relPath, { cwd, guardDir: dir });
5096
5066
  if (state.importAtTopLevel && state.callInAppScope) {
@@ -5160,17 +5130,17 @@ function firstStatementLine(lines) {
5160
5130
  return i;
5161
5131
  }
5162
5132
  function serverIsGuarded(cwd, spec, server, guardDir) {
5163
- const source = read(join14(cwd, server.relPath));
5133
+ const source = read(join12(cwd, server.relPath));
5164
5134
  const state = wiringState(source, spec, server.appVar, server.relPath, { cwd, guardDir });
5165
5135
  if (!state.importAtTopLevel || !state.callInAppScope || !state.ordered) return false;
5166
5136
  return !spec.callAfter || routesBefore(source, server.appVar, state.callIndex).length === 0;
5167
5137
  }
5168
5138
  function verifyRegister(cwd, spec) {
5169
- const dir = existsSync10(join14(cwd, "src")) ? "src/patchstack" : "patchstack";
5139
+ const dir = existsSync9(join12(cwd, "src")) ? "src/patchstack" : "patchstack";
5170
5140
  const entry = findAppInstance(cwd, spec.appRe);
5171
5141
  const target = entry ? guardTarget(cwd, entry.relPath, spec) : null;
5172
- const scaffolded = target ? existsSync10(join14(cwd, dir, target.file)) : false;
5173
- const entrySource = entry ? read(join14(cwd, entry.relPath)) : "";
5142
+ const scaffolded = target ? existsSync9(join12(cwd, dir, target.file)) : false;
5143
+ const entrySource = entry ? read(join12(cwd, entry.relPath)) : "";
5174
5144
  const state = entry ? wiringState(entrySource, spec, entry.appVar, entry.relPath, { cwd, guardDir: dir }) : { importAtTopLevel: false, callInAppScope: false, ordered: false, callIndex: -1, appIndex: -1 };
5175
5145
  const wired = state.importAtTopLevel && state.callInAppScope && state.ordered;
5176
5146
  const early = spec.callAfter && entry ? routesBefore(entrySource, entry.appVar, state.callIndex) : [];
@@ -5260,8 +5230,8 @@ var expressAdapter = {
5260
5230
  };
5261
5231
 
5262
5232
  // src/protect/install/reporting.ts
5263
- import { existsSync as existsSync11 } from "fs";
5264
- import { join as join15 } from "path";
5233
+ import { existsSync as existsSync10 } from "fs";
5234
+ import { join as join13 } from "path";
5265
5235
 
5266
5236
  // src/protect/reporting-state.js
5267
5237
  var REPORTING_STATES = Object.freeze([
@@ -5319,9 +5289,9 @@ function explainReportingState(state) {
5319
5289
 
5320
5290
  // src/protect/install/reporting.ts
5321
5291
  function siteIdentity(cwd, env) {
5322
- const rc = join15(cwd, ".patchstackrc.json");
5292
+ const rc = join13(cwd, ".patchstackrc.json");
5323
5293
  let recorded;
5324
- if (existsSync11(rc)) {
5294
+ if (existsSync10(rc)) {
5325
5295
  try {
5326
5296
  recorded = JSON.parse(read(rc)).siteUuid;
5327
5297
  } catch {
@@ -5470,7 +5440,7 @@ function runVerify(cwd) {
5470
5440
  }
5471
5441
 
5472
5442
  // src/widget.ts
5473
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
5443
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
5474
5444
  import path11 from "path";
5475
5445
  var WIDGET_SCRIPT_URL = "https://cdn.patchstack.com/patchstack-widget.js";
5476
5446
  var WIDGET_MARKER_ATTR = "data-patchstack-connect-widget";
@@ -5509,7 +5479,7 @@ ${indent}</body>`;
5509
5479
  }
5510
5480
  function findSourceShell(cwd) {
5511
5481
  for (const candidate of SOURCE_SHELL_CANDIDATES) {
5512
- if (existsSync12(path11.join(cwd, candidate))) {
5482
+ if (existsSync11(path11.join(cwd, candidate))) {
5513
5483
  return candidate;
5514
5484
  }
5515
5485
  }
@@ -5521,7 +5491,7 @@ function ensureSourceWidget(cwd, siteUuid, jsxShell = null) {
5521
5491
  return { shell: null, action: "no-shell" };
5522
5492
  }
5523
5493
  const file = path11.join(cwd, shell);
5524
- if (!existsSync12(file)) {
5494
+ if (!existsSync11(file)) {
5525
5495
  return { shell: null, action: "no-shell" };
5526
5496
  }
5527
5497
  const before = readFileSync10(file, "utf8");
@@ -5606,7 +5576,7 @@ function detectPackageManager(cwd) {
5606
5576
  return declared;
5607
5577
  }
5608
5578
  for (const { filename, pm } of PM_BY_LOCKFILE) {
5609
- if (existsSync13(path12.join(cwd, filename))) {
5579
+ if (existsSync12(path12.join(cwd, filename))) {
5610
5580
  return pm;
5611
5581
  }
5612
5582
  }
@@ -5703,7 +5673,7 @@ function resolveWidgetFileHint(cwd, framework) {
5703
5673
  ...GENERIC_WIDGET_FILES
5704
5674
  ];
5705
5675
  for (const candidate of candidates) {
5706
- if (existsSync13(path12.join(cwd, candidate))) {
5676
+ if (existsSync12(path12.join(cwd, candidate))) {
5707
5677
  return candidate;
5708
5678
  }
5709
5679
  }
@@ -5823,7 +5793,11 @@ function renderGuideChecklist(state, useColor) {
5823
5793
  lines.push("");
5824
5794
  if (!state.hasPackageJson) {
5825
5795
  lines.push(todo("No package.json found in this directory."));
5826
- lines.push(detail("Run the guide from the project root."));
5796
+ lines.push(detail("For a JS/Node app, run the guide from its package directory; check that package.json is readable and valid."));
5797
+ lines.push(detail("For a standalone HTML/CSS/browser-JavaScript site, use the disclosure widget directly."));
5798
+ lines.push(detail("Do not create a Node project, build hooks, or a server just to install the widget."));
5799
+ lines.push(detail("Use the correct site UUID or widget snippet from the Patchstack dashboard; never invent one."));
5800
+ lines.push(detail('See "Plain HTML sites" in AGENT-INSTALL.md. Widget-only setup provides no dependency scan or runtime protection.'));
5827
5801
  return lines.join("\n");
5828
5802
  }
5829
5803
  if (countRemainingSteps(state) > 0) {
@@ -5835,6 +5809,17 @@ function renderGuideChecklist(state, useColor) {
5835
5809
  lines.push(" Avoid lockfile / dependency / manifest / npm / UUID when speaking to them.");
5836
5810
  lines.push("");
5837
5811
  }
5812
+ if (state.siteUuid === null) {
5813
+ lines.push(` ${paint(ANSI.cyan, "\u279C")} ${paint(ANSI.bold, "Nothing is set up yet \u2014 two commands cover the steps below:")}`);
5814
+ if (state.installed?.section !== "dependencies") {
5815
+ lines.push(` ${installCommand(state.packageManager)}`);
5816
+ }
5817
+ lines.push(" npx @patchstack/connect setup");
5818
+ lines.push(" setup provisions the site, adds the widget, installs and verifies runtime protection,");
5819
+ lines.push(" and wires the install and build scans, then prints this checklist again. Anything");
5820
+ lines.push(" still listed there is a step setup could not apply safely, and is yours to finish.");
5821
+ lines.push("");
5822
+ }
5838
5823
  if (state.installed?.section === "dependencies") {
5839
5824
  lines.push(done(`@patchstack/connect installed (${state.installed.version}, ${state.installed.section})`));
5840
5825
  } else if (state.installed !== null) {
@@ -5945,11 +5930,19 @@ function renderGuideChecklist(state, useColor) {
5945
5930
  }
5946
5931
  lines.push("");
5947
5932
  if (state.claimUrl !== null) {
5948
- lines.push(` ${paint(ANSI.cyan, "\u279C")} ${paint(ANSI.bold, "Dashboard link (open to view reports):")}`);
5949
- lines.push(` ${paint(ANSI.cyan, state.claimUrl)}`);
5950
- lines.push(detail("Open this link in a browser. The CLI never opens it."));
5951
- lines.push(detail("Or from this terminal \u2192 npx @patchstack/connect claim"));
5952
- lines.push(detail(" (prints a link to sign in with, then attaches the site to that account)"));
5933
+ lines.push(` ${paint(ANSI.cyan, "\u279C")} ${paint(ANSI.bold, "Connect this site to your Patchstack account:")}`);
5934
+ let route = 1;
5935
+ if (widgetTagInPlace(state)) {
5936
+ lines.push(` ${route++}. In the preview \u2014 while the site is unclaimed the widget shows a`);
5937
+ lines.push(' "Connect this website" panel. Signing in there attaches the site.');
5938
+ }
5939
+ lines.push(` ${route++}. In a browser \u2014 open the dashboard link (the CLI never opens it):`);
5940
+ lines.push(` ${paint(ANSI.cyan, state.claimUrl)}`);
5941
+ lines.push(` ${route}. From this terminal \u2192 npx @patchstack/connect claim`);
5942
+ lines.push(" (prints a link to sign in with, then attaches the site to that account)");
5943
+ lines.push(detail("Reports have no owner to reach until one of these completes. The site UUID ships"));
5944
+ lines.push(detail("in the page and claiming is first-come, so an unclaimed site stays claimable by"));
5945
+ lines.push(detail("anyone who loads it."));
5953
5946
  if (state.endpointOverride !== null) {
5954
5947
  lines.push(detail("(this URL inherits the endpoint override above)"));
5955
5948
  }
@@ -5959,9 +5952,11 @@ function renderGuideChecklist(state, useColor) {
5959
5952
  if (widgetTagInPlace(state)) {
5960
5953
  lines.push("");
5961
5954
  lines.push(` ${paint(ANSI.cyan, "\u279C")} ${paint(ANSI.bold, "Refresh the preview to see the widget:")}`);
5962
- lines.push(' The "Report a vulnerability" button loads with the page, so a preview that was');
5963
- lines.push(" already open still shows the HTML from before this change. Builders that hot");
5964
- lines.push(" reload refresh it themselves; if the button is missing, refresh the preview once.");
5955
+ lines.push(" The widget loads with the page, so a preview that was already open still shows");
5956
+ lines.push(" the HTML from before this change. Builders that hot reload refresh it themselves;");
5957
+ lines.push(" if nothing appears, refresh the preview once.");
5958
+ lines.push(' Unclaimed, the widget shows the "Connect this website" panel; the public');
5959
+ lines.push(' "Report a vulnerability" button takes its place once the site is claimed.');
5965
5960
  }
5966
5961
  if (state.siteUuid !== null) {
5967
5962
  lines.push("");
@@ -5991,11 +5986,6 @@ function renderGuideChecklist(state, useColor) {
5991
5986
  return lines.join("\n");
5992
5987
  }
5993
5988
 
5994
- // src/login.ts
5995
- import { mkdtempSync } from "fs";
5996
- import { tmpdir as tmpdir2 } from "os";
5997
- import path14 from "path";
5998
-
5999
5989
  // src/device-flow.ts
6000
5990
  import {
6001
5991
  closeSync as closeSync2,
@@ -6295,8 +6285,8 @@ async function claim2(config, onPrompt, deps = {}) {
6295
6285
  import { relative as relative4 } from "path";
6296
6286
 
6297
6287
  // src/protect/install/runtime/entry.ts
6298
- import { existsSync as existsSync14, readFileSync as readFileSync13, realpathSync as realpathSync4, statSync as statSync6 } from "fs";
6299
- import { join as join16, resolve as resolve4, sep as sep2 } from "path";
6288
+ import { existsSync as existsSync13, readFileSync as readFileSync13, realpathSync as realpathSync4, statSync as statSync6 } from "fs";
6289
+ import { join as join14, resolve as resolve4, sep as sep2 } from "path";
6300
6290
  var CONVENTIONAL = [
6301
6291
  "server.js",
6302
6292
  "server.mjs",
@@ -6322,15 +6312,15 @@ var CONVENTIONAL = [
6322
6312
  var LOADABLE = /\.(?:js|mjs|cjs)$/;
6323
6313
  function readPackage2(cwd) {
6324
6314
  try {
6325
- const parsed = JSON.parse(readFileSync13(join16(cwd, "package.json"), "utf8"));
6315
+ const parsed = JSON.parse(readFileSync13(join14(cwd, "package.json"), "utf8"));
6326
6316
  return parsed !== null && typeof parsed === "object" ? parsed : null;
6327
6317
  } catch {
6328
6318
  return null;
6329
6319
  }
6330
6320
  }
6331
- function isFile(path18) {
6321
+ function isFile(path17) {
6332
6322
  try {
6333
- return statSync6(path18).isFile();
6323
+ return statSync6(path17).isFile();
6334
6324
  } catch {
6335
6325
  return false;
6336
6326
  }
@@ -6339,14 +6329,14 @@ function loadable(cwd, candidate) {
6339
6329
  const written = resolve4(cwd, candidate);
6340
6330
  if (!LOADABLE.test(written) || !isFile(written)) return null;
6341
6331
  let root;
6342
- let path18;
6332
+ let path17;
6343
6333
  try {
6344
6334
  root = realpathSync4(cwd);
6345
- path18 = realpathSync4(written);
6335
+ path17 = realpathSync4(written);
6346
6336
  } catch {
6347
6337
  return null;
6348
6338
  }
6349
- if (path18 !== root && !path18.startsWith(root + sep2)) return null;
6339
+ if (path17 !== root && !path17.startsWith(root + sep2)) return null;
6350
6340
  return written;
6351
6341
  }
6352
6342
  function passable(token) {
@@ -6392,14 +6382,14 @@ function resolveEntry(cwd) {
6392
6382
  }
6393
6383
  return {
6394
6384
  kind: "unavailable",
6395
- reason: existsSync14(join16(cwd, "package.json")) ? 'no directly loadable entry was found \u2014 declare one as a "start" script of the form `node <file>`, or run the check against a built output' : "there is no package.json here"
6385
+ reason: existsSync13(join14(cwd, "package.json")) ? 'no directly loadable entry was found \u2014 declare one as a "start" script of the form `node <file>`, or run the check against a built output' : "there is no package.json here"
6396
6386
  };
6397
6387
  }
6398
6388
 
6399
6389
  // src/protect/install/runtime/probe.ts
6400
6390
  import { spawn } from "child_process";
6401
6391
  import { createHash as createHash3, randomBytes } from "crypto";
6402
- import { existsSync as existsSync15 } from "fs";
6392
+ import { existsSync as existsSync14 } from "fs";
6403
6393
  import { request as httpRequest } from "http";
6404
6394
  import { request as httpsRequest, Agent as HttpsAgent } from "https";
6405
6395
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -6426,8 +6416,8 @@ function preloadPath() {
6426
6416
  // beside this file, in the repository
6427
6417
  ];
6428
6418
  for (const candidate of candidates) {
6429
- const path18 = fileURLToPath2(candidate);
6430
- if (existsSync15(path18)) return path18;
6419
+ const path17 = fileURLToPath2(candidate);
6420
+ if (existsSync14(path17)) return path17;
6431
6421
  }
6432
6422
  return null;
6433
6423
  }
@@ -6774,15 +6764,15 @@ function formatRuntimeCheck(report) {
6774
6764
  }
6775
6765
 
6776
6766
  // src/map-command.ts
6777
- import path15 from "path";
6767
+ import path14 from "path";
6778
6768
 
6779
6769
  // src/map/ts-loader.ts
6780
6770
  import { createRequire } from "module";
6781
6771
  import { pathToFileURL } from "url";
6782
- import { join as join17 } from "path";
6772
+ import { join as join15 } from "path";
6783
6773
  async function loadTypeScript(cwd) {
6784
6774
  try {
6785
- const req = createRequire(pathToFileURL(join17(cwd, "package.json")));
6775
+ const req = createRequire(pathToFileURL(join15(cwd, "package.json")));
6786
6776
  const resolved = req.resolve("typescript");
6787
6777
  const mod = await import(pathToFileURL(resolved).href);
6788
6778
  return mod.default ?? mod;
@@ -7212,7 +7202,7 @@ function dedupeSinks(sinks, owner) {
7212
7202
 
7213
7203
  // src/map/module-graph.ts
7214
7204
  import { readFileSync as readFileSync14, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
7215
- import { dirname as dirname8, join as join18, relative as relative5, resolve as resolvePath } from "path";
7205
+ import { dirname as dirname8, join as join16, relative as relative5, resolve as resolvePath } from "path";
7216
7206
  var RESOLVE_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
7217
7207
  function createModuleGraph(ts, opts) {
7218
7208
  const cache = /* @__PURE__ */ new Map();
@@ -7290,7 +7280,7 @@ function resolveRelativeModule(fromFile, spec) {
7290
7280
  }
7291
7281
  candidates.push(base);
7292
7282
  for (const e of RESOLVE_EXTS) candidates.push(base + e);
7293
- for (const e of RESOLVE_EXTS) candidates.push(join18(base, "index" + e));
7283
+ for (const e of RESOLVE_EXTS) candidates.push(join16(base, "index" + e));
7294
7284
  for (const c of candidates) {
7295
7285
  try {
7296
7286
  if (statSync7(c).isFile()) return c;
@@ -7319,8 +7309,8 @@ function collectCallees(sf, ts) {
7319
7309
  }
7320
7310
 
7321
7311
  // src/map/coordinates.ts
7322
- function runtimeCoordinate(source, path18) {
7323
- if (/\[\d*\]/.test(path18)) {
7312
+ function runtimeCoordinate(source, path17) {
7313
+ if (/\[\d*\]/.test(path17)) {
7324
7314
  return { runtimeParameter: null, runtimeParameterReason: "array traversal: needs an array_key_value rule, not a dotted parameter" };
7325
7315
  }
7326
7316
  switch (source) {
@@ -7329,15 +7319,15 @@ function runtimeCoordinate(source, path18) {
7329
7319
  case "multipart":
7330
7320
  case "body":
7331
7321
  case "server-fn-data":
7332
- return { runtimeParameter: `post.${path18}` };
7322
+ return { runtimeParameter: `post.${path17}` };
7333
7323
  case "query":
7334
- return { runtimeParameter: `get.${path18}` };
7324
+ return { runtimeParameter: `get.${path17}` };
7335
7325
  case "cookie":
7336
- return { runtimeParameter: `cookie.${path18}` };
7326
+ return { runtimeParameter: `cookie.${path17}` };
7337
7327
  case "file":
7338
- return { runtimeParameter: `files.${path18}` };
7328
+ return { runtimeParameter: `files.${path17}` };
7339
7329
  case "header":
7340
- return { runtimeParameter: `server.HTTP_${path18.toUpperCase().replace(/-/g, "_")}` };
7330
+ return { runtimeParameter: `server.HTTP_${path17.toUpperCase().replace(/-/g, "_")}` };
7341
7331
  case "route-param":
7342
7332
  return { runtimeParameter: null, runtimeParameterReason: "route parameters are not exposed by the runtime resolver" };
7343
7333
  default:
@@ -7369,8 +7359,8 @@ function addressSpaceOf(source) {
7369
7359
  function isProvenFlow(confidence) {
7370
7360
  return confidence === "exact-local" || confidence === "transformed-local";
7371
7361
  }
7372
- function inputIdOf(source, path18) {
7373
- return `${addressSpaceOf(source)}:${path18}`;
7362
+ function inputIdOf(source, path17) {
7363
+ return `${addressSpaceOf(source)}:${path17}`;
7374
7364
  }
7375
7365
  function withCoordinates(fields, source) {
7376
7366
  return fields.map((f) => {
@@ -7588,8 +7578,8 @@ function linkFlows(bodyNode, params, inputs, sinks, ts, invocations) {
7588
7578
  }
7589
7579
  const CONTAINER_KEYS = /* @__PURE__ */ new Set([...REQ_SOURCES, "data", "input", "payload"]);
7590
7580
  const rootPath = /* @__PURE__ */ new Map();
7591
- const addRoot = (name, path18, space) => {
7592
- if (!rootPath.has(name)) rootPath.set(name, { path: path18, space });
7581
+ const addRoot = (name, path17, space) => {
7582
+ if (!rootPath.has(name)) rootPath.set(name, { path: path17, space });
7593
7583
  };
7594
7584
  for (const p of params ?? []) {
7595
7585
  if (!p?.name) continue;
@@ -7784,8 +7774,8 @@ function dedupeLimitations(list) {
7784
7774
  function join22(base, seg) {
7785
7775
  return base ? `${base}.${seg}` : seg;
7786
7776
  }
7787
- function normalizePath(path18) {
7788
- return path18.replace(/\[\d*\]/g, "").split(".").filter(Boolean).join(".");
7777
+ function normalizePath(path17) {
7778
+ return path17.replace(/\[\d*\]/g, "").split(".").filter(Boolean).join(".");
7789
7779
  }
7790
7780
  function fluentChainCalls(call, ts) {
7791
7781
  let root = call;
@@ -8151,7 +8141,7 @@ function handlerEntry(name, kindLabel, params, body, ts, localSinks, bindings, c
8151
8141
 
8152
8142
  // src/map/imports.ts
8153
8143
  import { readFileSync as readFileSync15 } from "fs";
8154
- import { join as join19 } from "path";
8144
+ import { join as join17 } from "path";
8155
8145
  var MAX_SITES2 = 5;
8156
8146
  var NPM_NAME = /^(?:@[^/@\s~][^/@\s]*\/)?[^/@\s.~][^/@\s]*$/;
8157
8147
  function isNpmPackageName(pkg) {
@@ -8162,7 +8152,7 @@ function readPathAliases(cwd) {
8162
8152
  for (const name of ["tsconfig.json", "jsconfig.json"]) {
8163
8153
  let paths;
8164
8154
  try {
8165
- const raw = readFileSync15(join19(cwd, name), "utf8");
8155
+ const raw = readFileSync15(join17(cwd, name), "utf8");
8166
8156
  const parsed = JSON.parse(stripJsonComments(raw));
8167
8157
  paths = parsed.compilerOptions?.paths;
8168
8158
  } catch {
@@ -8649,7 +8639,7 @@ function getStringFlag(flags, name) {
8649
8639
 
8650
8640
  // src/build-stamp.ts
8651
8641
  import { lstatSync as lstatSync4, readFileSync as readFileSync17, readdirSync as readdirSync6, realpathSync as realpathSync7 } from "fs";
8652
- import { join as join20, relative as relative7, sep as sep3 } from "path";
8642
+ import { join as join18, relative as relative7, sep as sep3 } from "path";
8653
8643
  var RULES_FILE_NAMES = /* @__PURE__ */ new Set(["rules.json", "patchstack.rules.json"]);
8654
8644
  var SKIP_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "out", "coverage", "tmp", "vendor"]);
8655
8645
  var MAX_DEPTH2 = 6;
@@ -8667,11 +8657,11 @@ function guardImportsRulesFile(dir, rulesName) {
8667
8657
  }
8668
8658
  for (const name of siblings) {
8669
8659
  if (!GUARD_SOURCE.test(name)) continue;
8670
- const path18 = join20(dir, name);
8660
+ const path17 = join18(dir, name);
8671
8661
  try {
8672
- const entry = lstatSync4(path18);
8662
+ const entry = lstatSync4(path17);
8673
8663
  if (!entry.isFile() || entry.isSymbolicLink() || entry.size > MAX_GUARD_SOURCE_BYTES) continue;
8674
- const source = stripComments(readFileSync17(path18, "utf8"));
8664
+ const source = stripComments(readFileSync17(path17, "utf8"));
8675
8665
  if (source.includes("@patchstack/connect/protect") && importsRules.test(source)) return true;
8676
8666
  } catch {
8677
8667
  }
@@ -8692,9 +8682,9 @@ function findRulesFile(cwd) {
8692
8682
  } catch {
8693
8683
  return { kind: "none" };
8694
8684
  }
8695
- const contained = (path18) => {
8685
+ const contained = (path17) => {
8696
8686
  try {
8697
- const real = realpathSync7(path18);
8687
+ const real = realpathSync7(path17);
8698
8688
  return real === root || real.startsWith(root + sep3);
8699
8689
  } catch {
8700
8690
  return false;
@@ -8710,25 +8700,25 @@ function findRulesFile(cwd) {
8710
8700
  }
8711
8701
  for (const name of entries) {
8712
8702
  if (name.startsWith(".")) continue;
8713
- const path18 = join20(dir, name);
8703
+ const path17 = join18(dir, name);
8714
8704
  let entry;
8715
8705
  try {
8716
- entry = lstatSync4(path18);
8706
+ entry = lstatSync4(path17);
8717
8707
  } catch {
8718
8708
  continue;
8719
8709
  }
8720
8710
  if (entry.isSymbolicLink()) continue;
8721
8711
  if (entry.isDirectory()) {
8722
- if (!SKIP_DIRECTORIES.has(name)) walk2(path18, depth + 1);
8712
+ if (!SKIP_DIRECTORIES.has(name)) walk2(path17, depth + 1);
8723
8713
  continue;
8724
8714
  }
8725
8715
  if (!entry.isFile() || !RULES_FILE_NAMES.has(name)) continue;
8726
- if (!contained(path18)) continue;
8716
+ if (!contained(path17)) continue;
8727
8717
  if (!guardImportsRulesFile(dir, name)) continue;
8728
8718
  try {
8729
- if (isRuleBundle(JSON.parse(readFileSync17(path18, "utf8")))) found.push(path18);
8719
+ if (isRuleBundle(JSON.parse(readFileSync17(path17, "utf8")))) found.push(path17);
8730
8720
  } catch {
8731
- unreadable.push(path18);
8721
+ unreadable.push(path17);
8732
8722
  }
8733
8723
  }
8734
8724
  };
@@ -8920,7 +8910,7 @@ async function runMap(flags) {
8920
8910
  const json = JSON.stringify(map, null, 2);
8921
8911
  const out = getStringFlag(flags, "out");
8922
8912
  if (out) {
8923
- atomicWriteFileSync(path15.resolve(out), json, { encoding: "utf8" });
8913
+ atomicWriteFileSync(path14.resolve(out), json, { encoding: "utf8" });
8924
8914
  console.error(`patchstack: wrote ${out}`);
8925
8915
  } else if (flags.get("upload") !== true) {
8926
8916
  console.log(json);
@@ -8970,7 +8960,7 @@ async function runMap(flags) {
8970
8960
 
8971
8961
  // src/setup.ts
8972
8962
  import { readFileSync as readFileSync18 } from "fs";
8973
- import path16 from "path";
8963
+ import path15 from "path";
8974
8964
  var SCAN_COMMAND = "patchstack-connect scan";
8975
8965
  var MARK_BUILD_COMMAND = "patchstack-connect mark-build";
8976
8966
  function setupProtection(cwd) {
@@ -8995,7 +8985,7 @@ function prependHook(existing, command) {
8995
8985
  return [command, ...remaining].join(" && ");
8996
8986
  }
8997
8987
  function wireBuildScripts(cwd, packageManager) {
8998
- const target = path16.join(cwd, "package.json");
8988
+ const target = path15.join(cwd, "package.json");
8999
8989
  const raw = readFileSync18(target, "utf8");
9000
8990
  const pkg = JSON.parse(raw);
9001
8991
  const scripts = pkg.scripts ?? {};
@@ -9263,6 +9253,20 @@ function parseArgs(argv) {
9263
9253
  flags
9264
9254
  };
9265
9255
  }
9256
+ function resolveCliConfig(args, extra = {}) {
9257
+ return resolveConfig({
9258
+ cwd: process.cwd(),
9259
+ cliSiteUuid: getStringFlag(args.flags, "site-uuid"),
9260
+ cliEndpoint: getStringFlag(args.flags, "endpoint"),
9261
+ ...extra
9262
+ });
9263
+ }
9264
+ function runningInCi() {
9265
+ return process.env.CI !== void 0 && process.env.CI !== "" && process.env.CI !== "false";
9266
+ }
9267
+ function gitignoreOutcomeLine(ignore) {
9268
+ return ignore.ignored ? " Added to .gitignore." : ` NOT ignored by git \u2014 ${ignore.reason ?? "unknown reason"}. Add it to .gitignore yourself before committing.`;
9269
+ }
9266
9270
  async function runInit(args) {
9267
9271
  const uuid = args.positional[0];
9268
9272
  if (!uuid) {
@@ -9270,7 +9274,7 @@ async function runInit(args) {
9270
9274
  console.error("Usage: patchstack-connect init <site-uuid>");
9271
9275
  return 1;
9272
9276
  }
9273
- if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(uuid)) {
9277
+ if (!isCanonicalUuid(uuid)) {
9274
9278
  console.error(`Error: "${uuid}" does not look like a valid UUID.`);
9275
9279
  return 1;
9276
9280
  }
@@ -9281,15 +9285,11 @@ async function runInit(args) {
9281
9285
  return 0;
9282
9286
  }
9283
9287
  async function runClaim(args) {
9284
- if (process.env.CI !== void 0 && process.env.CI !== "" && process.env.CI !== "false") {
9288
+ if (runningInCi()) {
9285
9289
  console.error("`claim` is interactive and cannot run in CI. Claim the site from a developer machine.");
9286
9290
  return 1;
9287
9291
  }
9288
- const config = await resolveConfig({
9289
- cwd: process.cwd(),
9290
- cliSiteUuid: getStringFlag(args.flags, "site-uuid"),
9291
- cliEndpoint: getStringFlag(args.flags, "endpoint")
9292
- });
9292
+ const config = await resolveCliConfig(args);
9293
9293
  const siteUuid = config.siteUuid;
9294
9294
  if (siteUuid === null) {
9295
9295
  console.error("\n No site to claim yet \u2014 run `npx @patchstack/connect scan` first.\n");
@@ -9304,9 +9304,7 @@ async function runClaim(args) {
9304
9304
  if (result2.credentialSaved === true) {
9305
9305
  const ignore = await secretFileIgnored(process.cwd());
9306
9306
  console.log(` A credential for this site was issued and saved to ${SECRET_CONFIG_FILENAME}.`);
9307
- console.log(
9308
- ignore.ignored ? " Added to .gitignore." : ` NOT ignored by git \u2014 ${ignore.reason ?? "unknown reason"}. Add it to .gitignore yourself before committing.`
9309
- );
9307
+ console.log(gitignoreOutcomeLine(ignore));
9310
9308
  }
9311
9309
  console.log("");
9312
9310
  return 0;
@@ -9382,22 +9380,16 @@ async function runClaim(args) {
9382
9380
  return 1;
9383
9381
  }
9384
9382
  async function runLogin(args) {
9385
- if (process.env.CI !== void 0 && process.env.CI !== "" && process.env.CI !== "false") {
9383
+ if (runningInCi()) {
9386
9384
  console.error("`login` is interactive and cannot run in CI. Set PATCHSTACK_PULSE_AUTH instead.");
9387
9385
  return 1;
9388
9386
  }
9389
- const config = await resolveConfig({
9390
- cwd: process.cwd(),
9391
- cliSiteUuid: getStringFlag(args.flags, "site-uuid"),
9392
- cliEndpoint: getStringFlag(args.flags, "endpoint")
9393
- });
9387
+ const config = await resolveCliConfig(args);
9394
9388
  const approved = async () => {
9395
9389
  const ignore = await secretFileIgnored(process.cwd());
9396
9390
  console.log(`
9397
9391
  \u2713 Credential restored and saved to ${SECRET_CONFIG_FILENAME}.`);
9398
- console.log(
9399
- ignore.ignored ? " Added to .gitignore." : ` NOT ignored by git \u2014 ${ignore.reason ?? "unknown reason"}. Add it to .gitignore yourself before committing.`
9400
- );
9392
+ console.log(gitignoreOutcomeLine(ignore));
9401
9393
  console.log(" The previous credential no longer works. Update it anywhere else it was set:");
9402
9394
  console.log(" CI secrets, hosting env vars, preview environments, other checkouts.\n");
9403
9395
  return 0;
@@ -9500,10 +9492,7 @@ async function postManifestWithPatience(config, payload) {
9500
9492
  }
9501
9493
  async function runScan(args, options = {}) {
9502
9494
  const dryRun = args.flags.get("dry-run") === true;
9503
- const config = await resolveConfig({
9504
- cwd: process.cwd(),
9505
- cliSiteUuid: getStringFlag(args.flags, "site-uuid"),
9506
- cliEndpoint: getStringFlag(args.flags, "endpoint"),
9495
+ const config = await resolveCliConfig(args, {
9507
9496
  cliClaimToken: getStringFlag(args.flags, "claim-token"),
9508
9497
  // The one command that reports them, so the one command that resolves them.
9509
9498
  detectSiteIdentity: true
@@ -9625,14 +9614,21 @@ async function runScan(args, options = {}) {
9625
9614
  const linkUuid = response.uuid ?? config.siteUuid;
9626
9615
  if (!connected && (provisioning || claimLines.length > 0) && linkUuid !== null && linkUuid !== void 0 && linkUuid.length > 0) {
9627
9616
  console.log("");
9628
- console.log("Open this dashboard link to view vulnerability reports:");
9629
- console.log(` ${buildClaimUrl(config.endpoint, linkUuid)}`);
9617
+ console.log("Connect this site to your Patchstack account \u2014 any one of these:");
9618
+ if (config.widget) {
9619
+ console.log(' 1. In the preview \u2014 the widget shows a "Connect this website" panel while the');
9620
+ console.log(" site is unclaimed. Signing in there attaches it.");
9621
+ console.log(" 2. Open this dashboard link in a browser:");
9622
+ console.log(` ${buildClaimUrl(config.endpoint, linkUuid)}`);
9623
+ console.log(" 3. From this terminal: npx @patchstack/connect claim");
9624
+ } else {
9625
+ console.log(" 1. Open this dashboard link in a browser:");
9626
+ console.log(` ${buildClaimUrl(config.endpoint, linkUuid)}`);
9627
+ console.log(" 2. From this terminal: npx @patchstack/connect claim");
9628
+ }
9630
9629
  if (config.endpoint !== DEFAULT_ENDPOINT) {
9631
9630
  console.log(" (this URL inherits the endpoint override above)");
9632
9631
  }
9633
- console.log("");
9634
- console.log("Or attach it to your account from this terminal:");
9635
- console.log(" npx @patchstack/connect claim");
9636
9632
  }
9637
9633
  if (options.showRemainingSetup !== false) {
9638
9634
  try {
@@ -9658,7 +9654,8 @@ function reportSourceWidget(siteUuid, framework) {
9658
9654
  const result = ensureSourceWidget(process.cwd(), siteUuid, jsxShell);
9659
9655
  switch (result.action) {
9660
9656
  case "added":
9661
- console.log(`Widget: added the "Report a vulnerability" tag to ${result.shell}. Reload your preview to see it.`);
9657
+ console.log(`Widget: added the disclosure widget tag to ${result.shell}. Reload your preview to see it.`);
9658
+ console.log(' Unclaimed, it shows a "Connect this website" panel; the "Report a vulnerability" button replaces it once the site is claimed.');
9662
9659
  break;
9663
9660
  case "updated":
9664
9661
  console.log(`Widget: updated the managed tag in ${result.shell} to site ${siteUuid}.`);
@@ -9767,12 +9764,7 @@ async function runDemoCommand(args) {
9767
9764
  try {
9768
9765
  const scenario = resolveDemoScenario(args.positional[0]);
9769
9766
  const cwd = process.cwd();
9770
- const config = await resolveConfig({
9771
- cwd,
9772
- cliSiteUuid: getStringFlag(args.flags, "site-uuid"),
9773
- cliEndpoint: getStringFlag(args.flags, "endpoint"),
9774
- requireSiteUuid: true
9775
- });
9767
+ const config = await resolveCliConfig(args, { requireSiteUuid: true });
9776
9768
  if (config.environment !== "production") {
9777
9769
  throw new DemoError(
9778
9770
  "The production-backed demo requires PATCHSTACK_ENVIRONMENT=production. Unset the sandbox override and try again."
@@ -9890,6 +9882,7 @@ async function runSetup(args) {
9890
9882
  const before = await collectGuideState(process.cwd());
9891
9883
  if (!before.hasPackageJson) {
9892
9884
  console.error("Error: no package.json found. Run setup from the project root.");
9885
+ console.error("For a standalone HTML site, use the widget-only instructions in AGENT-INSTALL.md; do not create a Node project just to run setup.");
9893
9886
  return 1;
9894
9887
  }
9895
9888
  if (before.installed === null) {
@@ -9967,16 +9960,12 @@ function setupOutcome(state, protection, wired) {
9967
9960
  if (protection.install.status === "not-applicable" && protection.install.leftovers.length > 0) {
9968
9961
  warnings.push(`earlier guard scaffold does nothing here and can be deleted: ${protection.install.leftovers.join(", ")}`);
9969
9962
  }
9970
- if (state.claimUrl !== null) warnings.push("the site is not attached to an account until the dashboard link is opened or `npx @patchstack/connect claim` completes");
9963
+ if (state.claimUrl !== null) warnings.push('the site is not attached to an account until someone signs in through the widget\'s "Connect this website" panel, the dashboard link is opened, or `npx @patchstack/connect claim` completes');
9971
9964
  if (warnings.length > 0) lines.push(["Warnings", warnings.join("; ")]);
9972
9965
  return lines;
9973
9966
  }
9974
9967
  async function runStatus(args) {
9975
- const config = await resolveConfig({
9976
- cwd: process.cwd(),
9977
- cliSiteUuid: getStringFlag(args.flags, "site-uuid"),
9978
- cliEndpoint: getStringFlag(args.flags, "endpoint")
9979
- });
9968
+ const config = await resolveCliConfig(args);
9980
9969
  console.log(`Site UUID: ${config.siteUuid ?? "(none yet \u2014 the next `scan` will provision one)"}`);
9981
9970
  console.log(
9982
9971
  `Endpoint: ${config.endpoint}${config.endpoint === DEFAULT_ENDPOINT ? "" : " (override)"}`
@@ -9985,7 +9974,9 @@ async function runStatus(args) {
9985
9974
  console.log(`Environment: ${config.environment}`);
9986
9975
  if (config.siteUuid !== null) {
9987
9976
  console.log(`Dashboard URL: ${buildClaimUrl(config.endpoint, config.siteUuid)}`);
9988
- console.log(" Not attached to an account yet? Run `npx @patchstack/connect claim`.");
9977
+ console.log(` Not attached to an account yet? Sign in through the widget's "Connect this`);
9978
+ console.log(' website" panel on the preview, open the link above, or run');
9979
+ console.log(" `npx @patchstack/connect claim`.");
9989
9980
  switch (await fetchSiteStatus(config)) {
9990
9981
  case "active":
9991
9982
  console.log("Site status: active on Patchstack");
@@ -10010,11 +10001,7 @@ async function runStatus(args) {
10010
10001
  return 0;
10011
10002
  }
10012
10003
  async function runUninstall(args) {
10013
- const config = await resolveConfig({
10014
- cwd: process.cwd(),
10015
- cliSiteUuid: getStringFlag(args.flags, "site-uuid"),
10016
- cliEndpoint: getStringFlag(args.flags, "endpoint")
10017
- });
10004
+ const config = await resolveCliConfig(args);
10018
10005
  if (config.siteUuid === null) {
10019
10006
  console.log("No site UUID configured \u2014 there is no site record to signal about.");
10020
10007
  console.log('Continue with the local removal steps in AGENT-INSTALL.md ("Uninstalling").');
@@ -10054,7 +10041,7 @@ function describeStack(stack) {
10054
10041
  }
10055
10042
  function readBuildScript(cwd) {
10056
10043
  try {
10057
- const pkg = JSON.parse(readFileSync19(path17.join(cwd, "package.json"), "utf8"));
10044
+ const pkg = JSON.parse(readFileSync19(path16.join(cwd, "package.json"), "utf8"));
10058
10045
  return pkg.scripts?.build;
10059
10046
  } catch {
10060
10047
  return void 0;