@rogatio/cli 6.16.2 → 6.16.4

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.
@@ -531,7 +531,11 @@ function createAIAssistPanel(_container, _editor, onApply, onClose, onSend) {
531
531
  `;
532
532
  const addDetail = (label, value) => {
533
533
  const detail = document.createElement("div");
534
- detail.innerHTML = `<span style="color:#666;">${label}:</span> ${value}`;
534
+ const labelEl = document.createElement("span");
535
+ labelEl.style.color = "#666";
536
+ labelEl.textContent = `${label}:`;
537
+ detail.appendChild(labelEl);
538
+ detail.appendChild(document.createTextNode(` ${value}`));
535
539
  ruleDetails.appendChild(detail);
536
540
  };
537
541
  if (rule.source) {
@@ -2301,6 +2301,7 @@ import { isAbsolute as isAbsolute3 } from "node:path";
2301
2301
  import { Buffer as Buffer2 } from "node:buffer";
2302
2302
  import { existsSync as existsSync2 } from "node:fs";
2303
2303
  import { join as join6 } from "node:path";
2304
+ import { lookup as dnsLookup2 } from "node:dns/promises";
2304
2305
  import {
2305
2306
  createServer as createServer2
2306
2307
  } from "node:http";
@@ -20072,7 +20073,7 @@ var require_x509_cjs = __commonJS({
20072
20073
  var _X509Certificate_signature;
20073
20074
  var _X509Certificate_extensions;
20074
20075
  var _X509Certificate_publicKey;
20075
- var X509Certificate5 = class extends PemData {
20076
+ var X509Certificate4 = class extends PemData {
20076
20077
  get publicKey() {
20077
20078
  if (!tslib.__classPrivateFieldGet(this, _X509Certificate_publicKey, "f")) {
20078
20079
  tslib.__classPrivateFieldSet(this, _X509Certificate_publicKey, new PublicKey(this.asn.tbsCertificate.subjectPublicKeyInfo, this.parseOptions), "f");
@@ -20315,7 +20316,7 @@ var require_x509_cjs = __commonJS({
20315
20316
  }
20316
20317
  };
20317
20318
  _X509Certificate_tbs = /* @__PURE__ */ new WeakMap(), _X509Certificate_serialNumber = /* @__PURE__ */ new WeakMap(), _X509Certificate_subjectName = /* @__PURE__ */ new WeakMap(), _X509Certificate_subject = /* @__PURE__ */ new WeakMap(), _X509Certificate_issuerName = /* @__PURE__ */ new WeakMap(), _X509Certificate_issuer = /* @__PURE__ */ new WeakMap(), _X509Certificate_notBefore = /* @__PURE__ */ new WeakMap(), _X509Certificate_notAfter = /* @__PURE__ */ new WeakMap(), _X509Certificate_signatureAlgorithm = /* @__PURE__ */ new WeakMap(), _X509Certificate_signature = /* @__PURE__ */ new WeakMap(), _X509Certificate_extensions = /* @__PURE__ */ new WeakMap(), _X509Certificate_publicKey = /* @__PURE__ */ new WeakMap();
20318
- X509Certificate5.NAME = "Certificate";
20319
+ X509Certificate4.NAME = "Certificate";
20319
20320
  var _X509Certificates_options;
20320
20321
  var X509Certificates = class extends Array {
20321
20322
  constructor(param, options) {
@@ -20323,7 +20324,7 @@ var require_x509_cjs = __commonJS({
20323
20324
  _X509Certificates_options.set(this, void 0);
20324
20325
  if (PemData.isAsnEncoded(param)) {
20325
20326
  this.import(param, options);
20326
- } else if (param instanceof X509Certificate5) {
20327
+ } else if (param instanceof X509Certificate4) {
20327
20328
  this.push(param);
20328
20329
  } else if (Array.isArray(param)) {
20329
20330
  for (const item of param) {
@@ -20361,7 +20362,7 @@ var require_x509_cjs = __commonJS({
20361
20362
  const certificates = [];
20362
20363
  for (const item of signedData.certificates || []) {
20363
20364
  if (item.certificate) {
20364
- certificates.push(new X509Certificate5(item.certificate, options));
20365
+ certificates.push(new X509Certificate4(item.certificate, options));
20365
20366
  }
20366
20367
  }
20367
20368
  this.clear();
@@ -20553,7 +20554,7 @@ var require_x509_cjs = __commonJS({
20553
20554
  throw Error("Cannot convert ASN.1 signature value to WebCrypto format");
20554
20555
  }
20555
20556
  asnX509.signatureValue = asnSignature;
20556
- return new X509Certificate5(asn1Schema.AsnConvert.serialize(asnX509));
20557
+ return new X509Certificate4(asn1Schema.AsnConvert.serialize(asnX509));
20557
20558
  }
20558
20559
  };
20559
20560
  var _X509CrlEntry_serialNumber;
@@ -20774,7 +20775,7 @@ var require_x509_cjs = __commonJS({
20774
20775
  let publicKey;
20775
20776
  const paramsKey = params.publicKey;
20776
20777
  try {
20777
- if (paramsKey instanceof X509Certificate5) {
20778
+ if (paramsKey instanceof X509Certificate4) {
20778
20779
  keyAlgorithm = {
20779
20780
  ...paramsKey.publicKey.algorithm,
20780
20781
  ...paramsKey.signatureAlgorithm
@@ -20978,7 +20979,7 @@ var require_x509_cjs = __commonJS({
20978
20979
  exports.TextObject = TextObject;
20979
20980
  exports.UPN = UPN;
20980
20981
  exports.URL = URL2;
20981
- exports.X509Certificate = X509Certificate5;
20982
+ exports.X509Certificate = X509Certificate4;
20982
20983
  exports.X509CertificateGenerator = X509CertificateGenerator2;
20983
20984
  exports.X509Certificates = X509Certificates;
20984
20985
  exports.X509ChainBuilder = X509ChainBuilder;
@@ -24441,11 +24442,6 @@ function parseMockRedirect(rawUrl) {
24441
24442
  if (!isSingleSegment(token) || !isSingleSegment(digest)) return null;
24442
24443
  return { token, digest };
24443
24444
  }
24444
- function supportedContentType(value) {
24445
- if (value === void 0) return false;
24446
- const mediaType = value.split(";", 1)[0]?.trim().toLowerCase() ?? "";
24447
- return mediaType === "application/json" || mediaType.startsWith("application/") && mediaType.endsWith("+json") || mediaType === "application/x-www-form-urlencoded" || mediaType.startsWith("text/");
24448
- }
24449
24445
  var REGEX_WORKER_SOURCE = `
24450
24446
  const workerThreads =
24451
24447
  typeof process.getBuiltinModule === "function"
@@ -24603,6 +24599,11 @@ function runRegexReplace(text, pattern, replacement, deadlineMs) {
24603
24599
  }
24604
24600
  );
24605
24601
  }
24602
+ function supportedContentType(value) {
24603
+ if (value === void 0) return false;
24604
+ const mediaType = value.split(";", 1)[0]?.trim().toLowerCase() ?? "";
24605
+ return mediaType === "application/json" || mediaType.startsWith("application/") && mediaType.endsWith("+json") || mediaType === "application/x-www-form-urlencoded" || mediaType.startsWith("text/");
24606
+ }
24606
24607
  async function rewriteRequestBody(input, action, captureContext) {
24607
24608
  if (!supportedContentType(input.contentType)) {
24608
24609
  return failure("runtime.request-body-unsupported-mime-type");
@@ -24881,8 +24882,12 @@ async function rewriteResponseBody(input, replacements, replaceAction, captureCo
24881
24882
  for (const entry of replacements) {
24882
24883
  if (entry.pattern.length === 0 || entry.pattern.length > LIMITS.maxResponseBodyPatternLength || entry.replacement.length > LIMITS.maxResponseBodyReplacementLength)
24883
24884
  return failure("runtime.size-limit");
24884
- const regex = new RegExp(entry.pattern, "gu");
24885
- text = text.replace(regex, entry.replacement);
24885
+ text = await runRegexReplace(
24886
+ text,
24887
+ entry.pattern,
24888
+ entry.replacement,
24889
+ RUNTIME_LIMITS.maxRegexDeadlineMs
24890
+ );
24886
24891
  if (new TextEncoder().encode(text).byteLength > RUNTIME_LIMITS.maxResponseBodyBytes)
24887
24892
  return failure("runtime.size-limit");
24888
24893
  }
@@ -25131,6 +25136,133 @@ function forwardRequestHeaders(headers, host, contentLength) {
25131
25136
  }
25132
25137
  return out;
25133
25138
  }
25139
+ var defaultResolver2 = {
25140
+ async lookup(hostname, signal) {
25141
+ if (signal?.aborted) throw new Error("aborted");
25142
+ const addresses = await dnsLookup2(hostname, { all: true });
25143
+ return addresses.map((address) => ({
25144
+ address: address.address,
25145
+ family: address.family === 6 ? 6 : 4
25146
+ }));
25147
+ }
25148
+ };
25149
+ var defaultDial = (port, address) => connect(port, address);
25150
+ function localOriginsFromProject(project) {
25151
+ if (project === null || typeof project !== "object") return [];
25152
+ const policy = project.requestBodyPolicy;
25153
+ if (policy === null || typeof policy !== "object") return [];
25154
+ const origins = policy.localOrigins;
25155
+ if (!Array.isArray(origins)) return [];
25156
+ return origins.filter(
25157
+ (origin) => typeof origin === "string"
25158
+ );
25159
+ }
25160
+ function effectiveLocalOrigins(policy) {
25161
+ if (policy === null) return /* @__PURE__ */ new Set();
25162
+ const raw = policy.localOrigins ?? localOriginsFromProject(policy.project);
25163
+ const origins = /* @__PURE__ */ new Set();
25164
+ for (const origin of raw) {
25165
+ const normalized = normalizeSiteOrigin(origin);
25166
+ if (normalized !== null) origins.add(normalized);
25167
+ }
25168
+ return origins;
25169
+ }
25170
+ function compareAddresses(left, right) {
25171
+ return left.family - right.family || (left.address < right.address ? -1 : left.address > right.address ? 1 : 0);
25172
+ }
25173
+ function selectPinnedAddress(addresses, allowNonPublic) {
25174
+ const publicOnly = validateResolvedAddresses(
25175
+ addresses,
25176
+ RUNTIME_LIMITS.maxDnsAddresses
25177
+ );
25178
+ if (publicOnly !== null) return publicOnly[0] ?? null;
25179
+ if (!allowNonPublic) return null;
25180
+ if (addresses.length === 0 || addresses.length > RUNTIME_LIMITS.maxDnsAddresses) {
25181
+ return null;
25182
+ }
25183
+ const checked = [];
25184
+ for (const address of addresses) {
25185
+ if (address.family !== 4 && address.family !== 6) return null;
25186
+ const classification = classifyAddress(address.address);
25187
+ if (classification === "invalid" || classification === "public") {
25188
+ return null;
25189
+ }
25190
+ checked.push({ address: address.address, family: address.family });
25191
+ }
25192
+ checked.sort(compareAddresses);
25193
+ return checked[0] ?? null;
25194
+ }
25195
+ async function pinHostname(hostname, origin, deps) {
25196
+ if (hostname.length === 0) return null;
25197
+ let resolved;
25198
+ try {
25199
+ resolved = await deps.resolver.lookup(hostname);
25200
+ } catch {
25201
+ return null;
25202
+ }
25203
+ const normalized = normalizeSiteOrigin(origin);
25204
+ const allowNonPublic = normalized !== null && deps.localOrigins.has(normalized);
25205
+ return selectPinnedAddress(resolved, allowNonPublic);
25206
+ }
25207
+ function httpUpstreamPort(target) {
25208
+ if (target.protocol !== "http:") return null;
25209
+ if (target.username.length > 0 || target.password.length > 0) return null;
25210
+ if (target.port.length === 0 || target.port === "80") return 80;
25211
+ return null;
25212
+ }
25213
+ function formatUpstreamRequest(method, path2, headers) {
25214
+ const lines = [];
25215
+ for (const [name, value] of Object.entries(headers)) {
25216
+ if (name.includes("\r") || name.includes("\n") || value.includes("\r") || value.includes("\n")) {
25217
+ return null;
25218
+ }
25219
+ lines.push(`${name}: ${value}`);
25220
+ }
25221
+ return `${method} ${path2} HTTP/1.1\r
25222
+ ${lines.join("\r\n")}\r
25223
+ \r
25224
+ `;
25225
+ }
25226
+ function httpsOrigin(host) {
25227
+ const authority = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
25228
+ try {
25229
+ return new URL(`https://${authority}`).origin;
25230
+ } catch {
25231
+ return null;
25232
+ }
25233
+ }
25234
+ function parseConnectAuthority(authority) {
25235
+ if (authority.length === 0) return null;
25236
+ let host;
25237
+ let portText;
25238
+ if (authority.startsWith("[")) {
25239
+ const end = authority.indexOf("]");
25240
+ if (end <= 1) return null;
25241
+ host = authority.slice(1, end);
25242
+ const rest = authority.slice(end + 1);
25243
+ if (!rest.startsWith(":")) return null;
25244
+ portText = rest.slice(1);
25245
+ } else {
25246
+ const colon = authority.lastIndexOf(":");
25247
+ if (colon <= 0) return null;
25248
+ host = authority.slice(0, colon);
25249
+ portText = authority.slice(colon + 1);
25250
+ }
25251
+ if (host.length === 0 || !/^\d+$/.test(portText)) return null;
25252
+ const port = Number(portText);
25253
+ if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
25254
+ return { host, port };
25255
+ }
25256
+ function endConnect(socket, status, reason) {
25257
+ if (socket.destroyed || socket.writableEnded) return;
25258
+ socket.end(
25259
+ `HTTP/1.1 ${status} ${reason}\r
25260
+ Content-Length: 0\r
25261
+ Connection: close\r
25262
+ \r
25263
+ `
25264
+ );
25265
+ }
25134
25266
  function pipeSockets(a, b) {
25135
25267
  a.pipe(b);
25136
25268
  b.pipe(a);
@@ -25143,11 +25275,16 @@ function pipeSockets(a, b) {
25143
25275
  a.on("close", () => b.destroy());
25144
25276
  b.on("close", () => a.destroy());
25145
25277
  }
25146
- async function upstreamHttp(method, target, headers, body) {
25147
- const port = target.port ? Number(target.port) : 80;
25278
+ async function upstreamHttp(method, target, headers, body, deps) {
25279
+ const port = httpUpstreamPort(target);
25280
+ if (port === null) return { ok: false, status: 403 };
25148
25281
  const path2 = `${target.pathname}${target.search}`;
25282
+ const head = formatUpstreamRequest(method, path2, headers);
25283
+ if (head === null) return { ok: false, status: 403 };
25284
+ const pinned = await pinHostname(target.hostname, target.origin, deps);
25285
+ if (pinned === null) return { ok: false, status: 403 };
25149
25286
  return new Promise((resolve12, reject) => {
25150
- const socket = connect(port, target.hostname);
25287
+ const socket = deps.dial(port, pinned.address);
25151
25288
  let buf = Buffer.alloc(0);
25152
25289
  let settled = false;
25153
25290
  const fail2 = (err) => {
@@ -25160,11 +25297,7 @@ async function upstreamHttp(method, target, headers, body) {
25160
25297
  socket.on("timeout", () => fail2(new Error("upstream timeout")));
25161
25298
  socket.on("error", (err) => fail2(err));
25162
25299
  socket.on("connect", () => {
25163
- const lines = Object.entries(headers).map(([k, v]) => `${k}: ${v}`).join("\r\n");
25164
- socket.write(`${method} ${path2} HTTP/1.1\r
25165
- ${lines}\r
25166
- \r
25167
- `);
25300
+ socket.write(head);
25168
25301
  if (body.byteLength > 0) socket.write(body);
25169
25302
  });
25170
25303
  socket.on("data", (chunk) => {
@@ -25172,9 +25305,9 @@ ${lines}\r
25172
25305
  buf = Buffer.concat([buf, piece]);
25173
25306
  const sep = buf.indexOf("\r\n\r\n");
25174
25307
  if (sep < 0) return;
25175
- const head = buf.subarray(0, sep).toString("latin1");
25308
+ const head2 = buf.subarray(0, sep).toString("latin1");
25176
25309
  const statusMatch = /^HTTP\/1\.[01] (\d+)(?: (.*))?/.exec(
25177
- head.split("\r\n")[0] ?? ""
25310
+ head2.split("\r\n")[0] ?? ""
25178
25311
  );
25179
25312
  if (!statusMatch) {
25180
25313
  fail2(new Error("bad upstream status"));
@@ -25183,7 +25316,7 @@ ${lines}\r
25183
25316
  const status = Number(statusMatch[1]);
25184
25317
  const statusMessage = statusMatch[2]?.trim() ?? "";
25185
25318
  const headerMap = {};
25186
- for (const line of head.split("\r\n").slice(1)) {
25319
+ for (const line of head2.split("\r\n").slice(1)) {
25187
25320
  const i = line.indexOf(":");
25188
25321
  if (i <= 0) continue;
25189
25322
  const name = line.slice(0, i).trim().toLowerCase();
@@ -25203,6 +25336,7 @@ ${lines}\r
25203
25336
  settled = true;
25204
25337
  socket.destroy();
25205
25338
  resolve12({
25339
+ ok: true,
25206
25340
  status,
25207
25341
  statusMessage,
25208
25342
  headers: headerMap,
@@ -25218,16 +25352,16 @@ ${lines}\r
25218
25352
  fail2(new Error("upstream closed early"));
25219
25353
  return;
25220
25354
  }
25221
- const head = buf.subarray(0, sep).toString("latin1");
25355
+ const head2 = buf.subarray(0, sep).toString("latin1");
25222
25356
  const statusMatch = /^HTTP\/1\.[01] (\d+)(?: (.*))?/.exec(
25223
- head.split("\r\n")[0] ?? ""
25357
+ head2.split("\r\n")[0] ?? ""
25224
25358
  );
25225
25359
  if (!statusMatch) {
25226
25360
  fail2(new Error("bad upstream status"));
25227
25361
  return;
25228
25362
  }
25229
25363
  const headerMap = {};
25230
- for (const line of head.split("\r\n").slice(1)) {
25364
+ for (const line of head2.split("\r\n").slice(1)) {
25231
25365
  const i = line.indexOf(":");
25232
25366
  if (i <= 0) continue;
25233
25367
  headerMap[line.slice(0, i).trim().toLowerCase()] = line.slice(i + 1).trim();
@@ -25242,6 +25376,7 @@ ${lines}\r
25242
25376
  }
25243
25377
  settled = true;
25244
25378
  resolve12({
25379
+ ok: true,
25245
25380
  status: Number(statusMatch[1]),
25246
25381
  statusMessage: statusMatch[2]?.trim() ?? "",
25247
25382
  headers: headerMap,
@@ -25317,6 +25452,8 @@ function authorizeOp(policy, op, url, method, headers) {
25317
25452
  async function startInterceptProxy(options = {}) {
25318
25453
  let policy = options.policy ?? null;
25319
25454
  const serveMock = options.serveMock;
25455
+ const resolver = options.resolver ?? defaultResolver2;
25456
+ const dial = options.dial ?? defaultDial;
25320
25457
  let activeMocks = 0;
25321
25458
  const mockAborts = /* @__PURE__ */ new Set();
25322
25459
  let stopped = false;
@@ -25411,8 +25548,24 @@ async function startInterceptProxy(options = {}) {
25411
25548
  method,
25412
25549
  target,
25413
25550
  forwardHeaders,
25414
- requestBody
25551
+ requestBody,
25552
+ {
25553
+ resolver,
25554
+ dial,
25555
+ localOrigins: effectiveLocalOrigins(active)
25556
+ }
25415
25557
  );
25558
+ if (!upstream.ok) {
25559
+ if (!res.headersSent) {
25560
+ res.writeHead(upstream.status, {
25561
+ "cache-control": "no-store",
25562
+ "content-length": "0",
25563
+ connection: "close"
25564
+ });
25565
+ res.end();
25566
+ }
25567
+ return;
25568
+ }
25416
25569
  let responseBody = upstream.body;
25417
25570
  if (responseOp !== null && active !== null) {
25418
25571
  if (responseBody.byteLength > RUNTIME_LIMITS.maxResponseBodyBytes) {
@@ -25608,25 +25761,52 @@ async function startInterceptProxy(options = {}) {
25608
25761
  );
25609
25762
  }
25610
25763
  function handleConnect(req, clientSocket, head) {
25611
- const authority = req.url ?? "";
25612
- const [host, portText] = authority.split(":");
25613
- const port = Number(portText);
25614
- if (!host || !Number.isInteger(port) || port <= 0) {
25615
- clientSocket.write("HTTP/1.1 400 Bad Request\r\n\r\n");
25616
- clientSocket.destroy();
25764
+ void tunnelConnect(req, clientSocket, head);
25765
+ }
25766
+ async function tunnelConnect(req, clientSocket, head) {
25767
+ let upstream;
25768
+ clientSocket.on("error", () => upstream?.destroy());
25769
+ const parsed = parseConnectAuthority(req.url ?? "");
25770
+ if (parsed === null) {
25771
+ endConnect(clientSocket, 400, "Bad Request");
25772
+ return;
25773
+ }
25774
+ if (parsed.port !== 443) {
25775
+ endConnect(clientSocket, 403, "Forbidden");
25617
25776
  return;
25618
25777
  }
25619
- const upstream = connect(port, host);
25620
- upstream.on("connect", () => {
25778
+ const pinned = await pinHostname(
25779
+ parsed.host,
25780
+ httpsOrigin(parsed.host) ?? "",
25781
+ {
25782
+ resolver,
25783
+ dial,
25784
+ localOrigins: effectiveLocalOrigins(policy)
25785
+ }
25786
+ );
25787
+ if (pinned === null || clientSocket.destroyed) {
25788
+ endConnect(clientSocket, 403, "Forbidden");
25789
+ return;
25790
+ }
25791
+ let upstreamSocket;
25792
+ try {
25793
+ upstreamSocket = dial(443, pinned.address);
25794
+ } catch {
25795
+ endConnect(clientSocket, 502, "Bad Gateway");
25796
+ return;
25797
+ }
25798
+ upstream = upstreamSocket;
25799
+ upstreamSocket.on("connect", () => {
25621
25800
  clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
25622
- if (head.byteLength > 0) upstream.write(head);
25623
- pipeSockets(clientSocket, upstream);
25801
+ if (head.byteLength > 0) upstreamSocket.write(head);
25802
+ pipeSockets(clientSocket, upstreamSocket);
25624
25803
  });
25625
- upstream.on("error", () => {
25626
- clientSocket.write("HTTP/1.1 502 Bad Gateway\r\n\r\n");
25627
- clientSocket.destroy();
25804
+ upstreamSocket.on("error", () => {
25805
+ if (!clientSocket.destroyed && !clientSocket.writableEnded) {
25806
+ endConnect(clientSocket, 502, "Bad Gateway");
25807
+ }
25808
+ upstreamSocket.destroy();
25628
25809
  });
25629
- clientSocket.on("error", () => upstream.destroy());
25630
25810
  }
25631
25811
  const endpoint = await new Promise((resolve12, reject) => {
25632
25812
  server.once("error", reject);
@@ -25677,7 +25857,10 @@ async function startInterception(activation, policyDigest, extensionId, pacRoute
25677
25857
  const sessionId = `session-${activation.startedAt}-${Math.random().toString(36).slice(2)}`;
25678
25858
  let proxy;
25679
25859
  try {
25680
- const started = await registeredProvider.start(activation);
25860
+ const started = await registeredProvider.start({
25861
+ ...activation,
25862
+ localOrigins: targetPolicy.localOrigins
25863
+ });
25681
25864
  if (started && typeof started === "object" && typeof started.host === "string" && typeof started.port === "number") {
25682
25865
  proxy = started;
25683
25866
  } else if (activation.proxy) {
@@ -27414,6 +27597,25 @@ function createNativeHost(options) {
27414
27597
  ...options.clock ? { clock: options.clock } : {}
27415
27598
  });
27416
27599
  let interceptProxy = null;
27600
+ function policyForProxy(activation) {
27601
+ const policy = controller.getActivePolicy();
27602
+ if (!policy) return null;
27603
+ const fromProject = localOriginsFromProject(policy.project);
27604
+ const fromSession = activation.localOrigins ?? [];
27605
+ const localOrigins = [];
27606
+ const seen = /* @__PURE__ */ new Set();
27607
+ for (const origin of [...fromProject, ...fromSession]) {
27608
+ if (seen.has(origin)) continue;
27609
+ seen.add(origin);
27610
+ localOrigins.push(origin);
27611
+ }
27612
+ return {
27613
+ project: policy.project,
27614
+ operations: policy.operations,
27615
+ presetDigest: policy.presetDigest,
27616
+ localOrigins
27617
+ };
27618
+ }
27417
27619
  let outboundWrite = null;
27418
27620
  let hostRequestCounter = 0;
27419
27621
  const pendingHost = /* @__PURE__ */ new Map();
@@ -27482,18 +27684,13 @@ function createNativeHost(options) {
27482
27684
  } catch {
27483
27685
  }
27484
27686
  },
27485
- async startTlsProxy() {
27687
+ async startTlsProxy(activation) {
27486
27688
  if (interceptProxy) {
27487
27689
  await interceptProxy.stop();
27488
27690
  interceptProxy = null;
27489
27691
  }
27490
- const policy = controller.getActivePolicy();
27491
27692
  interceptProxy = await startInterceptProxy({
27492
- policy: policy ? {
27493
- project: policy.project,
27494
- operations: policy.operations,
27495
- presetDigest: policy.presetDigest
27496
- } : null,
27693
+ policy: policyForProxy(activation),
27497
27694
  serveMock: (request) => controller.serveMock(request.token, {
27498
27695
  method: request.method,
27499
27696
  signal: request.signal
@@ -27516,14 +27713,7 @@ function createNativeHost(options) {
27516
27713
  async start(activation) {
27517
27714
  const routes = pendingRoutes.length > 0 ? pendingRoutes : activation.pacRoutes;
27518
27715
  const endpoint = await platformProvider.start(activation, routes);
27519
- const policy = controller.getActivePolicy();
27520
- interceptProxy?.setPolicy(
27521
- policy ? {
27522
- project: policy.project,
27523
- operations: policy.operations,
27524
- presetDigest: policy.presetDigest
27525
- } : null
27526
- );
27716
+ interceptProxy?.setPolicy(policyForProxy(activation));
27527
27717
  return endpoint;
27528
27718
  },
27529
27719
  async stop() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogatio/cli",
3
- "version": "6.16.2",
3
+ "version": "6.16.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Local-first browser request and response rules — editor host, file verification, test runner, and runtime dispatch.",