@rogatio/cli 6.16.1 → 6.16.3

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 (2) hide show
  1. package/dist/node/index.js +275 -61
  2. package/package.json +1 -1
@@ -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";
@@ -22681,6 +22682,18 @@ async function readPreviousRogatioCa(caCertFile) {
22681
22682
  return void 0;
22682
22683
  }
22683
22684
  }
22685
+ async function assertReadableIfRegular(path2, snapshot2) {
22686
+ if (snapshot2 !== void 0) return;
22687
+ try {
22688
+ const info = await lstat(path2);
22689
+ if (!info.isFile()) return;
22690
+ } catch {
22691
+ return;
22692
+ }
22693
+ throw new TrustError("trust.write-failed", "CA file could not be read", [
22694
+ "trust.write-failed"
22695
+ ]);
22696
+ }
22684
22697
  async function discardPreviousCa(caPreviousCertFile) {
22685
22698
  try {
22686
22699
  await rm(caPreviousCertFile, { force: true });
@@ -22732,6 +22745,9 @@ function createRequestBodyTrustController(options = {}) {
22732
22745
  let reusedExisting = false;
22733
22746
  let previousKeyPem;
22734
22747
  let previousPubPem;
22748
+ let replacedKey = false;
22749
+ let replacedPub = false;
22750
+ let replacedCert = false;
22735
22751
  const caCertFile = join2(
22736
22752
  installRoot,
22737
22753
  options.caCertFileName ?? ".rogatio-ca.crt"
@@ -22838,32 +22854,35 @@ function createRequestBodyTrustController(options = {}) {
22838
22854
  console.error("[rogatio] previous CA trust anchor was not removed");
22839
22855
  }
22840
22856
  }
22841
- async function removeLiveCaFiles() {
22842
- await rm(caKeyFile, { force: true });
22843
- await rm(caPubFile, { force: true });
22844
- await rm(caCertFile, { force: true });
22857
+ async function removeReplacedCaFiles() {
22858
+ if (replacedKey) await rm(caKeyFile, { force: true });
22859
+ if (replacedPub) await rm(caPubFile, { force: true });
22860
+ if (replacedCert) await rm(caCertFile, { force: true });
22861
+ }
22862
+ async function restoreOrDrop(path2, snapshot2, replaced, mode) {
22863
+ if (snapshot2 !== void 0) {
22864
+ await writeFileAtomic(path2, snapshot2, mode);
22865
+ return;
22866
+ }
22867
+ if (replaced) await rm(path2, { force: true });
22845
22868
  }
22846
22869
  async function rollbackReplacedCa() {
22847
22870
  if (reusedExisting) return;
22848
22871
  if (!replacingPrevious) {
22849
- await removeLiveCaFiles();
22872
+ await removeReplacedCaFiles();
22850
22873
  return;
22851
22874
  }
22852
22875
  const saved = await readPreviousRogatioCa(caPreviousCertFile);
22853
22876
  const live = await readPreviousRogatioCa(caCertFile);
22854
22877
  const copyKept = rememberedFingerprint !== void 0 && saved?.fingerprint === rememberedFingerprint;
22855
22878
  const liveDiffers = live?.fingerprint !== rememberedFingerprint;
22856
- if (copyKept && liveDiffers) {
22857
- await removeLiveCaFiles();
22879
+ if (copyKept && replacedCert && liveDiffers) {
22880
+ await removeReplacedCaFiles();
22858
22881
  return;
22859
22882
  }
22860
- if (copyKept && !liveDiffers) {
22861
- if (previousKeyPem !== void 0) {
22862
- await writeFileAtomic(caKeyFile, previousKeyPem, 384);
22863
- }
22864
- if (previousPubPem !== void 0) {
22865
- await writeFileAtomic(caPubFile, previousPubPem);
22866
- }
22883
+ if (copyKept && !replacedCert) {
22884
+ await restoreOrDrop(caKeyFile, previousKeyPem, replacedKey, 384);
22885
+ await restoreOrDrop(caPubFile, previousPubPem, replacedPub);
22867
22886
  }
22868
22887
  }
22869
22888
  async function runCaTrust() {
@@ -22881,12 +22900,21 @@ function createRequestBodyTrustController(options = {}) {
22881
22900
  reusedExisting = false;
22882
22901
  previousKeyPem = void 0;
22883
22902
  previousPubPem = void 0;
22903
+ replacedKey = false;
22904
+ replacedPub = false;
22905
+ replacedCert = false;
22884
22906
  const reusable = await reusableCaMaterial();
22885
22907
  reusedExisting = reusable;
22886
22908
  const liveAnchor = await readPreviousRogatioCa(caCertFile);
22887
22909
  const siblingAnchor = await readPreviousRogatioCa(caPreviousCertFile);
22888
22910
  let preserved;
22889
22911
  if (!reusable) {
22912
+ const rawCert = await readNoFollowRegularFile(caCertFile);
22913
+ previousKeyPem = await readNoFollowRegularFile(caKeyFile);
22914
+ previousPubPem = await readNoFollowRegularFile(caPubFile);
22915
+ await assertReadableIfRegular(caCertFile, rawCert);
22916
+ await assertReadableIfRegular(caKeyFile, previousKeyPem);
22917
+ await assertReadableIfRegular(caPubFile, previousPubPem);
22890
22918
  replacingPrevious = liveAnchor !== void 0 || siblingAnchor !== void 0;
22891
22919
  const { privateKey } = generateCaKeyPair(TRUST_LIMITS.caKeyBits);
22892
22920
  const certResult = await createCertificate(
@@ -22914,11 +22942,12 @@ function createRequestBodyTrustController(options = {}) {
22914
22942
  } else if (siblingAnchor) {
22915
22943
  await discardPreviousCa(caPreviousCertFile);
22916
22944
  }
22917
- previousKeyPem = await readNoFollowRegularFile(caKeyFile);
22918
- previousPubPem = await readNoFollowRegularFile(caPubFile);
22919
22945
  await writeFileAtomic(caKeyFile, certResult.keyPem, 384);
22946
+ replacedKey = true;
22920
22947
  await writeFileAtomic(caPubFile, certResult.certPem);
22948
+ replacedPub = true;
22921
22949
  await writeFileAtomic(caCertFile, certResult.certPem);
22950
+ replacedCert = true;
22922
22951
  }
22923
22952
  let installedNew = false;
22924
22953
  if (caTrustInstaller && !installerCalled) {
@@ -25103,6 +25132,133 @@ function forwardRequestHeaders(headers, host, contentLength) {
25103
25132
  }
25104
25133
  return out;
25105
25134
  }
25135
+ var defaultResolver2 = {
25136
+ async lookup(hostname, signal) {
25137
+ if (signal?.aborted) throw new Error("aborted");
25138
+ const addresses = await dnsLookup2(hostname, { all: true });
25139
+ return addresses.map((address) => ({
25140
+ address: address.address,
25141
+ family: address.family === 6 ? 6 : 4
25142
+ }));
25143
+ }
25144
+ };
25145
+ var defaultDial = (port, address) => connect(port, address);
25146
+ function localOriginsFromProject(project) {
25147
+ if (project === null || typeof project !== "object") return [];
25148
+ const policy = project.requestBodyPolicy;
25149
+ if (policy === null || typeof policy !== "object") return [];
25150
+ const origins = policy.localOrigins;
25151
+ if (!Array.isArray(origins)) return [];
25152
+ return origins.filter(
25153
+ (origin) => typeof origin === "string"
25154
+ );
25155
+ }
25156
+ function effectiveLocalOrigins(policy) {
25157
+ if (policy === null) return /* @__PURE__ */ new Set();
25158
+ const raw = policy.localOrigins ?? localOriginsFromProject(policy.project);
25159
+ const origins = /* @__PURE__ */ new Set();
25160
+ for (const origin of raw) {
25161
+ const normalized = normalizeSiteOrigin(origin);
25162
+ if (normalized !== null) origins.add(normalized);
25163
+ }
25164
+ return origins;
25165
+ }
25166
+ function compareAddresses(left, right) {
25167
+ return left.family - right.family || (left.address < right.address ? -1 : left.address > right.address ? 1 : 0);
25168
+ }
25169
+ function selectPinnedAddress(addresses, allowNonPublic) {
25170
+ const publicOnly = validateResolvedAddresses(
25171
+ addresses,
25172
+ RUNTIME_LIMITS.maxDnsAddresses
25173
+ );
25174
+ if (publicOnly !== null) return publicOnly[0] ?? null;
25175
+ if (!allowNonPublic) return null;
25176
+ if (addresses.length === 0 || addresses.length > RUNTIME_LIMITS.maxDnsAddresses) {
25177
+ return null;
25178
+ }
25179
+ const checked = [];
25180
+ for (const address of addresses) {
25181
+ if (address.family !== 4 && address.family !== 6) return null;
25182
+ const classification = classifyAddress(address.address);
25183
+ if (classification === "invalid" || classification === "public") {
25184
+ return null;
25185
+ }
25186
+ checked.push({ address: address.address, family: address.family });
25187
+ }
25188
+ checked.sort(compareAddresses);
25189
+ return checked[0] ?? null;
25190
+ }
25191
+ async function pinHostname(hostname, origin, deps) {
25192
+ if (hostname.length === 0) return null;
25193
+ let resolved;
25194
+ try {
25195
+ resolved = await deps.resolver.lookup(hostname);
25196
+ } catch {
25197
+ return null;
25198
+ }
25199
+ const normalized = normalizeSiteOrigin(origin);
25200
+ const allowNonPublic = normalized !== null && deps.localOrigins.has(normalized);
25201
+ return selectPinnedAddress(resolved, allowNonPublic);
25202
+ }
25203
+ function httpUpstreamPort(target) {
25204
+ if (target.protocol !== "http:") return null;
25205
+ if (target.username.length > 0 || target.password.length > 0) return null;
25206
+ if (target.port.length === 0 || target.port === "80") return 80;
25207
+ return null;
25208
+ }
25209
+ function formatUpstreamRequest(method, path2, headers) {
25210
+ const lines = [];
25211
+ for (const [name, value] of Object.entries(headers)) {
25212
+ if (name.includes("\r") || name.includes("\n") || value.includes("\r") || value.includes("\n")) {
25213
+ return null;
25214
+ }
25215
+ lines.push(`${name}: ${value}`);
25216
+ }
25217
+ return `${method} ${path2} HTTP/1.1\r
25218
+ ${lines.join("\r\n")}\r
25219
+ \r
25220
+ `;
25221
+ }
25222
+ function httpsOrigin(host) {
25223
+ const authority = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
25224
+ try {
25225
+ return new URL(`https://${authority}`).origin;
25226
+ } catch {
25227
+ return null;
25228
+ }
25229
+ }
25230
+ function parseConnectAuthority(authority) {
25231
+ if (authority.length === 0) return null;
25232
+ let host;
25233
+ let portText;
25234
+ if (authority.startsWith("[")) {
25235
+ const end = authority.indexOf("]");
25236
+ if (end <= 1) return null;
25237
+ host = authority.slice(1, end);
25238
+ const rest = authority.slice(end + 1);
25239
+ if (!rest.startsWith(":")) return null;
25240
+ portText = rest.slice(1);
25241
+ } else {
25242
+ const colon = authority.lastIndexOf(":");
25243
+ if (colon <= 0) return null;
25244
+ host = authority.slice(0, colon);
25245
+ portText = authority.slice(colon + 1);
25246
+ }
25247
+ if (host.length === 0 || !/^\d+$/.test(portText)) return null;
25248
+ const port = Number(portText);
25249
+ if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
25250
+ return { host, port };
25251
+ }
25252
+ function endConnect(socket, status, reason) {
25253
+ if (socket.destroyed || socket.writableEnded) return;
25254
+ socket.end(
25255
+ `HTTP/1.1 ${status} ${reason}\r
25256
+ Content-Length: 0\r
25257
+ Connection: close\r
25258
+ \r
25259
+ `
25260
+ );
25261
+ }
25106
25262
  function pipeSockets(a, b) {
25107
25263
  a.pipe(b);
25108
25264
  b.pipe(a);
@@ -25115,11 +25271,16 @@ function pipeSockets(a, b) {
25115
25271
  a.on("close", () => b.destroy());
25116
25272
  b.on("close", () => a.destroy());
25117
25273
  }
25118
- async function upstreamHttp(method, target, headers, body) {
25119
- const port = target.port ? Number(target.port) : 80;
25274
+ async function upstreamHttp(method, target, headers, body, deps) {
25275
+ const port = httpUpstreamPort(target);
25276
+ if (port === null) return { ok: false, status: 403 };
25120
25277
  const path2 = `${target.pathname}${target.search}`;
25278
+ const head = formatUpstreamRequest(method, path2, headers);
25279
+ if (head === null) return { ok: false, status: 403 };
25280
+ const pinned = await pinHostname(target.hostname, target.origin, deps);
25281
+ if (pinned === null) return { ok: false, status: 403 };
25121
25282
  return new Promise((resolve12, reject) => {
25122
- const socket = connect(port, target.hostname);
25283
+ const socket = deps.dial(port, pinned.address);
25123
25284
  let buf = Buffer.alloc(0);
25124
25285
  let settled = false;
25125
25286
  const fail2 = (err) => {
@@ -25132,11 +25293,7 @@ async function upstreamHttp(method, target, headers, body) {
25132
25293
  socket.on("timeout", () => fail2(new Error("upstream timeout")));
25133
25294
  socket.on("error", (err) => fail2(err));
25134
25295
  socket.on("connect", () => {
25135
- const lines = Object.entries(headers).map(([k, v]) => `${k}: ${v}`).join("\r\n");
25136
- socket.write(`${method} ${path2} HTTP/1.1\r
25137
- ${lines}\r
25138
- \r
25139
- `);
25296
+ socket.write(head);
25140
25297
  if (body.byteLength > 0) socket.write(body);
25141
25298
  });
25142
25299
  socket.on("data", (chunk) => {
@@ -25144,9 +25301,9 @@ ${lines}\r
25144
25301
  buf = Buffer.concat([buf, piece]);
25145
25302
  const sep = buf.indexOf("\r\n\r\n");
25146
25303
  if (sep < 0) return;
25147
- const head = buf.subarray(0, sep).toString("latin1");
25304
+ const head2 = buf.subarray(0, sep).toString("latin1");
25148
25305
  const statusMatch = /^HTTP\/1\.[01] (\d+)(?: (.*))?/.exec(
25149
- head.split("\r\n")[0] ?? ""
25306
+ head2.split("\r\n")[0] ?? ""
25150
25307
  );
25151
25308
  if (!statusMatch) {
25152
25309
  fail2(new Error("bad upstream status"));
@@ -25155,7 +25312,7 @@ ${lines}\r
25155
25312
  const status = Number(statusMatch[1]);
25156
25313
  const statusMessage = statusMatch[2]?.trim() ?? "";
25157
25314
  const headerMap = {};
25158
- for (const line of head.split("\r\n").slice(1)) {
25315
+ for (const line of head2.split("\r\n").slice(1)) {
25159
25316
  const i = line.indexOf(":");
25160
25317
  if (i <= 0) continue;
25161
25318
  const name = line.slice(0, i).trim().toLowerCase();
@@ -25175,6 +25332,7 @@ ${lines}\r
25175
25332
  settled = true;
25176
25333
  socket.destroy();
25177
25334
  resolve12({
25335
+ ok: true,
25178
25336
  status,
25179
25337
  statusMessage,
25180
25338
  headers: headerMap,
@@ -25190,16 +25348,16 @@ ${lines}\r
25190
25348
  fail2(new Error("upstream closed early"));
25191
25349
  return;
25192
25350
  }
25193
- const head = buf.subarray(0, sep).toString("latin1");
25351
+ const head2 = buf.subarray(0, sep).toString("latin1");
25194
25352
  const statusMatch = /^HTTP\/1\.[01] (\d+)(?: (.*))?/.exec(
25195
- head.split("\r\n")[0] ?? ""
25353
+ head2.split("\r\n")[0] ?? ""
25196
25354
  );
25197
25355
  if (!statusMatch) {
25198
25356
  fail2(new Error("bad upstream status"));
25199
25357
  return;
25200
25358
  }
25201
25359
  const headerMap = {};
25202
- for (const line of head.split("\r\n").slice(1)) {
25360
+ for (const line of head2.split("\r\n").slice(1)) {
25203
25361
  const i = line.indexOf(":");
25204
25362
  if (i <= 0) continue;
25205
25363
  headerMap[line.slice(0, i).trim().toLowerCase()] = line.slice(i + 1).trim();
@@ -25214,6 +25372,7 @@ ${lines}\r
25214
25372
  }
25215
25373
  settled = true;
25216
25374
  resolve12({
25375
+ ok: true,
25217
25376
  status: Number(statusMatch[1]),
25218
25377
  statusMessage: statusMatch[2]?.trim() ?? "",
25219
25378
  headers: headerMap,
@@ -25289,6 +25448,8 @@ function authorizeOp(policy, op, url, method, headers) {
25289
25448
  async function startInterceptProxy(options = {}) {
25290
25449
  let policy = options.policy ?? null;
25291
25450
  const serveMock = options.serveMock;
25451
+ const resolver = options.resolver ?? defaultResolver2;
25452
+ const dial = options.dial ?? defaultDial;
25292
25453
  let activeMocks = 0;
25293
25454
  const mockAborts = /* @__PURE__ */ new Set();
25294
25455
  let stopped = false;
@@ -25383,8 +25544,24 @@ async function startInterceptProxy(options = {}) {
25383
25544
  method,
25384
25545
  target,
25385
25546
  forwardHeaders,
25386
- requestBody
25547
+ requestBody,
25548
+ {
25549
+ resolver,
25550
+ dial,
25551
+ localOrigins: effectiveLocalOrigins(active)
25552
+ }
25387
25553
  );
25554
+ if (!upstream.ok) {
25555
+ if (!res.headersSent) {
25556
+ res.writeHead(upstream.status, {
25557
+ "cache-control": "no-store",
25558
+ "content-length": "0",
25559
+ connection: "close"
25560
+ });
25561
+ res.end();
25562
+ }
25563
+ return;
25564
+ }
25388
25565
  let responseBody = upstream.body;
25389
25566
  if (responseOp !== null && active !== null) {
25390
25567
  if (responseBody.byteLength > RUNTIME_LIMITS.maxResponseBodyBytes) {
@@ -25580,25 +25757,52 @@ async function startInterceptProxy(options = {}) {
25580
25757
  );
25581
25758
  }
25582
25759
  function handleConnect(req, clientSocket, head) {
25583
- const authority = req.url ?? "";
25584
- const [host, portText] = authority.split(":");
25585
- const port = Number(portText);
25586
- if (!host || !Number.isInteger(port) || port <= 0) {
25587
- clientSocket.write("HTTP/1.1 400 Bad Request\r\n\r\n");
25588
- clientSocket.destroy();
25760
+ void tunnelConnect(req, clientSocket, head);
25761
+ }
25762
+ async function tunnelConnect(req, clientSocket, head) {
25763
+ let upstream;
25764
+ clientSocket.on("error", () => upstream?.destroy());
25765
+ const parsed = parseConnectAuthority(req.url ?? "");
25766
+ if (parsed === null) {
25767
+ endConnect(clientSocket, 400, "Bad Request");
25768
+ return;
25769
+ }
25770
+ if (parsed.port !== 443) {
25771
+ endConnect(clientSocket, 403, "Forbidden");
25772
+ return;
25773
+ }
25774
+ const pinned = await pinHostname(
25775
+ parsed.host,
25776
+ httpsOrigin(parsed.host) ?? "",
25777
+ {
25778
+ resolver,
25779
+ dial,
25780
+ localOrigins: effectiveLocalOrigins(policy)
25781
+ }
25782
+ );
25783
+ if (pinned === null || clientSocket.destroyed) {
25784
+ endConnect(clientSocket, 403, "Forbidden");
25589
25785
  return;
25590
25786
  }
25591
- const upstream = connect(port, host);
25592
- upstream.on("connect", () => {
25787
+ let upstreamSocket;
25788
+ try {
25789
+ upstreamSocket = dial(443, pinned.address);
25790
+ } catch {
25791
+ endConnect(clientSocket, 502, "Bad Gateway");
25792
+ return;
25793
+ }
25794
+ upstream = upstreamSocket;
25795
+ upstreamSocket.on("connect", () => {
25593
25796
  clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
25594
- if (head.byteLength > 0) upstream.write(head);
25595
- pipeSockets(clientSocket, upstream);
25797
+ if (head.byteLength > 0) upstreamSocket.write(head);
25798
+ pipeSockets(clientSocket, upstreamSocket);
25596
25799
  });
25597
- upstream.on("error", () => {
25598
- clientSocket.write("HTTP/1.1 502 Bad Gateway\r\n\r\n");
25599
- clientSocket.destroy();
25800
+ upstreamSocket.on("error", () => {
25801
+ if (!clientSocket.destroyed && !clientSocket.writableEnded) {
25802
+ endConnect(clientSocket, 502, "Bad Gateway");
25803
+ }
25804
+ upstreamSocket.destroy();
25600
25805
  });
25601
- clientSocket.on("error", () => upstream.destroy());
25602
25806
  }
25603
25807
  const endpoint = await new Promise((resolve12, reject) => {
25604
25808
  server.once("error", reject);
@@ -25649,7 +25853,10 @@ async function startInterception(activation, policyDigest, extensionId, pacRoute
25649
25853
  const sessionId = `session-${activation.startedAt}-${Math.random().toString(36).slice(2)}`;
25650
25854
  let proxy;
25651
25855
  try {
25652
- const started = await registeredProvider.start(activation);
25856
+ const started = await registeredProvider.start({
25857
+ ...activation,
25858
+ localOrigins: targetPolicy.localOrigins
25859
+ });
25653
25860
  if (started && typeof started === "object" && typeof started.host === "string" && typeof started.port === "number") {
25654
25861
  proxy = started;
25655
25862
  } else if (activation.proxy) {
@@ -27386,6 +27593,25 @@ function createNativeHost(options) {
27386
27593
  ...options.clock ? { clock: options.clock } : {}
27387
27594
  });
27388
27595
  let interceptProxy = null;
27596
+ function policyForProxy(activation) {
27597
+ const policy = controller.getActivePolicy();
27598
+ if (!policy) return null;
27599
+ const fromProject = localOriginsFromProject(policy.project);
27600
+ const fromSession = activation.localOrigins ?? [];
27601
+ const localOrigins = [];
27602
+ const seen = /* @__PURE__ */ new Set();
27603
+ for (const origin of [...fromProject, ...fromSession]) {
27604
+ if (seen.has(origin)) continue;
27605
+ seen.add(origin);
27606
+ localOrigins.push(origin);
27607
+ }
27608
+ return {
27609
+ project: policy.project,
27610
+ operations: policy.operations,
27611
+ presetDigest: policy.presetDigest,
27612
+ localOrigins
27613
+ };
27614
+ }
27389
27615
  let outboundWrite = null;
27390
27616
  let hostRequestCounter = 0;
27391
27617
  const pendingHost = /* @__PURE__ */ new Map();
@@ -27454,18 +27680,13 @@ function createNativeHost(options) {
27454
27680
  } catch {
27455
27681
  }
27456
27682
  },
27457
- async startTlsProxy() {
27683
+ async startTlsProxy(activation) {
27458
27684
  if (interceptProxy) {
27459
27685
  await interceptProxy.stop();
27460
27686
  interceptProxy = null;
27461
27687
  }
27462
- const policy = controller.getActivePolicy();
27463
27688
  interceptProxy = await startInterceptProxy({
27464
- policy: policy ? {
27465
- project: policy.project,
27466
- operations: policy.operations,
27467
- presetDigest: policy.presetDigest
27468
- } : null,
27689
+ policy: policyForProxy(activation),
27469
27690
  serveMock: (request) => controller.serveMock(request.token, {
27470
27691
  method: request.method,
27471
27692
  signal: request.signal
@@ -27488,14 +27709,7 @@ function createNativeHost(options) {
27488
27709
  async start(activation) {
27489
27710
  const routes = pendingRoutes.length > 0 ? pendingRoutes : activation.pacRoutes;
27490
27711
  const endpoint = await platformProvider.start(activation, routes);
27491
- const policy = controller.getActivePolicy();
27492
- interceptProxy?.setPolicy(
27493
- policy ? {
27494
- project: policy.project,
27495
- operations: policy.operations,
27496
- presetDigest: policy.presetDigest
27497
- } : null
27498
- );
27712
+ interceptProxy?.setPolicy(policyForProxy(activation));
27499
27713
  return endpoint;
27500
27714
  },
27501
27715
  async stop() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogatio/cli",
3
- "version": "6.16.1",
3
+ "version": "6.16.3",
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.",