@validate.qa/runner 1.0.100 → 1.0.102

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.
Files changed (31) hide show
  1. package/README.md +3 -0
  2. package/dist/{chunk-MBKGTELT.mjs → chunk-3JM6XTSZ.mjs} +1862 -530
  3. package/dist/{chunk-2XD63NU5.mjs → chunk-4WLP3RWN.mjs} +941 -86
  4. package/dist/{chunk-MHFP3QXU.mjs → chunk-5DFBEL72.mjs} +1 -1
  5. package/dist/{chunk-II7QW7MZ.mjs → chunk-BXLEPT4M.mjs} +31 -18
  6. package/dist/{chunk-MAO6ADAO.mjs → chunk-CBVHPYVJ.mjs} +62 -2
  7. package/dist/{chunk-5P4ANVDY.mjs → chunk-DN3O6EYT.mjs} +43073 -23357
  8. package/dist/{chunk-GIIIVO2W.mjs → chunk-E2RRAE27.mjs} +155 -11
  9. package/dist/chunk-E2VEMBQQ.mjs +291 -0
  10. package/dist/{chunk-HMUC3DKS.mjs → chunk-HJ6FKHMM.mjs} +2281 -2
  11. package/dist/{chunk-WDXLAZ2J.mjs → chunk-PWFWMVZU.mjs} +3 -2
  12. package/dist/{chunk-6NIT2CCH.mjs → chunk-ZZYBRIBT.mjs} +18 -12
  13. package/dist/cli.js +139723 -114754
  14. package/dist/cli.mjs +536 -247
  15. package/dist/credential-mcp-server.js +1761 -358
  16. package/dist/credential-mcp-server.mjs +3 -3
  17. package/dist/discovery-mcp-server.js +1874 -379
  18. package/dist/discovery-mcp-server.mjs +4 -4
  19. package/dist/dist-52M5RDZ6.mjs +17 -0
  20. package/dist/inbox-mcp-server.js +1902 -505
  21. package/dist/inbox-mcp-server.mjs +3 -3
  22. package/dist/route-seed-worker.js +3976 -356
  23. package/dist/route-seed-worker.mjs +14 -7
  24. package/dist/run-write-guard-preload.js +2908 -572
  25. package/dist/run-write-guard-preload.mjs +5 -285
  26. package/dist/run-write-guard.js +2908 -572
  27. package/dist/run-write-guard.mjs +3 -3
  28. package/dist/spec-driver.js +1 -1
  29. package/dist/spec-driver.mjs +1 -1
  30. package/package.json +4 -3
  31. package/dist/dist-DFNLMH6L.mjs +0 -16
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  dist_exports,
3
3
  init_dist
4
- } from "./chunk-MBKGTELT.mjs";
4
+ } from "./chunk-3JM6XTSZ.mjs";
5
5
  import {
6
6
  __commonJS,
7
7
  __require,
@@ -21,8 +21,12 @@ var require_survey_network_guard = __commonJS({
21
21
  exports.maskedPath = maskedPath;
22
22
  exports.bodyKeysOf = bodyKeysOf;
23
23
  exports.graphqlDocumentIsQueryOnly = graphqlDocumentIsQueryOnly;
24
+ exports.graphqlOperationRoots = graphqlOperationRoots;
24
25
  exports.isTokenRefreshWrite = isTokenRefreshWrite;
25
26
  exports.isSignInPathWrite = isSignInPathWrite;
27
+ exports.graphqlUrlCarriesQuery = graphqlUrlCarriesQuery;
28
+ exports.graphqlUrlQueriesAreReads = graphqlUrlQueriesAreReads;
29
+ exports.graphqlGetMayWrite = graphqlGetMayWrite;
26
30
  exports.writeShapedGet = writeShapedGet;
27
31
  exports.decideSurveyRequest = decideSurveyRequest;
28
32
  exports.installSurveyNetworkGuard = installSurveyNetworkGuard;
@@ -299,6 +303,100 @@ var require_survey_network_guard = __commonJS({
299
303
  }
300
304
  return depth === 0 && parens === 0 && objects === 0 && sawOperation;
301
305
  }
306
+ function graphqlOperationRoots(text) {
307
+ const tokens = lexGraphql(text);
308
+ if (!tokens)
309
+ return null;
310
+ const ops = [];
311
+ let depth = 0;
312
+ let parens = 0;
313
+ let objects = 0;
314
+ let defStart = true;
315
+ let kind = null;
316
+ let current = null;
317
+ let prev = "";
318
+ for (const tok of tokens) {
319
+ const last = prev;
320
+ prev = tok;
321
+ if (tok === "(") {
322
+ parens++;
323
+ continue;
324
+ }
325
+ if (tok === ")") {
326
+ parens--;
327
+ if (parens < 0 || objects !== 0)
328
+ return null;
329
+ continue;
330
+ }
331
+ if (parens > 0) {
332
+ if (tok === "{")
333
+ objects++;
334
+ else if (tok === "}") {
335
+ objects--;
336
+ if (objects < 0)
337
+ return null;
338
+ }
339
+ continue;
340
+ }
341
+ if (tok === "{") {
342
+ if (depth === 0) {
343
+ if (defStart)
344
+ kind = "query";
345
+ else if (kind === null)
346
+ return null;
347
+ current = kind === "fragment" ? null : { kind, roots: [] };
348
+ if (current)
349
+ ops.push(current);
350
+ defStart = false;
351
+ }
352
+ depth++;
353
+ continue;
354
+ }
355
+ if (tok === "}") {
356
+ depth--;
357
+ if (depth < 0)
358
+ return null;
359
+ if (depth === 0) {
360
+ defStart = true;
361
+ kind = null;
362
+ current = null;
363
+ }
364
+ continue;
365
+ }
366
+ if (depth === 0) {
367
+ if (!/^[_A-Za-z]/.test(tok)) {
368
+ if (tok === "@")
369
+ continue;
370
+ return null;
371
+ }
372
+ if (defStart) {
373
+ if (tok !== "query" && tok !== "mutation" && tok !== "fragment")
374
+ return null;
375
+ kind = tok;
376
+ defStart = false;
377
+ }
378
+ continue;
379
+ }
380
+ if (depth > 1 || !current)
381
+ continue;
382
+ if (/^[_A-Za-z]/.test(tok)) {
383
+ if (last === "@")
384
+ continue;
385
+ if (last === ":") {
386
+ if (current.roots.length === 0)
387
+ return null;
388
+ current.roots[current.roots.length - 1] = tok;
389
+ continue;
390
+ }
391
+ current.roots.push(tok);
392
+ continue;
393
+ }
394
+ if (tok === ":" || tok === "@")
395
+ continue;
396
+ return null;
397
+ }
398
+ return depth === 0 && parens === 0 && objects === 0 ? ops : null;
399
+ }
302
400
  function isGraphqlQueryOnly(postData) {
303
401
  if (!postData || postData.length > MAX_BODY_CHARS)
304
402
  return false;
@@ -336,6 +434,34 @@ var require_survey_network_guard = __commonJS({
336
434
  "remove"
337
435
  ]);
338
436
  var NOT_A_SESSION_END = (segs) => !segs.some((seg) => SESSION_END_SEGMENTS.has(seg));
437
+ var DESTRUCTIVE_WORDS = /* @__PURE__ */ new Set([
438
+ "delete",
439
+ "remove",
440
+ "destroy",
441
+ "deactivate",
442
+ "terminate",
443
+ "purge",
444
+ "wipe",
445
+ "erase",
446
+ "cancel",
447
+ "close",
448
+ "revoke",
449
+ "unlink",
450
+ "disconnect"
451
+ ]);
452
+ var DESTRUCTIVE_PREFIXES = ["delete", "remove", "destroy", "deactivate", "terminate", "purge"];
453
+ function hasDestructiveSegment(rawSegs) {
454
+ return rawSegs.some((raw) => {
455
+ let seg = raw;
456
+ try {
457
+ seg = decodeURIComponent(raw);
458
+ } catch {
459
+ }
460
+ const words = seg.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-z0-9]+/);
461
+ return words.some((word) => DESTRUCTIVE_WORDS.has(word) || DESTRUCTIVE_PREFIXES.some((p) => word.startsWith(p)));
462
+ });
463
+ }
464
+ var rawPathSegments = (pathname) => pathname.split("/").map((seg) => seg.split(";")[0]).filter(Boolean);
339
465
  var pathSegments = (pathname) => pathname.toLowerCase().split("/").map((seg) => seg.split(";")[0]).filter(Boolean);
340
466
  function isTokenRefreshWrite(method, pathname, recentAction = false) {
341
467
  if (method.toUpperCase() !== "POST")
@@ -352,6 +478,8 @@ var require_survey_network_guard = __commonJS({
352
478
  var AUTH_PAGE_PATH_RE = /(?:^|\/)(?:log-?in|sign-?in|sign_in|auth|oauth2?|sso|callback)(?:\/|$)/;
353
479
  var SIGN_IN_SEGMENT_RE = /^(?:log-?in|sign-?in|sign_in)$/;
354
480
  var CALLBACK_ROOT_SEGMENTS = /* @__PURE__ */ new Set(["auth", "oauth", "oauth2", "sso"]);
481
+ var CALLBACK_PROTOCOL_SEGMENTS = /* @__PURE__ */ new Set(["oidc", "openid", "openid-connect", "openidconnect", "saml", "saml2", "oauth", "oauth2"]);
482
+ var API_VERSION_SEGMENT_RE = /^v[0-9]{1,3}$/;
355
483
  var PROVIDER_SEGMENT_RE = /^[a-z][a-z0-9_-]{0,39}$/;
356
484
  var NOT_A_PROVIDER_SEGMENTS = /* @__PURE__ */ new Set([
357
485
  "link",
@@ -390,14 +518,21 @@ var require_survey_network_guard = __commonJS({
390
518
  if (!NOT_A_SESSION_END(segs))
391
519
  return false;
392
520
  if (AUTH_END_PATH_RE.test(`/${segs.join("/")}`))
393
- return true;
521
+ return !hasDestructiveSegment(rawPathSegments(pathname).slice(0, -1));
522
+ let top = segs[0] === "api" ? 1 : 0;
523
+ if (top < segs.length && API_VERSION_SEGMENT_RE.test(segs[top]))
524
+ top += 1;
525
+ const below = segs.length - top;
526
+ const isProvider = (seg) => PROVIDER_SEGMENT_RE.test(seg) && !NOT_A_PROVIDER_SEGMENTS.has(seg);
394
527
  const provider = segs[segs.length - 1];
395
- const authRootAtTop = segs.length === 3 || segs[segs.length - 4] === "api" && (segs.length === 4 || segs[segs.length - 3] === "auth");
396
- if (segs.length >= 3 && authRootAtTop && CALLBACK_ROOT_SEGMENTS.has(segs[segs.length - 3]) && PROVIDER_SEGMENT_RE.test(provider) && !NOT_A_PROVIDER_SEGMENTS.has(provider)) {
528
+ const authRootAtTop = below === 3 || segs[segs.length - 4] === "api" && segs[segs.length - 3] === "auth";
529
+ if (segs.length >= 3 && authRootAtTop && CALLBACK_ROOT_SEGMENTS.has(segs[segs.length - 3]) && isProvider(provider)) {
397
530
  const step = segs[segs.length - 2];
398
531
  if (step === "callback" || step === "signin")
399
532
  return true;
400
533
  }
534
+ if (below === 4 && CALLBACK_ROOT_SEGMENTS.has(segs[top]) && CALLBACK_PROTOCOL_SEGMENTS.has(segs[top + 1]) && isProvider(segs[top + 2]) && segs[top + 3] === "callback")
535
+ return true;
401
536
  if (segs.length < 2 || segs[segs.length - 1] !== "callback")
402
537
  return false;
403
538
  const parent = segs[segs.length - 2];
@@ -424,7 +559,7 @@ var require_survey_network_guard = __commonJS({
424
559
  try {
425
560
  const a = new URL(url);
426
561
  const b = new URL(appBaseUrl);
427
- const path = (u) => u.pathname.replace(/\/+$/, "");
562
+ const path = (u) => (0, shared_1.stripTrailingSlashes)(u.pathname);
428
563
  return a.origin === b.origin && path(a) === path(b);
429
564
  } catch {
430
565
  return false;
@@ -446,9 +581,18 @@ var require_survey_network_guard = __commonJS({
446
581
  const bodyHash = (0, node_crypto_1.createHash)("sha256").update(req.postData ?? "").digest("hex").slice(0, 16);
447
582
  return `${record.method} ${url.hostname.toLowerCase()}${url.pathname} ${bodyHash}`;
448
583
  }
449
- function isGraphqlGetWrite(url, s) {
450
- const doc = url.searchParams.get("query");
451
- return doc !== null && isGraphqlEndpoint(url, s) && !graphqlDocumentIsQueryOnly(doc);
584
+ function graphqlUrlCarriesQuery(params) {
585
+ return params.has("query");
586
+ }
587
+ function graphqlUrlQueriesAreReads(params) {
588
+ return params.getAll("query").every((doc) => doc.trim() !== "" && graphqlDocumentIsQueryOnly(doc));
589
+ }
590
+ function graphqlGetMayWrite(url, body) {
591
+ const docs = url.searchParams.getAll("query");
592
+ return docs.length > 0 && (typeof body === "string" && body.length > 0 || docs.some((doc) => !graphqlDocumentIsQueryOnly(doc)));
593
+ }
594
+ function isGraphqlGetWrite(url, s, body) {
595
+ return isGraphqlEndpoint(url, s) && graphqlGetMayWrite(url, body);
452
596
  }
453
597
  exports.WRITE_VERBS = /* @__PURE__ */ new Set([
454
598
  "cancel",
@@ -652,7 +796,7 @@ var require_survey_network_guard = __commonJS({
652
796
  if (url.protocol !== "http:" && url.protocol !== "https:")
653
797
  return { action: "allow", rule: readMethod ? "read" : "non-http" };
654
798
  const appSite = isAppSite(url.hostname, s.appBaseUrl);
655
- const graphqlGet = method === "GET" && isGraphqlGetWrite(url, s);
799
+ const graphqlGet = method === "GET" && isGraphqlGetWrite(url, s, req.postData);
656
800
  const inActionWindow = s.lastActionAt > 0 && s.now - s.lastActionAt <= ACTION_NAVIGATION_WINDOW_MS;
657
801
  const typedLoad = s.agentLoad === true && req.resourceType === "document";
658
802
  const writeShaped = method === "GET" && appSite && !graphqlGet && (inActionWindow || typedLoad) ? writeShapedGet(req.url, {
@@ -686,7 +830,7 @@ var require_survey_network_guard = __commonJS({
686
830
  return { action: "allow", rule: "extra-pattern", reason: extra.reason, record };
687
831
  if (graphqlGet)
688
832
  return { action: "block", rule: "app-write", record };
689
- if (method === "POST" && isGraphqlEndpoint(url, s) && isGraphqlQueryOnly(req.postData))
833
+ if (method === "POST" && isGraphqlEndpoint(url, s) && graphqlUrlQueriesAreReads(url.searchParams) && isGraphqlQueryOnly(req.postData))
690
834
  return { action: "allow", rule: "graphql-query", record };
691
835
  const passive = s.lastNavigationAt > 0 && (s.lastActionAt === 0 || s.lastNavigationAt >= s.lastActionAt) && s.now - s.lastNavigationAt <= s.passiveWindowMs;
692
836
  const signature = learnableSignature(req, url, record, s);
@@ -718,7 +862,7 @@ var require_survey_network_guard = __commonJS({
718
862
  const re = new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ""));
719
863
  return { reason, test: (hostPath) => re.test(hostPath) };
720
864
  }
721
- const p = pattern.trim().toLowerCase().replace(/\/+$/, "");
865
+ const p = (0, shared_1.stripTrailingSlashes)(pattern.trim().toLowerCase());
722
866
  if (p.includes("/"))
723
867
  return { reason, test: (hostPath) => hostPath.toLowerCase() === p || hostPath.toLowerCase().startsWith(`${p}/`) };
724
868
  return { reason, test: (hostPath) => {
@@ -0,0 +1,291 @@
1
+ import {
2
+ require_run_write_guard
3
+ } from "./chunk-4WLP3RWN.mjs";
4
+ import {
5
+ require_survey_network_guard
6
+ } from "./chunk-E2RRAE27.mjs";
7
+ import {
8
+ __commonJS,
9
+ __require
10
+ } from "./chunk-WQXBGQU4.mjs";
11
+
12
+ // ../runner-core/dist/services/run-write-guard-preload.js
13
+ var require_run_write_guard_preload = __commonJS({
14
+ "../runner-core/dist/services/run-write-guard-preload.js"(exports) {
15
+ "use strict";
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.VERIFIED_PLAYWRIGHT_CORE = exports.installRunWriteGuard = exports.installNodeFetchGuard = exports.clearRunWriteRelay = exports.addRunWriteBrokerToken = exports.addRunWriteAuthHandler = void 0;
18
+ exports.describeBuiltRequest = describeBuiltRequest;
19
+ exports.installHttpGuard = installHttpGuard;
20
+ exports.installPlaywrightContextGuard = installPlaywrightContextGuard;
21
+ exports.startRunWriteGuardPreload = startRunWriteGuardPreload;
22
+ var node_module_1 = __require("module");
23
+ var node_path_1 = __require("path");
24
+ var survey_network_guard_js_1 = require_survey_network_guard();
25
+ var run_write_guard_js_1 = require_run_write_guard();
26
+ var run_write_guard_js_2 = require_run_write_guard();
27
+ Object.defineProperty(exports, "addRunWriteAuthHandler", { enumerable: true, get: function() {
28
+ return run_write_guard_js_2.addRunWriteAuthHandler;
29
+ } });
30
+ Object.defineProperty(exports, "addRunWriteBrokerToken", { enumerable: true, get: function() {
31
+ return run_write_guard_js_2.addRunWriteBrokerToken;
32
+ } });
33
+ Object.defineProperty(exports, "clearRunWriteRelay", { enumerable: true, get: function() {
34
+ return run_write_guard_js_2.clearRunWriteRelay;
35
+ } });
36
+ Object.defineProperty(exports, "installNodeFetchGuard", { enumerable: true, get: function() {
37
+ return run_write_guard_js_2.installNodeFetchGuard;
38
+ } });
39
+ Object.defineProperty(exports, "installRunWriteGuard", { enumerable: true, get: function() {
40
+ return run_write_guard_js_2.installRunWriteGuard;
41
+ } });
42
+ var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
43
+ var MAX_DECIDED_BODY_BYTES = 1024 * 1024;
44
+ function describeBuiltRequest(req) {
45
+ const method = typeof req.method === "string" && req.method ? req.method.toUpperCase() : "GET";
46
+ const protocol = req.protocol === "https:" ? "https:" : "http:";
47
+ const path = typeof req.path === "string" && req.path.startsWith("/") ? req.path : null;
48
+ if (path === null)
49
+ throw new Error("unusable request path");
50
+ if (typeof req.socketPath === "string" && req.socketPath) {
51
+ return { method, url: `${protocol}//unix-socket.invalid${path}` };
52
+ }
53
+ if (typeof req.host !== "string" || !req.host)
54
+ throw new Error("unusable request host");
55
+ const host = req.host.includes(":") && !req.host.startsWith("[") ? `[${req.host}]` : req.host;
56
+ return { method, url: new URL(`${protocol}//${host}${path}`).href };
57
+ }
58
+ function headerString(value) {
59
+ if (typeof value === "string")
60
+ return value;
61
+ if (Array.isArray(value))
62
+ return value.map(String).join(", ");
63
+ if (typeof value === "number")
64
+ return String(value);
65
+ return null;
66
+ }
67
+ function installHttpGuard(policy, opts, mod) {
68
+ if (policy.mode === "off")
69
+ return void 0;
70
+ const original = mod.request;
71
+ if (typeof original !== "function" || original.__vqaWriteGuarded)
72
+ return void 0;
73
+ const guard = new run_write_guard_js_1.RunWriteGuard(policy, opts);
74
+ const wrapped = function guardedRequest(...args) {
75
+ const req = original.apply(this, args);
76
+ const fields = req;
77
+ const connectedTo = { host: fields.host, socketPath: fields.socketPath, protocol: fields.protocol };
78
+ const chunks = [];
79
+ let bytes = 0;
80
+ let state = "pending";
81
+ const held = () => state === "held";
82
+ const originalWrite = req.write.bind(req);
83
+ const originalEnd = req.end.bind(req);
84
+ const originalFlushHeaders = req.flushHeaders.bind(req);
85
+ const take = (chunk, encoding) => {
86
+ if (chunk === void 0 || chunk === null || typeof chunk === "function")
87
+ return;
88
+ const buf = Buffer.isBuffer(chunk) ? chunk : chunk instanceof Uint8Array ? Buffer.from(chunk) : Buffer.from(String(chunk), typeof encoding === "string" ? encoding : "utf8");
89
+ chunks.push(buf);
90
+ bytes += buf.length;
91
+ };
92
+ const decide = (withBody) => {
93
+ const builtLine = typeof fields._header === "string" ? /^([A-Z]+) (\S+) HTTP\//.exec(fields._header) : null;
94
+ let described = null;
95
+ try {
96
+ described = describeBuiltRequest({
97
+ ...connectedTo,
98
+ method: builtLine ? builtLine[1] : fields.method,
99
+ path: builtLine ? builtLine[2] : fields.path
100
+ });
101
+ } catch {
102
+ described = null;
103
+ }
104
+ const moved = fields.host !== connectedTo.host || fields.socketPath !== connectedTo.socketPath || fields.protocol !== connectedTo.protocol;
105
+ let decision;
106
+ try {
107
+ if (!described || moved || typeof fields._header === "string" && !builtLine)
108
+ throw new Error("undescribable request");
109
+ const host = new URL(described.url).hostname.toLowerCase();
110
+ decision = LOOPBACK_HOSTS.has(host) && !policy.appSites.includes(host) ? { action: "allow", rule: "non-http" } : guard.decide({
111
+ method: described.method,
112
+ url: described.url,
113
+ postData: withBody ? Buffer.concat(chunks).toString("utf8") : null,
114
+ contentType: headerString(req.getHeader("content-type")),
115
+ amzTarget: headerString(req.getHeader("x-amz-target"))
116
+ });
117
+ } catch {
118
+ decision = {
119
+ action: "write",
120
+ rule: "decision-error",
121
+ record: { method: described?.method ?? "REQUEST", host: "", path: described ? (0, survey_network_guard_js_1.maskedPath)(described.url) : "(undescribable)", keys: [], rule: "decision-error" }
122
+ };
123
+ }
124
+ if (decision.action === "write" && decision.record) {
125
+ guard.note(decision.record);
126
+ if (guard.holds(decision.rule)) {
127
+ state = "held";
128
+ chunks.length = 0;
129
+ req.destroy(new Error(`blocked by the run write guard: ${decision.record.method} ${decision.record.host}${decision.record.path}`));
130
+ return;
131
+ }
132
+ }
133
+ state = "allowed";
134
+ for (const buf of chunks.splice(0))
135
+ originalWrite(buf);
136
+ };
137
+ req.write = (chunk, encoding, cb) => {
138
+ const done = typeof encoding === "function" ? encoding : cb;
139
+ if (state === "allowed")
140
+ return originalWrite(chunk, encoding, cb);
141
+ if (state === "pending") {
142
+ take(chunk, encoding);
143
+ if (bytes > MAX_DECIDED_BODY_BYTES)
144
+ decide(false);
145
+ }
146
+ if (held()) {
147
+ if (done)
148
+ process.nextTick(done, new Error("blocked by the run write guard"));
149
+ return false;
150
+ }
151
+ if (done)
152
+ process.nextTick(done);
153
+ return true;
154
+ };
155
+ req.flushHeaders = () => {
156
+ if (state === "allowed")
157
+ originalFlushHeaders();
158
+ };
159
+ req.end = (chunk, encoding, cb) => {
160
+ if (state === "allowed")
161
+ return originalEnd(chunk, encoding, cb);
162
+ if (state === "held")
163
+ return req;
164
+ const done = [chunk, encoding, cb].find((a) => typeof a === "function");
165
+ if (typeof chunk !== "function")
166
+ take(chunk, typeof encoding === "function" ? void 0 : encoding);
167
+ decide(bytes <= MAX_DECIDED_BODY_BYTES);
168
+ if (held())
169
+ return req;
170
+ return originalEnd(done);
171
+ };
172
+ return req;
173
+ };
174
+ Object.defineProperty(wrapped, "__vqaWriteGuarded", { value: true });
175
+ const wrappedGet = function guardedGet(...args) {
176
+ const req = wrapped.apply(this, args);
177
+ req.end();
178
+ return req;
179
+ };
180
+ Object.defineProperty(wrappedGet, "__vqaWriteGuarded", { value: true });
181
+ const install = (name, value) => {
182
+ if (policy.mode === "block") {
183
+ Object.defineProperty(mod, name, { value, writable: false, configurable: false, enumerable: true });
184
+ } else {
185
+ mod[name] = value;
186
+ }
187
+ };
188
+ install("request", wrapped);
189
+ if (typeof mod.get === "function")
190
+ install("get", wrappedGet);
191
+ return guard;
192
+ }
193
+ exports.VERIFIED_PLAYWRIGHT_CORE = /^1\.64\./;
194
+ function installPlaywrightContextGuard(policy, opts, from = __filename) {
195
+ if (policy.mode === "off")
196
+ return true;
197
+ let pw;
198
+ let version = "";
199
+ try {
200
+ const req = (0, node_module_1.createRequire)(from);
201
+ let base = from;
202
+ try {
203
+ base = (0, node_path_1.dirname)(req.resolve("@playwright/test/package.json"));
204
+ } catch {
205
+ }
206
+ try {
207
+ base = (0, node_path_1.dirname)((0, node_module_1.createRequire)(`${base}/`).resolve("playwright/package.json"));
208
+ } catch {
209
+ }
210
+ const fromPlaywright = (0, node_module_1.createRequire)(`${base}/`);
211
+ version = String(fromPlaywright("playwright-core/package.json").version ?? "");
212
+ pw = fromPlaywright("playwright-core");
213
+ } catch {
214
+ return false;
215
+ }
216
+ if (!exports.VERIFIED_PLAYWRIGHT_CORE.test(version)) {
217
+ if (policy.mode === "block")
218
+ return false;
219
+ opts.onLog?.(`[run-write-guard] observe: playwright-core ${version || "(unknown)"} is not a version the context hook was verified on`);
220
+ }
221
+ const add = pw?._instrumentation?.addListener;
222
+ if (typeof add !== "function")
223
+ return false;
224
+ add.call(pw._instrumentation, {
225
+ // Block mode: the context's service workers are off (design §4), whatever the test asked for.
226
+ // Playwright passes the options object it builds the context from (browser.newContext,
227
+ // launchPersistentContext); a context whose options cannot be set is still routed below.
228
+ runBeforeCreateBrowserContext: async (options) => {
229
+ if (options && typeof options === "object")
230
+ Object.assign(options, (0, run_write_guard_js_1.runWriteContextOptions)(policy));
231
+ },
232
+ runAfterCreateBrowserContext: async (context) => {
233
+ await (0, run_write_guard_js_1.installRunWriteGuard)(context, policy, opts);
234
+ }
235
+ });
236
+ return true;
237
+ }
238
+ function startRunWriteGuardPreload(env = process.env) {
239
+ const raw = env[run_write_guard_js_1.RUN_WRITE_POLICY_ENV];
240
+ if (!raw)
241
+ return [];
242
+ let policy = null;
243
+ try {
244
+ policy = (0, run_write_guard_js_1.parseRunWritePolicy)(JSON.parse(raw));
245
+ } catch {
246
+ policy = null;
247
+ }
248
+ if (!policy) {
249
+ console.log(`${run_write_guard_js_1.RUN_WRITE_UNAVAILABLE_LINE}the run write policy could not be read`);
250
+ return ["policy"];
251
+ }
252
+ if (policy.mode === "off")
253
+ return [];
254
+ const names = (env[run_write_guard_js_1.RUN_WRITE_SIGNIN_VARS_ENV] ?? "").split(",").map((n) => n.trim()).filter((n) => /^[A-Za-z_][A-Za-z0-9_]{0,63}$/.test(n)).slice(0, 16);
255
+ const signInSecrets = names.map((n) => env[n]).filter((v) => typeof v === "string");
256
+ const opts = { onLog: (line) => console.log(line), signInSecrets };
257
+ const missing = [];
258
+ try {
259
+ (0, run_write_guard_js_1.installNodeFetchGuard)(policy, opts);
260
+ } catch {
261
+ missing.push("fetch");
262
+ }
263
+ const nodeRequire = (0, node_module_1.createRequire)(__filename);
264
+ try {
265
+ installHttpGuard(policy, opts, nodeRequire("node:http"));
266
+ } catch {
267
+ missing.push("http");
268
+ }
269
+ try {
270
+ installHttpGuard(policy, opts, nodeRequire("node:https"));
271
+ } catch {
272
+ missing.push("https");
273
+ }
274
+ try {
275
+ (0, node_module_1.syncBuiltinESMExports)();
276
+ } catch {
277
+ }
278
+ if (!installPlaywrightContextGuard(policy, opts))
279
+ missing.push("browser contexts");
280
+ for (const piece of missing)
281
+ console.log(`${run_write_guard_js_1.RUN_WRITE_UNAVAILABLE_LINE}the preload could not guard ${piece}`);
282
+ return missing;
283
+ }
284
+ if (process.env[run_write_guard_js_1.RUN_WRITE_POLICY_ENV])
285
+ startRunWriteGuardPreload();
286
+ }
287
+ });
288
+
289
+ export {
290
+ require_run_write_guard_preload
291
+ };