tesseract-agent 0.9.30 → 0.9.32

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-bundle/cli.js +1731 -255
  2. package/package.json +1 -1
@@ -1885,7 +1885,7 @@ var require_sender = __commonJS({
1885
1885
  * @param {Function} [cb] Callback
1886
1886
  * @private
1887
1887
  */
1888
- getBlobData(blob, compress, options, cb) {
1888
+ getBlobData(blob, compress2, options, cb) {
1889
1889
  this._bufferedBytes += options[kByteLength];
1890
1890
  this._state = GET_BLOB_DATA;
1891
1891
  blob.arrayBuffer().then((arrayBuffer) => {
@@ -1898,12 +1898,12 @@ var require_sender = __commonJS({
1898
1898
  }
1899
1899
  this._bufferedBytes -= options[kByteLength];
1900
1900
  const data = toBuffer(arrayBuffer);
1901
- if (!compress) {
1901
+ if (!compress2) {
1902
1902
  this._state = DEFAULT;
1903
1903
  this.sendFrame(_Sender.frame(data, options), cb);
1904
1904
  this.dequeue();
1905
1905
  } else {
1906
- this.dispatch(data, compress, options, cb);
1906
+ this.dispatch(data, compress2, options, cb);
1907
1907
  }
1908
1908
  }).catch((err2) => {
1909
1909
  process.nextTick(onError, this, err2, cb);
@@ -1932,8 +1932,8 @@ var require_sender = __commonJS({
1932
1932
  * @param {Function} [cb] Callback
1933
1933
  * @private
1934
1934
  */
1935
- dispatch(data, compress, options, cb) {
1936
- if (!compress) {
1935
+ dispatch(data, compress2, options, cb) {
1936
+ if (!compress2) {
1937
1937
  this.sendFrame(_Sender.frame(data, options), cb);
1938
1938
  return;
1939
1939
  }
@@ -2249,7 +2249,7 @@ var require_extension = __commonJS({
2249
2249
  if (dest[name] === void 0) dest[name] = [elem];
2250
2250
  else dest[name].push(elem);
2251
2251
  }
2252
- function parse3(header2) {
2252
+ function parse4(header2) {
2253
2253
  const offers = /* @__PURE__ */ Object.create(null);
2254
2254
  let params = /* @__PURE__ */ Object.create(null);
2255
2255
  let mustUnescape = false;
@@ -2389,7 +2389,7 @@ var require_extension = __commonJS({
2389
2389
  }).join(", ");
2390
2390
  }).join(", ");
2391
2391
  }
2392
- module.exports = { format, parse: parse3 };
2392
+ module.exports = { format, parse: parse4 };
2393
2393
  }
2394
2394
  });
2395
2395
 
@@ -2423,7 +2423,7 @@ var require_websocket = __commonJS({
2423
2423
  var {
2424
2424
  EventTarget: { addEventListener, removeEventListener }
2425
2425
  } = require_event_target();
2426
- var { format, parse: parse3 } = require_extension();
2426
+ var { format, parse: parse4 } = require_extension();
2427
2427
  var { toBuffer } = require_buffer_util();
2428
2428
  var kAborted = Symbol("kAborted");
2429
2429
  var protocolVersions = [8, 13];
@@ -2941,7 +2941,7 @@ var require_websocket = __commonJS({
2941
2941
  }
2942
2942
  const defaultPort = isSecure ? 443 : 80;
2943
2943
  const key2 = randomBytes12(16).toString("base64");
2944
- const request = isSecure ? https.request : http.request;
2944
+ const request2 = isSecure ? https.request : http.request;
2945
2945
  const protocolSet = /* @__PURE__ */ new Set();
2946
2946
  let perMessageDeflate;
2947
2947
  opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect);
@@ -3018,12 +3018,12 @@ var require_websocket = __commonJS({
3018
3018
  if (opts.auth && !options.headers.authorization) {
3019
3019
  options.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64");
3020
3020
  }
3021
- req = websocket._req = request(opts);
3021
+ req = websocket._req = request2(opts);
3022
3022
  if (websocket._redirects) {
3023
3023
  websocket.emit("redirect", websocket.url, req);
3024
3024
  }
3025
3025
  } else {
3026
- req = websocket._req = request(opts);
3026
+ req = websocket._req = request2(opts);
3027
3027
  }
3028
3028
  if (opts.timeout) {
3029
3029
  req.on("timeout", () => {
@@ -3100,7 +3100,7 @@ var require_websocket = __commonJS({
3100
3100
  }
3101
3101
  let extensions;
3102
3102
  try {
3103
- extensions = parse3(secWebSocketExtensions);
3103
+ extensions = parse4(secWebSocketExtensions);
3104
3104
  } catch (err2) {
3105
3105
  const message = "Invalid Sec-WebSocket-Extensions header";
3106
3106
  abortHandshake(websocket, socket2, message);
@@ -3392,7 +3392,7 @@ var require_subprotocol = __commonJS({
3392
3392
  "../../node_modules/ws/lib/subprotocol.js"(exports, module) {
3393
3393
  "use strict";
3394
3394
  var { tokenChars } = require_validation();
3395
- function parse3(header2) {
3395
+ function parse4(header2) {
3396
3396
  const protocols = /* @__PURE__ */ new Set();
3397
3397
  let start3 = -1;
3398
3398
  let end2 = -1;
@@ -3428,7 +3428,7 @@ var require_subprotocol = __commonJS({
3428
3428
  protocols.add(protocol);
3429
3429
  return protocols;
3430
3430
  }
3431
- module.exports = { parse: parse3 };
3431
+ module.exports = { parse: parse4 };
3432
3432
  }
3433
3433
  });
3434
3434
 
@@ -5580,11 +5580,11 @@ function parseEnginePathStore(raw) {
5580
5580
  function engineEnvKeySuffix(engineId) {
5581
5581
  return engineId.toUpperCase().replace(/[^A-Z0-9]/g, "_");
5582
5582
  }
5583
- function pathSep(platform7) {
5584
- return platform7 === "win32" ? "\\" : "/";
5583
+ function pathSep(platform8) {
5584
+ return platform8 === "win32" ? "\\" : "/";
5585
5585
  }
5586
- function joinPath2(platform7, ...parts) {
5587
- const sep10 = pathSep(platform7);
5586
+ function joinPath2(platform8, ...parts) {
5587
+ const sep10 = pathSep(platform8);
5588
5588
  return parts.filter((p) => p !== "").map((p, i) => i === 0 ? p.replace(/[\\/]+$/, "") : p.replace(/^[\\/]+|[\\/]+$/g, "")).join(sep10);
5589
5589
  }
5590
5590
  function dedupe(dirs) {
@@ -5600,10 +5600,10 @@ function dedupe(dirs) {
5600
5600
  return out;
5601
5601
  }
5602
5602
  function engineSearchDirs(opts) {
5603
- const { home, platform: platform7 } = opts;
5603
+ const { home, platform: platform8 } = opts;
5604
5604
  const env = opts.env ?? {};
5605
- const j = (...parts) => joinPath2(platform7, ...parts);
5606
- if (platform7 === "win32") {
5605
+ const j = (...parts) => joinPath2(platform8, ...parts);
5606
+ if (platform8 === "win32") {
5607
5607
  const appData = env.APPDATA ?? j(home, "AppData", "Roaming");
5608
5608
  const localAppData = env.LOCALAPPDATA ?? j(home, "AppData", "Local");
5609
5609
  const programFiles = env.ProgramFiles ?? "C:\\Program Files";
@@ -5620,7 +5620,7 @@ function engineSearchDirs(opts) {
5620
5620
  j(programFiles, "nodejs")
5621
5621
  ]);
5622
5622
  }
5623
- const pnpmHome = env.PNPM_HOME ?? (platform7 === "darwin" ? j(home, "Library", "pnpm") : j(home, ".local", "share", "pnpm"));
5623
+ const pnpmHome = env.PNPM_HOME ?? (platform8 === "darwin" ? j(home, "Library", "pnpm") : j(home, ".local", "share", "pnpm"));
5624
5624
  return dedupe([
5625
5625
  "/opt/homebrew/bin",
5626
5626
  "/usr/local/bin",
@@ -9225,8 +9225,8 @@ function base64urlToUint8Array(base64url3) {
9225
9225
  function uint8ArrayToBase64url(bytes2) {
9226
9226
  return uint8ArrayToBase64(bytes2).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
9227
9227
  }
9228
- function hexToUint8Array(hex5) {
9229
- const cleanHex = hex5.replace(/^0x/, "");
9228
+ function hexToUint8Array(hex6) {
9229
+ const cleanHex = hex6.replace(/^0x/, "");
9230
9230
  if (cleanHex.length % 2 !== 0) {
9231
9231
  throw new Error("Invalid hex string length");
9232
9232
  }
@@ -32377,8 +32377,8 @@ ${full.slice(-8e3)}`;
32377
32377
  return;
32378
32378
  }
32379
32379
  const todos = live.todos?.map((t) => ({ content: t.content, status: String(t.status) }));
32380
- const call2 = gate === "review" ? reviewGrade(rv.task, finalText) : completenessGrade(rv.task, finalText, todos);
32381
- const raw = await llm({ model: live.model, system: call2.system, prompt: call2.prompt, maxTokens: 16e3, schema: call2.schema });
32380
+ const call3 = gate === "review" ? reviewGrade(rv.task, finalText) : completenessGrade(rv.task, finalText, todos);
32381
+ const raw = await llm({ model: live.model, system: call3.system, prompt: call3.prompt, maxTokens: 16e3, schema: call3.schema });
32382
32382
  if (live.rv !== rv || live.reaped) {
32383
32383
  if (live.reaped || live.rv === void 0) {
32384
32384
  emitVerification({ action: "done", gate, cycle: rv.cycles, maxCycles: RV_MAX_CYCLES, unavailable: "This run ended before it could be verified." });
@@ -32632,19 +32632,19 @@ ${qText}`;
32632
32632
  * reply (→ respondToUserDialog). Mirrors onElicitation: the CLI parks the flow until
32633
32633
  * we answer; an unanswered/aborted dialog resolves 'cancelled' so the CLI applies the
32634
32634
  * dialog's default behavior (e.g. the classic refusal message) rather than hanging. */
32635
- raiseUserDialog(live, request, signal) {
32635
+ raiseUserDialog(live, request2, signal) {
32636
32636
  return new Promise((resolve16) => {
32637
32637
  const requestId = randomUUID6();
32638
- log("user_dialog raised:", request.dialogKind, "requestId=" + requestId, "payloadKeys=" + Object.keys(request.payload ?? {}).join(","));
32638
+ log("user_dialog raised:", request2.dialogKind, "requestId=" + requestId, "payloadKeys=" + Object.keys(request2.payload ?? {}).join(","));
32639
32639
  const onAbort = () => {
32640
32640
  if (this.pendingUserDialogs.delete(requestId)) {
32641
- log("user_dialog aborted (cancelled):", request.dialogKind, requestId);
32641
+ log("user_dialog aborted (cancelled):", request2.dialogKind, requestId);
32642
32642
  resolve16({ behavior: "cancelled" });
32643
32643
  }
32644
32644
  };
32645
32645
  const cleanup2 = () => signal.removeEventListener("abort", onAbort);
32646
32646
  if (signal.aborted) {
32647
- log("user_dialog pre-aborted (cancelled):", request.dialogKind);
32647
+ log("user_dialog pre-aborted (cancelled):", request2.dialogKind);
32648
32648
  resolve16({ behavior: "cancelled" });
32649
32649
  return;
32650
32650
  }
@@ -32654,15 +32654,15 @@ ${qText}`;
32654
32654
  type: "agent:user_dialog_request",
32655
32655
  sessionId: live.sessionId,
32656
32656
  requestId,
32657
- dialogKind: request.dialogKind,
32658
- payload: request.payload ?? {},
32659
- ...request.toolUseID ? { toolUseId: request.toolUseID } : {}
32657
+ dialogKind: request2.dialogKind,
32658
+ payload: request2.payload ?? {},
32659
+ ...request2.toolUseID ? { toolUseId: request2.toolUseID } : {}
32660
32660
  };
32661
32661
  if (live.clientRequestId)
32662
32662
  this.send({ ...evt, clientRequestId: live.clientRequestId }, live.origin);
32663
32663
  else
32664
32664
  this.send(evt, live.origin);
32665
- this.autoAnswerPrompt(live, requestId, { kind: "dialog", dialogKind: request.dialogKind }, (a) => {
32665
+ this.autoAnswerPrompt(live, requestId, { kind: "dialog", dialogKind: request2.dialogKind }, (a) => {
32666
32666
  if (!this.pendingUserDialogs.has(requestId))
32667
32667
  return false;
32668
32668
  this.respondToUserDialog(requestId, a.dialogResult ? { behavior: "completed", result: a.dialogResult } : { behavior: "cancelled" });
@@ -34042,7 +34042,7 @@ CRITICAL RULES:
34042
34042
  // M5 H6 — an MCP server requesting user input (a form, or url-based OAuth).
34043
34043
  // Default is auto-cancel; we park a Promise and raise an inline card, then
34044
34044
  // resolve it from chat:elicitation (respondToElicitation). Mirrors canUseTool.
34045
- onElicitation: (request, opts) => new Promise((resolve16) => {
34045
+ onElicitation: (request2, opts) => new Promise((resolve16) => {
34046
34046
  const requestId = randomUUID6();
34047
34047
  const onAbort = () => {
34048
34048
  if (this.pendingElicitations.delete(requestId))
@@ -34059,19 +34059,19 @@ CRITICAL RULES:
34059
34059
  type: "agent:elicitation_request",
34060
34060
  sessionId: live.sessionId,
34061
34061
  requestId,
34062
- serverName: request.serverName,
34063
- message: request.message,
34064
- ...request.mode ? { mode: request.mode } : {},
34065
- ...request.url ? { url: request.url } : {},
34066
- ...request.elicitationId ? { elicitationId: request.elicitationId } : {},
34067
- ...request.requestedSchema ? { requestedSchema: request.requestedSchema } : {},
34068
- ...request.title ? { title: request.title } : {}
34062
+ serverName: request2.serverName,
34063
+ message: request2.message,
34064
+ ...request2.mode ? { mode: request2.mode } : {},
34065
+ ...request2.url ? { url: request2.url } : {},
34066
+ ...request2.elicitationId ? { elicitationId: request2.elicitationId } : {},
34067
+ ...request2.requestedSchema ? { requestedSchema: request2.requestedSchema } : {},
34068
+ ...request2.title ? { title: request2.title } : {}
34069
34069
  };
34070
34070
  if (live.clientRequestId)
34071
34071
  this.send({ ...evt, clientRequestId: live.clientRequestId }, live.origin);
34072
34072
  else
34073
34073
  this.send(evt, live.origin);
34074
- this.autoAnswerPrompt(live, requestId, { kind: "elicitation", serverName: request.serverName }, () => {
34074
+ this.autoAnswerPrompt(live, requestId, { kind: "elicitation", serverName: request2.serverName }, () => {
34075
34075
  if (!this.pendingElicitations.has(requestId))
34076
34076
  return false;
34077
34077
  this.respondToElicitation(requestId, { action: "decline" });
@@ -34082,7 +34082,7 @@ CRITICAL RULES:
34082
34082
  // asks the host to render. Without this the flow degrades to no-dialog (a model
34083
34083
  // refusal ends the turn with the classic error). We declare the kinds we render
34084
34084
  // (supportedDialogKinds); the CLI fails closed and never emits an undeclared kind.
34085
- onUserDialog: (request, opts) => this.raiseUserDialog(live, request, opts.signal),
34085
+ onUserDialog: (request2, opts) => this.raiseUserDialog(live, request2, opts.signal),
34086
34086
  supportedDialogKinds: KNOWN_DIALOG_KINDS,
34087
34087
  // Capture file edits for the client's "Review changes" (see pendingEdits
34088
34088
  // above). Bash-driven writes aren't visible here — only the editing tools.
@@ -35859,7 +35859,7 @@ async function startTesseractMcpEndpoint() {
35859
35859
  }
35860
35860
  const id = msg.id ?? null;
35861
35861
  const reply3 = (result) => send2(res, 200, { jsonrpc: "2.0", id, result });
35862
- const fail3 = (code, message) => send2(res, 200, { jsonrpc: "2.0", id, error: { code, message } });
35862
+ const fail4 = (code, message) => send2(res, 200, { jsonrpc: "2.0", id, error: { code, message } });
35863
35863
  switch (msg.method) {
35864
35864
  case "initialize":
35865
35865
  reply3({
@@ -35879,7 +35879,7 @@ async function startTesseractMcpEndpoint() {
35879
35879
  const name = String(msg.params?.name ?? "");
35880
35880
  const tool19 = byName.get(name);
35881
35881
  if (!tool19) {
35882
- fail3(-32602, `Unknown tool "${name}"`);
35882
+ fail4(-32602, `Unknown tool "${name}"`);
35883
35883
  return;
35884
35884
  }
35885
35885
  try {
@@ -35891,7 +35891,7 @@ async function startTesseractMcpEndpoint() {
35891
35891
  return;
35892
35892
  }
35893
35893
  default:
35894
- fail3(-32601, `Method not found: ${String(msg.method)}`);
35894
+ fail4(-32601, `Method not found: ${String(msg.method)}`);
35895
35895
  }
35896
35896
  } catch (e) {
35897
35897
  try {
@@ -44102,7 +44102,7 @@ var require_decoder = __commonJS({
44102
44102
  }).bind(this);
44103
44103
  xhr.send(null);
44104
44104
  },
44105
- parse: function parse3(data) {
44105
+ parse: function parse4(data) {
44106
44106
  var maxResolutionInPixels = this.opts.maxResolutionInMP * 1e3 * 1e3;
44107
44107
  var offset = 0, length = data.length;
44108
44108
  function readUint16() {
@@ -46147,7 +46147,7 @@ function __addDisposableResource(env, value, async) {
46147
46147
  return value;
46148
46148
  }
46149
46149
  function __disposeResources(env) {
46150
- function fail3(e) {
46150
+ function fail4(e) {
46151
46151
  env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
46152
46152
  env.hasError = true;
46153
46153
  }
@@ -46159,12 +46159,12 @@ function __disposeResources(env) {
46159
46159
  if (r.dispose) {
46160
46160
  var result = r.dispose.call(r.value);
46161
46161
  if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
46162
- fail3(e);
46162
+ fail4(e);
46163
46163
  return next();
46164
46164
  });
46165
46165
  } else s |= 1;
46166
46166
  } catch (e) {
46167
- fail3(e);
46167
+ fail4(e);
46168
46168
  }
46169
46169
  }
46170
46170
  if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
@@ -48583,8 +48583,8 @@ ${values.join("\n")}` : `${blockName} :`;
48583
48583
  assertBigInt();
48584
48584
  const bigIntValue = BigInt(value);
48585
48585
  const writer = new ViewWriter();
48586
- const hex5 = bigIntValue.toString(16).replace(/^-/, "");
48587
- const view = new Uint8Array(pvtsutils__namespace.Convert.FromHex(hex5));
48586
+ const hex6 = bigIntValue.toString(16).replace(/^-/, "");
48587
+ const view = new Uint8Array(pvtsutils__namespace.Convert.FromHex(hex6));
48588
48588
  if (bigIntValue < 0) {
48589
48589
  const first = new Uint8Array(view.length + (view[0] & 128 ? 1 : 0));
48590
48590
  first[0] |= 128;
@@ -51735,11 +51735,11 @@ var require_hex = __commonJS({
51735
51735
  "use strict";
51736
51736
  Object.defineProperty(exports, "__esModule", { value: true });
51737
51737
  exports.hex = exports.formats = void 0;
51738
- exports.normalize = normalize2;
51738
+ exports.normalize = normalize3;
51739
51739
  exports.is = is;
51740
51740
  exports.encode = encode3;
51741
51741
  exports.decode = decode3;
51742
- exports.parse = parse3;
51742
+ exports.parse = parse4;
51743
51743
  exports.format = format;
51744
51744
  var index_js_1 = require_bytes();
51745
51745
  var HEX_CHARACTER_REGEX = /^[0-9a-f]$/i;
@@ -51893,7 +51893,7 @@ var require_hex = __commonJS({
51893
51893
  }
51894
51894
  return chunks.join(group.separator);
51895
51895
  }
51896
- function normalize2(text9, options = {}) {
51896
+ function normalize3(text9, options = {}) {
51897
51897
  return normalizeText(text9, options);
51898
51898
  }
51899
51899
  function is(text9, options = {}) {
@@ -51901,7 +51901,7 @@ var require_hex = __commonJS({
51901
51901
  return false;
51902
51902
  }
51903
51903
  try {
51904
- normalize2(text9, options);
51904
+ normalize3(text9, options);
51905
51905
  return true;
51906
51906
  } catch {
51907
51907
  return false;
@@ -51932,15 +51932,15 @@ var require_hex = __commonJS({
51932
51932
  return `${options.prefix ?? ""}${body}`;
51933
51933
  }
51934
51934
  function decode3(text9, options = {}) {
51935
- const normalized = normalize2(text9, options);
51935
+ const normalized = normalize3(text9, options);
51936
51936
  const result = new Uint8Array(normalized.length / 2);
51937
51937
  for (let i = 0; i < normalized.length; i += 2) {
51938
51938
  result[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
51939
51939
  }
51940
51940
  return result;
51941
51941
  }
51942
- function parse3(text9, options = {}) {
51943
- const normalized = normalize2(text9, options);
51942
+ function parse4(text9, options = {}) {
51943
+ const normalized = normalize3(text9, options);
51944
51944
  return {
51945
51945
  bytes: decode3(normalized),
51946
51946
  format: detectFormat(text9),
@@ -51958,7 +51958,7 @@ var require_hex = __commonJS({
51958
51958
  groupsOf4: Object.freeze({ group: { size: 4, separator: " " } }),
51959
51959
  prefixed: Object.freeze({ prefix: "0x" })
51960
51960
  };
51961
- exports.hex = { encode: encode3, decode: decode3, format, formats: exports.formats, is, normalize: normalize2, parse: parse3 };
51961
+ exports.hex = { encode: encode3, decode: decode3, format, formats: exports.formats, is, normalize: normalize3, parse: parse4 };
51962
51962
  }
51963
51963
  });
51964
51964
 
@@ -52017,7 +52017,7 @@ var require_base64 = __commonJS({
52017
52017
  "use strict";
52018
52018
  Object.defineProperty(exports, "__esModule", { value: true });
52019
52019
  exports.base64 = void 0;
52020
- exports.normalize = normalize2;
52020
+ exports.normalize = normalize3;
52021
52021
  exports.pad = pad2;
52022
52022
  exports.is = is;
52023
52023
  exports.encode = encode3;
@@ -52028,7 +52028,7 @@ var require_base64 = __commonJS({
52028
52028
  function nodeBuffer() {
52029
52029
  return globalThis.Buffer;
52030
52030
  }
52031
- function normalize2(text9) {
52031
+ function normalize3(text9) {
52032
52032
  return text9.replace(/[\n\r\t ]/g, "");
52033
52033
  }
52034
52034
  function pad2(text9) {
@@ -52039,7 +52039,7 @@ var require_base64 = __commonJS({
52039
52039
  if (typeof text9 !== "string") {
52040
52040
  return false;
52041
52041
  }
52042
- const normalized = normalize2(text9);
52042
+ const normalized = normalize3(text9);
52043
52043
  return normalized === "" || BASE64_REGEX.test(normalized);
52044
52044
  }
52045
52045
  function encode3(data, _options) {
@@ -52051,7 +52051,7 @@ var require_base64 = __commonJS({
52051
52051
  return btoa((0, binary_js_1.encode)(bytes2));
52052
52052
  }
52053
52053
  function decode3(text9, _options) {
52054
- const normalized = normalize2(text9);
52054
+ const normalized = normalize3(text9);
52055
52055
  if (!is(normalized)) {
52056
52056
  throw new TypeError("Input is not valid Base64 text");
52057
52057
  }
@@ -52061,7 +52061,7 @@ var require_base64 = __commonJS({
52061
52061
  }
52062
52062
  return (0, binary_js_1.decode)(atob(normalized));
52063
52063
  }
52064
- exports.base64 = { encode: encode3, decode: decode3, is, normalize: normalize2, pad: pad2 };
52064
+ exports.base64 = { encode: encode3, decode: decode3, is, normalize: normalize3, pad: pad2 };
52065
52065
  }
52066
52066
  });
52067
52067
 
@@ -52071,29 +52071,29 @@ var require_base64url = __commonJS({
52071
52071
  "use strict";
52072
52072
  Object.defineProperty(exports, "__esModule", { value: true });
52073
52073
  exports.base64url = void 0;
52074
- exports.normalize = normalize2;
52074
+ exports.normalize = normalize3;
52075
52075
  exports.is = is;
52076
52076
  exports.encode = encode3;
52077
52077
  exports.decode = decode3;
52078
52078
  var base64_js_1 = require_base64();
52079
52079
  var BASE64URL_REGEX = /^[A-Za-z0-9_-]*$/;
52080
- function normalize2(text9) {
52080
+ function normalize3(text9) {
52081
52081
  return text9.replace(/[\n\r\t ]/g, "");
52082
52082
  }
52083
52083
  function is(text9) {
52084
- return typeof text9 === "string" && BASE64URL_REGEX.test(normalize2(text9));
52084
+ return typeof text9 === "string" && BASE64URL_REGEX.test(normalize3(text9));
52085
52085
  }
52086
52086
  function encode3(data, _options) {
52087
52087
  return base64_js_1.base64.encode(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
52088
52088
  }
52089
52089
  function decode3(text9, _options) {
52090
- const normalized = normalize2(text9);
52090
+ const normalized = normalize3(text9);
52091
52091
  if (!is(normalized)) {
52092
52092
  throw new TypeError("Input is not valid Base64Url text");
52093
52093
  }
52094
52094
  return base64_js_1.base64.decode(base64_js_1.base64.pad(normalized.replace(/-/g, "+").replace(/_/g, "/")));
52095
52095
  }
52096
- exports.base64url = { encode: encode3, decode: decode3, is, normalize: normalize2 };
52096
+ exports.base64url = { encode: encode3, decode: decode3, is, normalize: normalize3 };
52097
52097
  }
52098
52098
  });
52099
52099
 
@@ -59756,8 +59756,8 @@ var require_x509_cjs = __commonJS({
59756
59756
  if (j === 8) {
59757
59757
  row.push("");
59758
59758
  }
59759
- const hex5 = view[i++].toString(16).padStart(2, "0");
59760
- row.push(hex5);
59759
+ const hex6 = view[i++].toString(16).padStart(2, "0");
59760
+ row.push(hex6);
59761
59761
  }
59762
59762
  res.push(`${pad2}${row.join(" ")}`);
59763
59763
  }
@@ -60181,7 +60181,7 @@ var require_x509_cjs = __commonJS({
60181
60181
  if (!matches) {
60182
60182
  throw new Error("Cannot parse GUID value. Value doesn't match to regular expression");
60183
60183
  }
60184
- const hex5 = matches.slice(1).map((o, i) => {
60184
+ const hex6 = matches.slice(1).map((o, i) => {
60185
60185
  if (i < 3) {
60186
60186
  return pvtsutils.Convert.ToHex(new Uint8Array(pvtsutils.Convert.FromHex(o)).reverse());
60187
60187
  }
@@ -60190,7 +60190,7 @@ var require_x509_cjs = __commonJS({
60190
60190
  name = new asn1X509__namespace.GeneralName({
60191
60191
  otherName: new asn1X509__namespace.OtherName({
60192
60192
  typeId: id_GUID,
60193
- value: asn1Schema.AsnConvert.serialize(new asn1Schema.OctetString(pvtsutils.Convert.FromHex(hex5)))
60193
+ value: asn1Schema.AsnConvert.serialize(new asn1Schema.OctetString(pvtsutils.Convert.FromHex(hex6)))
60194
60194
  })
60195
60195
  });
60196
60196
  break;
@@ -63139,9 +63139,9 @@ function socketPeerLink(socket2, peerHostId, path6, opts) {
63139
63139
  });
63140
63140
  const hsTimer = setTimeout(() => {
63141
63141
  if (!authed)
63142
- fail3(new Error("peer-link: token handshake timeout"));
63142
+ fail4(new Error("peer-link: token handshake timeout"));
63143
63143
  }, TOKEN_HANDSHAKE_MS);
63144
- function fail3(err2) {
63144
+ function fail4(err2) {
63145
63145
  if (closed)
63146
63146
  return;
63147
63147
  closed = true;
@@ -63167,7 +63167,7 @@ function socketPeerLink(socket2, peerHostId, path6, opts) {
63167
63167
  try {
63168
63168
  frames = dec.push(new Uint8Array(d.buffer, d.byteOffset, d.byteLength));
63169
63169
  } catch (e) {
63170
- fail3(e);
63170
+ fail4(e);
63171
63171
  return;
63172
63172
  }
63173
63173
  for (const f of frames) {
@@ -63177,7 +63177,7 @@ function socketPeerLink(socket2, peerHostId, path6, opts) {
63177
63177
  clearTimeout(hsTimer);
63178
63178
  resolveReady();
63179
63179
  } else {
63180
- fail3(new Error("peer-link: bad/absent token (fail-closed)"));
63180
+ fail4(new Error("peer-link: bad/absent token (fail-closed)"));
63181
63181
  return;
63182
63182
  }
63183
63183
  continue;
@@ -63186,7 +63186,7 @@ function socketPeerLink(socket2, peerHostId, path6, opts) {
63186
63186
  cb(f);
63187
63187
  }
63188
63188
  });
63189
- socket2.once("error", (e) => fail3(e instanceof Error ? e : new Error(String(e))));
63189
+ socket2.once("error", (e) => fail4(e instanceof Error ? e : new Error(String(e))));
63190
63190
  socket2.once("close", () => closeOk());
63191
63191
  if (opts.sendToken) {
63192
63192
  try {
@@ -63194,7 +63194,7 @@ function socketPeerLink(socket2, peerHostId, path6, opts) {
63194
63194
  clearTimeout(hsTimer);
63195
63195
  resolveReady();
63196
63196
  } catch (e) {
63197
- fail3(e);
63197
+ fail4(e);
63198
63198
  }
63199
63199
  }
63200
63200
  const link = {
@@ -63560,12 +63560,13 @@ function wrapConstructorWithOpts(hashCons) {
63560
63560
  hashC.create = (opts) => hashCons(opts);
63561
63561
  return hashC;
63562
63562
  }
63563
- var u8, u32, isLE, byteSwap, byteSwapIfBE, Hash, toStr;
63563
+ var u8, u32, rotr, isLE, byteSwap, byteSwapIfBE, Hash, toStr;
63564
63564
  var init_utils = __esm({
63565
63565
  "../../node_modules/@noble/hashes/esm/utils.js"() {
63566
63566
  init_assert();
63567
63567
  u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
63568
63568
  u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
63569
+ rotr = (word, shift) => word << 32 - shift | word >>> shift;
63569
63570
  isLE = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
63570
63571
  byteSwap = (word) => word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255;
63571
63572
  byteSwapIfBE = isLE ? (n) => n : (n) => byteSwap(n);
@@ -64820,7 +64821,7 @@ var require_cjs12 = __commonJS({
64820
64821
  out.publicSuffix = (_a4 = hostnameParts[hostnameParts.length - 1]) !== null && _a4 !== void 0 ? _a4 : null;
64821
64822
  }
64822
64823
  var RESULT = getEmptyResult();
64823
- function parse3(url2, options = {}) {
64824
+ function parse4(url2, options = {}) {
64824
64825
  return parseImpl(url2, 5, suffixLookup, options, getEmptyResult());
64825
64826
  }
64826
64827
  function getHostname(url2, options = {}) {
@@ -64848,7 +64849,7 @@ var require_cjs12 = __commonJS({
64848
64849
  exports.getHostname = getHostname;
64849
64850
  exports.getPublicSuffix = getPublicSuffix;
64850
64851
  exports.getSubdomain = getSubdomain;
64851
- exports.parse = parse3;
64852
+ exports.parse = parse4;
64852
64853
  }
64853
64854
  });
64854
64855
 
@@ -64863,7 +64864,10 @@ function compareUtf8(a, b) {
64863
64864
  }
64864
64865
  return ea.length === eb.length ? 0 : ea.length < eb.length ? -1 : 1;
64865
64866
  }
64866
- var MeshCodecError, fail, LIMITS, Writer, Reader;
64867
+ function canonicalStrs(items) {
64868
+ return [...new Set(items)].sort(compareUtf8);
64869
+ }
64870
+ var MeshCodecError, fail2, LIMITS, Writer, Reader;
64867
64871
  var init_codec = __esm({
64868
64872
  "../../packages/mesh-pki/dist/codec.js"() {
64869
64873
  "use strict";
@@ -64875,7 +64879,7 @@ var init_codec = __esm({
64875
64879
  this.reason = reason;
64876
64880
  }
64877
64881
  };
64878
- fail = (reason, detail) => {
64882
+ fail2 = (reason, detail) => {
64879
64883
  throw new MeshCodecError(reason, detail);
64880
64884
  };
64881
64885
  LIMITS = {
@@ -64909,17 +64913,17 @@ var init_codec = __esm({
64909
64913
  }
64910
64914
  u8(v) {
64911
64915
  if (!Number.isInteger(v) || v < 0 || v > 255)
64912
- fail("bad-value", `u8 ${v}`);
64916
+ fail2("bad-value", `u8 ${v}`);
64913
64917
  return this.#push(new Uint8Array([v]));
64914
64918
  }
64915
64919
  u16(v) {
64916
64920
  if (!Number.isInteger(v) || v < 0 || v > 65535)
64917
- fail("bad-value", `u16 ${v}`);
64921
+ fail2("bad-value", `u16 ${v}`);
64918
64922
  return this.#push(new Uint8Array([v >>> 8 & 255, v & 255]));
64919
64923
  }
64920
64924
  u32(v) {
64921
64925
  if (!Number.isInteger(v) || v < 0 || v > 4294967295)
64922
- fail("bad-value", `u32 ${v}`);
64926
+ fail2("bad-value", `u32 ${v}`);
64923
64927
  return this.#push(new Uint8Array([v >>> 24 & 255, v >>> 16 & 255, v >>> 8 & 255, v & 255]));
64924
64928
  }
64925
64929
  /** Milliseconds-since-epoch and similar. JS numbers are exact to 2^53, which is
@@ -64927,7 +64931,7 @@ var init_codec = __esm({
64927
64931
  * than silently losing precision. */
64928
64932
  u64(v) {
64929
64933
  if (!Number.isInteger(v) || v < 0 || v > Number.MAX_SAFE_INTEGER)
64930
- fail("bad-value", `u64 ${v}`);
64934
+ fail2("bad-value", `u64 ${v}`);
64931
64935
  const hi = Math.floor(v / 4294967296);
64932
64936
  const lo = v >>> 0;
64933
64937
  return this.u32(hi).u32(lo);
@@ -64935,13 +64939,13 @@ var init_codec = __esm({
64935
64939
  /** Fixed-width opaque bytes — no length prefix; the field's width is positional. */
64936
64940
  fixed(b, width) {
64937
64941
  if (b.length !== width)
64938
- fail("bad-value", `fixed expected ${width} got ${b.length}`);
64942
+ fail2("bad-value", `fixed expected ${width} got ${b.length}`);
64939
64943
  return this.#push(b);
64940
64944
  }
64941
64945
  /** Length-prefixed opaque bytes. */
64942
64946
  bytes(b, max = LIMITS.STR) {
64943
64947
  if (b.length > max)
64944
- fail("too-long", `bytes ${b.length} > ${max}`);
64948
+ fail2("too-long", `bytes ${b.length} > ${max}`);
64945
64949
  return this.u16(b.length).#push(b);
64946
64950
  }
64947
64951
  /** Length-prefixed UTF-8 string. */
@@ -64954,13 +64958,13 @@ var init_codec = __esm({
64954
64958
  */
64955
64959
  sortedStrs(items, max = LIMITS.VEC) {
64956
64960
  if (items.length > max)
64957
- fail("too-long", `vec ${items.length} > ${max}`);
64961
+ fail2("too-long", `vec ${items.length} > ${max}`);
64958
64962
  for (let i = 1; i < items.length; i++) {
64959
64963
  const cmp = compareUtf8(items[i - 1], items[i]);
64960
64964
  if (cmp === 0)
64961
- fail("duplicate", items[i]);
64965
+ fail2("duplicate", items[i]);
64962
64966
  if (cmp > 0)
64963
- fail("not-sorted", `${items[i - 1]} > ${items[i]}`);
64967
+ fail2("not-sorted", `${items[i - 1]} > ${items[i]}`);
64964
64968
  }
64965
64969
  this.u16(items.length);
64966
64970
  for (const s of items)
@@ -64970,7 +64974,7 @@ var init_codec = __esm({
64970
64974
  /** A sequence whose order is meaningful (signatures, key lists). */
64971
64975
  vec(items, each, max = LIMITS.VEC) {
64972
64976
  if (items.length > max)
64973
- fail("too-long", `vec ${items.length} > ${max}`);
64977
+ fail2("too-long", `vec ${items.length} > ${max}`);
64974
64978
  this.u16(items.length);
64975
64979
  for (const it of items)
64976
64980
  each(this, it);
@@ -65000,7 +65004,7 @@ var init_codec = __esm({
65000
65004
  }
65001
65005
  #need(n) {
65002
65006
  if (n < 0 || this.#o + n > this.#b.length) {
65003
- fail("truncated", `need ${n} at ${this.#o}, have ${this.#b.length - this.#o}`);
65007
+ fail2("truncated", `need ${n} at ${this.#o}, have ${this.#b.length - this.#o}`);
65004
65008
  }
65005
65009
  }
65006
65010
  u8() {
@@ -65024,7 +65028,7 @@ var init_codec = __esm({
65024
65028
  const lo = this.u32();
65025
65029
  const v = hi * 4294967296 + lo;
65026
65030
  if (!Number.isSafeInteger(v))
65027
- fail("bad-value", "u64 exceeds 2^53");
65031
+ fail2("bad-value", "u64 exceeds 2^53");
65028
65032
  return v;
65029
65033
  }
65030
65034
  fixed(width) {
@@ -65036,7 +65040,7 @@ var init_codec = __esm({
65036
65040
  bytes(max = LIMITS.STR) {
65037
65041
  const n = this.u16();
65038
65042
  if (n > max)
65039
- fail("too-long", `bytes ${n} > ${max}`);
65043
+ fail2("too-long", `bytes ${n} > ${max}`);
65040
65044
  return this.fixed(n);
65041
65045
  }
65042
65046
  str(max = LIMITS.STR) {
@@ -65045,7 +65049,7 @@ var init_codec = __esm({
65045
65049
  try {
65046
65050
  s = new TextDecoder("utf-8", { fatal: true }).decode(raw);
65047
65051
  } catch {
65048
- return fail("bad-utf8");
65052
+ return fail2("bad-utf8");
65049
65053
  }
65050
65054
  return s;
65051
65055
  }
@@ -65053,16 +65057,16 @@ var init_codec = __esm({
65053
65057
  sortedStrs(max = LIMITS.VEC) {
65054
65058
  const n = this.u16();
65055
65059
  if (n > max)
65056
- fail("too-long", `vec ${n} > ${max}`);
65060
+ fail2("too-long", `vec ${n} > ${max}`);
65057
65061
  const out = [];
65058
65062
  for (let i = 0; i < n; i++) {
65059
65063
  const s = this.str();
65060
65064
  if (i > 0) {
65061
65065
  const cmp = compareUtf8(out[i - 1], s);
65062
65066
  if (cmp === 0)
65063
- fail("duplicate", s);
65067
+ fail2("duplicate", s);
65064
65068
  if (cmp > 0)
65065
- fail("not-sorted", `${out[i - 1]} > ${s}`);
65069
+ fail2("not-sorted", `${out[i - 1]} > ${s}`);
65066
65070
  }
65067
65071
  out.push(s);
65068
65072
  }
@@ -65071,7 +65075,7 @@ var init_codec = __esm({
65071
65075
  vec(each, max = LIMITS.VEC) {
65072
65076
  const n = this.u16();
65073
65077
  if (n > max)
65074
- fail("too-long", `vec ${n} > ${max}`);
65078
+ fail2("too-long", `vec ${n} > ${max}`);
65075
65079
  const out = [];
65076
65080
  for (let i = 0; i < n; i++)
65077
65081
  out.push(each(this));
@@ -65080,7 +65084,7 @@ var init_codec = __esm({
65080
65084
  /** Assert the value consumed the whole buffer. Trailing bytes are an error. */
65081
65085
  finish() {
65082
65086
  if (this.#o !== this.#b.length) {
65083
- fail("trailing", `${this.#b.length - this.#o} byte(s) after value`);
65087
+ fail2("trailing", `${this.#b.length - this.#o} byte(s) after value`);
65084
65088
  }
65085
65089
  }
65086
65090
  };
@@ -65104,6 +65108,20 @@ function isMasked(addr, len) {
65104
65108
  }
65105
65109
  return true;
65106
65110
  }
65111
+ function mask(addr, len) {
65112
+ const out = new Uint8Array(addr);
65113
+ for (let i = 0; i < out.length; i++) {
65114
+ const bitsBefore = i * 8;
65115
+ if (bitsBefore >= len) {
65116
+ out[i] = 0;
65117
+ continue;
65118
+ }
65119
+ const keep = Math.min(8, len - bitsBefore);
65120
+ if (keep < 8)
65121
+ out[i] &= 255 << 8 - keep;
65122
+ }
65123
+ return out;
65124
+ }
65107
65125
  function makePrefix(afi, addr, len) {
65108
65126
  if (afi !== AFI_V4 && afi !== AFI_V6)
65109
65127
  throw new MeshCodecError("bad-value", `afi ${afi}`);
@@ -65140,6 +65158,10 @@ function comparePrefix(a, b) {
65140
65158
  }
65141
65159
  return a.len === b.len ? 0 : a.len < b.len ? -1 : 1;
65142
65160
  }
65161
+ function canonicalPrefixes(items) {
65162
+ const sorted = [...items].sort(comparePrefix);
65163
+ return sorted.filter((p, i) => i === 0 || comparePrefix(sorted[i - 1], p) !== 0);
65164
+ }
65143
65165
  function writePrefixes(w, items) {
65144
65166
  if (items.length > LIMITS.VEC)
65145
65167
  throw new MeshCodecError("too-long", `routes ${items.length}`);
@@ -65187,6 +65209,26 @@ function isValidMeshRange(p) {
65187
65209
  return (p.addr[0] & 254) === 252;
65188
65210
  return false;
65189
65211
  }
65212
+ function prefixContainsAddr(p, addr) {
65213
+ if (addr.length !== widthOf(p.afi))
65214
+ return false;
65215
+ let bits = p.len;
65216
+ for (let i = 0; i < addr.length && bits > 0; i++) {
65217
+ const keep = Math.min(8, bits);
65218
+ const m = keep === 8 ? 255 : 255 << 8 - keep & 255;
65219
+ if ((addr[i] & m) !== (p.addr[i] & m))
65220
+ return false;
65221
+ bits -= keep;
65222
+ }
65223
+ return true;
65224
+ }
65225
+ function prefixContains(outer, inner) {
65226
+ if (outer.afi !== inner.afi)
65227
+ return false;
65228
+ if (inner.len < outer.len)
65229
+ return false;
65230
+ return prefixContainsAddr(outer, inner.addr);
65231
+ }
65190
65232
  function formatPrefix(p) {
65191
65233
  return `${formatAddr(p.afi, p.addr)}/${p.len}`;
65192
65234
  }
@@ -65233,7 +65275,71 @@ function formatAddr(afi, addr) {
65233
65275
  s = s + ":";
65234
65276
  return s;
65235
65277
  }
65236
- var AFI_V4, AFI_V6, widthOf, maxLenOf, MIN_MESH_PREFIX_LEN;
65278
+ function parsePrefix(text9) {
65279
+ const slash = text9.lastIndexOf("/");
65280
+ if (slash < 0)
65281
+ throw new MeshCodecError("bad-value", `missing / in ${text9}`);
65282
+ const host = text9.slice(0, slash);
65283
+ const lenStr = text9.slice(slash + 1);
65284
+ if (!/^\d{1,3}$/.test(lenStr))
65285
+ throw new MeshCodecError("bad-value", `prefix len ${lenStr}`);
65286
+ const len = Number(lenStr);
65287
+ const { afi, addr } = parseAddr(host);
65288
+ if (len > maxLenOf(afi))
65289
+ throw new MeshCodecError("bad-value", `len ${len} for v${afi}`);
65290
+ return makePrefix(afi, mask(addr, len), len);
65291
+ }
65292
+ function parseAddr(text9) {
65293
+ if (text9.includes(":"))
65294
+ return { afi: AFI_V6, addr: parseV6(text9) };
65295
+ return { afi: AFI_V4, addr: parseV4(text9) };
65296
+ }
65297
+ function parseV4(text9) {
65298
+ const parts = text9.split(".");
65299
+ if (parts.length !== 4)
65300
+ throw new MeshCodecError("bad-value", `bad IPv4 ${text9}`);
65301
+ const out = new Uint8Array(4);
65302
+ for (let i = 0; i < 4; i++) {
65303
+ if (!/^(0|[1-9]\d{0,2})$/.test(parts[i]))
65304
+ throw new MeshCodecError("bad-value", `bad IPv4 octet ${parts[i]}`);
65305
+ const v = Number(parts[i]);
65306
+ if (v > 255)
65307
+ throw new MeshCodecError("bad-value", `bad IPv4 octet ${parts[i]}`);
65308
+ out[i] = v;
65309
+ }
65310
+ return out;
65311
+ }
65312
+ function parseV6(text9) {
65313
+ if (text9.includes("::")) {
65314
+ const halves = text9.split("::");
65315
+ if (halves.length !== 2)
65316
+ throw new MeshCodecError("bad-value", `bad IPv6 ${text9}`);
65317
+ const head = halves[0] ? halves[0].split(":") : [];
65318
+ const tail3 = halves[1] ? halves[1].split(":") : [];
65319
+ if (head.length + tail3.length > 7)
65320
+ throw new MeshCodecError("bad-value", `bad IPv6 ${text9}`);
65321
+ const zeros = new Array(8 - head.length - tail3.length).fill("0");
65322
+ return groupsToBytes([...head, ...zeros, ...tail3], text9);
65323
+ }
65324
+ const g = text9.split(":");
65325
+ if (g.length !== 8)
65326
+ throw new MeshCodecError("bad-value", `bad IPv6 ${text9}`);
65327
+ return groupsToBytes(g, text9);
65328
+ }
65329
+ function groupsToBytes(groups, orig) {
65330
+ if (groups.length !== 8)
65331
+ throw new MeshCodecError("bad-value", `bad IPv6 ${orig}`);
65332
+ const out = new Uint8Array(16);
65333
+ for (let i = 0; i < 8; i++) {
65334
+ if (!/^[0-9a-fA-F]{1,4}$/.test(groups[i]))
65335
+ throw new MeshCodecError("bad-value", `bad IPv6 group ${groups[i]}`);
65336
+ const v = parseInt(groups[i], 16);
65337
+ out[i * 2] = v >>> 8 & 255;
65338
+ out[i * 2 + 1] = v & 255;
65339
+ }
65340
+ return out;
65341
+ }
65342
+ var AFI_V4, AFI_V6, widthOf, maxLenOf, prefixEqual, MIN_MESH_PREFIX_LEN;
65237
65343
  var init_prefix = __esm({
65238
65344
  "../../packages/mesh-pki/dist/prefix.js"() {
65239
65345
  "use strict";
@@ -65242,10 +65348,130 @@ var init_prefix = __esm({
65242
65348
  AFI_V6 = 6;
65243
65349
  widthOf = (afi) => afi === AFI_V4 ? 4 : 16;
65244
65350
  maxLenOf = (afi) => afi === AFI_V4 ? 32 : 128;
65351
+ prefixEqual = (a, b) => comparePrefix(a, b) === 0;
65245
65352
  MIN_MESH_PREFIX_LEN = 8;
65246
65353
  }
65247
65354
  });
65248
65355
 
65356
+ // ../../node_modules/@noble/hashes/esm/blake2s.js
65357
+ function G1s(a, b, c, d, x) {
65358
+ a = a + b + x | 0;
65359
+ d = rotr(d ^ a, 16);
65360
+ c = c + d | 0;
65361
+ b = rotr(b ^ c, 12);
65362
+ return { a, b, c, d };
65363
+ }
65364
+ function G2s(a, b, c, d, x) {
65365
+ a = a + b + x | 0;
65366
+ d = rotr(d ^ a, 8);
65367
+ c = c + d | 0;
65368
+ b = rotr(b ^ c, 7);
65369
+ return { a, b, c, d };
65370
+ }
65371
+ function compress(s, offset, msg, rounds, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) {
65372
+ let j = 0;
65373
+ for (let i = 0; i < rounds; i++) {
65374
+ ({ a: v0, b: v4, c: v8, d: v12 } = G1s(v0, v4, v8, v12, msg[offset + s[j++]]));
65375
+ ({ a: v0, b: v4, c: v8, d: v12 } = G2s(v0, v4, v8, v12, msg[offset + s[j++]]));
65376
+ ({ a: v1, b: v5, c: v9, d: v13 } = G1s(v1, v5, v9, v13, msg[offset + s[j++]]));
65377
+ ({ a: v1, b: v5, c: v9, d: v13 } = G2s(v1, v5, v9, v13, msg[offset + s[j++]]));
65378
+ ({ a: v2, b: v6, c: v10, d: v14 } = G1s(v2, v6, v10, v14, msg[offset + s[j++]]));
65379
+ ({ a: v2, b: v6, c: v10, d: v14 } = G2s(v2, v6, v10, v14, msg[offset + s[j++]]));
65380
+ ({ a: v3, b: v7, c: v11, d: v15 } = G1s(v3, v7, v11, v15, msg[offset + s[j++]]));
65381
+ ({ a: v3, b: v7, c: v11, d: v15 } = G2s(v3, v7, v11, v15, msg[offset + s[j++]]));
65382
+ ({ a: v0, b: v5, c: v10, d: v15 } = G1s(v0, v5, v10, v15, msg[offset + s[j++]]));
65383
+ ({ a: v0, b: v5, c: v10, d: v15 } = G2s(v0, v5, v10, v15, msg[offset + s[j++]]));
65384
+ ({ a: v1, b: v6, c: v11, d: v12 } = G1s(v1, v6, v11, v12, msg[offset + s[j++]]));
65385
+ ({ a: v1, b: v6, c: v11, d: v12 } = G2s(v1, v6, v11, v12, msg[offset + s[j++]]));
65386
+ ({ a: v2, b: v7, c: v8, d: v13 } = G1s(v2, v7, v8, v13, msg[offset + s[j++]]));
65387
+ ({ a: v2, b: v7, c: v8, d: v13 } = G2s(v2, v7, v8, v13, msg[offset + s[j++]]));
65388
+ ({ a: v3, b: v4, c: v9, d: v14 } = G1s(v3, v4, v9, v14, msg[offset + s[j++]]));
65389
+ ({ a: v3, b: v4, c: v9, d: v14 } = G2s(v3, v4, v9, v14, msg[offset + s[j++]]));
65390
+ }
65391
+ return { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 };
65392
+ }
65393
+ var B2S_IV, BLAKE2s, blake2s;
65394
+ var init_blake2s = __esm({
65395
+ "../../node_modules/@noble/hashes/esm/blake2s.js"() {
65396
+ init_blake();
65397
+ init_u64();
65398
+ init_utils();
65399
+ B2S_IV = /* @__PURE__ */ new Uint32Array([
65400
+ 1779033703,
65401
+ 3144134277,
65402
+ 1013904242,
65403
+ 2773480762,
65404
+ 1359893119,
65405
+ 2600822924,
65406
+ 528734635,
65407
+ 1541459225
65408
+ ]);
65409
+ BLAKE2s = class extends BLAKE {
65410
+ constructor(opts = {}) {
65411
+ super(64, opts.dkLen === void 0 ? 32 : opts.dkLen, opts, 32, 8, 8);
65412
+ this.v0 = B2S_IV[0] | 0;
65413
+ this.v1 = B2S_IV[1] | 0;
65414
+ this.v2 = B2S_IV[2] | 0;
65415
+ this.v3 = B2S_IV[3] | 0;
65416
+ this.v4 = B2S_IV[4] | 0;
65417
+ this.v5 = B2S_IV[5] | 0;
65418
+ this.v6 = B2S_IV[6] | 0;
65419
+ this.v7 = B2S_IV[7] | 0;
65420
+ const keyLength = opts.key ? opts.key.length : 0;
65421
+ this.v0 ^= this.outputLen | keyLength << 8 | 1 << 16 | 1 << 24;
65422
+ if (opts.salt) {
65423
+ const salt = u32(toBytes(opts.salt));
65424
+ this.v4 ^= byteSwapIfBE(salt[0]);
65425
+ this.v5 ^= byteSwapIfBE(salt[1]);
65426
+ }
65427
+ if (opts.personalization) {
65428
+ const pers = u32(toBytes(opts.personalization));
65429
+ this.v6 ^= byteSwapIfBE(pers[0]);
65430
+ this.v7 ^= byteSwapIfBE(pers[1]);
65431
+ }
65432
+ if (opts.key) {
65433
+ const tmp = new Uint8Array(this.blockLen);
65434
+ tmp.set(toBytes(opts.key));
65435
+ this.update(tmp);
65436
+ }
65437
+ }
65438
+ get() {
65439
+ const { v0, v1, v2, v3, v4, v5, v6, v7 } = this;
65440
+ return [v0, v1, v2, v3, v4, v5, v6, v7];
65441
+ }
65442
+ // prettier-ignore
65443
+ set(v0, v1, v2, v3, v4, v5, v6, v7) {
65444
+ this.v0 = v0 | 0;
65445
+ this.v1 = v1 | 0;
65446
+ this.v2 = v2 | 0;
65447
+ this.v3 = v3 | 0;
65448
+ this.v4 = v4 | 0;
65449
+ this.v5 = v5 | 0;
65450
+ this.v6 = v6 | 0;
65451
+ this.v7 = v7 | 0;
65452
+ }
65453
+ compress(msg, offset, isLast) {
65454
+ const { h, l } = fromBig(BigInt(this.length));
65455
+ const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(SIGMA, offset, msg, 10, this.v0, this.v1, this.v2, this.v3, this.v4, this.v5, this.v6, this.v7, B2S_IV[0], B2S_IV[1], B2S_IV[2], B2S_IV[3], l ^ B2S_IV[4], h ^ B2S_IV[5], isLast ? ~B2S_IV[6] : B2S_IV[6], B2S_IV[7]);
65456
+ this.v0 ^= v0 ^ v8;
65457
+ this.v1 ^= v1 ^ v9;
65458
+ this.v2 ^= v2 ^ v10;
65459
+ this.v3 ^= v3 ^ v11;
65460
+ this.v4 ^= v4 ^ v12;
65461
+ this.v5 ^= v5 ^ v13;
65462
+ this.v6 ^= v6 ^ v14;
65463
+ this.v7 ^= v7 ^ v15;
65464
+ }
65465
+ destroy() {
65466
+ this.destroyed = true;
65467
+ this.buffer32.fill(0);
65468
+ this.set(0, 0, 0, 0, 0, 0, 0, 0);
65469
+ }
65470
+ };
65471
+ blake2s = /* @__PURE__ */ wrapConstructorWithOpts((opts) => new BLAKE2s(opts));
65472
+ }
65473
+ });
65474
+
65249
65475
  // ../../packages/mesh-pki/dist/crypto.js
65250
65476
  function randomBytes9(n) {
65251
65477
  return globalThis.crypto.getRandomValues(new Uint8Array(n));
@@ -65255,6 +65481,11 @@ async function generateSigningKey(extractable = true) {
65255
65481
  const publicRaw = new Uint8Array(await subtle4.exportKey("raw", kp.publicKey));
65256
65482
  return { privateKey: kp.privateKey, publicRaw };
65257
65483
  }
65484
+ async function importSigningPublic(raw) {
65485
+ if (raw.length !== 32)
65486
+ throw new Error(`Ed25519 public key must be 32 bytes, got ${raw.length}`);
65487
+ return subtle4.importKey("raw", bs4(raw), ED25519, true, ["verify"]);
65488
+ }
65258
65489
  async function signingKeyFromSeed(seed) {
65259
65490
  if (seed.length !== 32)
65260
65491
  throw new Error(`Ed25519 seed must be 32 bytes, got ${seed.length}`);
@@ -65292,9 +65523,28 @@ async function exportStaticPrivate(kp) {
65292
65523
  throw new Error(`X25519 private key must be 32 bytes, got ${raw.length}`);
65293
65524
  return raw;
65294
65525
  }
65526
+ async function exportSigningPrivate(kp) {
65527
+ return subtle4.exportKey("jwk", kp.privateKey);
65528
+ }
65529
+ async function importSigningPrivate(jwk) {
65530
+ const privateKey = await subtle4.importKey("jwk", jwk, ED25519, true, ["sign"]);
65531
+ if (typeof jwk.x !== "string")
65532
+ throw new Error("Ed25519 JWK missing x");
65533
+ return { privateKey, publicRaw: unb64u2(jwk.x) };
65534
+ }
65295
65535
  async function sign2(privateKey, message) {
65296
65536
  return new Uint8Array(await subtle4.sign(ED25519, privateKey, bs4(message)));
65297
65537
  }
65538
+ async function verify2(publicRaw, message, sig) {
65539
+ if (sig.length !== 64 || publicRaw.length !== 32)
65540
+ return false;
65541
+ try {
65542
+ const key2 = await importSigningPublic(publicRaw);
65543
+ return await subtle4.verify(ED25519, key2, bs4(sig), bs4(message));
65544
+ } catch {
65545
+ return false;
65546
+ }
65547
+ }
65298
65548
  async function generateStaticKey(extractable = true) {
65299
65549
  const kp = await subtle4.generateKey(X25519, extractable, ["deriveBits"]);
65300
65550
  const publicRaw = new Uint8Array(await subtle4.exportKey("raw", kp.publicKey));
@@ -65303,6 +65553,15 @@ async function generateStaticKey(extractable = true) {
65303
65553
  async function sha2562(bytes2) {
65304
65554
  return new Uint8Array(await subtle4.digest("SHA-256", bs4(bytes2)));
65305
65555
  }
65556
+ function blake2s256(bytes2) {
65557
+ return blake2s(bytes2, { dkLen: 32 });
65558
+ }
65559
+ function b64u2(bytes2) {
65560
+ let s = "";
65561
+ for (const b of bytes2)
65562
+ s += String.fromCharCode(b);
65563
+ return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
65564
+ }
65306
65565
  function unb64u2(s) {
65307
65566
  const pad2 = s.length % 4 === 0 ? "" : "=".repeat(4 - s.length % 4);
65308
65567
  const b = atob(s.replace(/-/g, "+").replace(/_/g, "/") + pad2);
@@ -65311,7 +65570,7 @@ function unb64u2(s) {
65311
65570
  out[i] = b.charCodeAt(i);
65312
65571
  return out;
65313
65572
  }
65314
- function hex3(bytes2) {
65573
+ function hex4(bytes2) {
65315
65574
  return Array.from(bytes2, (b) => b.toString(16).padStart(2, "0")).join("");
65316
65575
  }
65317
65576
  function utf83(s) {
@@ -65327,10 +65586,19 @@ function concat2(...parts) {
65327
65586
  }
65328
65587
  return out;
65329
65588
  }
65589
+ function bytesEqual(a, b) {
65590
+ if (a.length !== b.length)
65591
+ return false;
65592
+ let diff = 0;
65593
+ for (let i = 0; i < a.length; i++)
65594
+ diff |= a[i] ^ b[i];
65595
+ return diff === 0;
65596
+ }
65330
65597
  var subtle4, bs4, ED25519, X25519;
65331
65598
  var init_crypto = __esm({
65332
65599
  "../../packages/mesh-pki/dist/crypto.js"() {
65333
65600
  "use strict";
65601
+ init_blake2s();
65334
65602
  subtle4 = globalThis.crypto.subtle;
65335
65603
  bs4 = (b) => b;
65336
65604
  ED25519 = "Ed25519";
@@ -65417,9 +65685,55 @@ function readGenesisBody(r) {
65417
65685
  validateGenesis(g);
65418
65686
  return g;
65419
65687
  }
65688
+ function encodeSignedGenesis(sg) {
65689
+ const body = encodeGenesis(sg.block);
65690
+ const w = new Writer();
65691
+ w.bytes(body, LIMITS.GENESIS);
65692
+ w.vec(sg.sigs, (ww, s) => {
65693
+ ww.u8(s.keyIndex).fixed(s.sig, 64);
65694
+ });
65695
+ return w.finish();
65696
+ }
65697
+ function decodeSignedGenesis(bytes2) {
65698
+ const r = new Reader(bytes2);
65699
+ const body = r.bytes(LIMITS.GENESIS);
65700
+ const sigs = r.vec((rr) => ({ keyIndex: rr.u8(), sig: rr.fixed(64) }));
65701
+ r.finish();
65702
+ return { block: decodeGenesis(body), sigs };
65703
+ }
65420
65704
  async function genesisFingerprint(g) {
65421
65705
  return sha2562(encodeGenesis(g));
65422
65706
  }
65707
+ function fingerprintShort(fp, groups = 12) {
65708
+ const h = hex4(fp.subarray(0, Math.min(fp.length, groups * 2)));
65709
+ return (h.match(/.{1,4}/g) ?? []).join(" ");
65710
+ }
65711
+ async function signGenesis(block2, signers) {
65712
+ const body = encodeGenesis(block2);
65713
+ const sigs = [];
65714
+ for (const s of [...signers].sort((a, b) => a.keyIndex - b.keyIndex)) {
65715
+ if (s.keyIndex < 0 || s.keyIndex >= block2.caKeys.length) {
65716
+ throw new MeshCodecError("bad-value", `signer index ${s.keyIndex}`);
65717
+ }
65718
+ sigs.push({ keyIndex: s.keyIndex, sig: await sign2(s.privateKey, body) });
65719
+ }
65720
+ return { block: block2, sigs };
65721
+ }
65722
+ async function verifyGenesis(sg) {
65723
+ const { block: block2, sigs } = sg;
65724
+ const body = encodeGenesis(block2);
65725
+ const seen = /* @__PURE__ */ new Set();
65726
+ for (const s of sigs) {
65727
+ if (s.keyIndex >= block2.caKeys.length)
65728
+ return false;
65729
+ if (seen.has(s.keyIndex))
65730
+ return false;
65731
+ if (!await verify2(block2.caKeys[s.keyIndex], body, s.sig))
65732
+ return false;
65733
+ seen.add(s.keyIndex);
65734
+ }
65735
+ return seen.size >= block2.kCa;
65736
+ }
65423
65737
  async function deriveMeshPrefix6(orgId) {
65424
65738
  const h = await sha2562(new TextEncoder().encode(orgId));
65425
65739
  const out = new Uint8Array(6);
@@ -65562,6 +65876,9 @@ function decodeCert(bytes2) {
65562
65876
  r.finish();
65563
65877
  return { details: decodeDetails(body), sigs };
65564
65878
  }
65879
+ async function certFingerprint(d) {
65880
+ return sha2562(encodeDetails(d));
65881
+ }
65565
65882
  async function issueCert(details, signers) {
65566
65883
  const body = encodeDetails(details);
65567
65884
  const sigs = [];
@@ -65570,7 +65887,115 @@ async function issueCert(details, signers) {
65570
65887
  }
65571
65888
  return { details, sigs };
65572
65889
  }
65573
- var TNC_VERSION, FLAG_IS_CA, FLAG_IS_EXIT_NODE, FLAG_IS_RELAY, FLAG_IS_EPHEMERAL, KNOWN_FLAGS, NAME_RE, ZERO16;
65890
+ async function verifyCert(leaf, genesis, opts) {
65891
+ const genFp = await genesisFingerprint(genesis);
65892
+ const byFp = /* @__PURE__ */ new Map();
65893
+ for (const c of opts.intermediates ?? []) {
65894
+ byFp.set(hexKey(await certFingerprint(c.details)), c);
65895
+ }
65896
+ let cur = leaf;
65897
+ let depth = 0;
65898
+ const seen = /* @__PURE__ */ new Set();
65899
+ for (; ; ) {
65900
+ const d = cur.details;
65901
+ if (d.version !== TNC_VERSION)
65902
+ return no("bad-version");
65903
+ if (!bytesEqual(d.genesisFp, genFp))
65904
+ return no("wrong-mesh");
65905
+ if (!opts.ignoreTime) {
65906
+ if (opts.now + CLOCK_SKEW_MS < d.notBefore)
65907
+ return no("not-yet-valid");
65908
+ if (opts.now - CLOCK_SKEW_MS > d.notAfter)
65909
+ return no("expired");
65910
+ }
65911
+ if (opts.revokedSerials?.some((s) => bytesEqual(s, d.serial)))
65912
+ return no("revoked", "serial");
65913
+ if (opts.revokedStatics?.some((s) => bytesEqual(s, d.staticPub)))
65914
+ return no("revoked", "staticPub");
65915
+ const selfFp = await certFingerprint(d);
65916
+ const selfKey = hexKey(selfFp);
65917
+ if (seen.has(selfKey))
65918
+ return no("chain-cycle");
65919
+ seen.add(selfKey);
65920
+ const body = encodeDetails(d);
65921
+ if (bytesEqual(d.issuerFp, genFp)) {
65922
+ const q2 = await checkQuorum(body, cur.sigs, genesis.caKeys, genesis.kCa);
65923
+ if (q2 !== "ok")
65924
+ return no(q2);
65925
+ return { ok: true, details: leaf.details, chainDepth: depth };
65926
+ }
65927
+ const parent = byFp.get(hexKey(d.issuerFp));
65928
+ if (!parent)
65929
+ return no("unknown-issuer");
65930
+ if (!isCa(parent.details))
65931
+ return no("issuer-not-ca");
65932
+ const q = await checkQuorum(body, cur.sigs, [parent.details.sigPub], 1);
65933
+ if (q !== "ok")
65934
+ return no(q);
65935
+ const narrow = checkNarrowing(parent.details, d);
65936
+ if (narrow)
65937
+ return no(narrow);
65938
+ depth++;
65939
+ if (depth >= MAX_CHAIN_DEPTH)
65940
+ return no("chain-too-deep");
65941
+ cur = parent;
65942
+ }
65943
+ }
65944
+ function no(reason, detail) {
65945
+ return { ok: false, reason, detail };
65946
+ }
65947
+ async function checkQuorum(body, sigs, keys, threshold) {
65948
+ const seen = /* @__PURE__ */ new Set();
65949
+ for (const s of sigs) {
65950
+ if (s.keyIndex >= keys.length)
65951
+ return "bad-signature";
65952
+ if (seen.has(s.keyIndex))
65953
+ return "bad-signature";
65954
+ if (!await verify2(keys[s.keyIndex], body, s.sig))
65955
+ return "bad-signature";
65956
+ seen.add(s.keyIndex);
65957
+ }
65958
+ return seen.size >= threshold ? "ok" : "quorum-not-met";
65959
+ }
65960
+ function checkNarrowing(parent, child) {
65961
+ const parentGroups = new Set(parent.groups);
65962
+ for (const g of child.groups) {
65963
+ if (!parentGroups.has(g))
65964
+ return "narrowing-groups";
65965
+ }
65966
+ for (const r of child.routes) {
65967
+ if (!parent.routes.some((p) => prefixContains(p, r)))
65968
+ return "narrowing-routes";
65969
+ }
65970
+ if (child.notAfter > parent.notAfter)
65971
+ return "narrowing-expiry";
65972
+ if (parent.overlayIp4 !== 0 && child.overlayIp4 !== parent.overlayIp4)
65973
+ return "narrowing-address";
65974
+ if (hasV6(parent) && !bytesEqual(child.overlayIp6, parent.overlayIp6))
65975
+ return "narrowing-address";
65976
+ const widened = child.flags & ~parent.flags & (FLAG_IS_EXIT_NODE | FLAG_IS_RELAY);
65977
+ if (widened !== 0)
65978
+ return "narrowing-address";
65979
+ return null;
65980
+ }
65981
+ function maySourceAddr(d, afi, src) {
65982
+ if (afi === AFI_V4) {
65983
+ if (src.length !== 4)
65984
+ return false;
65985
+ const asU32 = (src[0] << 24 >>> 0) + (src[1] << 16) + (src[2] << 8) + src[3];
65986
+ if (d.overlayIp4 !== 0 && asU32 === d.overlayIp4)
65987
+ return true;
65988
+ } else if (afi === AFI_V6) {
65989
+ if (src.length !== 16)
65990
+ return false;
65991
+ if (hasV6(d) && bytesEqual(src, d.overlayIp6))
65992
+ return true;
65993
+ } else {
65994
+ return false;
65995
+ }
65996
+ return d.routes.some((p) => p.afi === afi && prefixContainsAddr(p, src));
65997
+ }
65998
+ var TNC_VERSION, FLAG_IS_CA, FLAG_IS_EXIT_NODE, FLAG_IS_RELAY, FLAG_IS_EPHEMERAL, KNOWN_FLAGS, CLOCK_SKEW_MS, MAX_CHAIN_DEPTH, NAME_RE, isCa, isExitNode, isRelay, ZERO16, hasV6, hexKey;
65574
65999
  var init_cert = __esm({
65575
66000
  "../../packages/mesh-pki/dist/cert.js"() {
65576
66001
  "use strict";
@@ -65584,12 +66009,56 @@ var init_cert = __esm({
65584
66009
  FLAG_IS_RELAY = 1 << 2;
65585
66010
  FLAG_IS_EPHEMERAL = 1 << 3;
65586
66011
  KNOWN_FLAGS = FLAG_IS_CA | FLAG_IS_EXIT_NODE | FLAG_IS_RELAY | FLAG_IS_EPHEMERAL;
66012
+ CLOCK_SKEW_MS = 12e4;
66013
+ MAX_CHAIN_DEPTH = 4;
65587
66014
  NAME_RE = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
66015
+ isCa = (d) => (d.flags & FLAG_IS_CA) !== 0;
66016
+ isExitNode = (d) => (d.flags & FLAG_IS_EXIT_NODE) !== 0;
66017
+ isRelay = (d) => (d.flags & FLAG_IS_RELAY) !== 0;
65588
66018
  ZERO16 = new Uint8Array(16);
66019
+ hasV6 = (d) => !bytesEqual(d.overlayIp6, ZERO16);
66020
+ hexKey = (b) => Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
65589
66021
  }
65590
66022
  });
65591
66023
 
65592
66024
  // ../../packages/mesh-pki/dist/addr.js
66025
+ function deriveOverlayV6(meshPrefix6, genesisFp, staticPub) {
66026
+ if (meshPrefix6.length !== 6)
66027
+ throw new MeshCodecError("bad-value", "meshPrefix6 must be 6 bytes");
66028
+ if (genesisFp.length !== 32)
66029
+ throw new MeshCodecError("bad-value", "genesisFp must be 32 bytes");
66030
+ if (staticPub.length !== 32)
66031
+ throw new MeshCodecError("bad-value", "staticPub must be 32 bytes");
66032
+ const iid = blake2s256(concat2(CTX_V6, genesisFp, staticPub));
66033
+ const out = new Uint8Array(16);
66034
+ out.set(meshPrefix6, 0);
66035
+ out.set(iid.subarray(0, 10), 6);
66036
+ return out;
66037
+ }
66038
+ function deriveOverlayV4Hint(cidr, genesisFp, staticPub) {
66039
+ if (cidr.afi !== AFI_V4)
66040
+ throw new MeshCodecError("bad-value", "cidr must be IPv4");
66041
+ const hostBits = maxLenOf(AFI_V4) - cidr.len;
66042
+ if (hostBits < 2)
66043
+ throw new MeshCodecError("bad-value", `mesh cidr /${cidr.len} too small`);
66044
+ const h = blake2s256(concat2(CTX_V4, genesisFp, staticPub));
66045
+ const raw = (h[0] << 24 >>> 0) + (h[1] << 16) + (h[2] << 8) + h[3];
66046
+ const span = hostBits >= 32 ? 4294967296 : 2 ** hostBits;
66047
+ const host = raw % (span - 2) + 1;
66048
+ const base = (cidr.addr[0] << 24 >>> 0) + (cidr.addr[1] << 16) + (cidr.addr[2] << 8) + cidr.addr[3];
66049
+ return base + host >>> 0;
66050
+ }
66051
+ function u32ToAddr(v) {
66052
+ return new Uint8Array([v >>> 24 & 255, v >>> 16 & 255, v >>> 8 & 255, v & 255]);
66053
+ }
66054
+ function addrToU32(a) {
66055
+ if (a.length !== 4)
66056
+ throw new MeshCodecError("bad-value", "IPv4 must be 4 bytes");
66057
+ return (a[0] << 24 >>> 0) + (a[1] << 16) + (a[2] << 8) + a[3] >>> 0;
66058
+ }
66059
+ function meshFqdn(name, orgSlug) {
66060
+ return `${name}.${orgSlug}.tsr.internal`;
66061
+ }
65593
66062
  var CTX_V6, CTX_V4;
65594
66063
  var init_addr = __esm({
65595
66064
  "../../packages/mesh-pki/dist/addr.js"() {
@@ -65603,6 +66072,35 @@ var init_addr = __esm({
65603
66072
  });
65604
66073
 
65605
66074
  // ../../packages/mesh-pki/dist/policy.js
66075
+ function canonicalGroups(indices) {
66076
+ return [...new Set(indices)].sort((a, b) => a - b);
66077
+ }
66078
+ function canonicalPorts(ranges) {
66079
+ const sorted = [...ranges].sort((a, b) => a.lo - b.lo || a.hi - b.hi);
66080
+ for (let i = 0; i < sorted.length; i++) {
66081
+ const r = sorted[i];
66082
+ if (!Number.isInteger(r.lo) || !Number.isInteger(r.hi) || r.lo < 0 || r.hi > 65535 || r.lo > r.hi) {
66083
+ throw new MeshCodecError("bad-value", `port range ${r.lo}-${r.hi}`);
66084
+ }
66085
+ if (i > 0 && r.lo <= sorted[i - 1].hi) {
66086
+ throw new MeshCodecError("bad-value", `overlapping port ranges ${sorted[i - 1].lo}-${sorted[i - 1].hi} / ${r.lo}-${r.hi}`);
66087
+ }
66088
+ }
66089
+ return sorted;
66090
+ }
66091
+ function makeRule(r = {}) {
66092
+ const rule = {
66093
+ action: r.action ?? ACTION_ACCEPT,
66094
+ proto: r.proto ?? PROTO_ANY,
66095
+ srcGroups: canonicalGroups(r.srcGroups ?? []),
66096
+ srcCidrs: canonicalPrefixes(r.srcCidrs ?? []),
66097
+ dstCidrs: canonicalPrefixes(r.dstCidrs ?? []),
66098
+ ports: canonicalPorts(r.ports ?? []),
66099
+ caps: r.caps ?? 0
66100
+ };
66101
+ validateRule(rule);
66102
+ return rule;
66103
+ }
65606
66104
  function validateRule(r) {
65607
66105
  if (r.action !== ACTION_ACCEPT && r.action !== ACTION_DROP) {
65608
66106
  throw new MeshCodecError("bad-value", `action ${r.action}`);
@@ -65638,6 +66136,107 @@ function writeRule(w, r) {
65638
66136
  w.u16(p.lo).u16(p.hi);
65639
66137
  w.u32(r.caps);
65640
66138
  }
66139
+ function readRule(r) {
66140
+ const action = r.u8();
66141
+ const proto = r.u8();
66142
+ const nG = r.u16();
66143
+ if (nG > LIMITS.VEC)
66144
+ throw new MeshCodecError("too-long", "srcGroups");
66145
+ const srcGroups = [];
66146
+ for (let i = 0; i < nG; i++) {
66147
+ const g = r.u16();
66148
+ if (i > 0) {
66149
+ if (g === srcGroups[i - 1])
66150
+ throw new MeshCodecError("duplicate", "srcGroups");
66151
+ if (g < srcGroups[i - 1])
66152
+ throw new MeshCodecError("not-sorted", "srcGroups");
66153
+ }
66154
+ srcGroups.push(g);
66155
+ }
66156
+ const srcCidrs = readPrefixes(r);
66157
+ const dstCidrs = readPrefixes(r);
66158
+ const nP = r.u16();
66159
+ if (nP > LIMITS.VEC)
66160
+ throw new MeshCodecError("too-long", "ports");
66161
+ const ports = [];
66162
+ for (let i = 0; i < nP; i++) {
66163
+ const lo = r.u16();
66164
+ const hi = r.u16();
66165
+ if (lo > hi)
66166
+ throw new MeshCodecError("bad-value", `port range ${lo}-${hi}`);
66167
+ if (i > 0 && lo <= ports[i - 1].hi)
66168
+ throw new MeshCodecError("not-sorted", "ports");
66169
+ ports.push({ lo, hi });
66170
+ }
66171
+ const caps = r.u32();
66172
+ const rule = { action, proto, srcGroups, srcCidrs, dstCidrs, ports, caps };
66173
+ validateRule(rule);
66174
+ return rule;
66175
+ }
66176
+ function ruleMatches(r, peerGroups, q) {
66177
+ if (r.proto !== PROTO_ANY && r.proto !== q.proto)
66178
+ return false;
66179
+ if (r.srcGroups.length > 0 && !r.srcGroups.some((g) => peerGroups.has(g)))
66180
+ return false;
66181
+ if (r.srcCidrs.length > 0 && !r.srcCidrs.some((p) => p.afi === q.afi && prefixContainsAddr(p, q.src)))
66182
+ return false;
66183
+ if (r.dstCidrs.length > 0 && !r.dstCidrs.some((p) => p.afi === q.afi && prefixContainsAddr(p, q.dst)))
66184
+ return false;
66185
+ if (r.ports.length > 0) {
66186
+ if (!PORTED.has(q.proto))
66187
+ return false;
66188
+ const dp = q.dport;
66189
+ if (dp === void 0)
66190
+ return false;
66191
+ if (!r.ports.some((p) => dp >= p.lo && dp <= p.hi))
66192
+ return false;
66193
+ }
66194
+ return true;
66195
+ }
66196
+ function evaluate(rules, peerGroups, q) {
66197
+ for (let i = 0; i < rules.length; i++) {
66198
+ if (ruleMatches(rules[i], peerGroups, q)) {
66199
+ return {
66200
+ allowed: rules[i].action === ACTION_ACCEPT,
66201
+ caps: rules[i].action === ACTION_ACCEPT ? rules[i].caps : 0,
66202
+ ruleIndex: i
66203
+ };
66204
+ }
66205
+ }
66206
+ return { allowed: false, caps: 0, ruleIndex: -1 };
66207
+ }
66208
+ function compilePeerFilter(rules, peerGroups) {
66209
+ const live = rules.filter((r) => r.srcGroups.length === 0 || r.srcGroups.some((g) => peerGroups.has(g)));
66210
+ if (live.length === 0)
66211
+ return { kind: "deny-all" };
66212
+ const first = live[0];
66213
+ const unconditional = first.action === ACTION_ACCEPT && first.proto === PROTO_ANY && first.srcCidrs.length === 0 && first.dstCidrs.length === 0 && first.ports.length === 0;
66214
+ if (unconditional)
66215
+ return { kind: "allow-all", caps: first.caps };
66216
+ return { kind: "rules", rules: live };
66217
+ }
66218
+ function applyPeerFilter(f, peerGroups, q) {
66219
+ switch (f.kind) {
66220
+ case "deny-all":
66221
+ return { allowed: false, caps: 0 };
66222
+ case "allow-all":
66223
+ return { allowed: true, caps: f.caps };
66224
+ case "rules": {
66225
+ const r = evaluate(f.rules, peerGroups, q);
66226
+ return { allowed: r.allowed, caps: r.caps };
66227
+ }
66228
+ }
66229
+ }
66230
+ function resolveGroups(groupTable, certGroups) {
66231
+ const idx = new Map(groupTable.map((g, i) => [g, i]));
66232
+ const out = /* @__PURE__ */ new Set();
66233
+ for (const g of certGroups) {
66234
+ const i = idx.get(g);
66235
+ if (i !== void 0)
66236
+ out.add(i);
66237
+ }
66238
+ return out;
66239
+ }
65641
66240
  var ACTION_ACCEPT, ACTION_DROP, PROTO_ANY, PROTO_ICMP, PROTO_TCP, PROTO_UDP, PROTO_ICMPV6, KNOWN_PROTOS, PORTED, CAP_EXIT_NODE, CAP_USE_ROUTE, KNOWN_CAPS;
65642
66241
  var init_policy = __esm({
65643
66242
  "../../packages/mesh-pki/dist/policy.js"() {
@@ -65660,6 +66259,14 @@ var init_policy = __esm({
65660
66259
  });
65661
66260
 
65662
66261
  // ../../packages/mesh-pki/dist/bundle.js
66262
+ function sortedUniqueBytes(items, what) {
66263
+ const sorted = [...items].sort(cmpBytes);
66264
+ for (let i = 1; i < sorted.length; i++) {
66265
+ if (cmpBytes(sorted[i - 1], sorted[i]) === 0)
66266
+ throw new MeshCodecError("duplicate", what);
66267
+ }
66268
+ return sorted;
66269
+ }
65663
66270
  function validateBundle(b) {
65664
66271
  if (b.version !== TPB_VERSION)
65665
66272
  throw new MeshCodecError("bad-value", `bundle version ${b.version}`);
@@ -65735,6 +66342,101 @@ function writeRevocations(w, items, width) {
65735
66342
  for (const it of items)
65736
66343
  w.fixed(it, width);
65737
66344
  }
66345
+ function readRevocations(r, width) {
66346
+ const n = r.u16();
66347
+ if (n > LIMITS.REVOKED)
66348
+ throw new MeshCodecError("too-long", "revocations");
66349
+ const out = [];
66350
+ for (let i = 0; i < n; i++) {
66351
+ const v = r.fixed(width);
66352
+ if (i > 0) {
66353
+ const c = cmpBytes(out[i - 1], v);
66354
+ if (c === 0)
66355
+ throw new MeshCodecError("duplicate", "revocations");
66356
+ if (c > 0)
66357
+ throw new MeshCodecError("not-sorted", "revocations");
66358
+ }
66359
+ out.push(v);
66360
+ }
66361
+ return out;
66362
+ }
66363
+ function decodeBundle(bytes2) {
66364
+ if (bytes2.length > LIMITS.BUNDLE)
66365
+ throw new MeshCodecError("too-long", "bundle");
66366
+ const r = new Reader(bytes2);
66367
+ const version2 = r.u8();
66368
+ const genesisFp = r.fixed(32);
66369
+ const epoch2 = r.u64();
66370
+ const issuedAt = r.u64();
66371
+ const maxStaleness = r.u32();
66372
+ const nG = r.u16();
66373
+ if (nG > LIMITS.GROUPS)
66374
+ throw new MeshCodecError("too-long", "groupTable");
66375
+ const groupTable = [];
66376
+ for (let i = 0; i < nG; i++)
66377
+ groupTable.push(r.str());
66378
+ const nR = r.u16();
66379
+ if (nR > LIMITS.RULES)
66380
+ throw new MeshCodecError("too-long", "rules");
66381
+ const rules = [];
66382
+ for (let i = 0; i < nR; i++)
66383
+ rules.push(readRule(r));
66384
+ const nRo = r.u16();
66385
+ if (nRo > LIMITS.ROSTER)
66386
+ throw new MeshCodecError("too-long", "roster");
66387
+ const roster = [];
66388
+ for (let i = 0; i < nRo; i++) {
66389
+ const e = {
66390
+ nodeId: r.str(),
66391
+ name: r.str(),
66392
+ staticPub: r.fixed(32),
66393
+ certFp: r.fixed(32),
66394
+ ip4: r.u32(),
66395
+ ip6: r.fixed(16)
66396
+ };
66397
+ if (i > 0) {
66398
+ const c = cmpBytes(roster[i - 1].staticPub, e.staticPub);
66399
+ if (c === 0)
66400
+ throw new MeshCodecError("duplicate", "roster");
66401
+ if (c > 0)
66402
+ throw new MeshCodecError("not-sorted", "roster");
66403
+ }
66404
+ roster.push(e);
66405
+ }
66406
+ const revokedSerials = readRevocations(r, 16);
66407
+ const revokedStatics = readRevocations(r, 32);
66408
+ const nE = r.u16();
66409
+ if (nE > LIMITS.ROSTER)
66410
+ throw new MeshCodecError("too-long", "ip4Exceptions");
66411
+ const ip4Exceptions = [];
66412
+ for (let i = 0; i < nE; i++) {
66413
+ const e = { staticPub: r.fixed(32), ip4: r.u32() };
66414
+ if (i > 0) {
66415
+ const c = cmpBytes(ip4Exceptions[i - 1].staticPub, e.staticPub);
66416
+ if (c === 0)
66417
+ throw new MeshCodecError("duplicate", "ip4Exceptions");
66418
+ if (c > 0)
66419
+ throw new MeshCodecError("not-sorted", "ip4Exceptions");
66420
+ }
66421
+ ip4Exceptions.push(e);
66422
+ }
66423
+ r.finish();
66424
+ const b = {
66425
+ version: version2,
66426
+ genesisFp,
66427
+ epoch: epoch2,
66428
+ issuedAt,
66429
+ maxStaleness,
66430
+ groupTable,
66431
+ rules,
66432
+ roster,
66433
+ revokedSerials,
66434
+ revokedStatics,
66435
+ ip4Exceptions
66436
+ };
66437
+ validateBundle(b);
66438
+ return b;
66439
+ }
65738
66440
  function encodeSignedBundle(sb) {
65739
66441
  const body = encodeBundle(sb.bundle);
65740
66442
  const w = new Writer();
@@ -65744,6 +66446,13 @@ function encodeSignedBundle(sb) {
65744
66446
  });
65745
66447
  return w.finish();
65746
66448
  }
66449
+ function decodeSignedBundle(bytes2) {
66450
+ const r = new Reader(bytes2);
66451
+ const body = r.bytes(LIMITS.BUNDLE);
66452
+ const sigs = r.vec((rr) => ({ keyIndex: rr.u8(), sig: rr.fixed(64) }));
66453
+ r.finish();
66454
+ return { bundle: decodeBundle(body), sigs };
66455
+ }
65747
66456
  async function signBundle(bundle, signers) {
65748
66457
  const body = encodeBundle(bundle);
65749
66458
  const sigs = [];
@@ -65752,7 +66461,38 @@ async function signBundle(bundle, signers) {
65752
66461
  }
65753
66462
  return { bundle, sigs };
65754
66463
  }
65755
- var TPB_VERSION, DEFAULT_MAX_STALENESS_MS, cmpBytes;
66464
+ async function verifyBundle(sb, genesis, genesisFp, opts) {
66465
+ const b = sb.bundle;
66466
+ if (b.version !== TPB_VERSION)
66467
+ return { ok: false, reason: "bad-version" };
66468
+ if (!bytesEqual(b.genesisFp, genesisFp))
66469
+ return { ok: false, reason: "wrong-mesh" };
66470
+ if (opts.knownEpoch !== void 0 && b.epoch <= opts.knownEpoch) {
66471
+ return { ok: false, reason: "rollback" };
66472
+ }
66473
+ if (!opts.ignoreStaleness && opts.now - b.issuedAt > b.maxStaleness) {
66474
+ return { ok: false, reason: "stale" };
66475
+ }
66476
+ const body = encodeBundle(b);
66477
+ const seen = /* @__PURE__ */ new Set();
66478
+ for (const s of sb.sigs) {
66479
+ if (s.keyIndex >= genesis.polKeys.length)
66480
+ return { ok: false, reason: "bad-signature" };
66481
+ if (seen.has(s.keyIndex))
66482
+ return { ok: false, reason: "bad-signature" };
66483
+ if (!await verify2(genesis.polKeys[s.keyIndex], body, s.sig)) {
66484
+ return { ok: false, reason: "bad-signature" };
66485
+ }
66486
+ seen.add(s.keyIndex);
66487
+ }
66488
+ if (seen.size < genesis.kPol)
66489
+ return { ok: false, reason: "quorum-not-met" };
66490
+ return { ok: true };
66491
+ }
66492
+ async function bundleHash(b) {
66493
+ return sha2562(encodeBundle(b));
66494
+ }
66495
+ var TPB_VERSION, DEFAULT_MAX_STALENESS_MS, cmpBytes, canonicalRoster, canonicalExceptions, canonicalRevocations, isFresh, revokes;
65756
66496
  var init_bundle = __esm({
65757
66497
  "../../packages/mesh-pki/dist/bundle.js"() {
65758
66498
  "use strict";
@@ -65768,6 +66508,11 @@ var init_bundle = __esm({
65768
66508
  return a[i] < b[i] ? -1 : 1;
65769
66509
  return a.length === b.length ? 0 : a.length < b.length ? -1 : 1;
65770
66510
  };
66511
+ canonicalRoster = (r) => [...r].sort((a, b) => cmpBytes(a.staticPub, b.staticPub));
66512
+ canonicalExceptions = (e) => [...e].sort((a, b) => cmpBytes(a.staticPub, b.staticPub));
66513
+ canonicalRevocations = (r) => sortedUniqueBytes(r, "revocation");
66514
+ isFresh = (b, now2) => now2 - b.issuedAt <= b.maxStaleness;
66515
+ revokes = (b, serial, staticPub) => b.revokedSerials.some((s) => bytesEqual(s, serial)) || b.revokedStatics.some((s) => bytesEqual(s, staticPub));
65771
66516
  }
65772
66517
  });
65773
66518
 
@@ -67827,7 +68572,66 @@ zoo`.split("\n");
67827
68572
  });
67828
68573
 
67829
68574
  // ../../packages/mesh-pki/dist/sas.js
67830
- var WORD_BITS, WORD_MASK, CTX_ENROLL;
68575
+ function wordsFromDigest(digest, count = SAS_WORDS) {
68576
+ const bits = count * WORD_BITS;
68577
+ if (bits < SAS_MIN_BITS) {
68578
+ throw new MeshCodecError("bad-value", `${count} words = ${bits} bits, below the ${SAS_MIN_BITS}-bit floor`);
68579
+ }
68580
+ const needBytes = Math.ceil((bits + 7) / 8) + 1;
68581
+ if (digest.length < needBytes) {
68582
+ throw new MeshCodecError("bad-value", `digest too short: need ${needBytes}, got ${digest.length}`);
68583
+ }
68584
+ const out = [];
68585
+ for (let i = 0; i < count; i++) {
68586
+ const bitOffset = i * WORD_BITS;
68587
+ const byteIdx = bitOffset >>> 3;
68588
+ const bitInByte = bitOffset & 7;
68589
+ const chunk = (digest[byteIdx] << 16 | digest[byteIdx + 1] << 8 | digest[byteIdx + 2]) >>> 0;
68590
+ const idx = chunk >>> 24 - bitInByte - WORD_BITS & WORD_MASK;
68591
+ out.push(wordlist[idx]);
68592
+ }
68593
+ return out;
68594
+ }
68595
+ function enrolmentSas(genesisFp, staticPub, count = SAS_WORDS) {
68596
+ if (genesisFp.length !== 32)
68597
+ throw new MeshCodecError("bad-value", "genesisFp must be 32 bytes");
68598
+ if (staticPub.length !== 32)
68599
+ throw new MeshCodecError("bad-value", "staticPub must be 32 bytes");
68600
+ return wordsFromDigest(blake2s256(concat2(CTX_ENROLL, genesisFp, staticPub)), count);
68601
+ }
68602
+ function fingerprintWords(genesisFp, count = SAS_WORDS) {
68603
+ if (genesisFp.length !== 32)
68604
+ throw new MeshCodecError("bad-value", "genesisFp must be 32 bytes");
68605
+ return wordsFromDigest(genesisFp, count);
68606
+ }
68607
+ function nameWords(entropy, count = 2) {
68608
+ if (count < 1 || count > 8)
68609
+ throw new MeshCodecError("bad-value", `nameWords count ${count}`);
68610
+ if (entropy.length < count * 2) {
68611
+ throw new MeshCodecError("bad-value", "not enough entropy for that many words");
68612
+ }
68613
+ const out = [];
68614
+ for (let i = 0; i < count; i++) {
68615
+ const idx = (entropy[i * 2] << 8 | entropy[i * 2 + 1]) & 2047;
68616
+ out.push(wordlist[idx]);
68617
+ }
68618
+ return out;
68619
+ }
68620
+ function sasEqual(a, b) {
68621
+ if (a.length !== b.length)
68622
+ return false;
68623
+ let diff = 0;
68624
+ for (let i = 0; i < a.length; i++) {
68625
+ const x = a[i];
68626
+ const y = b[i];
68627
+ diff |= x.length ^ y.length;
68628
+ for (let j = 0; j < Math.max(x.length, y.length); j++) {
68629
+ diff |= (x.charCodeAt(j) | 0) ^ (y.charCodeAt(j) | 0);
68630
+ }
68631
+ }
68632
+ return diff === 0;
68633
+ }
68634
+ var WORD_BITS, WORD_MASK, SAS_WORDS, SAS_MIN_BITS, CTX_ENROLL, formatWords;
67831
68635
  var init_sas = __esm({
67832
68636
  "../../packages/mesh-pki/dist/sas.js"() {
67833
68637
  "use strict";
@@ -67836,10 +68640,13 @@ var init_sas = __esm({
67836
68640
  init_crypto();
67837
68641
  WORD_BITS = 11;
67838
68642
  WORD_MASK = (1 << WORD_BITS) - 1;
68643
+ SAS_WORDS = 6;
68644
+ SAS_MIN_BITS = 64;
67839
68645
  CTX_ENROLL = utf83("tsr-enroll-sas-v1");
67840
68646
  if (wordlist.length !== 1 << WORD_BITS) {
67841
68647
  throw new Error(`BIP-39 wordlist must have ${1 << WORD_BITS} entries, got ${wordlist.length}`);
67842
68648
  }
68649
+ formatWords = (words) => words.join("-");
67843
68650
  }
67844
68651
  });
67845
68652
 
@@ -67874,7 +68681,7 @@ function clean(...arrays) {
67874
68681
  function createView(arr) {
67875
68682
  return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
67876
68683
  }
67877
- function rotr(word, shift) {
68684
+ function rotr2(word, shift) {
67878
68685
  return word << 32 - shift | word >>> shift;
67879
68686
  }
67880
68687
  function utf8ToBytes2(str3) {
@@ -68136,15 +68943,15 @@ var init_sha2 = __esm({
68136
68943
  for (let i = 16; i < 64; i++) {
68137
68944
  const W15 = SHA256_W[i - 15];
68138
68945
  const W2 = SHA256_W[i - 2];
68139
- const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
68140
- const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
68946
+ const s0 = rotr2(W15, 7) ^ rotr2(W15, 18) ^ W15 >>> 3;
68947
+ const s1 = rotr2(W2, 17) ^ rotr2(W2, 19) ^ W2 >>> 10;
68141
68948
  SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
68142
68949
  }
68143
68950
  let { A, B, C, D, E, F, G: G2, H } = this;
68144
68951
  for (let i = 0; i < 64; i++) {
68145
- const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
68952
+ const sigma1 = rotr2(E, 6) ^ rotr2(E, 11) ^ rotr2(E, 25);
68146
68953
  const T1 = H + sigma1 + Chi(E, F, G2) + SHA256_K[i] + SHA256_W[i] | 0;
68147
- const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
68954
+ const sigma0 = rotr2(A, 2) ^ rotr2(A, 13) ^ rotr2(A, 22);
68148
68955
  const T2 = sigma0 + Maj(A, B, C) | 0;
68149
68956
  H = G2;
68150
68957
  G2 = F;
@@ -68466,6 +69273,18 @@ var init_esm = __esm({
68466
69273
  });
68467
69274
 
68468
69275
  // ../../node_modules/@scure/bip39/esm/index.js
69276
+ function nfkd(str3) {
69277
+ if (typeof str3 !== "string")
69278
+ throw new TypeError("invalid mnemonic type: " + typeof str3);
69279
+ return str3.normalize("NFKD");
69280
+ }
69281
+ function normalize2(str3) {
69282
+ const norm = nfkd(str3);
69283
+ const words = norm.split(" ");
69284
+ if (![12, 15, 18, 21, 24].includes(words.length))
69285
+ throw new Error("Invalid mnemonic");
69286
+ return { nfkd: norm, words };
69287
+ }
68469
69288
  function aentropy(ent) {
68470
69289
  abytes(ent, 16, 20, 24, 28, 32);
68471
69290
  }
@@ -68478,11 +69297,25 @@ function getCoder(wordlist2) {
68478
69297
  });
68479
69298
  return utils.chain(utils.checksum(1, calcChecksum), utils.radix2(11, true), utils.alphabet(wordlist2));
68480
69299
  }
69300
+ function mnemonicToEntropy(mnemonic, wordlist2) {
69301
+ const { words } = normalize2(mnemonic);
69302
+ const entropy = getCoder(wordlist2).decode(words);
69303
+ aentropy(entropy);
69304
+ return entropy;
69305
+ }
68481
69306
  function entropyToMnemonic(entropy, wordlist2) {
68482
69307
  aentropy(entropy);
68483
69308
  const words = getCoder(wordlist2).encode(entropy);
68484
69309
  return words.join(isJapanese(wordlist2) ? "\u3000" : " ");
68485
69310
  }
69311
+ function validateMnemonic(mnemonic, wordlist2) {
69312
+ try {
69313
+ mnemonicToEntropy(mnemonic, wordlist2);
69314
+ } catch (e) {
69315
+ return false;
69316
+ }
69317
+ return true;
69318
+ }
68486
69319
  var isJapanese, calcChecksum;
68487
69320
  var init_esm2 = __esm({
68488
69321
  "../../node_modules/@scure/bip39/esm/index.js"() {
@@ -68568,11 +69401,26 @@ function caKeyToMnemonic(seed) {
68568
69401
  throw new MeshCodecError("bad-value", `CA seed must be ${SECRET_LEN} bytes`);
68569
69402
  return entropyToMnemonic(seed, wordlist);
68570
69403
  }
69404
+ function caKeyFromMnemonic(mnemonic) {
69405
+ const norm = mnemonic.normalize("NFKD").trim().replace(/\s+/g, " ").toLowerCase();
69406
+ if (norm.split(" ").length !== MNEMONIC_WORDS) {
69407
+ throw new MeshCodecError("bad-value", `recovery mnemonic must be ${MNEMONIC_WORDS} words`);
69408
+ }
69409
+ if (!validateMnemonic(norm, wordlist)) {
69410
+ throw new MeshCodecError("bad-value", "recovery mnemonic failed its checksum \u2014 check for a mistyped word");
69411
+ }
69412
+ return mnemonicToEntropy(norm, wordlist);
69413
+ }
68571
69414
  async function newDisablement() {
68572
69415
  const secret = randomBytes9(SECRET_LEN);
68573
69416
  return { secret, hash: await sha2562(secret) };
68574
69417
  }
68575
- var RECOVERY_VERSION, SECRET_LEN, KDF_MEMORY_KIB, KDF_PASSES, KDF_LANES, DEFAULT_KDF, KDF_MIN, KDF_MAX, SALT_LEN, NONCE_LEN, KEY_LEN, MAX_LABEL, DOMAIN;
69418
+ async function verifyDisablement(secret, committedHash) {
69419
+ if (secret.length !== SECRET_LEN || committedHash.length !== 32)
69420
+ return false;
69421
+ return bytesEqual(await sha2562(secret), committedHash);
69422
+ }
69423
+ var RECOVERY_VERSION, SECRET_LEN, MNEMONIC_WORDS, KDF_MEMORY_KIB, KDF_PASSES, KDF_LANES, DEFAULT_KDF, KDF_MIN, KDF_MAX, SALT_LEN, NONCE_LEN, KEY_LEN, MAX_LABEL, DOMAIN;
68576
69424
  var init_recovery = __esm({
68577
69425
  "../../packages/mesh-pki/dist/recovery.js"() {
68578
69426
  "use strict";
@@ -68583,6 +69431,7 @@ var init_recovery = __esm({
68583
69431
  init_crypto();
68584
69432
  RECOVERY_VERSION = 1;
68585
69433
  SECRET_LEN = 32;
69434
+ MNEMONIC_WORDS = 24;
68586
69435
  KDF_MEMORY_KIB = 64 * 1024;
68587
69436
  KDF_PASSES = 3;
68588
69437
  KDF_LANES = 4;
@@ -68598,7 +69447,109 @@ var init_recovery = __esm({
68598
69447
  });
68599
69448
 
68600
69449
  // ../../packages/mesh-pki/dist/enroll.js
68601
- var DEFAULT_TICKET_TTL_MS;
69450
+ async function mintJoinTicket(opts) {
69451
+ const genesisFp = await genesisFingerprint(opts.genesis);
69452
+ const ttl = opts.ttlMs ?? DEFAULT_TICKET_TTL_MS;
69453
+ const details = {
69454
+ version: 1,
69455
+ serial: randomBytes9(16),
69456
+ genesisFp,
69457
+ nodeId: opts.nodeId,
69458
+ name: opts.name,
69459
+ // The intermediate is a signing identity, not a data-plane peer. It carries no
69460
+ // usable X25519 static key — the redeeming node supplies its own.
69461
+ staticPub: new Uint8Array(32),
69462
+ sigPub: opts.intermediate.publicRaw,
69463
+ overlayIp4: opts.overlayIp4,
69464
+ overlayIp6: opts.overlayIp6,
69465
+ routes: canonicalPrefixes(opts.routes ?? []),
69466
+ flags: FLAG_IS_CA,
69467
+ groups: canonicalStrs(opts.groups),
69468
+ notBefore: opts.now - 6e4,
69469
+ // small backdate absorbs clock skew at redemption
69470
+ notAfter: opts.now + ttl,
69471
+ issuerFp: genesisFp
69472
+ };
69473
+ return {
69474
+ genesis: opts.genesis,
69475
+ caCert: await issueCert(details, opts.signers),
69476
+ caPrivate: opts.intermediate.privateScalar
69477
+ };
69478
+ }
69479
+ function encodeJoinTicket(t) {
69480
+ const w = new Writer();
69481
+ w.u8(TICKET_VERSION);
69482
+ w.bytes(encodeGenesis(t.genesis), LIMITS.GENESIS);
69483
+ w.bytes(encodeCert(t.caCert), LIMITS.CERT);
69484
+ w.fixed(t.caPrivate, 32);
69485
+ return w.finish();
69486
+ }
69487
+ function decodeJoinTicket(bytes2) {
69488
+ const r = new Reader(bytes2);
69489
+ const version2 = r.u8();
69490
+ if (version2 !== TICKET_VERSION)
69491
+ throw new MeshCodecError("bad-value", `ticket version ${version2}`);
69492
+ const genesis = decodeGenesis(r.bytes(LIMITS.GENESIS));
69493
+ const caCert = decodeCert(r.bytes(LIMITS.CERT));
69494
+ const caPrivate = r.fixed(32);
69495
+ r.finish();
69496
+ return { genesis, caCert, caPrivate };
69497
+ }
69498
+ async function redeemJoinTicket(opts) {
69499
+ const { ticket } = opts;
69500
+ const ca = ticket.caCert.details;
69501
+ if (!(ca.flags & FLAG_IS_CA))
69502
+ return { ok: false, reason: "ticket-not-ca" };
69503
+ if (opts.now > ca.notAfter)
69504
+ return { ok: false, reason: "ticket-expired" };
69505
+ const groups = canonicalStrs(opts.groups ?? ca.groups);
69506
+ const parentGroups = new Set(ca.groups);
69507
+ if (groups.some((g) => !parentGroups.has(g)))
69508
+ return { ok: false, reason: "widens-groups" };
69509
+ const routes = canonicalPrefixes(opts.routes ?? ca.routes);
69510
+ const parentKeys = new Set(ca.routes.map((p) => `${p.afi}/${p.len}/${p.addr.join(".")}`));
69511
+ if (routes.some((p) => !parentKeys.has(`${p.afi}/${p.len}/${p.addr.join(".")}`))) {
69512
+ return { ok: false, reason: "widens-routes" };
69513
+ }
69514
+ const wanted2 = opts.now + (opts.leafTtlMs ?? DEFAULT_TICKET_TTL_MS);
69515
+ const notAfter = Math.min(wanted2, ca.notAfter);
69516
+ const genesisFp = await genesisFingerprint(ticket.genesis);
69517
+ const details = {
69518
+ version: 1,
69519
+ serial: randomBytes9(16),
69520
+ genesisFp,
69521
+ nodeId: opts.nodeId ?? ca.nodeId,
69522
+ name: opts.name ?? ca.name,
69523
+ staticPub: opts.staticPub,
69524
+ sigPub: opts.sigPub,
69525
+ // Pinned by the ticket — narrowing forbids changing these.
69526
+ overlayIp4: ca.overlayIp4,
69527
+ overlayIp6: ca.overlayIp6,
69528
+ routes,
69529
+ flags: 0,
69530
+ groups,
69531
+ notBefore: opts.now - 6e4,
69532
+ notAfter,
69533
+ issuerFp: await certFingerprint(ca)
69534
+ };
69535
+ const key2 = await importSigningPrivate({
69536
+ kty: "OKP",
69537
+ crv: "Ed25519",
69538
+ d: b64u2(ticket.caPrivate),
69539
+ x: b64u2(ca.sigPub),
69540
+ key_ops: ["sign"],
69541
+ ext: true
69542
+ });
69543
+ const leaf = await issueCert(details, [{ keyIndex: 0, privateKey: key2.privateKey }]);
69544
+ return {
69545
+ ok: true,
69546
+ result: { leaf, genesis: ticket.genesis, intermediates: [ticket.caCert] }
69547
+ };
69548
+ }
69549
+ async function predictOverlayV6(genesis, staticPub) {
69550
+ return deriveOverlayV6(genesis.meshPrefix6, await genesisFingerprint(genesis), staticPub);
69551
+ }
69552
+ var TICKET_VERSION, DEFAULT_TICKET_TTL_MS, joinTicketToString, joinTicketFromString;
68602
69553
  var init_enroll = __esm({
68603
69554
  "../../packages/mesh-pki/dist/enroll.js"() {
68604
69555
  "use strict";
@@ -68609,11 +69560,167 @@ var init_enroll = __esm({
68609
69560
  init_crypto();
68610
69561
  init_codec();
68611
69562
  init_addr();
69563
+ TICKET_VERSION = 1;
68612
69564
  DEFAULT_TICKET_TTL_MS = 15 * 60 * 1e3;
69565
+ joinTicketToString = (t) => b64u2(encodeJoinTicket(t));
69566
+ joinTicketFromString = (s) => decodeJoinTicket(unb64u2(s));
68613
69567
  }
68614
69568
  });
68615
69569
 
68616
69570
  // ../../packages/mesh-pki/dist/index.js
69571
+ var dist_exports3 = {};
69572
+ __export(dist_exports3, {
69573
+ ACTION_ACCEPT: () => ACTION_ACCEPT,
69574
+ ACTION_DROP: () => ACTION_DROP,
69575
+ AFI_V4: () => AFI_V4,
69576
+ AFI_V6: () => AFI_V6,
69577
+ CAP_EXIT_NODE: () => CAP_EXIT_NODE,
69578
+ CAP_USE_ROUTE: () => CAP_USE_ROUTE,
69579
+ CLOCK_SKEW_MS: () => CLOCK_SKEW_MS,
69580
+ DEFAULT_MAX_STALENESS_MS: () => DEFAULT_MAX_STALENESS_MS,
69581
+ DEFAULT_MESH_CIDR4: () => DEFAULT_MESH_CIDR4,
69582
+ DEFAULT_TICKET_TTL_MS: () => DEFAULT_TICKET_TTL_MS,
69583
+ ED25519: () => ED25519,
69584
+ FLAG_IS_CA: () => FLAG_IS_CA,
69585
+ FLAG_IS_EPHEMERAL: () => FLAG_IS_EPHEMERAL,
69586
+ FLAG_IS_EXIT_NODE: () => FLAG_IS_EXIT_NODE,
69587
+ FLAG_IS_RELAY: () => FLAG_IS_RELAY,
69588
+ GENESIS_VERSION: () => GENESIS_VERSION,
69589
+ KDF_LANES: () => KDF_LANES,
69590
+ KDF_MEMORY_KIB: () => KDF_MEMORY_KIB,
69591
+ KDF_PASSES: () => KDF_PASSES,
69592
+ LIMITS: () => LIMITS,
69593
+ MAX_CHAIN_DEPTH: () => MAX_CHAIN_DEPTH,
69594
+ MIN_MESH_PREFIX_LEN: () => MIN_MESH_PREFIX_LEN,
69595
+ MNEMONIC_WORDS: () => MNEMONIC_WORDS,
69596
+ MeshCodecError: () => MeshCodecError,
69597
+ PROTO_ANY: () => PROTO_ANY,
69598
+ PROTO_ICMP: () => PROTO_ICMP,
69599
+ PROTO_ICMPV6: () => PROTO_ICMPV6,
69600
+ PROTO_TCP: () => PROTO_TCP,
69601
+ PROTO_UDP: () => PROTO_UDP,
69602
+ RECOVERY_VERSION: () => RECOVERY_VERSION,
69603
+ Reader: () => Reader,
69604
+ SAS_MIN_BITS: () => SAS_MIN_BITS,
69605
+ SAS_WORDS: () => SAS_WORDS,
69606
+ SECRET_LEN: () => SECRET_LEN,
69607
+ TICKET_VERSION: () => TICKET_VERSION,
69608
+ TNC_VERSION: () => TNC_VERSION,
69609
+ TPB_VERSION: () => TPB_VERSION,
69610
+ Writer: () => Writer,
69611
+ X25519: () => X25519,
69612
+ addrToU32: () => addrToU32,
69613
+ applyPeerFilter: () => applyPeerFilter,
69614
+ b64u: () => b64u2,
69615
+ blake2s256: () => blake2s256,
69616
+ bundleHash: () => bundleHash,
69617
+ bytesEqual: () => bytesEqual,
69618
+ caKeyFromMnemonic: () => caKeyFromMnemonic,
69619
+ caKeyToMnemonic: () => caKeyToMnemonic,
69620
+ canonicalExceptions: () => canonicalExceptions,
69621
+ canonicalGroups: () => canonicalGroups,
69622
+ canonicalPorts: () => canonicalPorts,
69623
+ canonicalPrefixes: () => canonicalPrefixes,
69624
+ canonicalRevocations: () => canonicalRevocations,
69625
+ canonicalRoster: () => canonicalRoster,
69626
+ canonicalStrs: () => canonicalStrs,
69627
+ certFingerprint: () => certFingerprint,
69628
+ checkNarrowing: () => checkNarrowing,
69629
+ comparePrefix: () => comparePrefix,
69630
+ compareUtf8: () => compareUtf8,
69631
+ compilePeerFilter: () => compilePeerFilter,
69632
+ concat: () => concat2,
69633
+ decodeBundle: () => decodeBundle,
69634
+ decodeCert: () => decodeCert,
69635
+ decodeDetails: () => decodeDetails,
69636
+ decodeGenesis: () => decodeGenesis,
69637
+ decodeJoinTicket: () => decodeJoinTicket,
69638
+ decodeRecoveryBundle: () => decodeRecoveryBundle,
69639
+ decodeSignedBundle: () => decodeSignedBundle,
69640
+ decodeSignedGenesis: () => decodeSignedGenesis,
69641
+ deriveMeshPrefix6: () => deriveMeshPrefix6,
69642
+ deriveOverlayV4Hint: () => deriveOverlayV4Hint,
69643
+ deriveOverlayV6: () => deriveOverlayV6,
69644
+ encodeBundle: () => encodeBundle,
69645
+ encodeCert: () => encodeCert,
69646
+ encodeDetails: () => encodeDetails,
69647
+ encodeGenesis: () => encodeGenesis,
69648
+ encodeJoinTicket: () => encodeJoinTicket,
69649
+ encodeRecoveryBundle: () => encodeRecoveryBundle,
69650
+ encodeSignedBundle: () => encodeSignedBundle,
69651
+ encodeSignedGenesis: () => encodeSignedGenesis,
69652
+ enrolmentSas: () => enrolmentSas,
69653
+ evaluate: () => evaluate,
69654
+ exportSigningPrivate: () => exportSigningPrivate,
69655
+ exportStaticPrivate: () => exportStaticPrivate,
69656
+ fingerprintShort: () => fingerprintShort,
69657
+ fingerprintWords: () => fingerprintWords,
69658
+ formatAddr: () => formatAddr,
69659
+ formatPrefix: () => formatPrefix,
69660
+ formatWords: () => formatWords,
69661
+ generateSigningKey: () => generateSigningKey,
69662
+ generateStaticKey: () => generateStaticKey,
69663
+ genesisFingerprint: () => genesisFingerprint,
69664
+ hex: () => hex4,
69665
+ importSigningPrivate: () => importSigningPrivate,
69666
+ importSigningPublic: () => importSigningPublic,
69667
+ isCa: () => isCa,
69668
+ isExitNode: () => isExitNode,
69669
+ isFresh: () => isFresh,
69670
+ isMasked: () => isMasked,
69671
+ isRelay: () => isRelay,
69672
+ isValidMeshRange: () => isValidMeshRange,
69673
+ issueCert: () => issueCert,
69674
+ joinTicketFromString: () => joinTicketFromString,
69675
+ joinTicketToString: () => joinTicketToString,
69676
+ makeGenesis: () => makeGenesis,
69677
+ makePrefix: () => makePrefix,
69678
+ makeRule: () => makeRule,
69679
+ mask: () => mask,
69680
+ maxLenOf: () => maxLenOf,
69681
+ maySourceAddr: () => maySourceAddr,
69682
+ meshFqdn: () => meshFqdn,
69683
+ mintJoinTicket: () => mintJoinTicket,
69684
+ nameWords: () => nameWords,
69685
+ newDisablement: () => newDisablement,
69686
+ openCaKey: () => openCaKey,
69687
+ parseAddr: () => parseAddr,
69688
+ parsePrefix: () => parsePrefix,
69689
+ predictOverlayV6: () => predictOverlayV6,
69690
+ prefixContains: () => prefixContains,
69691
+ prefixContainsAddr: () => prefixContainsAddr,
69692
+ prefixEqual: () => prefixEqual,
69693
+ randomBytes: () => randomBytes9,
69694
+ readPrefix: () => readPrefix,
69695
+ readPrefixes: () => readPrefixes,
69696
+ readRule: () => readRule,
69697
+ redeemJoinTicket: () => redeemJoinTicket,
69698
+ resolveGroups: () => resolveGroups,
69699
+ revokes: () => revokes,
69700
+ sasEqual: () => sasEqual,
69701
+ sealCaKey: () => sealCaKey,
69702
+ sha256: () => sha2562,
69703
+ sign: () => sign2,
69704
+ signBundle: () => signBundle,
69705
+ signGenesis: () => signGenesis,
69706
+ signingKeyFromSeed: () => signingKeyFromSeed,
69707
+ u32ToAddr: () => u32ToAddr,
69708
+ unb64u: () => unb64u2,
69709
+ utf8: () => utf83,
69710
+ validateBundle: () => validateBundle,
69711
+ validateDetails: () => validateDetails,
69712
+ validateGenesis: () => validateGenesis,
69713
+ verify: () => verify2,
69714
+ verifyBundle: () => verifyBundle,
69715
+ verifyCert: () => verifyCert,
69716
+ verifyDisablement: () => verifyDisablement,
69717
+ verifyGenesis: () => verifyGenesis,
69718
+ widthOf: () => widthOf,
69719
+ wordsFromDigest: () => wordsFromDigest,
69720
+ writePrefix: () => writePrefix,
69721
+ writePrefixes: () => writePrefixes,
69722
+ writeRule: () => writeRule
69723
+ });
68617
69724
  var init_dist6 = __esm({
68618
69725
  "../../packages/mesh-pki/dist/index.js"() {
68619
69726
  "use strict";
@@ -69799,10 +70906,10 @@ async function netCaCommand(rest, flags) {
69799
70906
  ensureDir(caDir);
69800
70907
  writeFileSync42(join76(caDir, "genesis.bin"), genesisBytes);
69801
70908
  writeSecretFile(join76(caDir, "ca.sealed"), encodeRecoveryBundle(await sealCaKey(seed, pass, `${org} mesh CA`)));
69802
- writeSecretFile(join76(caDir, "disablement.secret"), hex3(disable.secret));
70909
+ writeSecretFile(join76(caDir, "disablement.secret"), hex4(disable.secret));
69803
70910
  console.log(`
69804
70911
  Mesh created for "${org}".`);
69805
- console.log(` fingerprint: ${hex3(fp)}`);
70912
+ console.log(` fingerprint: ${hex4(fp)}`);
69806
70913
  console.log(` CA directory: ${caDir}`);
69807
70914
  console.log("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
69808
70915
  console.log("WRITE THESE DOWN NOW. They are not shown again.\n");
@@ -69811,7 +70918,7 @@ Mesh created for "${org}".`);
69811
70918
  `);
69812
70919
  console.log("Disablement secret (last resort if the CA AND the mnemonic are gone \u2014");
69813
70920
  console.log("it drops every node back to relay-trusted mode, permanently):");
69814
- console.log(` ${hex3(disable.secret)}`);
70921
+ console.log(` ${hex4(disable.secret)}`);
69815
70922
  console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
69816
70923
  console.log(`
69817
70924
  A copy of the disablement secret is in ${join76(caDir, "disablement.secret")}.`);
@@ -72086,10 +73193,10 @@ function createHostedVerification() {
72086
73193
  let reviewText = "";
72087
73194
  for (let i = 0; i < rv.RV_MAX_CYCLES * 2 + 2; i++) {
72088
73195
  const gate = state3.phase === "review" ? "review" : "completeness";
72089
- const call2 = gate === "review" ? rv.reviewGrade(task, reviewText || text9) : rv.completenessGrade(task, text9, todos);
73196
+ const call3 = gate === "review" ? rv.reviewGrade(task, reviewText || text9) : rv.completenessGrade(task, text9, todos);
72090
73197
  let verdict = null;
72091
73198
  try {
72092
- verdict = rv.parseVerdict(await grade({ model, system: call2.system, prompt: call2.prompt, maxTokens: 16e3, schema: call2.schema }));
73199
+ verdict = rv.parseVerdict(await grade({ model, system: call3.system, prompt: call3.prompt, maxTokens: 16e3, schema: call3.schema }));
72093
73200
  } catch {
72094
73201
  verdict = null;
72095
73202
  }
@@ -73373,7 +74480,7 @@ async function pickPort() {
73373
74480
  var CALL_TIMEOUT_MS = 8e3;
73374
74481
  function createEngineHttpApi(port, host = "127.0.0.1") {
73375
74482
  const baseUrl = `http://${host}:${port}`;
73376
- async function call2(method, path6, body, timeoutMs = CALL_TIMEOUT_MS) {
74483
+ async function call3(method, path6, body, timeoutMs = CALL_TIMEOUT_MS) {
73377
74484
  const ac = new AbortController();
73378
74485
  const timer2 = setTimeout(() => ac.abort(), timeoutMs);
73379
74486
  try {
@@ -73401,12 +74508,12 @@ function createEngineHttpApi(port, host = "127.0.0.1") {
73401
74508
  }
73402
74509
  return {
73403
74510
  baseUrl,
73404
- get: (path6, timeoutMs) => call2("GET", path6, void 0, timeoutMs),
73405
- post: (path6, body, timeoutMs, method) => call2(method ?? "POST", path6, body, timeoutMs),
74511
+ get: (path6, timeoutMs) => call3("GET", path6, void 0, timeoutMs),
74512
+ post: (path6, body, timeoutMs, method) => call3(method ?? "POST", path6, body, timeoutMs),
73406
74513
  async ready(timeoutMs = 5e3) {
73407
74514
  const deadline = Date.now() + timeoutMs;
73408
74515
  while (Date.now() < deadline) {
73409
- const h = await call2("GET", "/global/health", void 0, 1500);
74516
+ const h = await call3("GET", "/global/health", void 0, 1500);
73410
74517
  if (h && h !== true && h.healthy !== false)
73411
74518
  return true;
73412
74519
  if (h === true)
@@ -74784,20 +75891,20 @@ ${text9}`);
74784
75891
  }
74785
75892
  async function sendMessage(params) {
74786
75893
  const origin = params.origin;
74787
- const fail3 = (sessionId, error51, transient = false) => send4({ type: "chat:error", sessionId, clientRequestId: params.clientRequestId, error: error51, ...transient ? { transient: true } : {} }, origin);
75894
+ const fail4 = (sessionId, error51, transient = false) => send4({ type: "chat:error", sessionId, clientRequestId: params.clientRequestId, error: error51, ...transient ? { transient: true } : {} }, origin);
74788
75895
  const spawnCfg = resolve16(engine.id);
74789
75896
  if (!spawnCfg) {
74790
- fail3(params.sessionId ?? "", `${engine.label} isn't installed or configured. Open Settings \u2192 Models & accounts.`);
75897
+ fail4(params.sessionId ?? "", `${engine.label} isn't installed or configured. Open Settings \u2192 Models & accounts.`);
74791
75898
  return;
74792
75899
  }
74793
75900
  const configError = spawnConfigError(spawnCfg);
74794
75901
  if (configError) {
74795
- fail3(params.sessionId ?? "", configError);
75902
+ fail4(params.sessionId ?? "", configError);
74796
75903
  send4({ type: "agent:status", sessionId: params.sessionId ?? "", clientRequestId: params.clientRequestId, status: "error" }, origin);
74797
75904
  return;
74798
75905
  }
74799
75906
  if (!params.projectDir) {
74800
- fail3(params.sessionId ?? "", "No project folder is open. Open a folder to start working with the agent.");
75907
+ fail4(params.sessionId ?? "", "No project folder is open. Open a folder to start working with the agent.");
74801
75908
  return;
74802
75909
  }
74803
75910
  let t;
@@ -74819,13 +75926,13 @@ ${text9}`);
74819
75926
  try {
74820
75927
  t = await ensureProcess(spawnCfg.command, spawnCfg.env, params.projectDir, mcpSpecsFor(params), !!wantSandbox, JSON.stringify(engine.askEnv?.(params.permissionMode) ?? null));
74821
75928
  } catch (e) {
74822
- fail3(params.sessionId ?? "", `OpenCode failed to start: ${String(e?.message ?? e)}`, true);
75929
+ fail4(params.sessionId ?? "", `OpenCode failed to start: ${String(e?.message ?? e)}`, true);
74823
75930
  return;
74824
75931
  }
74825
75932
  if (params.message.trim() === "/compact" && !engine.compactCommand && params.sessionId) {
74826
75933
  const from = params.sessionId;
74827
75934
  if (turns.has(from)) {
74828
- fail3(from, `${engine.label} is still working on this conversation \u2014 compaction will run once it finishes.`, false);
75935
+ fail4(from, `${engine.label} is still working on this conversation \u2014 compaction will run once it finishes.`, false);
74829
75936
  send4({ type: "agent:status", sessionId: from, clientRequestId: params.clientRequestId, status: "idle" }, origin);
74830
75937
  return;
74831
75938
  }
@@ -74853,7 +75960,7 @@ ${text9}`);
74853
75960
  turns.delete(from);
74854
75961
  }
74855
75962
  if (!snapshot3) {
74856
- fail3(from, `${engine.label} could not summarise this conversation to compact it.`, false);
75963
+ fail4(from, `${engine.label} could not summarise this conversation to compact it.`, false);
74857
75964
  send4({ type: "agent:status", sessionId: from, clientRequestId: params.clientRequestId, status: "idle" }, origin);
74858
75965
  return;
74859
75966
  }
@@ -74861,7 +75968,7 @@ ${text9}`);
74861
75968
  const fresh = await t.request("session/new", { cwd: params.projectDir, mcpServers: mcpServersFor(params, compactHold) }).catch(() => null);
74862
75969
  const next = fresh?.sessionId;
74863
75970
  if (!next) {
74864
- fail3(from, `${engine.label} could not open a fresh session to compact into.`, true);
75971
+ fail4(from, `${engine.label} could not open a fresh session to compact into.`, true);
74865
75972
  send4({ type: "agent:status", sessionId: from, clientRequestId: params.clientRequestId, status: "error" }, origin);
74866
75973
  return;
74867
75974
  }
@@ -74932,7 +76039,7 @@ ${text9}`);
74932
76039
  await applyRunMode(t, sid, params.permissionMode, params.model);
74933
76040
  await applyThinking(t, sid, params.thinking);
74934
76041
  } catch (e) {
74935
- fail3(params.sessionId ?? "", `Couldn't start a ${engineLabel} session: ${String(e?.message ?? e)}`, true);
76042
+ fail4(params.sessionId ?? "", `Couldn't start a ${engineLabel} session: ${String(e?.message ?? e)}`, true);
74936
76043
  return;
74937
76044
  }
74938
76045
  const userSeq = userTurnSeq.get(sid) ?? 0;
@@ -75067,7 +76174,7 @@ ${text9}`);
75067
76174
  send4({ type: "agent:status", sessionId: sid, clientRequestId: params.clientRequestId, status: "idle" }, origin);
75068
76175
  return;
75069
76176
  }
75070
- fail3(sid, overflow ? `${CONTEXT_OVERFLOW_HINT}
76177
+ fail4(sid, overflow ? `${CONTEXT_OVERFLOW_HINT}
75071
76178
 
75072
76179
  ${detail}` : detail, !overflow);
75073
76180
  send4({ type: "agent:status", sessionId: sid, clientRequestId: params.clientRequestId, status: "error" }, origin);
@@ -76090,7 +77197,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76090
77197
  }
76091
77198
  const pendingApprovals = /* @__PURE__ */ new Map();
76092
77199
  const pendingDialogs = /* @__PURE__ */ new Map();
76093
- const fail3 = (sessionId, clientRequestId, error51, origin, transient = false) => {
77200
+ const fail4 = (sessionId, clientRequestId, error51, origin, transient = false) => {
76094
77201
  send4({ type: "chat:error", sessionId, clientRequestId, error: error51, ...transient ? { transient: true } : {} }, origin);
76095
77202
  };
76096
77203
  function parkApproval(raw, toolName, allow, allowPersist, deny, detail) {
@@ -76292,7 +77399,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76292
77399
  const t = p.turn ?? {};
76293
77400
  if (t.status === "failed" && !turn.reported) {
76294
77401
  turn.reported = true;
76295
- fail3(threadId, turn.clientRequestId, codexErrorText(t.error), turn.origin, true);
77402
+ fail4(threadId, turn.clientRequestId, codexErrorText(t.error), turn.origin, true);
76296
77403
  }
76297
77404
  turn.finish(t.status ?? null);
76298
77405
  return;
@@ -76303,7 +77410,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76303
77410
  return;
76304
77411
  if (!turn.reported) {
76305
77412
  turn.reported = true;
76306
- fail3(threadId, turn.clientRequestId, codexErrorText(p.error), turn.origin, true);
77413
+ fail4(threadId, turn.clientRequestId, codexErrorText(p.error), turn.origin, true);
76307
77414
  }
76308
77415
  turn.finish(null);
76309
77416
  return;
@@ -76377,7 +77484,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76377
77484
  spawnedCwd = null;
76378
77485
  for (const [tid, turn] of turns) {
76379
77486
  turn.finish(null);
76380
- fail3(tid, turn.clientRequestId, `${label} restarted.`, turn.origin, true);
77487
+ fail4(tid, turn.clientRequestId, `${label} restarted.`, turn.origin, true);
76381
77488
  }
76382
77489
  turns.clear();
76383
77490
  for (const w of compactWaiters.values())
@@ -76496,17 +77603,17 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76496
77603
  const origin = params.origin;
76497
77604
  const cfg2 = resolve16(ENGINE_ID2);
76498
77605
  if (!cfg2) {
76499
- fail3(params.sessionId ?? "", params.clientRequestId, `${label} isn't installed or configured. Open Settings \u2192 Models & accounts.`, origin);
77606
+ fail4(params.sessionId ?? "", params.clientRequestId, `${label} isn't installed or configured. Open Settings \u2192 Models & accounts.`, origin);
76500
77607
  return;
76501
77608
  }
76502
77609
  const cfgErr = spawnConfigError(cfg2);
76503
77610
  if (cfgErr) {
76504
- fail3(params.sessionId ?? "", params.clientRequestId, cfgErr, origin);
77611
+ fail4(params.sessionId ?? "", params.clientRequestId, cfgErr, origin);
76505
77612
  send4({ type: "agent:status", sessionId: params.sessionId ?? "", clientRequestId: params.clientRequestId, status: "error" }, origin);
76506
77613
  return;
76507
77614
  }
76508
77615
  if (!params.projectDir) {
76509
- fail3(params.sessionId ?? "", params.clientRequestId, "No project folder is open. Open a folder to start working with the agent.", origin);
77616
+ fail4(params.sessionId ?? "", params.clientRequestId, "No project folder is open. Open a folder to start working with the agent.", origin);
76510
77617
  return;
76511
77618
  }
76512
77619
  await ensureHostedToolset();
@@ -76514,7 +77621,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76514
77621
  try {
76515
77622
  t = await ensureProcess(cfg2.command, cfg2.env, params.projectDir);
76516
77623
  } catch (e) {
76517
- fail3(params.sessionId ?? "", params.clientRequestId, `${label} failed to start: ${String(e?.message ?? e)}`, origin, true);
77624
+ fail4(params.sessionId ?? "", params.clientRequestId, `${label} failed to start: ${String(e?.message ?? e)}`, origin, true);
76518
77625
  return;
76519
77626
  }
76520
77627
  await installTools(t, { ...injectedServers, ...params.mcpServers ?? {} });
@@ -76546,18 +77653,18 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76546
77653
  if (model)
76547
77654
  sessionModel.set(threadId, model);
76548
77655
  } catch (e) {
76549
- fail3(params.sessionId ?? "", params.clientRequestId, `Couldn't start a ${label} thread: ${String(e?.message ?? e)}`, origin, true);
77656
+ fail4(params.sessionId ?? "", params.clientRequestId, `Couldn't start a ${label} thread: ${String(e?.message ?? e)}`, origin, true);
76550
77657
  return;
76551
77658
  }
76552
77659
  if (params.message.trim() === "/compact") {
76553
77660
  const ok = await t.request("thread/compact/start", { threadId }).then(() => true).catch(() => false);
76554
77661
  if (!ok) {
76555
- fail3(threadId, params.clientRequestId, `${label} could not compact this conversation.`, origin);
77662
+ fail4(threadId, params.clientRequestId, `${label} could not compact this conversation.`, origin);
76556
77663
  send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "error" }, origin);
76557
77664
  return;
76558
77665
  }
76559
77666
  if (compactWaiters.has(threadId)) {
76560
- fail3(threadId, params.clientRequestId, `${label} is already compacting this conversation.`, origin);
77667
+ fail4(threadId, params.clientRequestId, `${label} is already compacting this conversation.`, origin);
76561
77668
  send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "idle" }, origin);
76562
77669
  return;
76563
77670
  }
@@ -76578,7 +77685,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76578
77685
  compactWaiters.set(threadId, { settle: finish, keepAlive: arm });
76579
77686
  });
76580
77687
  if (!compacted) {
76581
- fail3(threadId, params.clientRequestId, `${label} did not finish compacting this conversation in time.`, origin);
77688
+ fail4(threadId, params.clientRequestId, `${label} did not finish compacting this conversation in time.`, origin);
76582
77689
  send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "error" }, origin);
76583
77690
  return;
76584
77691
  }
@@ -76691,7 +77798,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76691
77798
  send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "idle" }, origin);
76692
77799
  return;
76693
77800
  }
76694
- fail3(threadId, params.clientRequestId, detail, origin, true);
77801
+ fail4(threadId, params.clientRequestId, detail, origin, true);
76695
77802
  send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "error" }, origin);
76696
77803
  }
76697
77804
  }
@@ -90468,13 +91575,13 @@ var ActiveLinkEngine = class {
90468
91575
  localByHash.set(h, j);
90469
91576
  });
90470
91577
  const reuse = /* @__PURE__ */ new Map();
90471
- const request = [];
91578
+ const request2 = [];
90472
91579
  blocks.forEach((h, i) => {
90473
91580
  const j = localByHash.get(h);
90474
91581
  if (j !== void 0)
90475
91582
  reuse.set(i, j);
90476
91583
  else
90477
- request.push(i);
91584
+ request2.push(i);
90478
91585
  });
90479
91586
  const existing = this.pendingPulls.get(rel);
90480
91587
  if (existing)
@@ -90482,14 +91589,14 @@ var ActiveLinkEngine = class {
90482
91589
  });
90483
91590
  const assembler = new BlockAssembler(this.stagingPath(rel, "blk"));
90484
91591
  await assembler.open();
90485
- const pending2 = { mtimeMs, mode, size, wholeHash, blocks, reuse, localSize: localRec?.size ?? 0, remaining: new Set(request), assembler };
91592
+ const pending2 = { mtimeMs, mode, size, wholeHash, blocks, reuse, localSize: localRec?.size ?? 0, remaining: new Set(request2), assembler };
90486
91593
  this.pendingPulls.set(rel, pending2);
90487
91594
  this.touchInbound();
90488
- if (request.length === 0) {
91595
+ if (request2.length === 0) {
90489
91596
  await this.finalizeBlockPull(rel);
90490
91597
  return;
90491
91598
  }
90492
- this.send({ type: "link:requestBlocks", linkId: this.opts.linkId, fromHost: this.opts.ownHostId, rel, mtimeMs, indexes: request });
91599
+ this.send({ type: "link:requestBlocks", linkId: this.opts.linkId, fromHost: this.opts.ownHostId, rel, mtimeMs, indexes: request2 });
90493
91600
  }
90494
91601
  async onBlockData(frame) {
90495
91602
  const pending2 = this.pendingPulls.get(frame.rel);
@@ -97372,10 +98479,13 @@ function readLocal(meshId) {
97372
98479
  function writeLocal(meshId, state3) {
97373
98480
  try {
97374
98481
  mkdirSync32(oneMeshDir(meshId), { recursive: true, mode: 448 });
97375
- writeFileSync33(join60(oneMeshDir(meshId), FILES.local), JSON.stringify(state3, null, 2));
98482
+ writeFileSync33(join60(oneMeshDir(meshId), FILES.local), JSON.stringify(state3, null, 2), { mode: 384 });
97376
98483
  } catch {
97377
98484
  }
97378
98485
  }
98486
+ function updateLocal(meshId, patch) {
98487
+ writeLocal(meshId, { ...readLocal(meshId), ...patch });
98488
+ }
97379
98489
  function loadMesh(meshId) {
97380
98490
  if (!isMeshId(meshId))
97381
98491
  return null;
@@ -97633,6 +98743,9 @@ function loadMeshCore() {
97633
98743
  }
97634
98744
  }
97635
98745
  var meshCore = loadMeshCore();
98746
+ function meshEngineStatus() {
98747
+ return { available: meshCore.available === true, reason: meshCore.loadError ?? null };
98748
+ }
97636
98749
  var TICK_MS2 = 1e3;
97637
98750
  var BIND_PORT = 0;
97638
98751
  var shortKey = (k) => k.subarray(0, 4).toString("hex");
@@ -97927,11 +99040,11 @@ var MeshNode = class {
97927
99040
  const engine = this.#engine;
97928
99041
  if (!engine)
97929
99042
  return;
97930
- const hex5 = staticPub.toString("hex");
99043
+ const hex6 = staticPub.toString("hex");
97931
99044
  try {
97932
- if (!this.#peers.has(hex5)) {
99045
+ if (!this.#peers.has(hex6)) {
97933
99046
  engine.addPeer(staticPub, 0, Buffer.alloc(16));
97934
- this.#peers.set(hex5, staticPub);
99047
+ this.#peers.set(hex6, staticPub);
97935
99048
  }
97936
99049
  engine.addPath(staticPub, `${address}:${port}`, false);
97937
99050
  engine.startHandshake(staticPub, Date.now());
@@ -98008,10 +99121,10 @@ var MeshNode = class {
98008
99121
  const pk = Buffer.from(m.fromStaticPub, "base64");
98009
99122
  if (pk.length !== 32)
98010
99123
  break;
98011
- const hex5 = pk.toString("hex");
98012
- if (!this.#peers.has(hex5)) {
99124
+ const hex6 = pk.toString("hex");
99125
+ if (!this.#peers.has(hex6)) {
98013
99126
  engine.addPeer(pk, 0, Buffer.alloc(16));
98014
- this.#peers.set(hex5, pk);
99127
+ this.#peers.set(hex6, pk);
98015
99128
  }
98016
99129
  for (const ep of m.endpoints ?? []) {
98017
99130
  try {
@@ -98025,8 +99138,8 @@ var MeshNode = class {
98025
99138
  case "mesh:gone": {
98026
99139
  const pk = Buffer.from(m.staticPub, "base64");
98027
99140
  if (pk.length === 32) {
98028
- const hex5 = pk.toString("hex");
98029
- this.#peers.delete(hex5);
99141
+ const hex6 = pk.toString("hex");
99142
+ this.#peers.delete(hex6);
98030
99143
  this.#established.delete(shortKey(pk));
98031
99144
  this.#relayed.delete(shortKey(pk));
98032
99145
  }
@@ -98052,10 +99165,10 @@ var MeshNode = class {
98052
99165
  const pk = Buffer.from(p.staticPub, "base64");
98053
99166
  if (pk.length !== 32)
98054
99167
  return;
98055
- const hex5 = pk.toString("hex");
98056
- if (!this.#peers.has(hex5)) {
99168
+ const hex6 = pk.toString("hex");
99169
+ if (!this.#peers.has(hex6)) {
98057
99170
  engine.addPeer(pk, 0, Buffer.alloc(16));
98058
- this.#peers.set(hex5, pk);
99171
+ this.#peers.set(hex6, pk);
98059
99172
  }
98060
99173
  for (const e of p.endpoints)
98061
99174
  engine.addPath(pk, `${e.ip}:${e.port}`, false);
@@ -98190,16 +99303,26 @@ var MeshManager = class {
98190
99303
  */
98191
99304
  disable(meshId) {
98192
99305
  this.stop(meshId);
98193
- writeLocal(meshId, { ...readLocal(meshId), enabled: false });
99306
+ updateLocal(meshId, { enabled: false });
98194
99307
  }
98195
99308
  /** Undo `disable`, and start it. */
98196
99309
  enable(meshId) {
98197
- writeLocal(meshId, { ...readLocal(meshId), enabled: true });
99310
+ updateLocal(meshId, { enabled: true });
98198
99311
  return this.start(meshId);
98199
99312
  }
98200
99313
  node(meshId) {
98201
99314
  return this.#nodes.get(meshId) ?? null;
98202
99315
  }
99316
+ /**
99317
+ * The meshes with a LIVE node, which is what routes may be installed for.
99318
+ *
99319
+ * Deliberately not `ids()`: a certificate on disk is not a reason to steer traffic, and a
99320
+ * disabled mesh has one. `syncRoutes` takes this rather than the on-disk list precisely so
99321
+ * that confusion has to be made on purpose.
99322
+ */
99323
+ running() {
99324
+ return [...this.#nodes.keys()];
99325
+ }
98203
99326
  /** The first-joined running mesh — for callers that predate multi-mesh. */
98204
99327
  primary() {
98205
99328
  for (const meshId of this.ids()) {
@@ -98225,6 +99348,240 @@ function meshManager() {
98225
99348
  return singleton3;
98226
99349
  }
98227
99350
 
99351
+ // ../../packages/host-core/dist/mesh/netd-client.js
99352
+ import { connect as connect2 } from "node:net";
99353
+ import { platform as platform3 } from "node:process";
99354
+ var NETD_WIRE_VERSION = 1;
99355
+ var MAX_LINE = 1024 * 1024;
99356
+ var TIMEOUT_MS2 = 15e3;
99357
+ function netdEndpoint() {
99358
+ if (platform3 === "win32")
99359
+ return "\\\\.\\pipe\\tesseract-netd";
99360
+ if (platform3 === "darwin")
99361
+ return "/var/run/tesseract-netd.sock";
99362
+ return "/run/tesseract-netd.sock";
99363
+ }
99364
+ function endpointOverride() {
99365
+ return process.env.CCB_NETD_SOCKET ?? null;
99366
+ }
99367
+ function fail(code, detail) {
99368
+ return { ok: false, code, detail };
99369
+ }
99370
+ async function call(line) {
99371
+ const endpoint2 = endpointOverride() ?? netdEndpoint();
99372
+ return new Promise((resolve16) => {
99373
+ let settled = false;
99374
+ const done = (r) => {
99375
+ if (settled)
99376
+ return;
99377
+ settled = true;
99378
+ try {
99379
+ sock.destroy();
99380
+ } catch {
99381
+ }
99382
+ resolve16(r);
99383
+ };
99384
+ let sock;
99385
+ try {
99386
+ sock = connect2(endpoint2);
99387
+ } catch (e) {
99388
+ return resolve16(fail("not-installed", e instanceof Error ? e.message : String(e)));
99389
+ }
99390
+ const timer2 = setTimeout(() => {
99391
+ done(fail("timeout", `no answer from the network helper in ${TIMEOUT_MS2}ms`));
99392
+ }, TIMEOUT_MS2);
99393
+ timer2.unref?.();
99394
+ sock.setTimeout(TIMEOUT_MS2);
99395
+ sock.on("timeout", () => {
99396
+ clearTimeout(timer2);
99397
+ done(fail("timeout", "socket idle"));
99398
+ });
99399
+ sock.on("error", (e) => {
99400
+ clearTimeout(timer2);
99401
+ const absent = e.code === "ENOENT" || e.code === "ECONNREFUSED";
99402
+ done(fail(absent ? "not-installed" : "io", e.message));
99403
+ });
99404
+ let buf = "";
99405
+ sock.on("data", (chunk) => {
99406
+ buf += chunk.toString("utf8");
99407
+ if (buf.length > MAX_LINE) {
99408
+ clearTimeout(timer2);
99409
+ done(fail("protocol", "the helper sent an oversized line"));
99410
+ return;
99411
+ }
99412
+ const nl = buf.indexOf("\n");
99413
+ if (nl === -1)
99414
+ return;
99415
+ clearTimeout(timer2);
99416
+ done({ ok: true, line: buf.slice(0, nl) });
99417
+ });
99418
+ sock.on("close", () => {
99419
+ clearTimeout(timer2);
99420
+ done(fail("protocol", "the helper closed the connection without answering"));
99421
+ });
99422
+ sock.on("connect", () => {
99423
+ sock.write(`${line}
99424
+ `);
99425
+ });
99426
+ });
99427
+ }
99428
+ function parse3(line) {
99429
+ let body;
99430
+ try {
99431
+ body = JSON.parse(line);
99432
+ } catch {
99433
+ return fail("protocol", "the helper sent something that is not JSON");
99434
+ }
99435
+ if (typeof body !== "object" || body === null) {
99436
+ return fail("protocol", "the helper sent something that is not an object");
99437
+ }
99438
+ const o = body;
99439
+ if (o.ok === false) {
99440
+ const code = typeof o.code === "string" ? o.code : "refused";
99441
+ const detail = typeof o.detail === "string" ? o.detail : "the helper refused";
99442
+ return fail(code, detail);
99443
+ }
99444
+ if (o.ok !== true)
99445
+ return fail("protocol", "the helper did not say whether it succeeded");
99446
+ return { ok: true, body: o };
99447
+ }
99448
+ async function request(line) {
99449
+ const r = await call(line);
99450
+ return r.ok ? parse3(r.line) : r;
99451
+ }
99452
+ function hex3(b) {
99453
+ return Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
99454
+ }
99455
+ async function netdHello() {
99456
+ const r = await request(JSON.stringify({ op: "hello", wireVersion: NETD_WIRE_VERSION }));
99457
+ if (!r.ok)
99458
+ return r;
99459
+ const v = r.body.wireVersion;
99460
+ if (typeof v !== "number")
99461
+ return fail("protocol", "the helper did not report a wire version");
99462
+ if (v !== NETD_WIRE_VERSION) {
99463
+ return fail("wire-version", `the helper speaks ${v}, this build speaks ${NETD_WIRE_VERSION}`);
99464
+ }
99465
+ return { ok: true, wireVersion: v };
99466
+ }
99467
+ async function netdStatus() {
99468
+ const r = await request(JSON.stringify({ op: "status" }));
99469
+ if (!r.ok)
99470
+ return r;
99471
+ const meshes = Array.isArray(r.body.meshes) ? r.body.meshes.filter((m) => typeof m === "string") : [];
99472
+ const iface = typeof r.body.interface === "string" ? r.body.interface : null;
99473
+ return { ok: true, meshes, interface: iface };
99474
+ }
99475
+ async function netdUp(args) {
99476
+ const r = await request(JSON.stringify({
99477
+ op: "up",
99478
+ meshId: args.meshId,
99479
+ genesis: hex3(args.genesis),
99480
+ cert: hex3(args.cert),
99481
+ fullTunnel: args.fullTunnel === true
99482
+ }));
99483
+ return r.ok ? { ok: true } : r;
99484
+ }
99485
+ async function netdDown(meshId) {
99486
+ const r = await request(JSON.stringify({ op: "down", meshId }));
99487
+ return r.ok ? { ok: true } : r;
99488
+ }
99489
+ async function netdAvailable() {
99490
+ return (await netdHello()).ok;
99491
+ }
99492
+
99493
+ // ../../packages/host-core/dist/mesh/route-sync.js
99494
+ async function syncRoutes(running2, log9 = () => {
99495
+ }) {
99496
+ const out = { up: [], down: [], failed: [], helperAbsent: false };
99497
+ if (!await netdAvailable()) {
99498
+ out.helperAbsent = true;
99499
+ return out;
99500
+ }
99501
+ const status2 = await netdStatus();
99502
+ if (!status2.ok) {
99503
+ out.failed.push({ meshId: "*", reason: status2.detail });
99504
+ return out;
99505
+ }
99506
+ const installed = new Set(status2.meshes);
99507
+ const want = new Set(running2);
99508
+ for (const meshId of want) {
99509
+ const identity = loadMesh(meshId);
99510
+ if (identity === null) {
99511
+ out.failed.push({ meshId, reason: "no enrolment on disk" });
99512
+ continue;
99513
+ }
99514
+ const r = await netdUp({
99515
+ meshId,
99516
+ genesis: identity.genesis,
99517
+ cert: identity.cert,
99518
+ // The per-machine choice, and `=== true` rather than a truthiness check: an absent or
99519
+ // malformed field must read as NO. netd unions this across meshes itself — any mesh
99520
+ // asking for a full tunnel makes it one for the machine — so this stays per mesh here.
99521
+ fullTunnel: readLocal(meshId)?.fullTunnel === true
99522
+ });
99523
+ if (r.ok) {
99524
+ out.up.push(meshId);
99525
+ log9(`routes installed for ${meshId}`);
99526
+ } else {
99527
+ out.failed.push({ meshId, reason: r.detail });
99528
+ log9(`routes NOT installed for ${meshId}: ${r.detail}`);
99529
+ }
99530
+ }
99531
+ for (const meshId of installed) {
99532
+ if (want.has(meshId))
99533
+ continue;
99534
+ const r = await netdDown(meshId);
99535
+ if (r.ok) {
99536
+ out.down.push(meshId);
99537
+ log9(`routes removed for ${meshId}`);
99538
+ } else {
99539
+ out.failed.push({ meshId, reason: r.detail });
99540
+ log9(`routes could NOT be removed for ${meshId}: ${r.detail}`);
99541
+ }
99542
+ }
99543
+ return out;
99544
+ }
99545
+
99546
+ // ../../packages/host-core/dist/mesh/start-meshes.js
99547
+ function startMeshes(log9) {
99548
+ const running2 = startNodes(log9);
99549
+ void syncRoutes(running2, log9).then((r) => {
99550
+ if (r.helperAbsent) {
99551
+ log9("routes: the network helper is not installed \u2014 the overlay carries no traffic yet");
99552
+ return;
99553
+ }
99554
+ if (r.up.length)
99555
+ log9(`routes: installed for ${r.up.join(", ")}`);
99556
+ if (r.down.length)
99557
+ log9(`routes: removed for ${r.down.join(", ")}`);
99558
+ for (const f of r.failed)
99559
+ log9(`routes: ${f.meshId} refused \u2014 ${f.reason}`);
99560
+ }).catch((e) => {
99561
+ log9(`routes: sync threw \u2014 ${e instanceof Error ? e.message : String(e)}`);
99562
+ });
99563
+ }
99564
+ function startNodes(log9) {
99565
+ const ids = listMeshIds();
99566
+ if (ids.length <= 1) {
99567
+ const only = ids[0];
99568
+ if (only !== void 0 && readLocal(only)?.enabled === false) {
99569
+ log9("mesh: the only network is switched off");
99570
+ return [];
99571
+ }
99572
+ const started2 = meshNode().start();
99573
+ log9(started2.ok ? "mesh: node up" : `mesh: not started \u2014 ${started2.reason}`);
99574
+ return started2.ok && only !== void 0 ? [only] : [];
99575
+ }
99576
+ const running2 = [];
99577
+ for (const r of meshManager().startAll()) {
99578
+ log9(r.ok ? `mesh ${r.meshId}: up` : `mesh ${r.meshId}: not started \u2014 ${r.reason}`);
99579
+ if (r.ok)
99580
+ running2.push(r.meshId);
99581
+ }
99582
+ return running2;
99583
+ }
99584
+
98228
99585
  // ../../packages/host-core/dist/drops/receive-ui.js
98229
99586
  import { basename as basename12, dirname as dirname25 } from "node:path";
98230
99587
  var log5 = (...a) => console.log("[drops]", ...a);
@@ -99078,11 +100435,11 @@ function startRdeskChannelClient(deps) {
99078
100435
  return;
99079
100436
  retry = setTimeout(() => {
99080
100437
  retry = null;
99081
- connect2();
100438
+ connect3();
99082
100439
  }, RECONNECT_MS);
99083
100440
  retry.unref?.();
99084
100441
  };
99085
- function connect2() {
100442
+ function connect3() {
99086
100443
  if (stopped2 || sock)
99087
100444
  return;
99088
100445
  const url2 = readEndpoint(deps.daemonDir(), deps.selfPid);
@@ -99148,7 +100505,7 @@ function startRdeskChannelClient(deps) {
99148
100505
  ws.on("error", () => {
99149
100506
  });
99150
100507
  }
99151
- connect2();
100508
+ connect3();
99152
100509
  const claimPoll = setInterval(() => {
99153
100510
  if (stopped2 || holding)
99154
100511
  return;
@@ -100044,15 +101401,15 @@ function stopAutofillBridge() {
100044
101401
 
100045
101402
  // ../../packages/host-core/dist/power-node.js
100046
101403
  import { spawn as spawn13 } from "node:child_process";
100047
- import { platform as platform3 } from "node:os";
101404
+ import { platform as platform4 } from "node:os";
100048
101405
  function createNodePowerController() {
100049
101406
  const active = /* @__PURE__ */ new Set();
100050
101407
  let proc = null;
100051
101408
  function spawnInhibitor() {
100052
101409
  try {
100053
- if (platform3() === "darwin")
101410
+ if (platform4() === "darwin")
100054
101411
  return spawn13("caffeinate", ["-i"], { stdio: "ignore" });
100055
- if (platform3() === "linux") {
101412
+ if (platform4() === "linux") {
100056
101413
  return spawn13("systemd-inhibit", ["--what=sleep", "--why=tesseract agent running", "--mode=block", "sleep", "infinity"], { stdio: "ignore" });
100057
101414
  }
100058
101415
  } catch {
@@ -100102,7 +101459,7 @@ function createNodePowerController() {
100102
101459
  // ../../packages/host-core/dist/native-host.js
100103
101460
  import { execFileSync as execFileSync4 } from "node:child_process";
100104
101461
  import { chmodSync as chmodSync6, existsSync as existsSync33, mkdirSync as mkdirSync35, writeFileSync as writeFileSync36 } from "node:fs";
100105
- import { homedir as homedir11, platform as platform4 } from "node:os";
101462
+ import { homedir as homedir11, platform as platform5 } from "node:os";
100106
101463
  import { dirname as dirname27, join as join67, resolve as resolve12 } from "node:path";
100107
101464
  import { fileURLToPath as fileURLToPath5 } from "node:url";
100108
101465
  var HOST_NAME = "com.tesseract.companion";
@@ -100110,7 +101467,7 @@ var EXTENSION_IDS = ["icpnghhpcmaonjckkpilpajblfehpplo", "giolfpookdhjfafcchaflh
100110
101467
  var BRIDGE_BASENAME = "host.cjs";
100111
101468
  function browserProfileDirs() {
100112
101469
  const home = homedir11();
100113
- const p = platform4();
101470
+ const p = platform5();
100114
101471
  if (p === "darwin") {
100115
101472
  const base = join67(home, "Library/Application Support");
100116
101473
  return ["Google/Chrome", "Google/Chrome Beta", "Google/Chrome Dev", "Google/Chrome Canary", "Chromium", "Microsoft Edge", "BraveSoftware/Brave-Browser", "Vivaldi", "Arc"].map((b) => join67(base, b));
@@ -100138,7 +101495,7 @@ function resolveBridge(log9) {
100138
101495
  return null;
100139
101496
  }
100140
101497
  function writeLauncher(daemonDir3, bridge, runtime) {
100141
- const isWin = platform4() === "win32";
101498
+ const isWin = platform5() === "win32";
100142
101499
  const launcher = join67(daemonDir3, isWin ? "companion-host.cmd" : "companion-host.sh");
100143
101500
  if (isWin) {
100144
101501
  writeFileSync36(launcher, `@echo off\r
@@ -100170,7 +101527,7 @@ function registerNativeHost(opts) {
100170
101527
  type: "stdio",
100171
101528
  allowed_origins: EXTENSION_IDS.map((id) => `chrome-extension://${id}/`)
100172
101529
  }, null, 2);
100173
- if (platform4() === "win32")
101530
+ if (platform5() === "win32")
100174
101531
  return registerWindows(opts.daemonDir, manifestJson, log9);
100175
101532
  let wrote = 0;
100176
101533
  for (const profile of browserProfileDirs()) {
@@ -100513,17 +101870,6 @@ function backoff2() {
100513
101870
 
100514
101871
  // ../../packages/host-core/dist/daemon-runtime.js
100515
101872
  var daemonClipboardSync = null;
100516
- function startMeshes(log9) {
100517
- const ids = listMeshIds();
100518
- if (ids.length <= 1) {
100519
- const started2 = meshNode().start();
100520
- log9(started2.ok ? "mesh: node up" : `mesh: not started \u2014 ${started2.reason}`);
100521
- return;
100522
- }
100523
- for (const r of meshManager().startAll()) {
100524
- log9(r.ok ? `mesh ${r.meshId}: up` : `mesh ${r.meshId}: not started \u2014 ${r.reason}`);
100525
- }
100526
- }
100527
101873
  var REFRESH_INTERVAL_MS = 12 * 60 * 60 * 1e3;
100528
101874
  var GRACEFUL_KILL_MS = 4e3;
100529
101875
  async function runDaemon(opts = {}) {
@@ -100585,7 +101931,6 @@ async function runDaemon(opts = {}) {
100585
101931
  } catch {
100586
101932
  }
100587
101933
  }
100588
- const STANDALONE_MESH_APP = process.env.CCB_MESH_APP === "1";
100589
101934
  const WE_ARE_RDESK_ONLY = process.env.CCB_RDESK_ONLY === "1" || process.env.CCB_MESH_ONLY === "1";
100590
101935
  async function takeoverMachine() {
100591
101936
  let lockPid = 0;
@@ -100672,7 +102017,7 @@ async function runDaemon(opts = {}) {
100672
102017
  } catch {
100673
102018
  }
100674
102019
  }
100675
- const standaloneViewer = process.env.CCB_RDESK_ROLE === "client" || STANDALONE_MESH_APP;
102020
+ const standaloneViewer = process.env.CCB_RDESK_ROLE === "client";
100676
102021
  if (!standaloneViewer) {
100677
102022
  registerSelfAsDaemon(VERSION2);
100678
102023
  if (await takeoverMachine()) {
@@ -100893,6 +102238,13 @@ async function runDaemon(opts = {}) {
100893
102238
  const eapp = electronModule()?.app;
100894
102239
  if (eapp) {
100895
102240
  eapp.on("before-quit", (e) => {
102241
+ if (standaloneViewer) {
102242
+ try {
102243
+ log9("APP before-quit \u2014 allowed (standalone app, not the daemon)");
102244
+ } catch {
102245
+ }
102246
+ return;
102247
+ }
100896
102248
  if (mergedProcess) {
100897
102249
  if (deliberateMergedQuit()) {
100898
102250
  try {
@@ -100923,6 +102275,13 @@ async function runDaemon(opts = {}) {
100923
102275
  }
100924
102276
  });
100925
102277
  eapp.on("will-quit", (e) => {
102278
+ if (standaloneViewer) {
102279
+ try {
102280
+ log9("APP will-quit \u2014 allowed (standalone app)");
102281
+ } catch {
102282
+ }
102283
+ return;
102284
+ }
100926
102285
  if (mergedProcess) {
100927
102286
  if (!deliberateMergedQuit()) {
100928
102287
  try {
@@ -100945,6 +102304,17 @@ async function runDaemon(opts = {}) {
100945
102304
  }
100946
102305
  });
100947
102306
  eapp.on("window-all-closed", () => {
102307
+ if (standaloneViewer) {
102308
+ try {
102309
+ log9("APP window-all-closed \u2014 quitting (standalone app)");
102310
+ } catch {
102311
+ }
102312
+ try {
102313
+ electronModule()?.app?.quit();
102314
+ } catch {
102315
+ }
102316
+ return;
102317
+ }
100948
102318
  try {
100949
102319
  log9("APP window-all-closed (kept alive \u2014 no auto-quit)");
100950
102320
  } catch {
@@ -101706,28 +103076,8 @@ async function runDaemon(opts = {}) {
101706
103076
  startFileProviderBridge(log9);
101707
103077
  startAutofillBridge(log9);
101708
103078
  }
101709
- const meshAppShouldRun = STANDALONE_MESH_APP && !lockHeldByAnother();
101710
- if (ownsMachine || meshAppShouldRun) {
101711
- if (meshAppShouldRun)
101712
- log9("mesh app: no daemon owns this machine \u2014 running the node here");
103079
+ if (ownsMachine)
101713
103080
  startMeshes(log9);
101714
- }
101715
- if (meshAppShouldRun) {
101716
- let handedBack = false;
101717
- const handover = setInterval(() => {
101718
- if (handedBack || !lockHeldByAnother())
101719
- return;
101720
- handedBack = true;
101721
- log9("mesh app: a daemon now owns this machine \u2014 handing the node back to it");
101722
- try {
101723
- meshManager().stopAll();
101724
- meshNode().stop();
101725
- } catch {
101726
- }
101727
- clearInterval(handover);
101728
- }, 15e3);
101729
- handover.unref?.();
101730
- }
101731
103081
  const who = c.userId ? `user ${c.userId}` : "no account (unclaimed machine)";
101732
103082
  log9(`started \u2014 device ${c.deviceId}, ${who}, relay ${c.backendOrigin}, local :${localInfo?.localPort ?? "off"}, version ${VERSION2}`);
101733
103083
  await refresh();
@@ -101751,11 +103101,6 @@ var MAX_IMAGE_BYTES2 = 10 * 1024 * 1024;
101751
103101
  // ../../packages/host-core/dist/host-daemon-entry.js
101752
103102
  init_daemon_settings();
101753
103103
 
101754
- // ../../packages/host-core/dist/clipboard/clipboard-sync.js
101755
- var MAX_IMAGE_BYTES3 = 10 * 1024 * 1024;
101756
- var OVERSIZED_BYTES = 512 * 1024;
101757
- var CHUNK_BYTES = 256 * 1024;
101758
-
101759
103104
  // ../../packages/host-core/dist/mesh/mesh-ipc.js
101760
103105
  init_dist();
101761
103106
 
@@ -101764,17 +103109,17 @@ init_dist6();
101764
103109
  init_credentials();
101765
103110
  init_dist();
101766
103111
  var MESH_BASE = "/api/core/tesseract/mesh";
101767
- function fail2(code, detail) {
103112
+ function fail3(code, detail) {
101768
103113
  return { ok: false, code, detail };
101769
103114
  }
101770
- async function call(path6, init, auth = true) {
103115
+ async function call2(path6, init, auth = true) {
101771
103116
  const creds3 = auth ? readCredentials() : null;
101772
103117
  if (auth && !creds3) {
101773
- return fail2("not-signed-in", "sign in first: tesseract-agent login");
103118
+ return fail3("not-signed-in", "sign in first: tesseract-agent login");
101774
103119
  }
101775
103120
  const origin = creds3?.apiOrigin;
101776
103121
  if (!origin)
101777
- return fail2("not-signed-in", "no API origin is configured on this machine");
103122
+ return fail3("not-signed-in", "no API origin is configured on this machine");
101778
103123
  let res;
101779
103124
  try {
101780
103125
  res = await fetch(`${origin.replace(/\/$/, "")}${MESH_BASE}${path6}`, {
@@ -101786,7 +103131,7 @@ async function call(path6, init, auth = true) {
101786
103131
  ...init.body === void 0 ? {} : { body: JSON.stringify(init.body) }
101787
103132
  });
101788
103133
  } catch (e) {
101789
- return fail2("network", e instanceof Error ? e.message : String(e));
103134
+ return fail3("network", e instanceof Error ? e.message : String(e));
101790
103135
  }
101791
103136
  const text9 = await res.text();
101792
103137
  if (!res.ok) {
@@ -101797,30 +103142,31 @@ async function call(path6, init, auth = true) {
101797
103142
  detail = Array.isArray(parsed.message) ? parsed.message.join("; ") : parsed.message;
101798
103143
  } catch {
101799
103144
  }
101800
- return fail2(res.status >= 500 ? "server" : "refused", detail);
103145
+ return fail3(res.status >= 500 ? "server" : "refused", detail);
101801
103146
  }
101802
103147
  try {
101803
103148
  return { ok: true, data: text9 ? JSON.parse(text9) : {} };
101804
103149
  } catch {
101805
- return fail2("server", "the server sent something that is not JSON");
103150
+ return fail3("server", "the server sent something that is not JSON");
101806
103151
  }
101807
103152
  }
101808
103153
  async function listMeshes() {
101809
- const r = await call("/meshes", { method: "GET" });
103154
+ const r = await call2("/meshes", { method: "GET" });
101810
103155
  return r.ok ? { ok: true, meshes: r.data } : r;
101811
103156
  }
101812
103157
  async function deleteMesh(args) {
101813
- const r = await call(`/meshes/${encodeURIComponent(args.meshId)}?confirm=${encodeURIComponent(args.confirm)}`, { method: "DELETE" });
103158
+ const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}?confirm=${encodeURIComponent(args.confirm)}`, { method: "DELETE" });
101814
103159
  return r.ok ? { ok: true, deleted: r.data.deleted } : r;
101815
103160
  }
101816
103161
  async function createMesh(args = {}) {
101817
- const r = await call("/meshes", {
103162
+ const r = await call2("/meshes", {
101818
103163
  method: "POST",
101819
103164
  body: {
101820
103165
  ...args.name ? { name: args.name } : {},
101821
103166
  ...args.cidr ? { meshCidr4: args.cidr } : {},
101822
103167
  ...args.approvalMode ? { approvalMode: args.approvalMode } : {},
101823
103168
  ...args.allowExitNode !== void 0 ? { allowExitNode: args.allowExitNode } : {},
103169
+ ...args.fullTunnelDefault !== void 0 ? { fullTunnelDefault: args.fullTunnelDefault } : {},
101824
103170
  ...args.allowRelay !== void 0 ? { allowRelay: args.allowRelay } : {},
101825
103171
  ...args.magicDns !== void 0 ? { magicDns: args.magicDns } : {}
101826
103172
  }
@@ -101828,42 +103174,42 @@ async function createMesh(args = {}) {
101828
103174
  return r.ok ? { ok: true, ...r.data } : r;
101829
103175
  }
101830
103176
  async function joinToken(args) {
101831
- const r = await call(`/meshes/${encodeURIComponent(args.meshId)}/token`, { method: "GET" });
103177
+ const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/token`, { method: "GET" });
101832
103178
  return r.ok ? { ok: true, token: r.data.token } : r;
101833
103179
  }
101834
103180
  async function rotateJoinToken(args) {
101835
- const r = await call(`/meshes/${encodeURIComponent(args.meshId)}/token/rotate`, { method: "POST", body: {} });
103181
+ const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/token/rotate`, { method: "POST", body: {} });
101836
103182
  return r.ok ? { ok: true, token: r.data.token } : r;
101837
103183
  }
101838
103184
  async function approveNode(args) {
101839
- const r = await call(`/meshes/${encodeURIComponent(args.meshId)}/nodes/${encodeURIComponent(args.nodeId)}/approve`, { method: "POST", body: {} });
103185
+ const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/nodes/${encodeURIComponent(args.nodeId)}/approve`, { method: "POST", body: {} });
101840
103186
  return r.ok ? { ok: true, epoch: r.data.epoch } : r;
101841
103187
  }
101842
103188
  async function newJoinCode(args) {
101843
- const r = await call(`/meshes/${encodeURIComponent(args.meshId)}/codes`, { method: "POST", body: { uses: args.uses, ttlMinutes: args.ttlMinutes } });
103189
+ const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/codes`, { method: "POST", body: { uses: args.uses, ttlMinutes: args.ttlMinutes } });
101844
103190
  return r.ok ? { ok: true, ...r.data } : r;
101845
103191
  }
101846
103192
  async function evictNode(args) {
101847
- const r = await call(`/meshes/${encodeURIComponent(args.meshId)}/nodes/${encodeURIComponent(args.nodeId)}`, { method: "DELETE", body: {} });
103193
+ const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/nodes/${encodeURIComponent(args.nodeId)}`, { method: "DELETE", body: {} });
101848
103194
  return r.ok ? { ok: true, epoch: r.data.epoch } : r;
101849
103195
  }
101850
103196
  async function enrolWith(requested, post) {
101851
103197
  const name = normaliseNodeName(requested);
101852
103198
  if (!name) {
101853
- return fail2("bad-name", `"${requested}" cannot be a machine name \u2014 names are DNS labels, so letters, digits and hyphens only`);
103199
+ return fail3("bad-name", `"${requested}" cannot be a machine name \u2014 names are DNS labels, so letters, digits and hyphens only`);
101854
103200
  }
101855
103201
  const stat9 = await generateStaticKey();
101856
103202
  const sig = await generateSigningKey();
101857
103203
  const staticPrivate = await rawPrivate(stat9.privateKey);
101858
103204
  const sigPrivate = await rawPrivate(sig.privateKey);
101859
- const r = await post(hex4(stat9.publicRaw), hex4(sig.publicRaw), name);
103205
+ const r = await post(hex5(stat9.publicRaw), hex5(sig.publicRaw), name);
101860
103206
  if (!r.ok)
101861
103207
  return r;
101862
103208
  const cert = fromHexOrB64(r.data.cert);
101863
103209
  const genesis = fromHexOrB64(r.data.genesis);
101864
103210
  const meshId = meshIdOf(cert);
101865
103211
  if (!meshId)
101866
- return fail2("server", "the certificate the server returned is unreadable");
103212
+ return fail3("server", "the certificate the server returned is unreadable");
101867
103213
  let issuedName = name;
101868
103214
  try {
101869
103215
  issuedName = decodeCert(cert).details.name || name;
@@ -101872,8 +103218,14 @@ async function enrolWith(requested, post) {
101872
103218
  try {
101873
103219
  saveMesh(meshId, { genesis, cert, staticPrivate, sigPrivate });
101874
103220
  writeLocal(meshId, { joinedAt: Date.now(), enabled: true });
103221
+ if (r.data.bundle) {
103222
+ try {
103223
+ cacheBundle(fromHexOrB64(r.data.bundle), meshId);
103224
+ } catch {
103225
+ }
103226
+ }
101875
103227
  } catch (e) {
101876
- return fail2("disk", `the certificate was issued but could not be saved: ${e instanceof Error ? e.message : String(e)}. Ask an admin for a new join code \u2014 this one has been used.`);
103228
+ return fail3("disk", `the certificate was issued but could not be saved: ${e instanceof Error ? e.message : String(e)}. Ask an admin for a new join code \u2014 this one has been used.`);
101877
103229
  }
101878
103230
  return {
101879
103231
  ok: true,
@@ -101887,9 +103239,9 @@ async function enrolWith(requested, post) {
101887
103239
  };
101888
103240
  }
101889
103241
  async function enrol(args) {
101890
- return enrolWith(args.name, (staticPub, sigPub, name) => call(`/meshes/${encodeURIComponent(args.meshId)}/nodes`, {
103242
+ return enrolWith(args.name, (staticPub, sigPub, name) => call2(`/meshes/${encodeURIComponent(args.meshId)}/nodes`, {
101891
103243
  method: "POST",
101892
- body: { name, staticPub, sigPub }
103244
+ body: { name, staticPub, sigPub, ...args.exitNode === true ? { exitNode: true } : {} }
101893
103245
  }));
101894
103246
  }
101895
103247
  async function joinWithToken(args) {
@@ -101898,7 +103250,7 @@ async function joinWithToken(args) {
101898
103250
  async function postJoin(origin, body) {
101899
103251
  const base = origin ?? readCredentials()?.apiOrigin;
101900
103252
  if (!base) {
101901
- return fail2("not-signed-in", "this machine has never signed in \u2014 pass --origin https://\u2026 so it knows which server to ask");
103253
+ return fail3("not-signed-in", "this machine has never signed in \u2014 pass --origin https://\u2026 so it knows which server to ask");
101902
103254
  }
101903
103255
  let res;
101904
103256
  try {
@@ -101908,7 +103260,7 @@ async function postJoin(origin, body) {
101908
103260
  body: JSON.stringify(body)
101909
103261
  });
101910
103262
  } catch (e) {
101911
- return fail2("network", e instanceof Error ? e.message : String(e));
103263
+ return fail3("network", e instanceof Error ? e.message : String(e));
101912
103264
  }
101913
103265
  const text9 = await res.text();
101914
103266
  if (!res.ok) {
@@ -101919,7 +103271,7 @@ async function postJoin(origin, body) {
101919
103271
  detail = String(parsed.message);
101920
103272
  } catch {
101921
103273
  }
101922
- return fail2(res.status >= 500 ? "server" : "refused", detail);
103274
+ return fail3(res.status >= 500 ? "server" : "refused", detail);
101923
103275
  }
101924
103276
  return { ok: true, data: JSON.parse(text9) };
101925
103277
  }
@@ -101933,7 +103285,7 @@ async function rawPrivate(key2) {
101933
103285
  }
101934
103286
  return pkcs8.subarray(16);
101935
103287
  }
101936
- function hex4(b) {
103288
+ function hex5(b) {
101937
103289
  return Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
101938
103290
  }
101939
103291
  function fromHexOrB64(s) {
@@ -101949,8 +103301,63 @@ function meshIdOf(cert) {
101949
103301
  return meshDirNameFromWireId(Array.from(cert.subarray(OFFSET, OFFSET + 32), (b) => b.toString(16).padStart(2, "0")).join(""));
101950
103302
  }
101951
103303
 
101952
- // ../../packages/host-core/dist/mesh/netd-client.js
101953
- var MAX_LINE = 1024 * 1024;
103304
+ // ../../packages/host-core/dist/mesh/full-tunnel.js
103305
+ function fullTunnelState(i) {
103306
+ const no2 = (reason) => ({ allowed: false, reason, warnings: [] });
103307
+ if (i.platform !== "linux") {
103308
+ const name = i.platform === "darwin" ? "macOS" : i.platform === "win32" ? "Windows" : i.platform;
103309
+ return no2(`Routing all traffic needs the network helper, which does not exist on ${name} yet.`);
103310
+ }
103311
+ if (!i.engineAvailable) {
103312
+ return no2("This build shipped without the network engine, so no traffic can be routed. That is a packaging fault \u2014 please report it.");
103313
+ }
103314
+ if (i.helperCode === "wire-version") {
103315
+ return no2("Update the network helper \u2014 this build speaks a newer protocol than the one installed.");
103316
+ }
103317
+ if (!i.helperAvailable) {
103318
+ return no2("Turn this network on to install the network helper \u2014 nothing can be routed until it is there.");
103319
+ }
103320
+ if (!i.hasBundle) {
103321
+ return no2("This machine has not received this network\u2019s policy yet, so nothing can be routed. It arrives from any other machine on the network.");
103322
+ }
103323
+ if (!i.networkAllows) {
103324
+ return no2("This network does not allow routing all traffic through it. An admin of the network chooses that.");
103325
+ }
103326
+ if (i.selfIsExitNode) {
103327
+ return no2("This machine is this network\u2019s way out to the internet, so it cannot route its own traffic through itself.");
103328
+ }
103329
+ if (i.exitNodes.length === 0) {
103330
+ return no2("No machine on this network offers to be the way out yet, so there is nowhere for the traffic to go.");
103331
+ }
103332
+ if (i.claimedBy) {
103333
+ return no2(`All traffic already goes through ${i.claimedBy}. A machine has one default route, so only one network can claim it.`);
103334
+ }
103335
+ if (!i.ownsNode) {
103336
+ return no2("The Tesseract app is running this network on this machine. Change this from there.");
103337
+ }
103338
+ if (i.pathToExit === "none") {
103339
+ return no2(`Waiting for a connection to ${i.exitNodes[0]}. All traffic cannot be routed until this machine can reach it.`);
103340
+ }
103341
+ const warnings = [];
103342
+ if (i.pathToExit === "relay") {
103343
+ warnings.push(`All traffic will go through ${i.exitNodes[0]} by way of a relay, so it will be slower than usual.`);
103344
+ }
103345
+ return { allowed: true, reason: null, warnings };
103346
+ }
103347
+ function bundleGrantsExitNode(bundle) {
103348
+ if (bundle === void 0 || bundle.length === 0)
103349
+ return false;
103350
+ try {
103351
+ const pki = (init_dist6(), __toCommonJS(dist_exports3));
103352
+ const decoded = pki.decodeSignedBundle(bundle);
103353
+ return decoded.bundle.rules.some((r) => (r.caps & pki.CAP_EXIT_NODE) !== 0);
103354
+ } catch {
103355
+ return false;
103356
+ }
103357
+ }
103358
+
103359
+ // ../../packages/host-core/dist/mesh/machine-owner.js
103360
+ init_credentials();
101954
103361
 
101955
103362
  // ../../packages/host-core/dist/service/exec.js
101956
103363
  import { execFile as execFile10, spawn as spawn14 } from "node:child_process";
@@ -101968,6 +103375,11 @@ function runInherit(cmd, args) {
101968
103375
  var UNIT = "tesseract-netd.service";
101969
103376
  var UNIT_PATH = `/etc/systemd/system/${UNIT}`;
101970
103377
 
103378
+ // ../../packages/host-core/dist/clipboard/clipboard-sync.js
103379
+ var MAX_IMAGE_BYTES3 = 10 * 1024 * 1024;
103380
+ var OVERSIZED_BYTES = 512 * 1024;
103381
+ var CHUNK_BYTES = 256 * 1024;
103382
+
101971
103383
  // ../../packages/host-core/dist/host-daemon-entry.js
101972
103384
  init_credentials();
101973
103385
 
@@ -101976,7 +103388,7 @@ init_daemon_settings();
101976
103388
  init_credentials();
101977
103389
 
101978
103390
  // ../../packages/host-core/dist/service/index.js
101979
- import { platform as platform5 } from "node:os";
103391
+ import { platform as platform6 } from "node:os";
101980
103392
 
101981
103393
  // ../../packages/host-core/dist/service/launchd.js
101982
103394
  init_credentials();
@@ -102256,7 +103668,7 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
102256
103668
  // ../../packages/host-core/dist/service/index.js
102257
103669
  function getServiceController(instanceId) {
102258
103670
  const id = instanceId && instanceId.length ? instanceId : void 0;
102259
- switch (platform5()) {
103671
+ switch (platform6()) {
102260
103672
  case "darwin":
102261
103673
  return makeLaunchd(id);
102262
103674
  case "linux":
@@ -102514,12 +103926,12 @@ function isReleaseVersion(v) {
102514
103926
  return /^\d+\.\d+\.\d+/.test(v.trim());
102515
103927
  }
102516
103928
  function isNewer(latest, current) {
102517
- const parse3 = (v) => {
103929
+ const parse4 = (v) => {
102518
103930
  const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(v.trim());
102519
103931
  return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
102520
103932
  };
102521
- const a = parse3(latest);
102522
- const b = parse3(current);
103933
+ const a = parse4(latest);
103934
+ const b = parse4(current);
102523
103935
  if (!a || !b) return false;
102524
103936
  for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] > b[i];
102525
103937
  return false;
@@ -102637,12 +104049,12 @@ function startSelfUpdater(current) {
102637
104049
 
102638
104050
  // src/service.ts
102639
104051
  import { join as join75 } from "node:path";
102640
- import { platform as platform6 } from "node:os";
104052
+ import { platform as platform7 } from "node:os";
102641
104053
  import { existsSync as existsSync40, readFileSync as readFileSync46 } from "node:fs";
102642
104054
  function controller(instanceId) {
102643
104055
  const c = getServiceController(instanceId);
102644
104056
  if (!c) {
102645
- throw new Error(`tesseract-agent can't manage a background service on ${platform6()}. Run it in the foreground instead: \`tesseract-agent run\` (e.g. as a Docker entrypoint).`);
104057
+ throw new Error(`tesseract-agent can't manage a background service on ${platform7()}. Run it in the foreground instead: \`tesseract-agent run\` (e.g. as a Docker entrypoint).`);
102646
104058
  }
102647
104059
  return c;
102648
104060
  }
@@ -102723,7 +104135,9 @@ Running a network (needs a signed-in account):
102723
104135
  tesseract-agent net new [NAME] Create a network and print its join token.
102724
104136
  [--approve auto|admin] who may join: the token alone, or you say yes
102725
104137
  [--cidr A.B.C.D/L] address range (default 100.96.0.0/12)
102726
- [--exit-node] [--no-relay] [--no-dns] everything is optional and has a default
104138
+ [--exit-node] let machines route ALL traffic through it
104139
+ [--full-tunnel-default] ...and start new machines that way (needs --exit-node)
104140
+ [--no-relay] [--no-dns] everything is optional and has a default
102727
104141
  tesseract-agent net networks [--json] List your networks and their machines
102728
104142
  tesseract-agent net token MESH [--rotate] Show the join token again, or replace it
102729
104143
  tesseract-agent net approve MESH NODE Let a waiting machine on
@@ -102732,8 +104146,13 @@ Running a network (needs a signed-in account):
102732
104146
  Delete a network for good. Irreversible.
102733
104147
  tesseract-agent net code new MESH [--uses N] [--ttl MIN] [--json]
102734
104148
  A ONE-SHOT code, for anyone who wants one
102735
- tesseract-agent net join-me MESH [--name N]
104149
+ tesseract-agent net route-all [MESH] [--off]
104150
+ Route ALL of this machine's traffic through a
104151
+ network (the classic-VPN posture), or stop
104152
+ tesseract-agent net join-me MESH [--name N] [--exit-node]
102736
104153
  Join THIS machine to a network you run
104154
+ --exit-node offers this machine as everyone's
104155
+ way out to the internet (the network must allow it)
102737
104156
 
102738
104157
  Admin (needs the mesh CA, not a node):
102739
104158
  tesseract-agent net init --org NAME [--ca-dir DIR]
@@ -102889,7 +104308,7 @@ async function netCommand(rest, flags) {
102889
104308
  console.error(`net ${sub}: not enrolled in ${meshId}`);
102890
104309
  process.exit(1);
102891
104310
  }
102892
- writeLocal(meshId, { ...readLocal(meshId), enabled: sub === "up" });
104311
+ updateLocal(meshId, { enabled: sub === "up" });
102893
104312
  console.log(`${meshId} ${sub === "up" ? "enabled" : "disabled"}`);
102894
104313
  }
102895
104314
  console.log("Run `tesseract-agent restart` for this to take effect now.");
@@ -102999,11 +104418,22 @@ async function netCommand(rest, flags) {
102999
104418
  console.error("net new: --approve must be 'auto' or 'admin'");
103000
104419
  process.exit(1);
103001
104420
  }
104421
+ if (flags["full-tunnel-default"] === true && flags["exit-node"] !== true) {
104422
+ console.error(
104423
+ "net new: --full-tunnel-default needs --exit-node \u2014 the first is a default, the second is the permission it depends on"
104424
+ );
104425
+ process.exit(1);
104426
+ }
103002
104427
  const r = await createMesh({
103003
104428
  ...name ? { name } : {},
103004
104429
  ...str2(flags.cidr) ? { cidr: str2(flags.cidr) } : {},
103005
104430
  ...approve ? { approvalMode: approve } : {},
103006
104431
  ...flags["exit-node"] === true ? { allowExitNode: true } : {},
104432
+ // The DEFAULT half. Clamped to the permission server-side, but refuse it here too
104433
+ // rather than sending a combination that can never take effect — an operator who
104434
+ // typed only --full-tunnel-default has misunderstood which flag does what, and a
104435
+ // silent clamp would let them keep believing it.
104436
+ ...flags["full-tunnel-default"] === true ? { fullTunnelDefault: true } : {},
103007
104437
  ...flags["no-relay"] === true ? { allowRelay: false } : {},
103008
104438
  ...flags["no-dns"] === true ? { magicDns: false } : {}
103009
104439
  });
@@ -103120,7 +104550,11 @@ async function netCommand(rest, flags) {
103120
104550
  console.error("net join-me: that name cannot be used \u2014 letters, digits and hyphens only");
103121
104551
  process.exit(1);
103122
104552
  }
103123
- const r = await enrol({ meshId, name: nm });
104553
+ const r = await enrol({
104554
+ meshId,
104555
+ name: nm,
104556
+ ...flags["exit-node"] === true ? { exitNode: true } : {}
104557
+ });
103124
104558
  if (!r.ok) {
103125
104559
  console.error(`net join-me: ${r.detail}`);
103126
104560
  process.exit(1);
@@ -103129,6 +104563,48 @@ async function netCommand(rest, flags) {
103129
104563
  if (r.name !== nm) console.log(`(another machine here is already called "${nm}")`);
103130
104564
  return;
103131
104565
  }
104566
+ if (sub === "route-all") {
104567
+ const ids = listMeshIds();
104568
+ const target = rest[1] ?? str2(flags.mesh);
104569
+ const off = flags.off === true;
104570
+ if (!ids.length) {
104571
+ console.error("net route-all: this machine is not in any network");
104572
+ process.exit(1);
104573
+ }
104574
+ if (!target && ids.length > 1) {
104575
+ console.error("net route-all: name a network \u2014 this machine is in several");
104576
+ for (const meshId2 of ids) console.error(` ${meshId2}`);
104577
+ process.exit(1);
104578
+ }
104579
+ const meshId = target ?? ids[0];
104580
+ if (!ids.includes(meshId)) {
104581
+ console.error(`net route-all: not enrolled in ${meshId}`);
104582
+ process.exit(1);
104583
+ }
104584
+ const identity = loadMesh(meshId);
104585
+ const state3 = fullTunnelState({
104586
+ platform: process.platform,
104587
+ helperAvailable: await netdAvailable(),
104588
+ helperCode: null,
104589
+ engineAvailable: meshEngineStatus().available,
104590
+ hasBundle: identity?.bundle !== void 0 && identity.bundle.length > 0,
104591
+ networkAllows: bundleGrantsExitNode(identity?.bundle),
104592
+ exitNodes: [],
104593
+ selfIsExitNode: false,
104594
+ pathToExit: "none",
104595
+ claimedBy: ids.find((id) => id !== meshId && readLocal(id)?.fullTunnel === true) ?? null,
104596
+ ownsNode: true
104597
+ });
104598
+ if (!off && !state3.allowed) {
104599
+ console.error(`net route-all: ${state3.reason}`);
104600
+ process.exit(1);
104601
+ }
104602
+ updateLocal(meshId, { fullTunnel: !off });
104603
+ console.log(off ? `${meshId} all traffic no longer routed through this network` : `${meshId} ALL traffic from this machine will go through this network`);
104604
+ for (const w of state3.warnings) console.log(` ${w}`);
104605
+ console.log("Run `tesseract-agent restart` for this to take effect now.");
104606
+ return;
104607
+ }
103132
104608
  if (sub === "peers") {
103133
104609
  const s = readStatus();
103134
104610
  if (!s || s.stale) {