@astrasyncai/verification-gateway 5.16.0 → 5.17.0

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 (71) hide show
  1. package/dist/adapters/express.js +1 -1
  2. package/dist/adapters/express.js.map +1 -1
  3. package/dist/adapters/express.mjs +1 -1
  4. package/dist/adapters/express.mjs.map +1 -1
  5. package/dist/adapters/mcp.js +1 -1
  6. package/dist/adapters/mcp.js.map +1 -1
  7. package/dist/adapters/mcp.mjs +1 -1
  8. package/dist/adapters/mcp.mjs.map +1 -1
  9. package/dist/adapters/nextjs.js +1 -1
  10. package/dist/adapters/nextjs.js.map +1 -1
  11. package/dist/adapters/nextjs.mjs +1 -1
  12. package/dist/adapters/nextjs.mjs.map +1 -1
  13. package/dist/adapters/sdk.js +1 -1
  14. package/dist/adapters/sdk.js.map +1 -1
  15. package/dist/adapters/sdk.mjs +1 -1
  16. package/dist/adapters/sdk.mjs.map +1 -1
  17. package/dist/agent/index.js +1 -1
  18. package/dist/agent/index.js.map +1 -1
  19. package/dist/agent/index.mjs +1 -1
  20. package/dist/agent/index.mjs.map +1 -1
  21. package/dist/bin/astrasync-claude-hook.js +1 -1
  22. package/dist/bin/astrasync-codex-hook.js +1 -1
  23. package/dist/bin/astrasync-guard.js +422 -25
  24. package/dist/bin/astrasync.js +445 -28
  25. package/dist/browser/background.js +1 -1
  26. package/dist/browser/background.js.map +1 -1
  27. package/dist/browser/background.mjs +1 -1
  28. package/dist/browser/background.mjs.map +1 -1
  29. package/dist/cli/index.js +1 -1
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/cli/index.mjs +1 -1
  32. package/dist/cli/index.mjs.map +1 -1
  33. package/dist/codex/index.js +1 -1
  34. package/dist/codex/index.js.map +1 -1
  35. package/dist/codex/index.mjs +1 -1
  36. package/dist/codex/index.mjs.map +1 -1
  37. package/dist/cursor/extension.js +1 -1
  38. package/dist/cursor/extension.js.map +1 -1
  39. package/dist/cursor/extension.mjs +1 -1
  40. package/dist/cursor/extension.mjs.map +1 -1
  41. package/dist/edge-config.js +1 -1
  42. package/dist/edge-config.js.map +1 -1
  43. package/dist/edge-config.mjs +1 -1
  44. package/dist/edge-config.mjs.map +1 -1
  45. package/dist/edge-core/index.js +1 -1
  46. package/dist/edge-core/index.js.map +1 -1
  47. package/dist/edge-core/index.mjs +1 -1
  48. package/dist/edge-core/index.mjs.map +1 -1
  49. package/dist/gateway/gateway.js +1 -1
  50. package/dist/gateway/gateway.js.map +1 -1
  51. package/dist/gateway/gateway.mjs +1 -1
  52. package/dist/gateway/gateway.mjs.map +1 -1
  53. package/dist/index.d.mts +2 -2
  54. package/dist/index.d.ts +2 -2
  55. package/dist/index.js +1 -1
  56. package/dist/index.js.map +1 -1
  57. package/dist/index.mjs +1 -1
  58. package/dist/index.mjs.map +1 -1
  59. package/dist/registration/index.js +1 -1
  60. package/dist/registration/index.js.map +1 -1
  61. package/dist/registration/index.mjs +1 -1
  62. package/dist/registration/index.mjs.map +1 -1
  63. package/dist/transport/index.js +1 -1
  64. package/dist/transport/index.js.map +1 -1
  65. package/dist/transport/index.mjs +1 -1
  66. package/dist/transport/index.mjs.map +1 -1
  67. package/dist/verify.js +1 -1
  68. package/dist/verify.js.map +1 -1
  69. package/dist/verify.mjs +1 -1
  70. package/dist/verify.mjs.map +1 -1
  71. package/package.json +1 -1
@@ -36,7 +36,7 @@ var SDK_VERSION;
36
36
  var init_version = __esm({
37
37
  "src/version.ts"() {
38
38
  "use strict";
39
- SDK_VERSION = "5.16.0";
39
+ SDK_VERSION = "5.17.0";
40
40
  }
41
41
  });
42
42
 
@@ -49,10 +49,10 @@ function withUserAgent(initHeaders) {
49
49
  return copy;
50
50
  }
51
51
  if (Array.isArray(initHeaders)) {
52
- const has2 = initHeaders.some(([name]) => name.toLowerCase() === "user-agent");
52
+ const has2 = initHeaders.some(([name2]) => name2.toLowerCase() === "user-agent");
53
53
  return has2 ? initHeaders : [...initHeaders, ["user-agent", SDK_USER_AGENT]];
54
54
  }
55
- const has = Object.keys(initHeaders).some((name) => name.toLowerCase() === "user-agent");
55
+ const has = Object.keys(initHeaders).some((name2) => name2.toLowerCase() === "user-agent");
56
56
  return has ? initHeaders : { "user-agent": SDK_USER_AGENT, ...initHeaders };
57
57
  }
58
58
  var SDK_USER_AGENT, sdkFetch;
@@ -611,9 +611,9 @@ function requireType() {
611
611
  }
612
612
  function Type2(tag, options) {
613
613
  options = options || {};
614
- Object.keys(options).forEach(function(name) {
615
- if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
616
- throw new YAMLException2('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
614
+ Object.keys(options).forEach(function(name2) {
615
+ if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name2) === -1) {
616
+ throw new YAMLException2('Unknown option "' + name2 + '" is met in definition of "' + tag + '" YAML type.');
617
617
  }
618
618
  });
619
619
  this.options = options;
@@ -644,9 +644,9 @@ function requireSchema() {
644
644
  hasRequiredSchema = 1;
645
645
  const YAMLException2 = requireException();
646
646
  const Type2 = requireType();
647
- function compileList(schema2, name) {
647
+ function compileList(schema2, name2) {
648
648
  const result = [];
649
- schema2[name].forEach(function(currentType) {
649
+ schema2[name2].forEach(function(currentType) {
650
650
  let newIndex = result.length;
651
651
  result.forEach(function(previousType, previousIndex) {
652
652
  if (previousType.tag === currentType.tag && previousType.kind === currentType.kind && previousType.multi === currentType.multi) {
@@ -1520,18 +1520,18 @@ function requireLoader() {
1520
1520
  state.onWarning.call(null, generateError(state, message));
1521
1521
  }
1522
1522
  }
1523
- function storeAnchor(state, name, value) {
1523
+ function storeAnchor(state, name2, value) {
1524
1524
  const transactions = state.anchorMapTransactions;
1525
1525
  if (transactions.length !== 0) {
1526
1526
  const transaction = transactions[transactions.length - 1];
1527
- if (!_hasOwnProperty.call(transaction, name)) {
1528
- transaction[name] = {
1529
- existed: _hasOwnProperty.call(state.anchorMap, name),
1530
- value: state.anchorMap[name]
1527
+ if (!_hasOwnProperty.call(transaction, name2)) {
1528
+ transaction[name2] = {
1529
+ existed: _hasOwnProperty.call(state.anchorMap, name2),
1530
+ value: state.anchorMap[name2]
1531
1531
  };
1532
1532
  }
1533
1533
  }
1534
- state.anchorMap[name] = value;
1534
+ state.anchorMap[name2] = value;
1535
1535
  }
1536
1536
  function beginAnchorTransaction(state) {
1537
1537
  state.anchorMapTransactions.push(/* @__PURE__ */ Object.create(null));
@@ -1543,9 +1543,9 @@ function requireLoader() {
1543
1543
  const parent = transactions[transactions.length - 1];
1544
1544
  const names = Object.keys(transaction);
1545
1545
  for (let index = 0, length = names.length; index < length; index += 1) {
1546
- const name = names[index];
1547
- if (!_hasOwnProperty.call(parent, name)) {
1548
- parent[name] = transaction[name];
1546
+ const name2 = names[index];
1547
+ if (!_hasOwnProperty.call(parent, name2)) {
1548
+ parent[name2] = transaction[name2];
1549
1549
  }
1550
1550
  }
1551
1551
  }
@@ -1586,7 +1586,7 @@ function requireLoader() {
1586
1586
  state.result = snapshot.result;
1587
1587
  }
1588
1588
  const directiveHandlers = {
1589
- YAML: function handleYamlDirective(state, name, args) {
1589
+ YAML: function handleYamlDirective(state, name2, args) {
1590
1590
  if (state.version !== null) {
1591
1591
  throwError(state, "duplication of %YAML directive");
1592
1592
  }
@@ -1608,7 +1608,7 @@ function requireLoader() {
1608
1608
  throwWarning(state, "unsupported YAML version of the document");
1609
1609
  }
1610
1610
  },
1611
- TAG: function handleTagDirective(state, name, args) {
1611
+ TAG: function handleTagDirective(state, name2, args) {
1612
1612
  let prefix;
1613
1613
  if (args.length !== 2) {
1614
1614
  throwError(state, "TAG directive accepts exactly two arguments");
@@ -3938,10 +3938,10 @@ ${category.label}
3938
3938
  scope.blockedResources = additionalBlocked;
3939
3939
  }
3940
3940
  this.print("");
3941
- const name = (await this.ask("Policy name [default: local-guard]: ")).trim() || "local-guard";
3941
+ const name2 = (await this.ask("Policy name [default: local-guard]: ")).trim() || "local-guard";
3942
3942
  const policy = {
3943
3943
  version: "1.0",
3944
- name,
3944
+ name: name2,
3945
3945
  purposes,
3946
3946
  ...scope && { scope },
3947
3947
  ...limits && { limits },
@@ -4662,8 +4662,8 @@ function extractBacktickSubstitutions(text, collect) {
4662
4662
  }
4663
4663
  function basename(token) {
4664
4664
  const slash = Math.max(token.lastIndexOf("/"), token.lastIndexOf("\\"));
4665
- const name = slash === -1 ? token : token.slice(slash + 1);
4666
- return name.replace(/\.(exe|cmd|bat|ps1)$/i, "");
4665
+ const name2 = slash === -1 ? token : token.slice(slash + 1);
4666
+ return name2.replace(/\.(exe|cmd|bat|ps1)$/i, "");
4667
4667
  }
4668
4668
  function matchSegment(segment, list) {
4669
4669
  const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
@@ -7617,7 +7617,7 @@ function ensureGuardSelfProtection(policyPath) {
7617
7617
  (0, import_fs5.writeFileSync)(policyPath, toYaml(parsed.policy), "utf-8");
7618
7618
  return true;
7619
7619
  }
7620
- function buildDefaultClaudeCodePolicy(name = "claude-code-local-guard") {
7620
+ function buildDefaultClaudeCodePolicy(name2 = "claude-code-local-guard") {
7621
7621
  const recommendedCommands = DEFAULT_BLOCKED_COMMANDS.filter((c) => c.recommended).map(
7622
7622
  (c) => c.pattern
7623
7623
  );
@@ -7625,7 +7625,7 @@ function buildDefaultClaudeCodePolicy(name = "claude-code-local-guard") {
7625
7625
  const permissive = RISK_PRESETS.find((p) => p.name === "permissive");
7626
7626
  return {
7627
7627
  version: "1.0",
7628
- name,
7628
+ name: name2,
7629
7629
  description: "AstraSync Local Guard for Claude Code \u2014 default coding-agent policy. Edit freely; the hook re-reads this file on every tool call.",
7630
7630
  purposes: [
7631
7631
  {
@@ -8344,6 +8344,390 @@ var init_git_route = __esm({
8344
8344
  }
8345
8345
  });
8346
8346
 
8347
+ // src/fleet/local-cert.ts
8348
+ function len(n) {
8349
+ if (n < 128) return Buffer.from([n]);
8350
+ const bytes = [];
8351
+ while (n > 0) {
8352
+ bytes.unshift(n & 255);
8353
+ n >>= 8;
8354
+ }
8355
+ return Buffer.from([128 | bytes.length, ...bytes]);
8356
+ }
8357
+ function oid(dotted) {
8358
+ const parts = dotted.split(".").map(Number);
8359
+ const out = [parts[0] * 40 + parts[1]];
8360
+ for (const p of parts.slice(2)) {
8361
+ const enc = [p & 127];
8362
+ let v = p >> 7;
8363
+ while (v > 0) {
8364
+ enc.unshift(v & 127 | 128);
8365
+ v >>= 7;
8366
+ }
8367
+ out.push(...enc);
8368
+ }
8369
+ return tlv(6, Buffer.from(out));
8370
+ }
8371
+ function integer(buf) {
8372
+ const b = buf[0] & 128 ? Buffer.concat([Buffer.from([0]), buf]) : buf;
8373
+ return tlv(2, b);
8374
+ }
8375
+ function utcTime(d) {
8376
+ const s = d.toISOString().replace(/[-:T]/g, "").slice(2, 14) + "Z";
8377
+ return tlv(23, Buffer.from(s, "ascii"));
8378
+ }
8379
+ function name(cn) {
8380
+ return seq2(set2(seq2(oid("2.5.4.3"), tlv(12, Buffer.from(cn, "utf8")))));
8381
+ }
8382
+ function createLocalCert(hosts, days = 30) {
8383
+ const { privateKey, publicKey } = import_node_crypto5.default.generateKeyPairSync("ec", { namedCurve: "P-256" });
8384
+ const spki = publicKey.export({ type: "spki", format: "der" });
8385
+ const now = Date.now();
8386
+ const san = seq2(...hosts.map((h) => tlv(130, Buffer.from(h, "ascii"))));
8387
+ const extensions = ctx(
8388
+ 3,
8389
+ seq2(
8390
+ seq2(oid("2.5.29.17"), tlv(4, san)),
8391
+ // subjectAltName
8392
+ seq2(oid("2.5.29.19"), tlv(4, seq2()))
8393
+ // basicConstraints: not a CA
8394
+ )
8395
+ );
8396
+ const subject = name("AstraSync Local Guard (browse)");
8397
+ const tbs = seq2(
8398
+ ctx(0, integer(Buffer.from([2]))),
8399
+ // v3
8400
+ integer(import_node_crypto5.default.randomBytes(16)),
8401
+ ECDSA_SHA256,
8402
+ subject,
8403
+ seq2(utcTime(new Date(now - 6e4)), utcTime(new Date(now + days * 864e5))),
8404
+ subject,
8405
+ spki,
8406
+ extensions
8407
+ );
8408
+ const signature = import_node_crypto5.default.sign("sha256", tbs, privateKey);
8409
+ const der = seq2(tbs, ECDSA_SHA256, tlv(3, Buffer.concat([Buffer.from([0]), signature])));
8410
+ const b64 = der.toString("base64").match(/.{1,64}/g).join("\n");
8411
+ return {
8412
+ cert: `-----BEGIN CERTIFICATE-----
8413
+ ${b64}
8414
+ -----END CERTIFICATE-----
8415
+ `,
8416
+ key: privateKey.export({ type: "pkcs8", format: "pem" }).toString()
8417
+ };
8418
+ }
8419
+ var import_node_crypto5, tlv, seq2, set2, ctx, ECDSA_SHA256;
8420
+ var init_local_cert = __esm({
8421
+ "src/fleet/local-cert.ts"() {
8422
+ "use strict";
8423
+ import_node_crypto5 = __toESM(require("crypto"));
8424
+ tlv = (tag, body) => Buffer.concat([Buffer.from([tag]), len(body.length), body]);
8425
+ seq2 = (...parts) => tlv(48, Buffer.concat(parts));
8426
+ set2 = (...parts) => tlv(49, Buffer.concat(parts));
8427
+ ctx = (n, body) => tlv(160 + n, body);
8428
+ ECDSA_SHA256 = seq2(oid("1.2.840.10045.4.3.2"));
8429
+ }
8430
+ });
8431
+
8432
+ // src/fleet/browse-proxy.ts
8433
+ function cleanHeaders(h) {
8434
+ const out = {};
8435
+ for (const [k, v] of Object.entries(h)) if (!HOP_BY_HOP.has(k) && v !== void 0) out[k] = v;
8436
+ return out;
8437
+ }
8438
+ async function startBrowseProxy(opts) {
8439
+ const hosts = new Set(opts.hosts.map((h) => h.toLowerCase()));
8440
+ const deviceHeader = `Device ${opts.deviceCredential}`;
8441
+ const { cert, key } = createLocalCert([...hosts]);
8442
+ function forward(req, res, target) {
8443
+ const headers = cleanHeaders(req.headers);
8444
+ headers["x-astra-device"] = deviceHeader;
8445
+ const mod = target.protocol === "https:" ? import_node_https.default : import_node_http.default;
8446
+ const upstream = mod.request(
8447
+ {
8448
+ host: target.host,
8449
+ port: target.port,
8450
+ method: req.method,
8451
+ path: target.path,
8452
+ headers,
8453
+ servername: target.protocol === "https:" ? String(req.headers.host ?? target.host).split(":")[0] : void 0,
8454
+ rejectUnauthorized: target.rejectUnauthorized ?? true
8455
+ },
8456
+ (up) => {
8457
+ res.writeHead(up.statusCode ?? 502, cleanHeaders(up.headers));
8458
+ up.pipe(res);
8459
+ }
8460
+ );
8461
+ upstream.on("error", () => {
8462
+ if (!res.headersSent) res.writeHead(502, { "content-type": "text/plain" });
8463
+ res.end("AstraSync browse proxy: upstream unreachable");
8464
+ });
8465
+ req.pipe(upstream);
8466
+ }
8467
+ function forwardUpgrade(req, socket, head, target) {
8468
+ const headers = { ...req.headers };
8469
+ delete headers["proxy-connection"];
8470
+ delete headers["proxy-authorization"];
8471
+ delete headers["x-astra-device"];
8472
+ if (target.addDevice) headers["x-astra-device"] = deviceHeader;
8473
+ const lines = [`${req.method} ${target.path} HTTP/1.1`];
8474
+ for (const [k, v] of Object.entries(headers)) {
8475
+ if (v === void 0) continue;
8476
+ for (const one of Array.isArray(v) ? v : [v]) lines.push(`${k}: ${one}`);
8477
+ }
8478
+ const onConnect = () => {
8479
+ upstream.write(lines.join("\r\n") + "\r\n\r\n");
8480
+ if (head.length) upstream.write(head);
8481
+ upstream.pipe(socket);
8482
+ socket.pipe(upstream);
8483
+ };
8484
+ const upstream = target.protocol === "https:" ? import_node_tls.default.connect(
8485
+ {
8486
+ host: target.host,
8487
+ port: target.port,
8488
+ servername: String(req.headers.host ?? target.host).split(":")[0],
8489
+ rejectUnauthorized: target.rejectUnauthorized ?? true
8490
+ },
8491
+ onConnect
8492
+ ) : import_node_net.default.connect(target.port, target.host, onConnect);
8493
+ upstream.on("error", () => socket.destroy());
8494
+ socket.on("error", () => upstream.destroy());
8495
+ }
8496
+ const inner = import_node_http.default.createServer((req, res) => {
8497
+ const hostHeader = String(req.headers.host ?? "");
8498
+ const [h, p] = hostHeader.split(":");
8499
+ const port2 = Number(p) || 443;
8500
+ const up = opts.upstreamFor?.(h, port2) ?? { host: h, port: port2 };
8501
+ forward(req, res, {
8502
+ protocol: "https:",
8503
+ host: up.host,
8504
+ port: up.port,
8505
+ path: req.url ?? "/",
8506
+ rejectUnauthorized: up.rejectUnauthorized
8507
+ });
8508
+ });
8509
+ const plainInner = import_node_http.default.createServer((req, res) => {
8510
+ const [h, p] = String(req.headers.host ?? "").split(":");
8511
+ forward(req, res, { protocol: "http:", host: h, port: Number(p) || 80, path: req.url ?? "/" });
8512
+ });
8513
+ plainInner.on("upgrade", (req, socket, head) => {
8514
+ const [h, p] = String(req.headers.host ?? "").split(":");
8515
+ forwardUpgrade(req, socket, head, {
8516
+ protocol: "http:",
8517
+ host: h,
8518
+ port: Number(p) || 80,
8519
+ path: req.url ?? "/",
8520
+ addDevice: true
8521
+ });
8522
+ });
8523
+ const server = import_node_http.default.createServer((req, res) => {
8524
+ let url;
8525
+ try {
8526
+ url = new URL(req.url ?? "");
8527
+ } catch {
8528
+ res.writeHead(400).end("absolute URL required");
8529
+ return;
8530
+ }
8531
+ if (hosts.has(url.hostname.toLowerCase())) {
8532
+ forward(req, res, {
8533
+ protocol: "http:",
8534
+ host: url.hostname,
8535
+ port: Number(url.port) || 80,
8536
+ path: `${url.pathname}${url.search}`
8537
+ });
8538
+ return;
8539
+ }
8540
+ const upstream = import_node_http.default.request(
8541
+ {
8542
+ host: url.hostname,
8543
+ port: Number(url.port) || 80,
8544
+ method: req.method,
8545
+ path: `${url.pathname}${url.search}`,
8546
+ headers: cleanHeaders(req.headers)
8547
+ },
8548
+ (up) => {
8549
+ res.writeHead(up.statusCode ?? 502, cleanHeaders(up.headers));
8550
+ up.pipe(res);
8551
+ }
8552
+ );
8553
+ upstream.on("error", () => res.writeHead(502).end());
8554
+ req.pipe(upstream);
8555
+ });
8556
+ inner.on("upgrade", (req, socket, head) => {
8557
+ const [h, p] = String(req.headers.host ?? "").split(":");
8558
+ const port2 = Number(p) || 443;
8559
+ const up = opts.upstreamFor?.(h, port2) ?? { host: h, port: port2 };
8560
+ forwardUpgrade(req, socket, head, {
8561
+ protocol: "https:",
8562
+ host: up.host,
8563
+ port: up.port,
8564
+ path: req.url ?? "/",
8565
+ addDevice: true,
8566
+ rejectUnauthorized: up.rejectUnauthorized
8567
+ });
8568
+ });
8569
+ server.on("upgrade", (req, socket, head) => {
8570
+ let url;
8571
+ try {
8572
+ url = new URL(req.url ?? "");
8573
+ } catch {
8574
+ socket.destroy();
8575
+ return;
8576
+ }
8577
+ forwardUpgrade(req, socket, head, {
8578
+ protocol: "http:",
8579
+ host: url.hostname,
8580
+ port: Number(url.port) || 80,
8581
+ path: `${url.pathname}${url.search}`,
8582
+ addDevice: hosts.has(url.hostname.toLowerCase())
8583
+ });
8584
+ });
8585
+ server.on("connect", (req, socket, head) => {
8586
+ const [host, portStr] = String(req.url ?? "").split(":");
8587
+ const port2 = Number(portStr) || 443;
8588
+ if (hosts.has(host.toLowerCase())) {
8589
+ socket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
8590
+ const start = (first) => {
8591
+ const s = socket;
8592
+ s.pause();
8593
+ s.unshift(first);
8594
+ if (first[0] === 22) {
8595
+ const tlsSocket = new import_node_tls.default.TLSSocket(s, {
8596
+ isServer: true,
8597
+ secureContext: import_node_tls.default.createSecureContext({ cert, key })
8598
+ });
8599
+ inner.emit("connection", tlsSocket);
8600
+ tlsSocket.on("error", () => socket.destroy());
8601
+ } else {
8602
+ plainInner.emit("connection", s);
8603
+ s.resume();
8604
+ }
8605
+ };
8606
+ if (head.length) start(head);
8607
+ else socket.once("data", (chunk) => start(chunk));
8608
+ return;
8609
+ }
8610
+ const upstream = import_node_net.default.connect(port2, host, () => {
8611
+ socket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
8612
+ if (head.length) upstream.write(head);
8613
+ upstream.pipe(socket);
8614
+ socket.pipe(upstream);
8615
+ });
8616
+ upstream.on("error", () => socket.destroy());
8617
+ socket.on("error", () => upstream.destroy());
8618
+ });
8619
+ await new Promise((resolve) => server.listen(opts.port ?? 0, "127.0.0.1", resolve));
8620
+ const port = server.address().port;
8621
+ return {
8622
+ port,
8623
+ close: () => new Promise((resolve) => {
8624
+ inner.close();
8625
+ plainInner.close();
8626
+ server.close(() => resolve());
8627
+ server.closeAllConnections?.();
8628
+ })
8629
+ };
8630
+ }
8631
+ var import_node_http, import_node_https, import_node_net, import_node_tls, HOP_BY_HOP;
8632
+ var init_browse_proxy = __esm({
8633
+ "src/fleet/browse-proxy.ts"() {
8634
+ "use strict";
8635
+ import_node_http = __toESM(require("http"));
8636
+ import_node_https = __toESM(require("https"));
8637
+ import_node_net = __toESM(require("net"));
8638
+ import_node_tls = __toESM(require("tls"));
8639
+ init_local_cert();
8640
+ HOP_BY_HOP = /* @__PURE__ */ new Set([
8641
+ "connection",
8642
+ "proxy-connection",
8643
+ "keep-alive",
8644
+ "transfer-encoding",
8645
+ "upgrade",
8646
+ "te",
8647
+ "trailer",
8648
+ "proxy-authorization"
8649
+ ]);
8650
+ }
8651
+ });
8652
+
8653
+ // src/fleet/browse.ts
8654
+ async function runBrowse(paths, opts) {
8655
+ const log = opts.log ?? ((l) => console.log(l));
8656
+ const f = opts.fetchImpl ?? fetch;
8657
+ const loaded = loadEnrolment(paths);
8658
+ if (!loaded || !("enrolment" in loaded)) {
8659
+ throw new Error("This machine is not enrolled. Run: astrasync guard enroll <token>");
8660
+ }
8661
+ const { credential, apiBaseUrl } = loaded.enrolment;
8662
+ if (!opts.checkpoint || !opts.slug) throw new Error("--checkpoint and --slug are required");
8663
+ const appOrigin = new URL(apiBaseUrl).origin;
8664
+ const hosts = [new URL(apiBaseUrl).hostname, ...opts.extraHosts ?? []];
8665
+ const device = `Device ${credential}`;
8666
+ const proxy = await startBrowseProxy({ hosts, deviceCredential: credential, port: opts.port });
8667
+ try {
8668
+ const base2 = opts.checkpoint.replace(/\/+$/, "");
8669
+ const signin = await f(
8670
+ `${base2}/a/${encodeURIComponent(opts.slug)}/h/${encodeURIComponent(opts.upstream ?? "astrasync-api")}/agent-sessions`,
8671
+ {
8672
+ method: "POST",
8673
+ headers: { authorization: device, "content-type": "application/json" },
8674
+ body: "{}"
8675
+ }
8676
+ );
8677
+ const body = await signin.json().catch(() => ({}));
8678
+ if (signin.status !== 201 && signin.status !== 202) {
8679
+ throw new Error(
8680
+ `Sign-in refused (${signin.status}${body.code ? ` ${body.code}` : ""}): ${body.message ?? "no detail"}`
8681
+ );
8682
+ }
8683
+ const sessionId = String(body.data?.sessionId ?? "");
8684
+ let code = body.data?.code;
8685
+ if (!code) {
8686
+ log("Waiting for the owner to approve this sign-in with their passkey\u2026");
8687
+ const deadline = Date.now() + (opts.waitMs ?? 10 * 6e4);
8688
+ while (!code) {
8689
+ if (Date.now() > deadline) throw new Error("The owner did not approve in time.");
8690
+ await new Promise((r) => setTimeout(r, opts.pollIntervalMs ?? 3e3));
8691
+ const poll = await f(
8692
+ `${apiBaseUrl.replace(/\/+$/, "")}/agent-sessions/${sessionId}/status`,
8693
+ {
8694
+ headers: { "x-astra-device": device }
8695
+ }
8696
+ );
8697
+ const p = await poll.json().catch(() => ({}));
8698
+ const status = p.data?.status;
8699
+ if (status === "approved") code = p.data?.code;
8700
+ else if (status === "denied" || status === "ended")
8701
+ throw new Error(`Sign-in ${status === "denied" ? "was not approved" : "ended"}.`);
8702
+ }
8703
+ }
8704
+ const openUrl = `${appOrigin}/agent-session#code=${code}`;
8705
+ log("");
8706
+ log(`Signed in. Open this once (within 2 minutes), through the proxy:`);
8707
+ log(` ${openUrl}`);
8708
+ log("");
8709
+ log(
8710
+ `Device proxy: http://127.0.0.1:${proxy.port} (adds this machine's credential for ${hosts.join(", ")})`
8711
+ );
8712
+ log("Playwright:");
8713
+ log(
8714
+ ` chromium.launch({ proxy: { server: 'http://127.0.0.1:${proxy.port}' } }) + newContext({ ignoreHTTPSErrors: true })`
8715
+ );
8716
+ log("Requests that skip the proxy end the session. Ctrl-C stops the proxy.");
8717
+ return { proxy, openUrl, sessionId };
8718
+ } catch (err) {
8719
+ await proxy.close();
8720
+ throw err;
8721
+ }
8722
+ }
8723
+ var init_browse = __esm({
8724
+ "src/fleet/browse.ts"() {
8725
+ "use strict";
8726
+ init_enrolment_store();
8727
+ init_browse_proxy();
8728
+ }
8729
+ });
8730
+
8347
8731
  // src/cli/guard.ts
8348
8732
  var guard_exports = {};
8349
8733
  function createPrompt() {
@@ -8878,6 +9262,28 @@ async function cmdFleetStatus() {
8878
9262
  const status = await getFleetStatus(fleetPaths());
8879
9263
  for (const line of formatFleetStatus(status)) console.log(line);
8880
9264
  }
9265
+ async function cmdBrowse() {
9266
+ try {
9267
+ const port = flagValue("--port");
9268
+ const { proxy } = await runBrowse(fleetPaths(), {
9269
+ checkpoint: flagValue("--checkpoint") ?? "",
9270
+ slug: flagValue("--slug") ?? "",
9271
+ upstream: flagValue("--upstream"),
9272
+ port: port ? Number(port) : void 0,
9273
+ extraHosts: flagValue("--host") ? [flagValue("--host")] : []
9274
+ });
9275
+ const stop = async () => {
9276
+ await proxy.close();
9277
+ process.exit(0);
9278
+ };
9279
+ process.on("SIGINT", stop);
9280
+ process.on("SIGTERM", stop);
9281
+ await new Promise(() => void 0);
9282
+ } catch (err) {
9283
+ console.error(`browse failed: ${err instanceof Error ? err.message : String(err)}`);
9284
+ process.exit(1);
9285
+ }
9286
+ }
8881
9287
  async function cmdGitRoute() {
8882
9288
  try {
8883
9289
  if (process.argv.includes("--undo")) {
@@ -8975,6 +9381,9 @@ async function main() {
8975
9381
  case "git-route":
8976
9382
  await cmdGitRoute();
8977
9383
  break;
9384
+ case "browse":
9385
+ await cmdBrowse();
9386
+ break;
8978
9387
  case "git-credential":
8979
9388
  await cmdGitCredential();
8980
9389
  break;
@@ -8998,6 +9407,12 @@ async function main() {
8998
9407
  console.log(" install-codex Install the Local Guard hook for OpenAI Codex CLI");
8999
9408
  console.log(" (same flags; policy shared with Claude Code)");
9000
9409
  console.log(" uninstall-codex Remove the Codex hook (--project for project scope)");
9410
+ console.log(
9411
+ " browse Sign an agent in to your dashboard from this machine and"
9412
+ );
9413
+ console.log(
9414
+ " run its device proxy (--checkpoint <url> --slug <agent>)"
9415
+ );
9001
9416
  console.log(" enroll <token> Enrol this machine in your organisation fleet");
9002
9417
  console.log(" (--api-base-url <url>, --system for machine scope)");
9003
9418
  console.log(" fleet-status Show fleet enrolment, signed policy and heartbeat");
@@ -9030,6 +9445,7 @@ var init_guard = __esm({
9030
9445
  init_cli();
9031
9446
  init_enrolment_store();
9032
9447
  init_git_route();
9448
+ init_browse();
9033
9449
  DEFAULT_POLICY_PATH = "./local-policy.yaml";
9034
9450
  DEFAULT_CONFIG_DIR = ".astrasync";
9035
9451
  main().catch((err) => {
@@ -9065,6 +9481,7 @@ COMMANDS:
9065
9481
  guard enroll <token> Enrol this machine in your organisation's fleet
9066
9482
  (--api-base-url <url>, --system for machine scope)
9067
9483
  guard fleet-status Fleet enrolment, signed policy and heartbeat state
9484
+ guard browse Sign an agent in to your dashboard via this machine's device proxy
9068
9485
  guard managed-settings MDM templates for Claude Code / Codex (--claude, --codex, --out <dir>)
9069
9486
 
9070
9487
  REGISTER OPTIONS:
@@ -9148,13 +9565,13 @@ async function main2() {
9148
9565
  baseUrl: config.baseUrl
9149
9566
  });
9150
9567
  if (command === "register") {
9151
- const name = commandArgs["name"];
9152
- if (!name) {
9568
+ const name2 = commandArgs["name"];
9569
+ if (!name2) {
9153
9570
  console.error("Error: --name is required for register command");
9154
9571
  process.exit(1);
9155
9572
  }
9156
9573
  const options = {
9157
- name,
9574
+ name: name2,
9158
9575
  ...commandArgs["description"] && { description: commandArgs["description"] },
9159
9576
  ...commandArgs["agent-type"] && { agentType: commandArgs["agent-type"] },
9160
9577
  ...commandArgs["api-endpoint"] && { apiEndpoint: commandArgs["api-endpoint"] }
@@ -3988,7 +3988,7 @@ function getTrustLevel(score) {
3988
3988
  }
3989
3989
 
3990
3990
  // src/version.ts
3991
- var SDK_VERSION = "5.16.0";
3991
+ var SDK_VERSION = "5.17.0";
3992
3992
 
3993
3993
  // src/http.ts
3994
3994
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;