tesseract-agent 0.9.31 → 0.9.33
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.
- package/dist-bundle/cli.js +2046 -367
- package/package.json +1 -1
package/dist-bundle/cli.js
CHANGED
|
@@ -1885,7 +1885,7 @@ var require_sender = __commonJS({
|
|
|
1885
1885
|
* @param {Function} [cb] Callback
|
|
1886
1886
|
* @private
|
|
1887
1887
|
*/
|
|
1888
|
-
getBlobData(blob,
|
|
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 (!
|
|
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,
|
|
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,
|
|
1936
|
-
if (!
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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:
|
|
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(
|
|
5584
|
-
return
|
|
5583
|
+
function pathSep(platform8) {
|
|
5584
|
+
return platform8 === "win32" ? "\\" : "/";
|
|
5585
5585
|
}
|
|
5586
|
-
function joinPath2(
|
|
5587
|
-
const sep10 = pathSep(
|
|
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:
|
|
5603
|
+
const { home, platform: platform8 } = opts;
|
|
5604
5604
|
const env = opts.env ?? {};
|
|
5605
|
-
const j = (...parts) => joinPath2(
|
|
5606
|
-
if (
|
|
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 ?? (
|
|
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(
|
|
9229
|
-
const cleanHex =
|
|
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
|
|
32381
|
-
const raw = await llm({ model: live.model, system:
|
|
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,
|
|
32635
|
+
raiseUserDialog(live, request2, signal) {
|
|
32636
32636
|
return new Promise((resolve16) => {
|
|
32637
32637
|
const requestId = randomUUID6();
|
|
32638
|
-
log("user_dialog raised:",
|
|
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):",
|
|
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):",
|
|
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:
|
|
32658
|
-
payload:
|
|
32659
|
-
...
|
|
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:
|
|
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: (
|
|
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:
|
|
34063
|
-
message:
|
|
34064
|
-
...
|
|
34065
|
-
...
|
|
34066
|
-
...
|
|
34067
|
-
...
|
|
34068
|
-
...
|
|
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:
|
|
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: (
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
46162
|
+
fail4(e);
|
|
46163
46163
|
return next();
|
|
46164
46164
|
});
|
|
46165
46165
|
} else s |= 1;
|
|
46166
46166
|
} catch (e) {
|
|
46167
|
-
|
|
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
|
|
48587
|
-
const view = new Uint8Array(pvtsutils__namespace.Convert.FromHex(
|
|
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 =
|
|
51738
|
+
exports.normalize = normalize3;
|
|
51739
51739
|
exports.is = is;
|
|
51740
51740
|
exports.encode = encode3;
|
|
51741
51741
|
exports.decode = decode3;
|
|
51742
|
-
exports.parse =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
|
51943
|
-
const normalized =
|
|
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:
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
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
|
|
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(
|
|
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 =
|
|
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:
|
|
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
|
|
59760
|
-
row.push(
|
|
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
|
|
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(
|
|
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
|
-
|
|
63142
|
+
fail4(new Error("peer-link: token handshake timeout"));
|
|
63143
63143
|
}, TOKEN_HANDSHAKE_MS);
|
|
63144
|
-
function
|
|
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
|
-
|
|
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
|
-
|
|
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) =>
|
|
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
|
-
|
|
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
|
|
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 =
|
|
64852
|
+
exports.parse = parse4;
|
|
64852
64853
|
}
|
|
64853
64854
|
});
|
|
64854
64855
|
|
|
@@ -64863,6 +64864,9 @@ function compareUtf8(a, b) {
|
|
|
64863
64864
|
}
|
|
64864
64865
|
return ea.length === eb.length ? 0 : ea.length < eb.length ? -1 : 1;
|
|
64865
64866
|
}
|
|
64867
|
+
function canonicalStrs(items) {
|
|
64868
|
+
return [...new Set(items)].sort(compareUtf8);
|
|
64869
|
+
}
|
|
64866
64870
|
var MeshCodecError, fail, LIMITS, Writer, Reader;
|
|
64867
64871
|
var init_codec = __esm({
|
|
64868
64872
|
"../../packages/mesh-pki/dist/codec.js"() {
|
|
@@ -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
|
-
|
|
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,19 +65348,144 @@ 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
|
-
function
|
|
65476
|
+
function randomBytes7(n) {
|
|
65251
65477
|
return globalThis.crypto.getRandomValues(new Uint8Array(n));
|
|
65252
65478
|
}
|
|
65253
65479
|
async function generateSigningKey(extractable = true) {
|
|
65254
|
-
const kp = await
|
|
65255
|
-
const publicRaw = new Uint8Array(await
|
|
65480
|
+
const kp = await subtle3.generateKey(ED25519, extractable, ["sign", "verify"]);
|
|
65481
|
+
const publicRaw = new Uint8Array(await subtle3.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 subtle3.importKey("raw", bs3(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}`);
|
|
@@ -65277,14 +65508,14 @@ async function signingKeyFromSeed(seed) {
|
|
|
65277
65508
|
32
|
|
65278
65509
|
]);
|
|
65279
65510
|
const pkcs8 = concat2(prefix, seed);
|
|
65280
|
-
const privateKey = await
|
|
65281
|
-
const jwk = await
|
|
65511
|
+
const privateKey = await subtle3.importKey("pkcs8", bs3(pkcs8), ED25519, true, ["sign"]);
|
|
65512
|
+
const jwk = await subtle3.exportKey("jwk", privateKey);
|
|
65282
65513
|
if (typeof jwk.x !== "string")
|
|
65283
65514
|
throw new Error("Ed25519 JWK missing x");
|
|
65284
65515
|
return { privateKey, publicRaw: unb64u2(jwk.x) };
|
|
65285
65516
|
}
|
|
65286
65517
|
async function exportStaticPrivate(kp) {
|
|
65287
|
-
const jwk = await
|
|
65518
|
+
const jwk = await subtle3.exportKey("jwk", kp.privateKey);
|
|
65288
65519
|
if (typeof jwk.d !== "string")
|
|
65289
65520
|
throw new Error("X25519 JWK missing d");
|
|
65290
65521
|
const raw = unb64u2(jwk.d);
|
|
@@ -65292,16 +65523,44 @@ 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 subtle3.exportKey("jwk", kp.privateKey);
|
|
65528
|
+
}
|
|
65529
|
+
async function importSigningPrivate(jwk) {
|
|
65530
|
+
const privateKey = await subtle3.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
|
-
return new Uint8Array(await
|
|
65536
|
+
return new Uint8Array(await subtle3.sign(ED25519, privateKey, bs3(message)));
|
|
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 subtle3.verify(ED25519, key2, bs3(sig), bs3(message));
|
|
65544
|
+
} catch {
|
|
65545
|
+
return false;
|
|
65546
|
+
}
|
|
65297
65547
|
}
|
|
65298
65548
|
async function generateStaticKey(extractable = true) {
|
|
65299
|
-
const kp = await
|
|
65300
|
-
const publicRaw = new Uint8Array(await
|
|
65549
|
+
const kp = await subtle3.generateKey(X25519, extractable, ["deriveBits"]);
|
|
65550
|
+
const publicRaw = new Uint8Array(await subtle3.exportKey("raw", kp.publicKey));
|
|
65301
65551
|
return { privateKey: kp.privateKey, publicRaw };
|
|
65302
65552
|
}
|
|
65303
65553
|
async function sha2562(bytes2) {
|
|
65304
|
-
return new Uint8Array(await
|
|
65554
|
+
return new Uint8Array(await subtle3.digest("SHA-256", bs3(bytes2)));
|
|
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(/=+$/, "");
|
|
65305
65564
|
}
|
|
65306
65565
|
function unb64u2(s) {
|
|
65307
65566
|
const pad2 = s.length % 4 === 0 ? "" : "=".repeat(4 - s.length % 4);
|
|
@@ -65314,7 +65573,7 @@ function unb64u2(s) {
|
|
|
65314
65573
|
function hex3(bytes2) {
|
|
65315
65574
|
return Array.from(bytes2, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
65316
65575
|
}
|
|
65317
|
-
function
|
|
65576
|
+
function utf82(s) {
|
|
65318
65577
|
return new TextEncoder().encode(s);
|
|
65319
65578
|
}
|
|
65320
65579
|
function concat2(...parts) {
|
|
@@ -65327,12 +65586,21 @@ function concat2(...parts) {
|
|
|
65327
65586
|
}
|
|
65328
65587
|
return out;
|
|
65329
65588
|
}
|
|
65330
|
-
|
|
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
|
+
}
|
|
65597
|
+
var subtle3, bs3, ED25519, X25519;
|
|
65331
65598
|
var init_crypto = __esm({
|
|
65332
65599
|
"../../packages/mesh-pki/dist/crypto.js"() {
|
|
65333
65600
|
"use strict";
|
|
65334
|
-
|
|
65335
|
-
|
|
65601
|
+
init_blake2s();
|
|
65602
|
+
subtle3 = globalThis.crypto.subtle;
|
|
65603
|
+
bs3 = (b) => b;
|
|
65336
65604
|
ED25519 = "Ed25519";
|
|
65337
65605
|
X25519 = "X25519";
|
|
65338
65606
|
}
|
|
@@ -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 = hex3(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
|
-
|
|
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"() {
|
|
@@ -65597,12 +66066,41 @@ var init_addr = __esm({
|
|
|
65597
66066
|
init_crypto();
|
|
65598
66067
|
init_prefix();
|
|
65599
66068
|
init_codec();
|
|
65600
|
-
CTX_V6 =
|
|
65601
|
-
CTX_V4 =
|
|
66069
|
+
CTX_V6 = utf82("tsr-addr6-v1");
|
|
66070
|
+
CTX_V4 = utf82("tsr-addr4-v1");
|
|
65602
66071
|
}
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
|
67839
|
-
|
|
68643
|
+
SAS_WORDS = 6;
|
|
68644
|
+
SAS_MIN_BITS = 64;
|
|
68645
|
+
CTX_ENROLL = utf82("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
|
|
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 =
|
|
68140
|
-
const s1 =
|
|
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 =
|
|
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 =
|
|
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;
|
|
@@ -68254,7 +69061,7 @@ function alphabet(letters) {
|
|
|
68254
69061
|
};
|
|
68255
69062
|
}
|
|
68256
69063
|
// @__NO_SIDE_EFFECTS__
|
|
68257
|
-
function
|
|
69064
|
+
function join61(separator = "") {
|
|
68258
69065
|
astr("join", separator);
|
|
68259
69066
|
return {
|
|
68260
69067
|
encode: (from) => {
|
|
@@ -68459,13 +69266,25 @@ var init_esm = __esm({
|
|
|
68459
69266
|
convertRadix2,
|
|
68460
69267
|
radix,
|
|
68461
69268
|
radix2,
|
|
68462
|
-
join:
|
|
69269
|
+
join: join61,
|
|
68463
69270
|
padding
|
|
68464
69271
|
};
|
|
68465
69272
|
}
|
|
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"() {
|
|
@@ -68504,7 +69337,7 @@ function validateKdf2(k) {
|
|
|
68504
69337
|
throw new MeshCodecError("bad-value", `unsupported KDF cost (m=${k.m} t=${k.t} p=${k.p})`);
|
|
68505
69338
|
}
|
|
68506
69339
|
function kdf(passphrase, salt, cost) {
|
|
68507
|
-
return argon2id(
|
|
69340
|
+
return argon2id(utf82(passphrase.normalize("NFKC")), salt, { ...cost, dkLen: KEY_LEN });
|
|
68508
69341
|
}
|
|
68509
69342
|
function header(version2, label, kdfCost, salt, nonce2) {
|
|
68510
69343
|
const w = new Writer();
|
|
@@ -68522,8 +69355,8 @@ async function sealCaKey(seed, passphrase, label = "mesh CA", cost = DEFAULT_KDF
|
|
|
68522
69355
|
if (label.length > MAX_LABEL)
|
|
68523
69356
|
throw new MeshCodecError("too-long", "label too long");
|
|
68524
69357
|
validateKdf2(cost);
|
|
68525
|
-
const salt =
|
|
68526
|
-
const nonce2 =
|
|
69358
|
+
const salt = randomBytes7(SALT_LEN);
|
|
69359
|
+
const nonce2 = randomBytes7(NONCE_LEN);
|
|
68527
69360
|
const aad = header(RECOVERY_VERSION, label, cost, salt, nonce2);
|
|
68528
69361
|
const key2 = await aesKey(kdf(passphrase, salt, cost));
|
|
68529
69362
|
const ct = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce2, additionalData: aad }, key2, seed));
|
|
@@ -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
|
-
const secret =
|
|
69415
|
+
const secret = randomBytes7(SECRET_LEN);
|
|
68573
69416
|
return { secret, hash: await sha2562(secret) };
|
|
68574
69417
|
}
|
|
68575
|
-
|
|
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;
|
|
@@ -68593,12 +69442,114 @@ var init_recovery = __esm({
|
|
|
68593
69442
|
NONCE_LEN = 12;
|
|
68594
69443
|
KEY_LEN = 32;
|
|
68595
69444
|
MAX_LABEL = 128;
|
|
68596
|
-
DOMAIN =
|
|
69445
|
+
DOMAIN = utf82("tesseract-mesh-recovery-v1");
|
|
68597
69446
|
}
|
|
68598
69447
|
});
|
|
68599
69448
|
|
|
68600
69449
|
// ../../packages/mesh-pki/dist/enroll.js
|
|
68601
|
-
|
|
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: randomBytes7(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: randomBytes7(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: () => hex3,
|
|
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: () => randomBytes7,
|
|
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: () => utf82,
|
|
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";
|
|
@@ -69782,7 +70889,7 @@ async function netCaCommand(rest, flags) {
|
|
|
69782
70889
|
if (pass.length < 12) die("Use a passphrase of at least 12 characters \u2014 this key issues every identity on the mesh.");
|
|
69783
70890
|
const confirm2 = await readPassphrase("Confirm: ");
|
|
69784
70891
|
if (pass !== confirm2) die("Passphrases did not match.");
|
|
69785
|
-
const seed =
|
|
70892
|
+
const seed = randomBytes7(SEED_LEN);
|
|
69786
70893
|
const ca = await signingKeyFromSeed(seed);
|
|
69787
70894
|
const pol = ca;
|
|
69788
70895
|
const disable = await newDisablement();
|
|
@@ -69847,7 +70954,7 @@ Next, issue an identity for a machine (pick a free address in ${formatPrefix(gen
|
|
|
69847
70954
|
const cert = await issueCert(
|
|
69848
70955
|
{
|
|
69849
70956
|
version: 1,
|
|
69850
|
-
serial:
|
|
70957
|
+
serial: randomBytes7(16),
|
|
69851
70958
|
genesisFp: fp,
|
|
69852
70959
|
nodeId: name,
|
|
69853
70960
|
name,
|
|
@@ -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
|
|
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:
|
|
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
|
|
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) =>
|
|
73405
|
-
post: (path6, body, timeoutMs, method) =>
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
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 (
|
|
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:
|
|
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);
|
|
@@ -91521,6 +92628,15 @@ function ownHostId() {
|
|
|
91521
92628
|
const mine = serverHosts.find((h) => h.hostId.endsWith(`:${deviceId}`));
|
|
91522
92629
|
return mine?.hostId ?? "local";
|
|
91523
92630
|
}
|
|
92631
|
+
var lastOwnHostLog = null;
|
|
92632
|
+
function logOwnHostVerdict() {
|
|
92633
|
+
const own2 = ownHostId();
|
|
92634
|
+
const verdict = own2 === "local" ? `NOT REGISTERED \u2014 the account lists ${serverHosts.length} host(s), none matching this deviceId=${deviceId.slice(0, 8)}; this machine is invisible to every client` : `registered as ${own2}`;
|
|
92635
|
+
if (verdict === lastOwnHostLog)
|
|
92636
|
+
return;
|
|
92637
|
+
lastOwnHostLog = verdict;
|
|
92638
|
+
console.log(`[control-link] own host: ${verdict}`);
|
|
92639
|
+
}
|
|
91524
92640
|
function presentedHosts() {
|
|
91525
92641
|
const out = serverHosts.slice();
|
|
91526
92642
|
if (!out.some((h) => h.hostId.endsWith(`:${deviceId}`))) {
|
|
@@ -92321,6 +93437,8 @@ function handleHostChannel(payload) {
|
|
|
92321
93437
|
entitlementDenied = true;
|
|
92322
93438
|
stopHeartbeat();
|
|
92323
93439
|
const message = typeof payload.message === "string" ? payload.message : "Running agents on your own machines requires a paid plan.";
|
|
93440
|
+
const d = payload;
|
|
93441
|
+
console.log(`[control-link] host:register DENIED reason=${String(d.reason ?? "?")} feature=${String(d.feature ?? "?")} limit=${String(d.limit ?? "?")} \u2014 ${message}`);
|
|
92324
93442
|
hooks?.notify({ type: "notify", level: "warning", message });
|
|
92325
93443
|
scheduleEntitlementRetry();
|
|
92326
93444
|
return;
|
|
@@ -92344,6 +93462,7 @@ function handleHostChannel(payload) {
|
|
|
92344
93462
|
setActiveLinkPeerOnline(l.linkId, true);
|
|
92345
93463
|
}
|
|
92346
93464
|
assertServerSelection();
|
|
93465
|
+
logOwnHostVerdict();
|
|
92347
93466
|
hooks?.ownHostResolved(ownHostId());
|
|
92348
93467
|
hooks?.pushHosts(presentedHosts());
|
|
92349
93468
|
resumeActiveLinks();
|
|
@@ -92365,6 +93484,7 @@ function registerAsHost() {
|
|
|
92365
93484
|
const upAdvert = upscaleAdvert();
|
|
92366
93485
|
if (upAdvert.gpu)
|
|
92367
93486
|
caps.push("gpu");
|
|
93487
|
+
console.log(`[control-link] host:register \u2192 deviceId=${deviceId.slice(0, 8)} machineId=${getMachinePublicId() ?? "none"} kind=${kind ?? "electron"} caps=${caps.join(",")}`);
|
|
92368
93488
|
send3("host", { type: "host:register", name, platform: process.platform, deviceId, publicMachineId: getMachinePublicId(), caps, ...kind ? { kind } : {}, ...staticMetrics(hostVersion), gpu: upAdvert.gpu, upscaleModels: upAdvert.upscaleModels, ...p2pAdvert ?? {} });
|
|
92369
93489
|
if (!heartbeat)
|
|
92370
93490
|
heartbeat = setInterval(() => send3("host", { type: "host:heartbeat", ...dynamicMetrics() }), 2e4);
|
|
@@ -92686,7 +93806,7 @@ function connect() {
|
|
|
92686
93806
|
} else if (rdSession && typeof p?.type === "string" && p.type.startsWith("rdesk:")) {
|
|
92687
93807
|
if (inbound) {
|
|
92688
93808
|
if (driving)
|
|
92689
|
-
hooks?.onRdesk?.(env.payload, clientId, rdSession);
|
|
93809
|
+
hooks?.onRdesk?.(env.payload, clientId, rdSession, env.viewerOwner === true);
|
|
92690
93810
|
} else
|
|
92691
93811
|
hooks?.deliverRdesk?.(env.payload, typeof env.hostId === "string" ? env.hostId : void 0, rdSession);
|
|
92692
93812
|
}
|
|
@@ -92699,7 +93819,7 @@ function connect() {
|
|
|
92699
93819
|
return;
|
|
92700
93820
|
if (inbound) {
|
|
92701
93821
|
if (driving)
|
|
92702
|
-
hooks?.onRdesk?.(p, clientId, sessionId);
|
|
93822
|
+
hooks?.onRdesk?.(p, clientId, sessionId, env.viewerOwner === true);
|
|
92703
93823
|
return;
|
|
92704
93824
|
}
|
|
92705
93825
|
hooks?.deliverRdesk?.(p, typeof env.hostId === "string" ? env.hostId : void 0, sessionId);
|
|
@@ -92931,6 +94051,32 @@ var RdeskSessionManager = class {
|
|
|
92931
94051
|
return 0;
|
|
92932
94052
|
return Math.min(PW_BACKOFF_BASE_MS * 2 ** (over - 1), PW_BACKOFF_MAX_MS);
|
|
92933
94053
|
}
|
|
94054
|
+
/** Tell the viewer that this host is (or is again) producing a picture.
|
|
94055
|
+
*
|
|
94056
|
+
* Sent by the HOST because only the host can know why: the OS reports a muted or ended
|
|
94057
|
+
* capture track as a fact, whereas a viewer sees an absence of frames and cannot tell a
|
|
94058
|
+
* slept display from a slow link from a genuinely black screen. Audited too, so "it just
|
|
94059
|
+
* showed black" is answerable after the fact. */
|
|
94060
|
+
reportCapture(sessionId, clientId, ok, message) {
|
|
94061
|
+
this.log(`capture ${ok ? "restored" : `lost \u2014 ${message}`} sessionId=${sessionId}`);
|
|
94062
|
+
this.audit({ event: "capture", sessionId, detail: ok ? "ok" : message });
|
|
94063
|
+
this.deps.sendControl(sessionId, clientId, { type: "rdesk:capture", ok, ...message ? { message } : {} });
|
|
94064
|
+
}
|
|
94065
|
+
/** Record which path a session's media actually took, once ICE has settled.
|
|
94066
|
+
*
|
|
94067
|
+
* Media is direct-first (no relay pinning); TURN exists only as a last resort for NATs
|
|
94068
|
+
* that never punch through. That makes relay usage a COST we pay, so it is written to
|
|
94069
|
+
* the audit trail rather than only logged — `path` events in rdesk-audit.jsonl answer
|
|
94070
|
+
* "what fraction of sessions actually relayed?" without grepping daemon logs. Candidate
|
|
94071
|
+
* types only: an audit file is not the place for peer addresses. */
|
|
94072
|
+
recordPath(sessionId, viewerUserId, path6, d) {
|
|
94073
|
+
this.audit({
|
|
94074
|
+
event: "path",
|
|
94075
|
+
sessionId,
|
|
94076
|
+
viewerUserId,
|
|
94077
|
+
detail: `${path6} local=${d.localType ?? "?"} remote=${d.remoteType ?? "?"}`
|
|
94078
|
+
});
|
|
94079
|
+
}
|
|
92934
94080
|
audit(e) {
|
|
92935
94081
|
this.deps.audit?.({ at: this.now(), ...e });
|
|
92936
94082
|
}
|
|
@@ -92955,10 +94101,10 @@ var RdeskSessionManager = class {
|
|
|
92955
94101
|
const viewer = viewerIn.name || !declared ? viewerIn : { ...viewerIn, name: declared };
|
|
92956
94102
|
const grant0 = grantOf(msg);
|
|
92957
94103
|
this.audit({ event: "connect", sessionId, viewerUserId: viewer.userId, viewerName: viewer.name, grant: grant0 });
|
|
92958
|
-
const deny = (reason) => {
|
|
92959
|
-
this.log(`connect denied sessionId=${sessionId} reason=${reason}`);
|
|
92960
|
-
this.audit({ event: "deny", sessionId, viewerUserId: viewer.userId, grant: grant0, detail: reason });
|
|
92961
|
-
this.deps.sendControl(sessionId, viewer.clientId, { type: "rdesk:denied", reason });
|
|
94104
|
+
const deny = (reason, message) => {
|
|
94105
|
+
this.log(`connect denied sessionId=${sessionId} reason=${reason}${message ? ` \u2014 ${message}` : ""}`);
|
|
94106
|
+
this.audit({ event: "deny", sessionId, viewerUserId: viewer.userId, grant: grant0, detail: message ? `${reason}: ${message}` : reason });
|
|
94107
|
+
this.deps.sendControl(sessionId, viewer.clientId, { type: "rdesk:denied", reason, ...message ? { message } : {} });
|
|
92962
94108
|
};
|
|
92963
94109
|
if (!this.deps.canServe())
|
|
92964
94110
|
return deny("entitlement");
|
|
@@ -92976,6 +94122,10 @@ var RdeskSessionManager = class {
|
|
|
92976
94122
|
return deny("busy");
|
|
92977
94123
|
}
|
|
92978
94124
|
const grant = grantOf(msg);
|
|
94125
|
+
if (grant === "registry" && viewer.sameAccount !== true) {
|
|
94126
|
+
this.log(`connect denied sessionId=${sessionId} \u2014 'registry' claimed by a viewer the relay does not consider the owner`);
|
|
94127
|
+
return deny("consent");
|
|
94128
|
+
}
|
|
92979
94129
|
if (grant === "password") {
|
|
92980
94130
|
if (this.now() < this.pwLockedUntil) {
|
|
92981
94131
|
this.log(`password attempt refused \u2014 locked for ${Math.ceil((this.pwLockedUntil - this.now()) / 1e3)}s`);
|
|
@@ -93016,7 +94166,9 @@ var RdeskSessionManager = class {
|
|
|
93016
94166
|
sendControl: (m) => this.deps.sendControl(sessionId, viewer.clientId, m),
|
|
93017
94167
|
sendData: (_m) => {
|
|
93018
94168
|
},
|
|
93019
|
-
log: (m) => this.log(`${sessionId}: ${m}`)
|
|
94169
|
+
log: (m) => this.log(`${sessionId}: ${m}`),
|
|
94170
|
+
onPath: (path6, d) => this.recordPath(sessionId, viewer.userId, path6, d),
|
|
94171
|
+
onCapture: (ok, message) => this.reportCapture(sessionId, viewer.clientId, ok, message)
|
|
93020
94172
|
};
|
|
93021
94173
|
let engine;
|
|
93022
94174
|
try {
|
|
@@ -93027,7 +94179,7 @@ var RdeskSessionManager = class {
|
|
|
93027
94179
|
const err2 = e instanceof Error ? e.message : String(e);
|
|
93028
94180
|
this.log(`engine start failed sessionId=${sessionId}: ${err2}`);
|
|
93029
94181
|
this.deps.onCaptureBlocked?.({ sessionId, viewerName: viewer.name, error: err2 });
|
|
93030
|
-
return deny("offline");
|
|
94182
|
+
return deny("offline", err2);
|
|
93031
94183
|
}
|
|
93032
94184
|
const monitors = await engine.listMonitors().catch(() => []);
|
|
93033
94185
|
const sources = await engine.listSources?.().catch(() => []) ?? [];
|
|
@@ -93096,7 +94248,9 @@ var RdeskSessionManager = class {
|
|
|
93096
94248
|
sendControl: (m) => this.deps.sendControl(s.sessionId, s.viewer.clientId, m),
|
|
93097
94249
|
sendData: () => {
|
|
93098
94250
|
},
|
|
93099
|
-
log: (m) => this.log(`${s.sessionId}: ${m}`)
|
|
94251
|
+
log: (m) => this.log(`${s.sessionId}: ${m}`),
|
|
94252
|
+
onPath: (path6, d) => this.recordPath(s.sessionId, s.viewer.userId, path6, d),
|
|
94253
|
+
onCapture: (ok, message) => this.reportCapture(s.sessionId, s.viewer.clientId, ok, message)
|
|
93100
94254
|
};
|
|
93101
94255
|
try {
|
|
93102
94256
|
s.engine = await this.deps.createEngine("tesseract", ctx2);
|
|
@@ -93271,6 +94425,93 @@ var RdeskSessionManager = class {
|
|
|
93271
94425
|
}
|
|
93272
94426
|
};
|
|
93273
94427
|
|
|
94428
|
+
// ../../packages/host-core/dist/daemon-identity-reload.js
|
|
94429
|
+
var reload = null;
|
|
94430
|
+
function setDaemonIdentityReload(fn) {
|
|
94431
|
+
reload = fn;
|
|
94432
|
+
}
|
|
94433
|
+
function nextDaemonIdentity(fresh, current) {
|
|
94434
|
+
if (!fresh?.accessToken)
|
|
94435
|
+
return { kind: "machine" };
|
|
94436
|
+
if (fresh.accessToken === current.accessToken && (fresh.userId ?? "") === current.userId)
|
|
94437
|
+
return { kind: "unchanged" };
|
|
94438
|
+
return { kind: "account" };
|
|
94439
|
+
}
|
|
94440
|
+
|
|
94441
|
+
// ../../packages/host-core/dist/rdesk/screen-permission.js
|
|
94442
|
+
function screenRecordingStatus() {
|
|
94443
|
+
if (process.platform !== "darwin")
|
|
94444
|
+
return "unsupported";
|
|
94445
|
+
try {
|
|
94446
|
+
const sp = electronModule()?.systemPreferences;
|
|
94447
|
+
const s = sp?.getMediaAccessStatus("screen");
|
|
94448
|
+
if (s === "granted" || s === "denied" || s === "restricted" || s === "not-determined")
|
|
94449
|
+
return s;
|
|
94450
|
+
return "not-determined";
|
|
94451
|
+
} catch {
|
|
94452
|
+
return "not-determined";
|
|
94453
|
+
}
|
|
94454
|
+
}
|
|
94455
|
+
function canCaptureScreen() {
|
|
94456
|
+
const s = screenRecordingStatus();
|
|
94457
|
+
return s === "granted" || s === "unsupported";
|
|
94458
|
+
}
|
|
94459
|
+
async function registerForScreenRecording() {
|
|
94460
|
+
try {
|
|
94461
|
+
const dc = electronModule()?.desktopCapturer;
|
|
94462
|
+
await dc?.getSources({ types: ["screen"], thumbnailSize: { width: 1, height: 1 } });
|
|
94463
|
+
} catch {
|
|
94464
|
+
}
|
|
94465
|
+
}
|
|
94466
|
+
async function openScreenRecordingSettings() {
|
|
94467
|
+
if (process.platform !== "darwin")
|
|
94468
|
+
return;
|
|
94469
|
+
await registerForScreenRecording();
|
|
94470
|
+
try {
|
|
94471
|
+
const shell = electronModule()?.shell;
|
|
94472
|
+
await shell?.openExternal("x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture");
|
|
94473
|
+
} catch {
|
|
94474
|
+
}
|
|
94475
|
+
}
|
|
94476
|
+
var PROMPT_COOLDOWN_MS = 6e4;
|
|
94477
|
+
var lastPromptAt = 0;
|
|
94478
|
+
async function promptForScreenRecording(opts = {}) {
|
|
94479
|
+
if (process.platform !== "darwin")
|
|
94480
|
+
return false;
|
|
94481
|
+
if (screenRecordingStatus() === "granted") {
|
|
94482
|
+
opts.log?.("capture failed although Screen Recording IS granted \u2014 the capture stack is wedged (seen after a GPU-process crash); restarting Tesseract clears it");
|
|
94483
|
+
return false;
|
|
94484
|
+
}
|
|
94485
|
+
const now2 = Date.now();
|
|
94486
|
+
if (now2 - lastPromptAt < PROMPT_COOLDOWN_MS)
|
|
94487
|
+
return false;
|
|
94488
|
+
lastPromptAt = now2;
|
|
94489
|
+
const el2 = electronModule();
|
|
94490
|
+
const who = opts.viewerName ? `${opts.viewerName} is` : "Someone is";
|
|
94491
|
+
opts.log?.(`screen recording not granted \u2014 prompting (${who} waiting)`);
|
|
94492
|
+
if (!el2?.dialog) {
|
|
94493
|
+
opts.log?.("no GUI to prompt with \u2014 grant Screen Recording in System Settings \u2192 Privacy & Security");
|
|
94494
|
+
return false;
|
|
94495
|
+
}
|
|
94496
|
+
try {
|
|
94497
|
+
const { response } = await el2.dialog.showMessageBox({
|
|
94498
|
+
type: "warning",
|
|
94499
|
+
buttons: ["Open System Settings", "Not Now"],
|
|
94500
|
+
defaultId: 0,
|
|
94501
|
+
cancelId: 1,
|
|
94502
|
+
message: "Allow screen sharing on this Mac?",
|
|
94503
|
+
detail: `${who} trying to connect to this computer, but macOS is blocking screen capture.
|
|
94504
|
+
|
|
94505
|
+
Open System Settings \u2192 Privacy & Security \u2192 Screen Recording and switch on Tesseract Remote Desktop, then ask them to connect again.`
|
|
94506
|
+
});
|
|
94507
|
+
if (response === 0)
|
|
94508
|
+
await openScreenRecordingSettings();
|
|
94509
|
+
return true;
|
|
94510
|
+
} catch {
|
|
94511
|
+
return false;
|
|
94512
|
+
}
|
|
94513
|
+
}
|
|
94514
|
+
|
|
93274
94515
|
// ../../packages/host-core/dist/rdesk/publisher-window.js
|
|
93275
94516
|
import { join as join54 } from "node:path";
|
|
93276
94517
|
var windows = /* @__PURE__ */ new Map();
|
|
@@ -93308,6 +94549,7 @@ function ensureIpc() {
|
|
|
93308
94549
|
el2.ipcMain.on("rdesk:pub:ready", (_e, p) => route2(p, (w) => w.handlers.onReady()));
|
|
93309
94550
|
el2.ipcMain.on("rdesk:pub:error", (_e, p) => route2(p, (w, x) => w.handlers.onError(String(x.error ?? "publisher error"))));
|
|
93310
94551
|
el2.ipcMain.on("rdesk:pub:path", (_e, p) => route2(p, (w, x) => w.handlers.onPath?.(String(x.path ?? "unknown"), { localType: x.localType ?? null, remoteType: x.remoteType ?? null })));
|
|
94552
|
+
el2.ipcMain.on("rdesk:pub:capture", (_e, p) => route2(p, (w, x) => w.handlers.onCapture?.(x.ok !== false, String(x.message ?? ""))));
|
|
93311
94553
|
el2.ipcMain.on("rdesk:pub:stopped", (_e, p) => route2(p, (w) => w.onStoppedAck()));
|
|
93312
94554
|
}
|
|
93313
94555
|
async function listPublisherMonitors() {
|
|
@@ -93354,21 +94596,41 @@ function displayBoundsById(monitorId) {
|
|
|
93354
94596
|
const d = el2.screen.getAllDisplays().find((x) => String(x.id) === monitorId) ?? el2.screen.getPrimaryDisplay();
|
|
93355
94597
|
return d ? { x: d.bounds.x, y: d.bounds.y, width: d.bounds.width, height: d.bounds.height } : null;
|
|
93356
94598
|
}
|
|
93357
|
-
async function
|
|
94599
|
+
async function wakeDisplay(log9) {
|
|
94600
|
+
if (process.platform !== "darwin")
|
|
94601
|
+
return;
|
|
94602
|
+
try {
|
|
94603
|
+
const { spawn: spawn17 } = await import("node:child_process");
|
|
94604
|
+
spawn17("caffeinate", ["-u", "-t", "5"], { detached: true, stdio: "ignore" }).unref();
|
|
94605
|
+
log9?.("display was asleep \u2014 declared user activity to wake it");
|
|
94606
|
+
await new Promise((r) => setTimeout(r, 1200));
|
|
94607
|
+
} catch {
|
|
94608
|
+
}
|
|
94609
|
+
}
|
|
94610
|
+
async function sourceIdForMonitor(monitorId, log9) {
|
|
93358
94611
|
const el2 = electronModule();
|
|
93359
94612
|
if (!el2?.desktopCapturer || !el2.screen)
|
|
93360
94613
|
throw new Error("Screen capture unavailable (Electron desktopCapturer/screen missing).");
|
|
93361
94614
|
const display = el2.screen.getAllDisplays().find((d) => String(d.id) === monitorId) ?? el2.screen.getPrimaryDisplay();
|
|
93362
|
-
const
|
|
94615
|
+
const list = async () => el2.desktopCapturer.getSources({ types: ["screen"], thumbnailSize: { width: 1, height: 1 } });
|
|
94616
|
+
let sources = await list();
|
|
94617
|
+
if (sources.length === 0) {
|
|
94618
|
+
await wakeDisplay(log9);
|
|
94619
|
+
sources = await list();
|
|
94620
|
+
}
|
|
93363
94621
|
const match = sources.find((s) => s.display_id === String(display.id)) ?? sources[0];
|
|
93364
|
-
if (!match)
|
|
93365
|
-
|
|
94622
|
+
if (!match) {
|
|
94623
|
+
const denied = !canCaptureScreen();
|
|
94624
|
+
throw new Error(denied ? "Screen capture failed: Screen Recording permission is not granted to this app." : "Screen capture failed: no screen source. Screen Recording IS granted, so this is usually a display that stayed asleep, or a Mac with no active display attached.");
|
|
94625
|
+
}
|
|
93366
94626
|
return match.id;
|
|
93367
94627
|
}
|
|
93368
94628
|
var PublisherWindow = class {
|
|
93369
94629
|
sessionId;
|
|
93370
94630
|
handlers;
|
|
93371
94631
|
win = null;
|
|
94632
|
+
/** powerSaveBlocker id held for the life of the session — see startDisplayHold(). */
|
|
94633
|
+
displayHold = null;
|
|
93372
94634
|
stopAck = null;
|
|
93373
94635
|
constructor(sessionId, handlers) {
|
|
93374
94636
|
this.sessionId = sessionId;
|
|
@@ -93386,6 +94648,7 @@ var PublisherWindow = class {
|
|
|
93386
94648
|
if (!el2?.BrowserWindow)
|
|
93387
94649
|
throw new Error("Publisher requires the daemon GUI shell (no BrowserWindow).");
|
|
93388
94650
|
ensureIpc();
|
|
94651
|
+
this.startDisplayHold();
|
|
93389
94652
|
const sourceId = opts.sourceId ?? await sourceIdForMonitor(opts.monitorId ?? await this.primaryMonitorId());
|
|
93390
94653
|
const win3 = new el2.BrowserWindow({
|
|
93391
94654
|
width: 320,
|
|
@@ -93499,7 +94762,36 @@ var PublisherWindow = class {
|
|
|
93499
94762
|
maxFps: opts.maxFps
|
|
93500
94763
|
});
|
|
93501
94764
|
}
|
|
94765
|
+
/** Hold the display awake for as long as this session lives.
|
|
94766
|
+
*
|
|
94767
|
+
* Waking it once at start is not enough: the idle timer keeps running, so an unattended
|
|
94768
|
+
* host would go dark again a few minutes into a session and capture would die with the
|
|
94769
|
+
* same empty source list it started with. Released in stop() — never leaked, or the host
|
|
94770
|
+
* can never sleep again. */
|
|
94771
|
+
startDisplayHold() {
|
|
94772
|
+
if (this.displayHold !== null)
|
|
94773
|
+
return;
|
|
94774
|
+
try {
|
|
94775
|
+
const psb = electronModule()?.powerSaveBlocker;
|
|
94776
|
+
if (psb)
|
|
94777
|
+
this.displayHold = psb.start("prevent-display-sleep");
|
|
94778
|
+
} catch {
|
|
94779
|
+
}
|
|
94780
|
+
}
|
|
94781
|
+
releaseDisplayHold() {
|
|
94782
|
+
const id = this.displayHold;
|
|
94783
|
+
this.displayHold = null;
|
|
94784
|
+
if (id === null)
|
|
94785
|
+
return;
|
|
94786
|
+
try {
|
|
94787
|
+
const psb = electronModule()?.powerSaveBlocker;
|
|
94788
|
+
if (psb?.isStarted(id))
|
|
94789
|
+
psb.stop(id);
|
|
94790
|
+
} catch {
|
|
94791
|
+
}
|
|
94792
|
+
}
|
|
93502
94793
|
async stop() {
|
|
94794
|
+
this.releaseDisplayHold();
|
|
93503
94795
|
const w = this.win;
|
|
93504
94796
|
this.win = null;
|
|
93505
94797
|
if (!w || w.isDestroyed()) {
|
|
@@ -93861,10 +95153,20 @@ var TesseractEngine = class {
|
|
|
93861
95153
|
}
|
|
93862
95154
|
},
|
|
93863
95155
|
onReady: () => this.ctx.log("publisher connected"),
|
|
93864
|
-
onError: (err2) =>
|
|
95156
|
+
onError: (err2) => {
|
|
95157
|
+
this.ctx.log(`publisher error: ${err2}`);
|
|
95158
|
+
this.ctx.sendControl({ type: "rdesk:closed", reason: "network" });
|
|
95159
|
+
},
|
|
93865
95160
|
// Media is direct-first; log which path actually won so a regression to relay
|
|
93866
95161
|
// (which costs real bandwidth) is visible instead of silent. Types only, no IPs.
|
|
93867
|
-
|
|
95162
|
+
onCapture: (ok, message) => {
|
|
95163
|
+
this.ctx.log(`capture ${ok ? "ok" : `LOST \u2014 ${message}`}`);
|
|
95164
|
+
this.ctx.onCapture?.(ok, message);
|
|
95165
|
+
},
|
|
95166
|
+
onPath: (path6, d) => {
|
|
95167
|
+
this.ctx.log(`media path=${path6} (local=${d.localType ?? "?"} remote=${d.remoteType ?? "?"})`);
|
|
95168
|
+
this.ctx.onPath?.(path6, d);
|
|
95169
|
+
}
|
|
93868
95170
|
});
|
|
93869
95171
|
this.pub = pub;
|
|
93870
95172
|
await pub.start({
|
|
@@ -96333,7 +97635,7 @@ async function startLocalServer(opts) {
|
|
|
96333
97635
|
const rd = opts.getRdesk?.();
|
|
96334
97636
|
if (rd && env.sessionId) {
|
|
96335
97637
|
rdeskSessions.add(env.sessionId);
|
|
96336
|
-
void rd.onClientMessage(env.sessionId, { clientId: loopbackOrigin, name: "This device" }, env.payload);
|
|
97638
|
+
void rd.onClientMessage(env.sessionId, { clientId: loopbackOrigin, name: "This device", sameAccount: true }, env.payload);
|
|
96337
97639
|
}
|
|
96338
97640
|
}
|
|
96339
97641
|
} else if (env.channel === "signal") {
|
|
@@ -96918,8 +98220,8 @@ async function startLocalServer(opts) {
|
|
|
96918
98220
|
init_base_paths();
|
|
96919
98221
|
import { readFileSync as readFileSync45, writeFileSync as writeFileSync38, existsSync as existsSync35, mkdirSync as mkdirSync37, unlinkSync as unlinkSync6, chmodSync as chmodSync7, statSync as statSync9 } from "node:fs";
|
|
96920
98222
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
96921
|
-
import { join as
|
|
96922
|
-
import { randomBytes as
|
|
98223
|
+
import { join as join70 } from "node:path";
|
|
98224
|
+
import { randomBytes as randomBytes10 } from "node:crypto";
|
|
96923
98225
|
import { hostname as hostname5 } from "node:os";
|
|
96924
98226
|
|
|
96925
98227
|
// ../../packages/shared/dist/daemon-registry.js
|
|
@@ -97372,10 +98674,13 @@ function readLocal(meshId) {
|
|
|
97372
98674
|
function writeLocal(meshId, state3) {
|
|
97373
98675
|
try {
|
|
97374
98676
|
mkdirSync32(oneMeshDir(meshId), { recursive: true, mode: 448 });
|
|
97375
|
-
writeFileSync33(join60(oneMeshDir(meshId), FILES.local), JSON.stringify(state3, null, 2));
|
|
98677
|
+
writeFileSync33(join60(oneMeshDir(meshId), FILES.local), JSON.stringify(state3, null, 2), { mode: 384 });
|
|
97376
98678
|
} catch {
|
|
97377
98679
|
}
|
|
97378
98680
|
}
|
|
98681
|
+
function updateLocal(meshId, patch) {
|
|
98682
|
+
writeLocal(meshId, { ...readLocal(meshId), ...patch });
|
|
98683
|
+
}
|
|
97379
98684
|
function loadMesh(meshId) {
|
|
97380
98685
|
if (!isMeshId(meshId))
|
|
97381
98686
|
return null;
|
|
@@ -97633,6 +98938,9 @@ function loadMeshCore() {
|
|
|
97633
98938
|
}
|
|
97634
98939
|
}
|
|
97635
98940
|
var meshCore = loadMeshCore();
|
|
98941
|
+
function meshEngineStatus() {
|
|
98942
|
+
return { available: meshCore.available === true, reason: meshCore.loadError ?? null };
|
|
98943
|
+
}
|
|
97636
98944
|
var TICK_MS2 = 1e3;
|
|
97637
98945
|
var BIND_PORT = 0;
|
|
97638
98946
|
var shortKey = (k) => k.subarray(0, 4).toString("hex");
|
|
@@ -97742,9 +99050,54 @@ var MeshNode = class {
|
|
|
97742
99050
|
#relayed = /* @__PURE__ */ new Set();
|
|
97743
99051
|
/** staticPub hex → the Buffer, so events can be matched back to a peer. */
|
|
97744
99052
|
#peers = /* @__PURE__ */ new Map();
|
|
99053
|
+
/**
|
|
99054
|
+
* Peers whose CERTIFICATE says they are this network's way out, by display name.
|
|
99055
|
+
*
|
|
99056
|
+
* A hint for the UI, never an authorisation: the engine checks the same signed bit per
|
|
99057
|
+
* packet, alongside our own selection and a bundle capability. This exists so a person
|
|
99058
|
+
* can be offered a choice that has somewhere to go.
|
|
99059
|
+
*/
|
|
99060
|
+
#exitNodes = /* @__PURE__ */ new Map();
|
|
97745
99061
|
#lan = null;
|
|
97746
99062
|
#offRejoin = null;
|
|
97747
99063
|
#statusTimer = null;
|
|
99064
|
+
/**
|
|
99065
|
+
* Route this machine's non-mesh traffic through the network's exit node, or stop.
|
|
99066
|
+
*
|
|
99067
|
+
* GATE 1 OF THREE, and the only one that lives on this machine. `Engine::exit_allowed`
|
|
99068
|
+
* additionally requires that the CA marked the peer's certificate and that the signed
|
|
99069
|
+
* bundle grants CAP_EXIT_NODE, both checked per packet — so selecting a peer widens
|
|
99070
|
+
* nothing by itself, and selecting one that turns out not to qualify simply drops the
|
|
99071
|
+
* traffic rather than misrouting it.
|
|
99072
|
+
*
|
|
99073
|
+
* Without this call netd installs the routes and the engine refuses every packet that
|
|
99074
|
+
* arrives on them: a machine with its default route captured and nothing carrying it,
|
|
99075
|
+
* which is the worst of both states.
|
|
99076
|
+
*
|
|
99077
|
+
* Returns the name selected, or null when there is nobody to select.
|
|
99078
|
+
*/
|
|
99079
|
+
useExitNode(on) {
|
|
99080
|
+
const engine = this.#engine;
|
|
99081
|
+
if (!engine)
|
|
99082
|
+
return null;
|
|
99083
|
+
if (!on) {
|
|
99084
|
+
try {
|
|
99085
|
+
engine.setExitNode?.(null);
|
|
99086
|
+
} catch {
|
|
99087
|
+
}
|
|
99088
|
+
return null;
|
|
99089
|
+
}
|
|
99090
|
+
const first = [...this.#exitNodes.entries()][0];
|
|
99091
|
+
if (first === void 0)
|
|
99092
|
+
return null;
|
|
99093
|
+
const [hex6, name] = first;
|
|
99094
|
+
try {
|
|
99095
|
+
engine.setExitNode?.(Buffer.from(hex6, "hex"));
|
|
99096
|
+
} catch {
|
|
99097
|
+
return null;
|
|
99098
|
+
}
|
|
99099
|
+
return name;
|
|
99100
|
+
}
|
|
97748
99101
|
status() {
|
|
97749
99102
|
return {
|
|
97750
99103
|
available: meshCore.available,
|
|
@@ -97756,6 +99109,14 @@ var MeshNode = class {
|
|
|
97756
99109
|
peers: this.#engine?.peerCount() ?? 0,
|
|
97757
99110
|
established: [...this.#established],
|
|
97758
99111
|
relayed: [...this.#relayed],
|
|
99112
|
+
exitNodes: [...this.#exitNodes.values()],
|
|
99113
|
+
// Derived from the SAME sets the peer list is: an exit node with no established
|
|
99114
|
+
// session is one that cannot carry traffic yet, and saying "waiting" is different
|
|
99115
|
+
// from saying "none". Keyed by name so a caller never has to hold a key to read it.
|
|
99116
|
+
exitPaths: Object.fromEntries([...this.#exitNodes.entries()].map(([hex6, name]) => [
|
|
99117
|
+
name,
|
|
99118
|
+
this.#established.has(hex6) ? this.#relayed.has(hex6) ? "relay" : "direct" : "none"
|
|
99119
|
+
])),
|
|
97759
99120
|
meter: this.#engine?.meter() ?? null,
|
|
97760
99121
|
lastError: this.#lastError,
|
|
97761
99122
|
// Surfaced so `net status` can say "removed" rather than "not running". Those look
|
|
@@ -97927,11 +99288,11 @@ var MeshNode = class {
|
|
|
97927
99288
|
const engine = this.#engine;
|
|
97928
99289
|
if (!engine)
|
|
97929
99290
|
return;
|
|
97930
|
-
const
|
|
99291
|
+
const hex6 = staticPub.toString("hex");
|
|
97931
99292
|
try {
|
|
97932
|
-
if (!this.#peers.has(
|
|
99293
|
+
if (!this.#peers.has(hex6)) {
|
|
97933
99294
|
engine.addPeer(staticPub, 0, Buffer.alloc(16));
|
|
97934
|
-
this.#peers.set(
|
|
99295
|
+
this.#peers.set(hex6, staticPub);
|
|
97935
99296
|
}
|
|
97936
99297
|
engine.addPath(staticPub, `${address}:${port}`, false);
|
|
97937
99298
|
engine.startHandshake(staticPub, Date.now());
|
|
@@ -98008,10 +99369,10 @@ var MeshNode = class {
|
|
|
98008
99369
|
const pk = Buffer.from(m.fromStaticPub, "base64");
|
|
98009
99370
|
if (pk.length !== 32)
|
|
98010
99371
|
break;
|
|
98011
|
-
const
|
|
98012
|
-
if (!this.#peers.has(
|
|
99372
|
+
const hex6 = pk.toString("hex");
|
|
99373
|
+
if (!this.#peers.has(hex6)) {
|
|
98013
99374
|
engine.addPeer(pk, 0, Buffer.alloc(16));
|
|
98014
|
-
this.#peers.set(
|
|
99375
|
+
this.#peers.set(hex6, pk);
|
|
98015
99376
|
}
|
|
98016
99377
|
for (const ep of m.endpoints ?? []) {
|
|
98017
99378
|
try {
|
|
@@ -98024,9 +99385,11 @@ var MeshNode = class {
|
|
|
98024
99385
|
}
|
|
98025
99386
|
case "mesh:gone": {
|
|
98026
99387
|
const pk = Buffer.from(m.staticPub, "base64");
|
|
99388
|
+
if (pk.length === 32)
|
|
99389
|
+
this.#exitNodes.delete(pk.toString("hex"));
|
|
98027
99390
|
if (pk.length === 32) {
|
|
98028
|
-
const
|
|
98029
|
-
this.#peers.delete(
|
|
99391
|
+
const hex6 = pk.toString("hex");
|
|
99392
|
+
this.#peers.delete(hex6);
|
|
98030
99393
|
this.#established.delete(shortKey(pk));
|
|
98031
99394
|
this.#relayed.delete(shortKey(pk));
|
|
98032
99395
|
}
|
|
@@ -98052,10 +99415,22 @@ var MeshNode = class {
|
|
|
98052
99415
|
const pk = Buffer.from(p.staticPub, "base64");
|
|
98053
99416
|
if (pk.length !== 32)
|
|
98054
99417
|
return;
|
|
98055
|
-
const
|
|
98056
|
-
if (
|
|
99418
|
+
const hex6 = pk.toString("hex");
|
|
99419
|
+
if (p.cert) {
|
|
99420
|
+
try {
|
|
99421
|
+
const bytes2 = Buffer.from(p.cert, "base64");
|
|
99422
|
+
const pki = (init_dist6(), __toCommonJS(dist_exports3));
|
|
99423
|
+
const details = pki.decodeCert(new Uint8Array(bytes2)).details;
|
|
99424
|
+
if (pki.isExitNode(details))
|
|
99425
|
+
this.#exitNodes.set(hex6, details.name);
|
|
99426
|
+
else
|
|
99427
|
+
this.#exitNodes.delete(hex6);
|
|
99428
|
+
} catch {
|
|
99429
|
+
}
|
|
99430
|
+
}
|
|
99431
|
+
if (!this.#peers.has(hex6)) {
|
|
98057
99432
|
engine.addPeer(pk, 0, Buffer.alloc(16));
|
|
98058
|
-
this.#peers.set(
|
|
99433
|
+
this.#peers.set(hex6, pk);
|
|
98059
99434
|
}
|
|
98060
99435
|
for (const e of p.endpoints)
|
|
98061
99436
|
engine.addPath(pk, `${e.ip}:${e.port}`, false);
|
|
@@ -98190,16 +99565,26 @@ var MeshManager = class {
|
|
|
98190
99565
|
*/
|
|
98191
99566
|
disable(meshId) {
|
|
98192
99567
|
this.stop(meshId);
|
|
98193
|
-
|
|
99568
|
+
updateLocal(meshId, { enabled: false });
|
|
98194
99569
|
}
|
|
98195
99570
|
/** Undo `disable`, and start it. */
|
|
98196
99571
|
enable(meshId) {
|
|
98197
|
-
|
|
99572
|
+
updateLocal(meshId, { enabled: true });
|
|
98198
99573
|
return this.start(meshId);
|
|
98199
99574
|
}
|
|
98200
99575
|
node(meshId) {
|
|
98201
99576
|
return this.#nodes.get(meshId) ?? null;
|
|
98202
99577
|
}
|
|
99578
|
+
/**
|
|
99579
|
+
* The meshes with a LIVE node, which is what routes may be installed for.
|
|
99580
|
+
*
|
|
99581
|
+
* Deliberately not `ids()`: a certificate on disk is not a reason to steer traffic, and a
|
|
99582
|
+
* disabled mesh has one. `syncRoutes` takes this rather than the on-disk list precisely so
|
|
99583
|
+
* that confusion has to be made on purpose.
|
|
99584
|
+
*/
|
|
99585
|
+
running() {
|
|
99586
|
+
return [...this.#nodes.keys()];
|
|
99587
|
+
}
|
|
98203
99588
|
/** The first-joined running mesh — for callers that predate multi-mesh. */
|
|
98204
99589
|
primary() {
|
|
98205
99590
|
for (const meshId of this.ids()) {
|
|
@@ -98225,17 +99610,238 @@ function meshManager() {
|
|
|
98225
99610
|
return singleton3;
|
|
98226
99611
|
}
|
|
98227
99612
|
|
|
99613
|
+
// ../../packages/host-core/dist/mesh/netd-client.js
|
|
99614
|
+
import { connect as connect2 } from "node:net";
|
|
99615
|
+
import { platform as platform3 } from "node:process";
|
|
99616
|
+
var NETD_WIRE_VERSION = 1;
|
|
99617
|
+
var MAX_LINE = 1024 * 1024;
|
|
99618
|
+
var TIMEOUT_MS2 = 15e3;
|
|
99619
|
+
function netdEndpoint() {
|
|
99620
|
+
if (platform3 === "win32")
|
|
99621
|
+
return "\\\\.\\pipe\\tesseract-netd";
|
|
99622
|
+
if (platform3 === "darwin")
|
|
99623
|
+
return "/var/run/tesseract-netd.sock";
|
|
99624
|
+
return "/run/tesseract-netd.sock";
|
|
99625
|
+
}
|
|
99626
|
+
function endpointOverride() {
|
|
99627
|
+
return process.env.CCB_NETD_SOCKET ?? null;
|
|
99628
|
+
}
|
|
99629
|
+
function fail2(code, detail) {
|
|
99630
|
+
return { ok: false, code, detail };
|
|
99631
|
+
}
|
|
99632
|
+
async function call(line) {
|
|
99633
|
+
const endpoint2 = endpointOverride() ?? netdEndpoint();
|
|
99634
|
+
return new Promise((resolve16) => {
|
|
99635
|
+
let settled = false;
|
|
99636
|
+
const done = (r) => {
|
|
99637
|
+
if (settled)
|
|
99638
|
+
return;
|
|
99639
|
+
settled = true;
|
|
99640
|
+
try {
|
|
99641
|
+
sock.destroy();
|
|
99642
|
+
} catch {
|
|
99643
|
+
}
|
|
99644
|
+
resolve16(r);
|
|
99645
|
+
};
|
|
99646
|
+
let sock;
|
|
99647
|
+
try {
|
|
99648
|
+
sock = connect2(endpoint2);
|
|
99649
|
+
} catch (e) {
|
|
99650
|
+
return resolve16(fail2("not-installed", e instanceof Error ? e.message : String(e)));
|
|
99651
|
+
}
|
|
99652
|
+
const timer2 = setTimeout(() => {
|
|
99653
|
+
done(fail2("timeout", `no answer from the network helper in ${TIMEOUT_MS2}ms`));
|
|
99654
|
+
}, TIMEOUT_MS2);
|
|
99655
|
+
timer2.unref?.();
|
|
99656
|
+
sock.setTimeout(TIMEOUT_MS2);
|
|
99657
|
+
sock.on("timeout", () => {
|
|
99658
|
+
clearTimeout(timer2);
|
|
99659
|
+
done(fail2("timeout", "socket idle"));
|
|
99660
|
+
});
|
|
99661
|
+
sock.on("error", (e) => {
|
|
99662
|
+
clearTimeout(timer2);
|
|
99663
|
+
const absent = e.code === "ENOENT" || e.code === "ECONNREFUSED";
|
|
99664
|
+
done(fail2(absent ? "not-installed" : "io", e.message));
|
|
99665
|
+
});
|
|
99666
|
+
let buf = "";
|
|
99667
|
+
sock.on("data", (chunk) => {
|
|
99668
|
+
buf += chunk.toString("utf8");
|
|
99669
|
+
if (buf.length > MAX_LINE) {
|
|
99670
|
+
clearTimeout(timer2);
|
|
99671
|
+
done(fail2("protocol", "the helper sent an oversized line"));
|
|
99672
|
+
return;
|
|
99673
|
+
}
|
|
99674
|
+
const nl = buf.indexOf("\n");
|
|
99675
|
+
if (nl === -1)
|
|
99676
|
+
return;
|
|
99677
|
+
clearTimeout(timer2);
|
|
99678
|
+
done({ ok: true, line: buf.slice(0, nl) });
|
|
99679
|
+
});
|
|
99680
|
+
sock.on("close", () => {
|
|
99681
|
+
clearTimeout(timer2);
|
|
99682
|
+
done(fail2("protocol", "the helper closed the connection without answering"));
|
|
99683
|
+
});
|
|
99684
|
+
sock.on("connect", () => {
|
|
99685
|
+
sock.write(`${line}
|
|
99686
|
+
`);
|
|
99687
|
+
});
|
|
99688
|
+
});
|
|
99689
|
+
}
|
|
99690
|
+
function parse3(line) {
|
|
99691
|
+
let body;
|
|
99692
|
+
try {
|
|
99693
|
+
body = JSON.parse(line);
|
|
99694
|
+
} catch {
|
|
99695
|
+
return fail2("protocol", "the helper sent something that is not JSON");
|
|
99696
|
+
}
|
|
99697
|
+
if (typeof body !== "object" || body === null) {
|
|
99698
|
+
return fail2("protocol", "the helper sent something that is not an object");
|
|
99699
|
+
}
|
|
99700
|
+
const o = body;
|
|
99701
|
+
if (o.ok === false) {
|
|
99702
|
+
const code = typeof o.code === "string" ? o.code : "refused";
|
|
99703
|
+
const detail = typeof o.detail === "string" ? o.detail : "the helper refused";
|
|
99704
|
+
return fail2(code, detail);
|
|
99705
|
+
}
|
|
99706
|
+
if (o.ok !== true)
|
|
99707
|
+
return fail2("protocol", "the helper did not say whether it succeeded");
|
|
99708
|
+
return { ok: true, body: o };
|
|
99709
|
+
}
|
|
99710
|
+
async function request(line) {
|
|
99711
|
+
const r = await call(line);
|
|
99712
|
+
return r.ok ? parse3(r.line) : r;
|
|
99713
|
+
}
|
|
99714
|
+
function hex4(b) {
|
|
99715
|
+
return Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
99716
|
+
}
|
|
99717
|
+
async function netdHello() {
|
|
99718
|
+
const r = await request(JSON.stringify({ op: "hello", wireVersion: NETD_WIRE_VERSION }));
|
|
99719
|
+
if (!r.ok)
|
|
99720
|
+
return r;
|
|
99721
|
+
const v = r.body.wireVersion;
|
|
99722
|
+
if (typeof v !== "number")
|
|
99723
|
+
return fail2("protocol", "the helper did not report a wire version");
|
|
99724
|
+
if (v !== NETD_WIRE_VERSION) {
|
|
99725
|
+
return fail2("wire-version", `the helper speaks ${v}, this build speaks ${NETD_WIRE_VERSION}`);
|
|
99726
|
+
}
|
|
99727
|
+
return { ok: true, wireVersion: v };
|
|
99728
|
+
}
|
|
99729
|
+
async function netdStatus() {
|
|
99730
|
+
const r = await request(JSON.stringify({ op: "status" }));
|
|
99731
|
+
if (!r.ok)
|
|
99732
|
+
return r;
|
|
99733
|
+
const meshes = Array.isArray(r.body.meshes) ? r.body.meshes.filter((m) => typeof m === "string") : [];
|
|
99734
|
+
const iface = typeof r.body.interface === "string" ? r.body.interface : null;
|
|
99735
|
+
return { ok: true, meshes, interface: iface };
|
|
99736
|
+
}
|
|
99737
|
+
async function netdUp(args) {
|
|
99738
|
+
const r = await request(JSON.stringify({
|
|
99739
|
+
op: "up",
|
|
99740
|
+
meshId: args.meshId,
|
|
99741
|
+
genesis: hex4(args.genesis),
|
|
99742
|
+
cert: hex4(args.cert),
|
|
99743
|
+
fullTunnel: args.fullTunnel === true
|
|
99744
|
+
}));
|
|
99745
|
+
return r.ok ? { ok: true } : r;
|
|
99746
|
+
}
|
|
99747
|
+
async function netdDown(meshId) {
|
|
99748
|
+
const r = await request(JSON.stringify({ op: "down", meshId }));
|
|
99749
|
+
return r.ok ? { ok: true } : r;
|
|
99750
|
+
}
|
|
99751
|
+
async function netdAvailable() {
|
|
99752
|
+
return (await netdHello()).ok;
|
|
99753
|
+
}
|
|
99754
|
+
|
|
99755
|
+
// ../../packages/host-core/dist/mesh/route-sync.js
|
|
99756
|
+
async function syncRoutes(running2, log9 = () => {
|
|
99757
|
+
}) {
|
|
99758
|
+
const out = { up: [], down: [], failed: [], helperAbsent: false };
|
|
99759
|
+
if (!await netdAvailable()) {
|
|
99760
|
+
out.helperAbsent = true;
|
|
99761
|
+
return out;
|
|
99762
|
+
}
|
|
99763
|
+
const status2 = await netdStatus();
|
|
99764
|
+
if (!status2.ok) {
|
|
99765
|
+
out.failed.push({ meshId: "*", reason: status2.detail });
|
|
99766
|
+
return out;
|
|
99767
|
+
}
|
|
99768
|
+
const installed = new Set(status2.meshes);
|
|
99769
|
+
const want = new Set(running2);
|
|
99770
|
+
for (const meshId of want) {
|
|
99771
|
+
const identity = loadMesh(meshId);
|
|
99772
|
+
if (identity === null) {
|
|
99773
|
+
out.failed.push({ meshId, reason: "no enrolment on disk" });
|
|
99774
|
+
continue;
|
|
99775
|
+
}
|
|
99776
|
+
const r = await netdUp({
|
|
99777
|
+
meshId,
|
|
99778
|
+
genesis: identity.genesis,
|
|
99779
|
+
cert: identity.cert,
|
|
99780
|
+
// The per-machine choice, and `=== true` rather than a truthiness check: an absent or
|
|
99781
|
+
// malformed field must read as NO. netd unions this across meshes itself — any mesh
|
|
99782
|
+
// asking for a full tunnel makes it one for the machine — so this stays per mesh here.
|
|
99783
|
+
fullTunnel: readLocal(meshId)?.fullTunnel === true
|
|
99784
|
+
});
|
|
99785
|
+
if (r.ok) {
|
|
99786
|
+
out.up.push(meshId);
|
|
99787
|
+
log9(`routes installed for ${meshId}`);
|
|
99788
|
+
} else {
|
|
99789
|
+
out.failed.push({ meshId, reason: r.detail });
|
|
99790
|
+
log9(`routes NOT installed for ${meshId}: ${r.detail}`);
|
|
99791
|
+
}
|
|
99792
|
+
}
|
|
99793
|
+
for (const meshId of installed) {
|
|
99794
|
+
if (want.has(meshId))
|
|
99795
|
+
continue;
|
|
99796
|
+
const r = await netdDown(meshId);
|
|
99797
|
+
if (r.ok) {
|
|
99798
|
+
out.down.push(meshId);
|
|
99799
|
+
log9(`routes removed for ${meshId}`);
|
|
99800
|
+
} else {
|
|
99801
|
+
out.failed.push({ meshId, reason: r.detail });
|
|
99802
|
+
log9(`routes could NOT be removed for ${meshId}: ${r.detail}`);
|
|
99803
|
+
}
|
|
99804
|
+
}
|
|
99805
|
+
return out;
|
|
99806
|
+
}
|
|
99807
|
+
|
|
98228
99808
|
// ../../packages/host-core/dist/mesh/start-meshes.js
|
|
98229
99809
|
function startMeshes(log9) {
|
|
99810
|
+
const running2 = startNodes(log9);
|
|
99811
|
+
void syncRoutes(running2, log9).then((r) => {
|
|
99812
|
+
if (r.helperAbsent) {
|
|
99813
|
+
log9("routes: the network helper is not installed \u2014 the overlay carries no traffic yet");
|
|
99814
|
+
return;
|
|
99815
|
+
}
|
|
99816
|
+
if (r.up.length)
|
|
99817
|
+
log9(`routes: installed for ${r.up.join(", ")}`);
|
|
99818
|
+
if (r.down.length)
|
|
99819
|
+
log9(`routes: removed for ${r.down.join(", ")}`);
|
|
99820
|
+
for (const f of r.failed)
|
|
99821
|
+
log9(`routes: ${f.meshId} refused \u2014 ${f.reason}`);
|
|
99822
|
+
}).catch((e) => {
|
|
99823
|
+
log9(`routes: sync threw \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
99824
|
+
});
|
|
99825
|
+
}
|
|
99826
|
+
function startNodes(log9) {
|
|
98230
99827
|
const ids = listMeshIds();
|
|
98231
99828
|
if (ids.length <= 1) {
|
|
99829
|
+
const only = ids[0];
|
|
99830
|
+
if (only !== void 0 && readLocal(only)?.enabled === false) {
|
|
99831
|
+
log9("mesh: the only network is switched off");
|
|
99832
|
+
return [];
|
|
99833
|
+
}
|
|
98232
99834
|
const started2 = meshNode().start();
|
|
98233
99835
|
log9(started2.ok ? "mesh: node up" : `mesh: not started \u2014 ${started2.reason}`);
|
|
98234
|
-
return;
|
|
99836
|
+
return started2.ok && only !== void 0 ? [only] : [];
|
|
98235
99837
|
}
|
|
99838
|
+
const running2 = [];
|
|
98236
99839
|
for (const r of meshManager().startAll()) {
|
|
98237
99840
|
log9(r.ok ? `mesh ${r.meshId}: up` : `mesh ${r.meshId}: not started \u2014 ${r.reason}`);
|
|
99841
|
+
if (r.ok)
|
|
99842
|
+
running2.push(r.meshId);
|
|
98238
99843
|
}
|
|
99844
|
+
return running2;
|
|
98239
99845
|
}
|
|
98240
99846
|
|
|
98241
99847
|
// ../../packages/host-core/dist/drops/receive-ui.js
|
|
@@ -98333,7 +99939,7 @@ import { basename as basename13 } from "node:path";
|
|
|
98333
99939
|
// ../../packages/host-core/dist/drops/paths.js
|
|
98334
99940
|
init_base_paths();
|
|
98335
99941
|
import { mkdir as mkdir12 } from "node:fs/promises";
|
|
98336
|
-
import { join as
|
|
99942
|
+
import { join as join62 } from "node:path";
|
|
98337
99943
|
|
|
98338
99944
|
// ../../packages/host-core/dist/drops/names.js
|
|
98339
99945
|
var WINDOWS_RESERVED = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i;
|
|
@@ -98342,8 +99948,8 @@ var BIDI = /[\u200e\u200f\u202a-\u202e\u2066-\u2069]/g;
|
|
|
98342
99948
|
var MAX_NAME_BYTES = 200;
|
|
98343
99949
|
var MAX_EXT_BYTES = 32;
|
|
98344
99950
|
var MAX_DEPTH2 = 32;
|
|
98345
|
-
var
|
|
98346
|
-
var byteLen = (s) =>
|
|
99951
|
+
var utf83 = new TextEncoder();
|
|
99952
|
+
var byteLen = (s) => utf83.encode(s).length;
|
|
98347
99953
|
function capBytes(stem, ext, max) {
|
|
98348
99954
|
if (byteLen(stem + ext) <= max)
|
|
98349
99955
|
return stem + ext;
|
|
@@ -98422,7 +100028,7 @@ function basenameOf(p) {
|
|
|
98422
100028
|
function resolveDropsRoot() {
|
|
98423
100029
|
const root = resolveHostRoot();
|
|
98424
100030
|
const preferred = dropsDir();
|
|
98425
|
-
return isInsideRoot(preferred, root) ? preferred :
|
|
100031
|
+
return isInsideRoot(preferred, root) ? preferred : join62(root, "Drops");
|
|
98426
100032
|
}
|
|
98427
100033
|
async function ensureDropsRoot() {
|
|
98428
100034
|
const dir2 = resolveDropsRoot();
|
|
@@ -98438,7 +100044,7 @@ async function ensureDropDir(opts) {
|
|
|
98438
100044
|
parts.push(sanitizeDropName(opts.sender, "Unknown sender"));
|
|
98439
100045
|
if (!opts.singleItem && opts.label)
|
|
98440
100046
|
parts.push(sanitizeDropName(opts.label, "Files"));
|
|
98441
|
-
const dir2 =
|
|
100047
|
+
const dir2 = join62(...parts);
|
|
98442
100048
|
await mkdir12(dir2, { recursive: true });
|
|
98443
100049
|
return dir2;
|
|
98444
100050
|
}
|
|
@@ -98581,7 +100187,7 @@ function createDropHandler(deps) {
|
|
|
98581
100187
|
// ../../packages/host-core/dist/drops/blob-fetch.js
|
|
98582
100188
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
98583
100189
|
import { mkdir as mkdir13, rm as rm5, chmod as chmod3 } from "node:fs/promises";
|
|
98584
|
-
import { dirname as dirname26, join as
|
|
100190
|
+
import { dirname as dirname26, join as join63 } from "node:path";
|
|
98585
100191
|
import { Readable as Readable2 } from "node:stream";
|
|
98586
100192
|
import { pipeline } from "node:stream/promises";
|
|
98587
100193
|
|
|
@@ -98593,10 +100199,10 @@ var HEADER_BYTES = MAGIC2.length + NONCE_BYTES;
|
|
|
98593
100199
|
var FRAME_BYTES = 1024 * 1024;
|
|
98594
100200
|
var TAG_BYTES = 16;
|
|
98595
100201
|
var MAX_FRAME_CIPHERTEXT = FRAME_BYTES + TAG_BYTES + 1024;
|
|
98596
|
-
var
|
|
98597
|
-
var
|
|
100202
|
+
var subtle4 = () => globalThis.crypto.subtle;
|
|
100203
|
+
var bs4 = (b) => b;
|
|
98598
100204
|
async function importKey(raw) {
|
|
98599
|
-
return
|
|
100205
|
+
return subtle4().importKey("raw", bs4(raw), { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
|
|
98600
100206
|
}
|
|
98601
100207
|
function nonceFor(base, index) {
|
|
98602
100208
|
const n = Buffer.from(base);
|
|
@@ -98691,7 +100297,7 @@ function decryptStream(source, keyRaw) {
|
|
|
98691
100297
|
const frame = q.peek(4 + len);
|
|
98692
100298
|
if (!frame)
|
|
98693
100299
|
break;
|
|
98694
|
-
const plain = Buffer.from(await
|
|
100300
|
+
const plain = Buffer.from(await subtle4().decrypt({ name: "AES-GCM", iv: bs4(nonceFor(base, index)), additionalData: bs4(aadFor(index)) }, key2, bs4(frame.subarray(4))));
|
|
98695
100301
|
this.push(plain);
|
|
98696
100302
|
index += 1;
|
|
98697
100303
|
q.consume(4 + len);
|
|
@@ -98753,7 +100359,7 @@ async function fetchBlobDrop(opts) {
|
|
|
98753
100359
|
log7(`drop ${opts.dropId}: refusing directory "${item.rel}"`);
|
|
98754
100360
|
continue;
|
|
98755
100361
|
}
|
|
98756
|
-
const abs =
|
|
100362
|
+
const abs = join63(opts.destDir, rel);
|
|
98757
100363
|
if (!isInsideRoot(abs, opts.destDir)) {
|
|
98758
100364
|
log7(`drop ${opts.dropId}: refusing directory outside the destination`);
|
|
98759
100365
|
continue;
|
|
@@ -98774,7 +100380,7 @@ async function fetchBlobDrop(opts) {
|
|
|
98774
100380
|
log7(`drop ${opts.dropId}: refusing "${item.rel}"`);
|
|
98775
100381
|
continue;
|
|
98776
100382
|
}
|
|
98777
|
-
let abs =
|
|
100383
|
+
let abs = join63(opts.destDir, rel);
|
|
98778
100384
|
if (!isInsideRoot(abs, opts.destDir)) {
|
|
98779
100385
|
log7(`drop ${opts.dropId}: refusing a path outside the destination`);
|
|
98780
100386
|
continue;
|
|
@@ -99052,12 +100658,12 @@ var RdeskServerChannel = class {
|
|
|
99052
100658
|
|
|
99053
100659
|
// ../../packages/host-core/dist/rdesk/channel-client.js
|
|
99054
100660
|
import { readFileSync as readFileSync44 } from "node:fs";
|
|
99055
|
-
import { join as
|
|
100661
|
+
import { join as join64 } from "node:path";
|
|
99056
100662
|
var RECONNECT_MS = 2e3;
|
|
99057
100663
|
var CLAIM_RETRY_MS = 5e3;
|
|
99058
100664
|
function readEndpoint(dir2, selfPid) {
|
|
99059
100665
|
try {
|
|
99060
|
-
const s = JSON.parse(readFileSync44(
|
|
100666
|
+
const s = JSON.parse(readFileSync44(join64(dir2, "status.json"), "utf8"));
|
|
99061
100667
|
if (selfPid && s.pid === selfPid)
|
|
99062
100668
|
return null;
|
|
99063
100669
|
return s.localPort && s.localToken ? `ws://127.0.0.1:${s.localPort}/?token=${s.localToken}` : null;
|
|
@@ -99091,11 +100697,11 @@ function startRdeskChannelClient(deps) {
|
|
|
99091
100697
|
return;
|
|
99092
100698
|
retry = setTimeout(() => {
|
|
99093
100699
|
retry = null;
|
|
99094
|
-
|
|
100700
|
+
connect3();
|
|
99095
100701
|
}, RECONNECT_MS);
|
|
99096
100702
|
retry.unref?.();
|
|
99097
100703
|
};
|
|
99098
|
-
function
|
|
100704
|
+
function connect3() {
|
|
99099
100705
|
if (stopped2 || sock)
|
|
99100
100706
|
return;
|
|
99101
100707
|
const url2 = readEndpoint(deps.daemonDir(), deps.selfPid);
|
|
@@ -99161,7 +100767,7 @@ function startRdeskChannelClient(deps) {
|
|
|
99161
100767
|
ws.on("error", () => {
|
|
99162
100768
|
});
|
|
99163
100769
|
}
|
|
99164
|
-
|
|
100770
|
+
connect3();
|
|
99165
100771
|
const claimPoll = setInterval(() => {
|
|
99166
100772
|
if (stopped2 || holding)
|
|
99167
100773
|
return;
|
|
@@ -99198,19 +100804,6 @@ function setRdeskServerAdmin(a) {
|
|
|
99198
100804
|
admin = a;
|
|
99199
100805
|
}
|
|
99200
100806
|
|
|
99201
|
-
// ../../packages/host-core/dist/daemon-identity-reload.js
|
|
99202
|
-
var reload = null;
|
|
99203
|
-
function setDaemonIdentityReload(fn) {
|
|
99204
|
-
reload = fn;
|
|
99205
|
-
}
|
|
99206
|
-
function nextDaemonIdentity(fresh, current) {
|
|
99207
|
-
if (!fresh?.accessToken)
|
|
99208
|
-
return { kind: "machine" };
|
|
99209
|
-
if (fresh.accessToken === current.accessToken && (fresh.userId ?? "") === current.userId)
|
|
99210
|
-
return { kind: "unchanged" };
|
|
99211
|
-
return { kind: "account" };
|
|
99212
|
-
}
|
|
99213
|
-
|
|
99214
100807
|
// ../../packages/host-core/dist/daemon-online-watch.js
|
|
99215
100808
|
var FIRST_DELAY_MS = 5e3;
|
|
99216
100809
|
var MAX_DELAY_MS = 3e4;
|
|
@@ -99503,10 +101096,10 @@ function registerRdpEngine() {
|
|
|
99503
101096
|
// ../../packages/host-core/dist/rdesk/audit.js
|
|
99504
101097
|
init_credentials();
|
|
99505
101098
|
import { appendFile, stat as stat8, rename as rename3 } from "node:fs/promises";
|
|
99506
|
-
import { join as
|
|
101099
|
+
import { join as join65 } from "node:path";
|
|
99507
101100
|
var MAX_BYTES = 2 * 1024 * 1024;
|
|
99508
101101
|
function rdeskAuditPath() {
|
|
99509
|
-
return
|
|
101102
|
+
return join65(daemonDir2(), "rdesk-audit.jsonl");
|
|
99510
101103
|
}
|
|
99511
101104
|
var queue = [];
|
|
99512
101105
|
var draining = false;
|
|
@@ -99546,81 +101139,13 @@ function appendRdeskAudit(e) {
|
|
|
99546
101139
|
}
|
|
99547
101140
|
}
|
|
99548
101141
|
|
|
99549
|
-
// ../../packages/host-core/dist/rdesk/screen-permission.js
|
|
99550
|
-
function screenRecordingStatus() {
|
|
99551
|
-
if (process.platform !== "darwin")
|
|
99552
|
-
return "unsupported";
|
|
99553
|
-
try {
|
|
99554
|
-
const sp = electronModule()?.systemPreferences;
|
|
99555
|
-
const s = sp?.getMediaAccessStatus("screen");
|
|
99556
|
-
if (s === "granted" || s === "denied" || s === "restricted" || s === "not-determined")
|
|
99557
|
-
return s;
|
|
99558
|
-
return "not-determined";
|
|
99559
|
-
} catch {
|
|
99560
|
-
return "not-determined";
|
|
99561
|
-
}
|
|
99562
|
-
}
|
|
99563
|
-
async function registerForScreenRecording() {
|
|
99564
|
-
try {
|
|
99565
|
-
const dc = electronModule()?.desktopCapturer;
|
|
99566
|
-
await dc?.getSources({ types: ["screen"], thumbnailSize: { width: 1, height: 1 } });
|
|
99567
|
-
} catch {
|
|
99568
|
-
}
|
|
99569
|
-
}
|
|
99570
|
-
async function openScreenRecordingSettings() {
|
|
99571
|
-
if (process.platform !== "darwin")
|
|
99572
|
-
return;
|
|
99573
|
-
await registerForScreenRecording();
|
|
99574
|
-
try {
|
|
99575
|
-
const shell = electronModule()?.shell;
|
|
99576
|
-
await shell?.openExternal("x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture");
|
|
99577
|
-
} catch {
|
|
99578
|
-
}
|
|
99579
|
-
}
|
|
99580
|
-
var PROMPT_COOLDOWN_MS = 6e4;
|
|
99581
|
-
var lastPromptAt = 0;
|
|
99582
|
-
async function promptForScreenRecording(opts = {}) {
|
|
99583
|
-
if (process.platform !== "darwin")
|
|
99584
|
-
return false;
|
|
99585
|
-
if (screenRecordingStatus() === "granted")
|
|
99586
|
-
return false;
|
|
99587
|
-
const now2 = Date.now();
|
|
99588
|
-
if (now2 - lastPromptAt < PROMPT_COOLDOWN_MS)
|
|
99589
|
-
return false;
|
|
99590
|
-
lastPromptAt = now2;
|
|
99591
|
-
const el2 = electronModule();
|
|
99592
|
-
const who = opts.viewerName ? `${opts.viewerName} is` : "Someone is";
|
|
99593
|
-
opts.log?.(`screen recording not granted \u2014 prompting (${who} waiting)`);
|
|
99594
|
-
if (!el2?.dialog) {
|
|
99595
|
-
opts.log?.("no GUI to prompt with \u2014 grant Screen Recording in System Settings \u2192 Privacy & Security");
|
|
99596
|
-
return false;
|
|
99597
|
-
}
|
|
99598
|
-
try {
|
|
99599
|
-
const { response } = await el2.dialog.showMessageBox({
|
|
99600
|
-
type: "warning",
|
|
99601
|
-
buttons: ["Open System Settings", "Not Now"],
|
|
99602
|
-
defaultId: 0,
|
|
99603
|
-
cancelId: 1,
|
|
99604
|
-
message: "Allow screen sharing on this Mac?",
|
|
99605
|
-
detail: `${who} trying to connect to this computer, but macOS is blocking screen capture.
|
|
99606
|
-
|
|
99607
|
-
Open System Settings \u2192 Privacy & Security \u2192 Screen Recording and switch on Tesseract Remote Desktop, then ask them to connect again.`
|
|
99608
|
-
});
|
|
99609
|
-
if (response === 0)
|
|
99610
|
-
await openScreenRecordingSettings();
|
|
99611
|
-
return true;
|
|
99612
|
-
} catch {
|
|
99613
|
-
return false;
|
|
99614
|
-
}
|
|
99615
|
-
}
|
|
99616
|
-
|
|
99617
101142
|
// ../../packages/host-core/dist/fileprovider-bridge.js
|
|
99618
101143
|
import { writeFileSync as writeFileSync34, mkdirSync as mkdirSync33, rmSync as rmSync8, existsSync as existsSync31 } from "node:fs";
|
|
99619
101144
|
import { homedir as homedir9 } from "node:os";
|
|
99620
|
-
import { join as
|
|
101145
|
+
import { join as join66 } from "node:path";
|
|
99621
101146
|
var APPEX_BUNDLE_ID = "dev.tesseract.FileProvider";
|
|
99622
101147
|
function appexBridgeInfoPath() {
|
|
99623
|
-
return
|
|
101148
|
+
return join66(homedir9(), "Library", "Containers", APPEX_BUNDLE_ID, "Data", "Library", "Application Support", "tesseract-bridge.json");
|
|
99624
101149
|
}
|
|
99625
101150
|
function clearBridgeInfo() {
|
|
99626
101151
|
if (process.platform !== "darwin")
|
|
@@ -99787,10 +101312,10 @@ function stopFileProviderBridge() {
|
|
|
99787
101312
|
}
|
|
99788
101313
|
|
|
99789
101314
|
// ../../packages/host-core/dist/vault/autofill-bridge.js
|
|
99790
|
-
import { randomBytes as
|
|
101315
|
+
import { randomBytes as randomBytes9 } from "node:crypto";
|
|
99791
101316
|
import { existsSync as existsSync32, mkdirSync as mkdirSync34, writeFileSync as writeFileSync35, rmSync as rmSync9 } from "node:fs";
|
|
99792
101317
|
import { homedir as homedir10 } from "node:os";
|
|
99793
|
-
import { join as
|
|
101318
|
+
import { join as join67 } from "node:path";
|
|
99794
101319
|
|
|
99795
101320
|
// ../../packages/host-core/dist/vault/peer-verify.js
|
|
99796
101321
|
import { execFile as execFile9 } from "node:child_process";
|
|
@@ -99852,10 +101377,10 @@ async function isTrustedAutofillPeer(remotePort) {
|
|
|
99852
101377
|
var APPEX_BUNDLE_ID2 = "dev.tesseract.AutoFill";
|
|
99853
101378
|
var BRIDGE_PORTS2 = [17872, 17873, 17874, 17875];
|
|
99854
101379
|
function appexContainerData() {
|
|
99855
|
-
return
|
|
101380
|
+
return join67(homedir10(), "Library", "Containers", APPEX_BUNDLE_ID2, "Data");
|
|
99856
101381
|
}
|
|
99857
101382
|
function bridgeInfoPath() {
|
|
99858
|
-
return
|
|
101383
|
+
return join67(appexContainerData(), "Library", "Application Support", "tesseract-autofill-bridge.json");
|
|
99859
101384
|
}
|
|
99860
101385
|
var infoLoggedOnce = false;
|
|
99861
101386
|
function writeBridgeInfo(port, token3, log9) {
|
|
@@ -99870,7 +101395,7 @@ function writeBridgeInfo(port, token3, log9) {
|
|
|
99870
101395
|
}
|
|
99871
101396
|
return;
|
|
99872
101397
|
}
|
|
99873
|
-
const dir2 =
|
|
101398
|
+
const dir2 = join67(containerData, "Library", "Application Support");
|
|
99874
101399
|
mkdirSync34(dir2, { recursive: true });
|
|
99875
101400
|
writeFileSync35(bridgeInfoPath(), JSON.stringify({ port, token: token3, pid: process.pid, ts: Date.now() }), { mode: 384 });
|
|
99876
101401
|
if (!infoLoggedOnce) {
|
|
@@ -100031,7 +101556,7 @@ function startAutofillBridge(log9 = () => {
|
|
|
100031
101556
|
if (process.platform !== "darwin" || wss2)
|
|
100032
101557
|
return;
|
|
100033
101558
|
stopping2 = false;
|
|
100034
|
-
token2 =
|
|
101559
|
+
token2 = randomBytes9(24).toString("base64url");
|
|
100035
101560
|
bind(0, log9);
|
|
100036
101561
|
}
|
|
100037
101562
|
function stopAutofillBridge() {
|
|
@@ -100057,15 +101582,15 @@ function stopAutofillBridge() {
|
|
|
100057
101582
|
|
|
100058
101583
|
// ../../packages/host-core/dist/power-node.js
|
|
100059
101584
|
import { spawn as spawn13 } from "node:child_process";
|
|
100060
|
-
import { platform as
|
|
101585
|
+
import { platform as platform4 } from "node:os";
|
|
100061
101586
|
function createNodePowerController() {
|
|
100062
101587
|
const active = /* @__PURE__ */ new Set();
|
|
100063
101588
|
let proc = null;
|
|
100064
101589
|
function spawnInhibitor() {
|
|
100065
101590
|
try {
|
|
100066
|
-
if (
|
|
101591
|
+
if (platform4() === "darwin")
|
|
100067
101592
|
return spawn13("caffeinate", ["-i"], { stdio: "ignore" });
|
|
100068
|
-
if (
|
|
101593
|
+
if (platform4() === "linux") {
|
|
100069
101594
|
return spawn13("systemd-inhibit", ["--what=sleep", "--why=tesseract agent running", "--mode=block", "sleep", "infinity"], { stdio: "ignore" });
|
|
100070
101595
|
}
|
|
100071
101596
|
} catch {
|
|
@@ -100115,28 +101640,28 @@ function createNodePowerController() {
|
|
|
100115
101640
|
// ../../packages/host-core/dist/native-host.js
|
|
100116
101641
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
100117
101642
|
import { chmodSync as chmodSync6, existsSync as existsSync33, mkdirSync as mkdirSync35, writeFileSync as writeFileSync36 } from "node:fs";
|
|
100118
|
-
import { homedir as homedir11, platform as
|
|
100119
|
-
import { dirname as dirname27, join as
|
|
101643
|
+
import { homedir as homedir11, platform as platform5 } from "node:os";
|
|
101644
|
+
import { dirname as dirname27, join as join68, resolve as resolve12 } from "node:path";
|
|
100120
101645
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
100121
101646
|
var HOST_NAME = "com.tesseract.companion";
|
|
100122
101647
|
var EXTENSION_IDS = ["icpnghhpcmaonjckkpilpajblfehpplo", "giolfpookdhjfafcchaflhmigghaeffn"];
|
|
100123
101648
|
var BRIDGE_BASENAME = "host.cjs";
|
|
100124
101649
|
function browserProfileDirs() {
|
|
100125
101650
|
const home = homedir11();
|
|
100126
|
-
const p =
|
|
101651
|
+
const p = platform5();
|
|
100127
101652
|
if (p === "darwin") {
|
|
100128
|
-
const base =
|
|
100129
|
-
return ["Google/Chrome", "Google/Chrome Beta", "Google/Chrome Dev", "Google/Chrome Canary", "Chromium", "Microsoft Edge", "BraveSoftware/Brave-Browser", "Vivaldi", "Arc"].map((b) =>
|
|
101653
|
+
const base = join68(home, "Library/Application Support");
|
|
101654
|
+
return ["Google/Chrome", "Google/Chrome Beta", "Google/Chrome Dev", "Google/Chrome Canary", "Chromium", "Microsoft Edge", "BraveSoftware/Brave-Browser", "Vivaldi", "Arc"].map((b) => join68(base, b));
|
|
100130
101655
|
}
|
|
100131
101656
|
if (p === "win32")
|
|
100132
101657
|
return [];
|
|
100133
|
-
const cfg2 =
|
|
100134
|
-
return ["google-chrome", "google-chrome-beta", "chromium", "microsoft-edge", "BraveSoftware/Brave-Browser", "vivaldi"].map((b) =>
|
|
101658
|
+
const cfg2 = join68(home, ".config");
|
|
101659
|
+
return ["google-chrome", "google-chrome-beta", "chromium", "microsoft-edge", "BraveSoftware/Brave-Browser", "vivaldi"].map((b) => join68(cfg2, b));
|
|
100135
101660
|
}
|
|
100136
101661
|
function resolveBridge(log9) {
|
|
100137
101662
|
const candidates = [
|
|
100138
101663
|
process.env.CCB_COMPANION_HOST_JS,
|
|
100139
|
-
process.resourcesPath ?
|
|
101664
|
+
process.resourcesPath ? join68(process.resourcesPath, "companion-host", BRIDGE_BASENAME) : void 0
|
|
100140
101665
|
];
|
|
100141
101666
|
try {
|
|
100142
101667
|
const here = dirname27(fileURLToPath5(import.meta.url));
|
|
@@ -100151,8 +101676,8 @@ function resolveBridge(log9) {
|
|
|
100151
101676
|
return null;
|
|
100152
101677
|
}
|
|
100153
101678
|
function writeLauncher(daemonDir3, bridge, runtime) {
|
|
100154
|
-
const isWin =
|
|
100155
|
-
const launcher =
|
|
101679
|
+
const isWin = platform5() === "win32";
|
|
101680
|
+
const launcher = join68(daemonDir3, isWin ? "companion-host.cmd" : "companion-host.sh");
|
|
100156
101681
|
if (isWin) {
|
|
100157
101682
|
writeFileSync36(launcher, `@echo off\r
|
|
100158
101683
|
set ELECTRON_RUN_AS_NODE=1\r
|
|
@@ -100183,16 +101708,16 @@ function registerNativeHost(opts) {
|
|
|
100183
101708
|
type: "stdio",
|
|
100184
101709
|
allowed_origins: EXTENSION_IDS.map((id) => `chrome-extension://${id}/`)
|
|
100185
101710
|
}, null, 2);
|
|
100186
|
-
if (
|
|
101711
|
+
if (platform5() === "win32")
|
|
100187
101712
|
return registerWindows(opts.daemonDir, manifestJson, log9);
|
|
100188
101713
|
let wrote = 0;
|
|
100189
101714
|
for (const profile of browserProfileDirs()) {
|
|
100190
101715
|
if (!existsSync33(profile))
|
|
100191
101716
|
continue;
|
|
100192
101717
|
try {
|
|
100193
|
-
const dir2 =
|
|
101718
|
+
const dir2 = join68(profile, "NativeMessagingHosts");
|
|
100194
101719
|
mkdirSync35(dir2, { recursive: true });
|
|
100195
|
-
writeFileSync36(
|
|
101720
|
+
writeFileSync36(join68(dir2, `${HOST_NAME}.json`), manifestJson);
|
|
100196
101721
|
wrote++;
|
|
100197
101722
|
} catch {
|
|
100198
101723
|
}
|
|
@@ -100204,7 +101729,7 @@ function registerNativeHost(opts) {
|
|
|
100204
101729
|
}
|
|
100205
101730
|
function registerWindows(daemonDir3, manifestJson, log9) {
|
|
100206
101731
|
try {
|
|
100207
|
-
const manifestPath =
|
|
101732
|
+
const manifestPath = join68(daemonDir3, `${HOST_NAME}.json`);
|
|
100208
101733
|
writeFileSync36(manifestPath, manifestJson);
|
|
100209
101734
|
for (const root of ["Software\\Google\\Chrome", "Software\\Microsoft\\Edge", "Software\\BraveSoftware\\Brave-Browser"]) {
|
|
100210
101735
|
try {
|
|
@@ -100224,9 +101749,9 @@ init_daemon_settings();
|
|
|
100224
101749
|
// ../../packages/host-core/dist/activity/activity-tracker.js
|
|
100225
101750
|
init_credentials();
|
|
100226
101751
|
import { promises as fsp, writeFileSync as writeFileSync37, mkdirSync as mkdirSync36, existsSync as existsSync34 } from "node:fs";
|
|
100227
|
-
import { join as
|
|
101752
|
+
import { join as join69 } from "node:path";
|
|
100228
101753
|
function activityProfilePath() {
|
|
100229
|
-
return
|
|
101754
|
+
return join69(daemonDir2(), "activity-profile.json");
|
|
100230
101755
|
}
|
|
100231
101756
|
var MAX_APPS = 300;
|
|
100232
101757
|
var MAX_AGE_DAYS = 120;
|
|
@@ -100535,8 +102060,8 @@ async function runDaemon(opts = {}) {
|
|
|
100535
102060
|
log9("paths", JSON.stringify(sealBasePaths()));
|
|
100536
102061
|
const OUR_STARTED_AT = procStartedAt(process.pid);
|
|
100537
102062
|
let ownsMachine = false;
|
|
100538
|
-
const pidfile = () =>
|
|
100539
|
-
const statusFile = () =>
|
|
102063
|
+
const pidfile = () => join70(daemonDir2(), "daemon.lock");
|
|
102064
|
+
const statusFile = () => join70(daemonDir2(), "status.json");
|
|
100540
102065
|
const isAlive2 = (pid) => {
|
|
100541
102066
|
try {
|
|
100542
102067
|
process.kill(pid, 0);
|
|
@@ -100976,12 +102501,43 @@ async function runDaemon(opts = {}) {
|
|
|
100976
102501
|
} catch {
|
|
100977
102502
|
}
|
|
100978
102503
|
});
|
|
100979
|
-
|
|
102504
|
+
const renderRecoveries = [];
|
|
102505
|
+
const RECOVER_WINDOW_MS = 6e4, RECOVER_MAX = 4, RECOVER_DELAY_MS = 300;
|
|
102506
|
+
const recoverRenderer = (wc, reason) => {
|
|
102507
|
+
if (!mergedProcess || deliberateMergedQuit())
|
|
102508
|
+
return;
|
|
102509
|
+
if (reason && !["killed", "crashed", "abnormal-exit", "oom", "launch-failed", "integrity-failure"].includes(reason))
|
|
102510
|
+
return;
|
|
102511
|
+
const now2 = Date.now();
|
|
102512
|
+
while (renderRecoveries.length && now2 - renderRecoveries[0] > RECOVER_WINDOW_MS)
|
|
102513
|
+
renderRecoveries.shift();
|
|
102514
|
+
if (renderRecoveries.length >= RECOVER_MAX) {
|
|
102515
|
+
try {
|
|
102516
|
+
log9(`render-recover: ${RECOVER_MAX} reloads in <60s \u2014 backing off (page may be genuinely crashing)`);
|
|
102517
|
+
} catch {
|
|
102518
|
+
}
|
|
102519
|
+
return;
|
|
102520
|
+
}
|
|
102521
|
+
renderRecoveries.push(now2);
|
|
102522
|
+
const contents = wc;
|
|
102523
|
+
setTimeout(() => {
|
|
102524
|
+
try {
|
|
102525
|
+
if (!contents || contents.isDestroyed?.())
|
|
102526
|
+
return;
|
|
102527
|
+
log9(`render-recover: reloading window after '${reason ?? "unknown"}' (recovery #${renderRecoveries.length})`);
|
|
102528
|
+
contents.reload?.();
|
|
102529
|
+
} catch {
|
|
102530
|
+
}
|
|
102531
|
+
}, RECOVER_DELAY_MS).unref?.();
|
|
102532
|
+
};
|
|
102533
|
+
eapp.on("render-process-gone", (_e, wc, details) => {
|
|
102534
|
+
const reason = details?.reason;
|
|
100980
102535
|
try {
|
|
100981
|
-
log9(`render-process-gone (kept alive) uptime=${Date.now() - daemonStartedAt}ms: ${JSON.stringify(
|
|
102536
|
+
log9(`render-process-gone (kept alive) uptime=${Date.now() - daemonStartedAt}ms: ${JSON.stringify(details ?? {})}`);
|
|
100982
102537
|
snapshotProcs("render-gone");
|
|
100983
102538
|
} catch {
|
|
100984
102539
|
}
|
|
102540
|
+
recoverRenderer(wc, reason);
|
|
100985
102541
|
});
|
|
100986
102542
|
eapp.on("child-process-gone", (_e, d) => {
|
|
100987
102543
|
try {
|
|
@@ -101000,7 +102556,7 @@ async function runDaemon(opts = {}) {
|
|
|
101000
102556
|
}
|
|
101001
102557
|
if (ownsMachine)
|
|
101002
102558
|
setHostDaemonRole(true);
|
|
101003
|
-
const localToken =
|
|
102559
|
+
const localToken = randomBytes10(24).toString("hex");
|
|
101004
102560
|
const sendToViewer = (kind, sessionId, clientId, msg) => {
|
|
101005
102561
|
const lb = loopbackRdeskSend.get(clientId);
|
|
101006
102562
|
if (lb) {
|
|
@@ -101159,7 +102715,7 @@ async function runDaemon(opts = {}) {
|
|
|
101159
102715
|
if (r.status === 401) {
|
|
101160
102716
|
log9("device token no longer valid \u2014 dropping to local-only on restart");
|
|
101161
102717
|
try {
|
|
101162
|
-
unlinkSync6(
|
|
102718
|
+
unlinkSync6(join70(daemonDir2(), "credentials.json"));
|
|
101163
102719
|
} catch {
|
|
101164
102720
|
}
|
|
101165
102721
|
shutdown(0, "token-revoked-401");
|
|
@@ -101557,14 +103113,14 @@ async function runDaemon(opts = {}) {
|
|
|
101557
103113
|
// is on; with it off it is the standalone Remote Desktop app, and we forward rather than
|
|
101558
103114
|
// handle. `provider()` re-reads the setting every time, so switching it back on takes the
|
|
101559
103115
|
// channel away from the claimant mid-flight — there is never a moment with two servers.
|
|
101560
|
-
onRdesk: (payload, clientId, sessionId) => {
|
|
103116
|
+
onRdesk: (payload, clientId, sessionId, viewerOwner) => {
|
|
101561
103117
|
const p = rdeskChannel.provider();
|
|
101562
103118
|
if (p && clientId) {
|
|
101563
103119
|
p.control(sessionId, clientId, payload);
|
|
101564
103120
|
return;
|
|
101565
103121
|
}
|
|
101566
103122
|
if (rdesk && clientId)
|
|
101567
|
-
void rdesk.onClientMessage(sessionId, { clientId }, payload);
|
|
103123
|
+
void rdesk.onClientMessage(sessionId, { clientId, sameAccount: viewerOwner }, payload);
|
|
101568
103124
|
},
|
|
101569
103125
|
onRdeskSignal: (payload, clientId, sessionId) => {
|
|
101570
103126
|
const p = rdeskChannel.provider();
|
|
@@ -101657,7 +103213,7 @@ async function runDaemon(opts = {}) {
|
|
|
101657
103213
|
if (appPid > 0 && appPid !== process.pid) {
|
|
101658
103214
|
const quitMarker = () => {
|
|
101659
103215
|
try {
|
|
101660
|
-
return Number(readFileSync45(
|
|
103216
|
+
return Number(readFileSync45(join70(daemonDir2(), "app-quit.marker"), "utf-8").trim()) || 0;
|
|
101661
103217
|
} catch {
|
|
101662
103218
|
return 0;
|
|
101663
103219
|
}
|
|
@@ -101682,7 +103238,7 @@ async function runDaemon(opts = {}) {
|
|
|
101682
103238
|
log9(`desktop app (pid ${appPid}) is gone with NO clean-quit marker \u2014 reporting`);
|
|
101683
103239
|
const tail3 = (name) => {
|
|
101684
103240
|
try {
|
|
101685
|
-
const buf = readFileSync45(
|
|
103241
|
+
const buf = readFileSync45(join70(daemonDir2(), name), "utf-8");
|
|
101686
103242
|
return buf.length > 4096 ? buf.slice(-4096) : buf;
|
|
101687
103243
|
} catch {
|
|
101688
103244
|
return void 0;
|
|
@@ -101713,7 +103269,7 @@ async function runDaemon(opts = {}) {
|
|
|
101713
103269
|
}
|
|
101714
103270
|
try {
|
|
101715
103271
|
const DAEMON_LOG_CAP = 2 * 1024 * 1024;
|
|
101716
|
-
const daemonLogFile =
|
|
103272
|
+
const daemonLogFile = join70(daemonDir2(), "daemon.log");
|
|
101717
103273
|
const capTimer = setInterval(() => {
|
|
101718
103274
|
try {
|
|
101719
103275
|
if (existsSync35(daemonLogFile) && statSync9(daemonLogFile).size > DAEMON_LOG_CAP) {
|
|
@@ -101765,17 +103321,17 @@ init_dist6();
|
|
|
101765
103321
|
init_credentials();
|
|
101766
103322
|
init_dist();
|
|
101767
103323
|
var MESH_BASE = "/api/core/tesseract/mesh";
|
|
101768
|
-
function
|
|
103324
|
+
function fail3(code, detail) {
|
|
101769
103325
|
return { ok: false, code, detail };
|
|
101770
103326
|
}
|
|
101771
|
-
async function
|
|
103327
|
+
async function call2(path6, init, auth = true) {
|
|
101772
103328
|
const creds3 = auth ? readCredentials() : null;
|
|
101773
103329
|
if (auth && !creds3) {
|
|
101774
|
-
return
|
|
103330
|
+
return fail3("not-signed-in", "sign in first: tesseract-agent login");
|
|
101775
103331
|
}
|
|
101776
103332
|
const origin = creds3?.apiOrigin;
|
|
101777
103333
|
if (!origin)
|
|
101778
|
-
return
|
|
103334
|
+
return fail3("not-signed-in", "no API origin is configured on this machine");
|
|
101779
103335
|
let res;
|
|
101780
103336
|
try {
|
|
101781
103337
|
res = await fetch(`${origin.replace(/\/$/, "")}${MESH_BASE}${path6}`, {
|
|
@@ -101787,7 +103343,7 @@ async function call(path6, init, auth = true) {
|
|
|
101787
103343
|
...init.body === void 0 ? {} : { body: JSON.stringify(init.body) }
|
|
101788
103344
|
});
|
|
101789
103345
|
} catch (e) {
|
|
101790
|
-
return
|
|
103346
|
+
return fail3("network", e instanceof Error ? e.message : String(e));
|
|
101791
103347
|
}
|
|
101792
103348
|
const text9 = await res.text();
|
|
101793
103349
|
if (!res.ok) {
|
|
@@ -101798,30 +103354,31 @@ async function call(path6, init, auth = true) {
|
|
|
101798
103354
|
detail = Array.isArray(parsed.message) ? parsed.message.join("; ") : parsed.message;
|
|
101799
103355
|
} catch {
|
|
101800
103356
|
}
|
|
101801
|
-
return
|
|
103357
|
+
return fail3(res.status >= 500 ? "server" : "refused", detail);
|
|
101802
103358
|
}
|
|
101803
103359
|
try {
|
|
101804
103360
|
return { ok: true, data: text9 ? JSON.parse(text9) : {} };
|
|
101805
103361
|
} catch {
|
|
101806
|
-
return
|
|
103362
|
+
return fail3("server", "the server sent something that is not JSON");
|
|
101807
103363
|
}
|
|
101808
103364
|
}
|
|
101809
103365
|
async function listMeshes() {
|
|
101810
|
-
const r = await
|
|
103366
|
+
const r = await call2("/meshes", { method: "GET" });
|
|
101811
103367
|
return r.ok ? { ok: true, meshes: r.data } : r;
|
|
101812
103368
|
}
|
|
101813
103369
|
async function deleteMesh(args) {
|
|
101814
|
-
const r = await
|
|
103370
|
+
const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}?confirm=${encodeURIComponent(args.confirm)}`, { method: "DELETE" });
|
|
101815
103371
|
return r.ok ? { ok: true, deleted: r.data.deleted } : r;
|
|
101816
103372
|
}
|
|
101817
103373
|
async function createMesh(args = {}) {
|
|
101818
|
-
const r = await
|
|
103374
|
+
const r = await call2("/meshes", {
|
|
101819
103375
|
method: "POST",
|
|
101820
103376
|
body: {
|
|
101821
103377
|
...args.name ? { name: args.name } : {},
|
|
101822
103378
|
...args.cidr ? { meshCidr4: args.cidr } : {},
|
|
101823
103379
|
...args.approvalMode ? { approvalMode: args.approvalMode } : {},
|
|
101824
103380
|
...args.allowExitNode !== void 0 ? { allowExitNode: args.allowExitNode } : {},
|
|
103381
|
+
...args.fullTunnelDefault !== void 0 ? { fullTunnelDefault: args.fullTunnelDefault } : {},
|
|
101825
103382
|
...args.allowRelay !== void 0 ? { allowRelay: args.allowRelay } : {},
|
|
101826
103383
|
...args.magicDns !== void 0 ? { magicDns: args.magicDns } : {}
|
|
101827
103384
|
}
|
|
@@ -101829,42 +103386,42 @@ async function createMesh(args = {}) {
|
|
|
101829
103386
|
return r.ok ? { ok: true, ...r.data } : r;
|
|
101830
103387
|
}
|
|
101831
103388
|
async function joinToken(args) {
|
|
101832
|
-
const r = await
|
|
103389
|
+
const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/token`, { method: "GET" });
|
|
101833
103390
|
return r.ok ? { ok: true, token: r.data.token } : r;
|
|
101834
103391
|
}
|
|
101835
103392
|
async function rotateJoinToken(args) {
|
|
101836
|
-
const r = await
|
|
103393
|
+
const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/token/rotate`, { method: "POST", body: {} });
|
|
101837
103394
|
return r.ok ? { ok: true, token: r.data.token } : r;
|
|
101838
103395
|
}
|
|
101839
103396
|
async function approveNode(args) {
|
|
101840
|
-
const r = await
|
|
103397
|
+
const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/nodes/${encodeURIComponent(args.nodeId)}/approve`, { method: "POST", body: {} });
|
|
101841
103398
|
return r.ok ? { ok: true, epoch: r.data.epoch } : r;
|
|
101842
103399
|
}
|
|
101843
103400
|
async function newJoinCode(args) {
|
|
101844
|
-
const r = await
|
|
103401
|
+
const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/codes`, { method: "POST", body: { uses: args.uses, ttlMinutes: args.ttlMinutes } });
|
|
101845
103402
|
return r.ok ? { ok: true, ...r.data } : r;
|
|
101846
103403
|
}
|
|
101847
103404
|
async function evictNode(args) {
|
|
101848
|
-
const r = await
|
|
103405
|
+
const r = await call2(`/meshes/${encodeURIComponent(args.meshId)}/nodes/${encodeURIComponent(args.nodeId)}`, { method: "DELETE", body: {} });
|
|
101849
103406
|
return r.ok ? { ok: true, epoch: r.data.epoch } : r;
|
|
101850
103407
|
}
|
|
101851
103408
|
async function enrolWith(requested, post) {
|
|
101852
103409
|
const name = normaliseNodeName(requested);
|
|
101853
103410
|
if (!name) {
|
|
101854
|
-
return
|
|
103411
|
+
return fail3("bad-name", `"${requested}" cannot be a machine name \u2014 names are DNS labels, so letters, digits and hyphens only`);
|
|
101855
103412
|
}
|
|
101856
103413
|
const stat9 = await generateStaticKey();
|
|
101857
103414
|
const sig = await generateSigningKey();
|
|
101858
103415
|
const staticPrivate = await rawPrivate(stat9.privateKey);
|
|
101859
103416
|
const sigPrivate = await rawPrivate(sig.privateKey);
|
|
101860
|
-
const r = await post(
|
|
103417
|
+
const r = await post(hex5(stat9.publicRaw), hex5(sig.publicRaw), name);
|
|
101861
103418
|
if (!r.ok)
|
|
101862
103419
|
return r;
|
|
101863
103420
|
const cert = fromHexOrB64(r.data.cert);
|
|
101864
103421
|
const genesis = fromHexOrB64(r.data.genesis);
|
|
101865
103422
|
const meshId = meshIdOf(cert);
|
|
101866
103423
|
if (!meshId)
|
|
101867
|
-
return
|
|
103424
|
+
return fail3("server", "the certificate the server returned is unreadable");
|
|
101868
103425
|
let issuedName = name;
|
|
101869
103426
|
try {
|
|
101870
103427
|
issuedName = decodeCert(cert).details.name || name;
|
|
@@ -101873,8 +103430,14 @@ async function enrolWith(requested, post) {
|
|
|
101873
103430
|
try {
|
|
101874
103431
|
saveMesh(meshId, { genesis, cert, staticPrivate, sigPrivate });
|
|
101875
103432
|
writeLocal(meshId, { joinedAt: Date.now(), enabled: true });
|
|
103433
|
+
if (r.data.bundle) {
|
|
103434
|
+
try {
|
|
103435
|
+
cacheBundle(fromHexOrB64(r.data.bundle), meshId);
|
|
103436
|
+
} catch {
|
|
103437
|
+
}
|
|
103438
|
+
}
|
|
101876
103439
|
} catch (e) {
|
|
101877
|
-
return
|
|
103440
|
+
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.`);
|
|
101878
103441
|
}
|
|
101879
103442
|
return {
|
|
101880
103443
|
ok: true,
|
|
@@ -101888,9 +103451,9 @@ async function enrolWith(requested, post) {
|
|
|
101888
103451
|
};
|
|
101889
103452
|
}
|
|
101890
103453
|
async function enrol(args) {
|
|
101891
|
-
return enrolWith(args.name, (staticPub, sigPub, name) =>
|
|
103454
|
+
return enrolWith(args.name, (staticPub, sigPub, name) => call2(`/meshes/${encodeURIComponent(args.meshId)}/nodes`, {
|
|
101892
103455
|
method: "POST",
|
|
101893
|
-
body: { name, staticPub, sigPub }
|
|
103456
|
+
body: { name, staticPub, sigPub, ...args.exitNode === true ? { exitNode: true } : {} }
|
|
101894
103457
|
}));
|
|
101895
103458
|
}
|
|
101896
103459
|
async function joinWithToken(args) {
|
|
@@ -101899,7 +103462,7 @@ async function joinWithToken(args) {
|
|
|
101899
103462
|
async function postJoin(origin, body) {
|
|
101900
103463
|
const base = origin ?? readCredentials()?.apiOrigin;
|
|
101901
103464
|
if (!base) {
|
|
101902
|
-
return
|
|
103465
|
+
return fail3("not-signed-in", "this machine has never signed in \u2014 pass --origin https://\u2026 so it knows which server to ask");
|
|
101903
103466
|
}
|
|
101904
103467
|
let res;
|
|
101905
103468
|
try {
|
|
@@ -101909,7 +103472,7 @@ async function postJoin(origin, body) {
|
|
|
101909
103472
|
body: JSON.stringify(body)
|
|
101910
103473
|
});
|
|
101911
103474
|
} catch (e) {
|
|
101912
|
-
return
|
|
103475
|
+
return fail3("network", e instanceof Error ? e.message : String(e));
|
|
101913
103476
|
}
|
|
101914
103477
|
const text9 = await res.text();
|
|
101915
103478
|
if (!res.ok) {
|
|
@@ -101920,7 +103483,7 @@ async function postJoin(origin, body) {
|
|
|
101920
103483
|
detail = String(parsed.message);
|
|
101921
103484
|
} catch {
|
|
101922
103485
|
}
|
|
101923
|
-
return
|
|
103486
|
+
return fail3(res.status >= 500 ? "server" : "refused", detail);
|
|
101924
103487
|
}
|
|
101925
103488
|
return { ok: true, data: JSON.parse(text9) };
|
|
101926
103489
|
}
|
|
@@ -101934,7 +103497,7 @@ async function rawPrivate(key2) {
|
|
|
101934
103497
|
}
|
|
101935
103498
|
return pkcs8.subarray(16);
|
|
101936
103499
|
}
|
|
101937
|
-
function
|
|
103500
|
+
function hex5(b) {
|
|
101938
103501
|
return Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
101939
103502
|
}
|
|
101940
103503
|
function fromHexOrB64(s) {
|
|
@@ -101950,8 +103513,63 @@ function meshIdOf(cert) {
|
|
|
101950
103513
|
return meshDirNameFromWireId(Array.from(cert.subarray(OFFSET, OFFSET + 32), (b) => b.toString(16).padStart(2, "0")).join(""));
|
|
101951
103514
|
}
|
|
101952
103515
|
|
|
101953
|
-
// ../../packages/host-core/dist/mesh/
|
|
101954
|
-
|
|
103516
|
+
// ../../packages/host-core/dist/mesh/full-tunnel.js
|
|
103517
|
+
function fullTunnelState(i) {
|
|
103518
|
+
const no2 = (reason) => ({ allowed: false, reason, warnings: [] });
|
|
103519
|
+
if (i.platform !== "linux") {
|
|
103520
|
+
const name = i.platform === "darwin" ? "macOS" : i.platform === "win32" ? "Windows" : i.platform;
|
|
103521
|
+
return no2(`Routing all traffic needs the network helper, which does not exist on ${name} yet.`);
|
|
103522
|
+
}
|
|
103523
|
+
if (!i.engineAvailable) {
|
|
103524
|
+
return no2("This build shipped without the network engine, so no traffic can be routed. That is a packaging fault \u2014 please report it.");
|
|
103525
|
+
}
|
|
103526
|
+
if (i.helperCode === "wire-version") {
|
|
103527
|
+
return no2("Update the network helper \u2014 this build speaks a newer protocol than the one installed.");
|
|
103528
|
+
}
|
|
103529
|
+
if (!i.helperAvailable) {
|
|
103530
|
+
return no2("Turn this network on to install the network helper \u2014 nothing can be routed until it is there.");
|
|
103531
|
+
}
|
|
103532
|
+
if (!i.hasBundle) {
|
|
103533
|
+
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.");
|
|
103534
|
+
}
|
|
103535
|
+
if (!i.networkAllows) {
|
|
103536
|
+
return no2("This network does not allow routing all traffic through it. An admin of the network chooses that.");
|
|
103537
|
+
}
|
|
103538
|
+
if (i.selfIsExitNode) {
|
|
103539
|
+
return no2("This machine is this network\u2019s way out to the internet, so it cannot route its own traffic through itself.");
|
|
103540
|
+
}
|
|
103541
|
+
if (i.exitNodes.length === 0) {
|
|
103542
|
+
return no2("No machine on this network offers to be the way out yet, so there is nowhere for the traffic to go.");
|
|
103543
|
+
}
|
|
103544
|
+
if (i.claimedBy) {
|
|
103545
|
+
return no2(`All traffic already goes through ${i.claimedBy}. A machine has one default route, so only one network can claim it.`);
|
|
103546
|
+
}
|
|
103547
|
+
if (!i.ownsNode) {
|
|
103548
|
+
return no2("The Tesseract app is running this network on this machine. Change this from there.");
|
|
103549
|
+
}
|
|
103550
|
+
if (i.pathToExit === "none") {
|
|
103551
|
+
return no2(`Waiting for a connection to ${i.exitNodes[0]}. All traffic cannot be routed until this machine can reach it.`);
|
|
103552
|
+
}
|
|
103553
|
+
const warnings = [];
|
|
103554
|
+
if (i.pathToExit === "relay") {
|
|
103555
|
+
warnings.push(`All traffic will go through ${i.exitNodes[0]} by way of a relay, so it will be slower than usual.`);
|
|
103556
|
+
}
|
|
103557
|
+
return { allowed: true, reason: null, warnings };
|
|
103558
|
+
}
|
|
103559
|
+
function bundleGrantsExitNode(bundle) {
|
|
103560
|
+
if (bundle === void 0 || bundle.length === 0)
|
|
103561
|
+
return false;
|
|
103562
|
+
try {
|
|
103563
|
+
const pki = (init_dist6(), __toCommonJS(dist_exports3));
|
|
103564
|
+
const decoded = pki.decodeSignedBundle(bundle);
|
|
103565
|
+
return decoded.bundle.rules.some((r) => (r.caps & pki.CAP_EXIT_NODE) !== 0);
|
|
103566
|
+
} catch {
|
|
103567
|
+
return false;
|
|
103568
|
+
}
|
|
103569
|
+
}
|
|
103570
|
+
|
|
103571
|
+
// ../../packages/host-core/dist/mesh/machine-owner.js
|
|
103572
|
+
init_credentials();
|
|
101955
103573
|
|
|
101956
103574
|
// ../../packages/host-core/dist/service/exec.js
|
|
101957
103575
|
import { execFile as execFile10, spawn as spawn14 } from "node:child_process";
|
|
@@ -101969,9 +103587,6 @@ function runInherit(cmd, args) {
|
|
|
101969
103587
|
var UNIT = "tesseract-netd.service";
|
|
101970
103588
|
var UNIT_PATH = `/etc/systemd/system/${UNIT}`;
|
|
101971
103589
|
|
|
101972
|
-
// ../../packages/host-core/dist/mesh/machine-owner.js
|
|
101973
|
-
init_credentials();
|
|
101974
|
-
|
|
101975
103590
|
// ../../packages/host-core/dist/clipboard/clipboard-sync.js
|
|
101976
103591
|
var MAX_IMAGE_BYTES3 = 10 * 1024 * 1024;
|
|
101977
103592
|
var OVERSIZED_BYTES = 512 * 1024;
|
|
@@ -101985,7 +103600,7 @@ init_daemon_settings();
|
|
|
101985
103600
|
init_credentials();
|
|
101986
103601
|
|
|
101987
103602
|
// ../../packages/host-core/dist/service/index.js
|
|
101988
|
-
import { platform as
|
|
103603
|
+
import { platform as platform6 } from "node:os";
|
|
101989
103604
|
|
|
101990
103605
|
// ../../packages/host-core/dist/service/launchd.js
|
|
101991
103606
|
init_credentials();
|
|
@@ -102265,7 +103880,7 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
102265
103880
|
// ../../packages/host-core/dist/service/index.js
|
|
102266
103881
|
function getServiceController(instanceId) {
|
|
102267
103882
|
const id = instanceId && instanceId.length ? instanceId : void 0;
|
|
102268
|
-
switch (
|
|
103883
|
+
switch (platform6()) {
|
|
102269
103884
|
case "darwin":
|
|
102270
103885
|
return makeLaunchd(id);
|
|
102271
103886
|
case "linux":
|
|
@@ -102523,12 +104138,12 @@ function isReleaseVersion(v) {
|
|
|
102523
104138
|
return /^\d+\.\d+\.\d+/.test(v.trim());
|
|
102524
104139
|
}
|
|
102525
104140
|
function isNewer(latest, current) {
|
|
102526
|
-
const
|
|
104141
|
+
const parse4 = (v) => {
|
|
102527
104142
|
const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(v.trim());
|
|
102528
104143
|
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
102529
104144
|
};
|
|
102530
|
-
const a =
|
|
102531
|
-
const b =
|
|
104145
|
+
const a = parse4(latest);
|
|
104146
|
+
const b = parse4(current);
|
|
102532
104147
|
if (!a || !b) return false;
|
|
102533
104148
|
for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] > b[i];
|
|
102534
104149
|
return false;
|
|
@@ -102646,12 +104261,12 @@ function startSelfUpdater(current) {
|
|
|
102646
104261
|
|
|
102647
104262
|
// src/service.ts
|
|
102648
104263
|
import { join as join75 } from "node:path";
|
|
102649
|
-
import { platform as
|
|
104264
|
+
import { platform as platform7 } from "node:os";
|
|
102650
104265
|
import { existsSync as existsSync40, readFileSync as readFileSync46 } from "node:fs";
|
|
102651
104266
|
function controller(instanceId) {
|
|
102652
104267
|
const c = getServiceController(instanceId);
|
|
102653
104268
|
if (!c) {
|
|
102654
|
-
throw new Error(`tesseract-agent can't manage a background service on ${
|
|
104269
|
+
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).`);
|
|
102655
104270
|
}
|
|
102656
104271
|
return c;
|
|
102657
104272
|
}
|
|
@@ -102732,7 +104347,9 @@ Running a network (needs a signed-in account):
|
|
|
102732
104347
|
tesseract-agent net new [NAME] Create a network and print its join token.
|
|
102733
104348
|
[--approve auto|admin] who may join: the token alone, or you say yes
|
|
102734
104349
|
[--cidr A.B.C.D/L] address range (default 100.96.0.0/12)
|
|
102735
|
-
[--exit-node]
|
|
104350
|
+
[--exit-node] let machines route ALL traffic through it
|
|
104351
|
+
[--full-tunnel-default] ...and start new machines that way (needs --exit-node)
|
|
104352
|
+
[--no-relay] [--no-dns] everything is optional and has a default
|
|
102736
104353
|
tesseract-agent net networks [--json] List your networks and their machines
|
|
102737
104354
|
tesseract-agent net token MESH [--rotate] Show the join token again, or replace it
|
|
102738
104355
|
tesseract-agent net approve MESH NODE Let a waiting machine on
|
|
@@ -102741,8 +104358,13 @@ Running a network (needs a signed-in account):
|
|
|
102741
104358
|
Delete a network for good. Irreversible.
|
|
102742
104359
|
tesseract-agent net code new MESH [--uses N] [--ttl MIN] [--json]
|
|
102743
104360
|
A ONE-SHOT code, for anyone who wants one
|
|
102744
|
-
tesseract-agent net
|
|
104361
|
+
tesseract-agent net route-all [MESH] [--off]
|
|
104362
|
+
Route ALL of this machine's traffic through a
|
|
104363
|
+
network (the classic-VPN posture), or stop
|
|
104364
|
+
tesseract-agent net join-me MESH [--name N] [--exit-node]
|
|
102745
104365
|
Join THIS machine to a network you run
|
|
104366
|
+
--exit-node offers this machine as everyone's
|
|
104367
|
+
way out to the internet (the network must allow it)
|
|
102746
104368
|
|
|
102747
104369
|
Admin (needs the mesh CA, not a node):
|
|
102748
104370
|
tesseract-agent net init --org NAME [--ca-dir DIR]
|
|
@@ -102898,7 +104520,7 @@ async function netCommand(rest, flags) {
|
|
|
102898
104520
|
console.error(`net ${sub}: not enrolled in ${meshId}`);
|
|
102899
104521
|
process.exit(1);
|
|
102900
104522
|
}
|
|
102901
|
-
|
|
104523
|
+
updateLocal(meshId, { enabled: sub === "up" });
|
|
102902
104524
|
console.log(`${meshId} ${sub === "up" ? "enabled" : "disabled"}`);
|
|
102903
104525
|
}
|
|
102904
104526
|
console.log("Run `tesseract-agent restart` for this to take effect now.");
|
|
@@ -103008,11 +104630,22 @@ async function netCommand(rest, flags) {
|
|
|
103008
104630
|
console.error("net new: --approve must be 'auto' or 'admin'");
|
|
103009
104631
|
process.exit(1);
|
|
103010
104632
|
}
|
|
104633
|
+
if (flags["full-tunnel-default"] === true && flags["exit-node"] !== true) {
|
|
104634
|
+
console.error(
|
|
104635
|
+
"net new: --full-tunnel-default needs --exit-node \u2014 the first is a default, the second is the permission it depends on"
|
|
104636
|
+
);
|
|
104637
|
+
process.exit(1);
|
|
104638
|
+
}
|
|
103011
104639
|
const r = await createMesh({
|
|
103012
104640
|
...name ? { name } : {},
|
|
103013
104641
|
...str2(flags.cidr) ? { cidr: str2(flags.cidr) } : {},
|
|
103014
104642
|
...approve ? { approvalMode: approve } : {},
|
|
103015
104643
|
...flags["exit-node"] === true ? { allowExitNode: true } : {},
|
|
104644
|
+
// The DEFAULT half. Clamped to the permission server-side, but refuse it here too
|
|
104645
|
+
// rather than sending a combination that can never take effect — an operator who
|
|
104646
|
+
// typed only --full-tunnel-default has misunderstood which flag does what, and a
|
|
104647
|
+
// silent clamp would let them keep believing it.
|
|
104648
|
+
...flags["full-tunnel-default"] === true ? { fullTunnelDefault: true } : {},
|
|
103016
104649
|
...flags["no-relay"] === true ? { allowRelay: false } : {},
|
|
103017
104650
|
...flags["no-dns"] === true ? { magicDns: false } : {}
|
|
103018
104651
|
});
|
|
@@ -103129,7 +104762,11 @@ async function netCommand(rest, flags) {
|
|
|
103129
104762
|
console.error("net join-me: that name cannot be used \u2014 letters, digits and hyphens only");
|
|
103130
104763
|
process.exit(1);
|
|
103131
104764
|
}
|
|
103132
|
-
const r = await enrol({
|
|
104765
|
+
const r = await enrol({
|
|
104766
|
+
meshId,
|
|
104767
|
+
name: nm,
|
|
104768
|
+
...flags["exit-node"] === true ? { exitNode: true } : {}
|
|
104769
|
+
});
|
|
103133
104770
|
if (!r.ok) {
|
|
103134
104771
|
console.error(`net join-me: ${r.detail}`);
|
|
103135
104772
|
process.exit(1);
|
|
@@ -103138,6 +104775,48 @@ async function netCommand(rest, flags) {
|
|
|
103138
104775
|
if (r.name !== nm) console.log(`(another machine here is already called "${nm}")`);
|
|
103139
104776
|
return;
|
|
103140
104777
|
}
|
|
104778
|
+
if (sub === "route-all") {
|
|
104779
|
+
const ids = listMeshIds();
|
|
104780
|
+
const target = rest[1] ?? str2(flags.mesh);
|
|
104781
|
+
const off = flags.off === true;
|
|
104782
|
+
if (!ids.length) {
|
|
104783
|
+
console.error("net route-all: this machine is not in any network");
|
|
104784
|
+
process.exit(1);
|
|
104785
|
+
}
|
|
104786
|
+
if (!target && ids.length > 1) {
|
|
104787
|
+
console.error("net route-all: name a network \u2014 this machine is in several");
|
|
104788
|
+
for (const meshId2 of ids) console.error(` ${meshId2}`);
|
|
104789
|
+
process.exit(1);
|
|
104790
|
+
}
|
|
104791
|
+
const meshId = target ?? ids[0];
|
|
104792
|
+
if (!ids.includes(meshId)) {
|
|
104793
|
+
console.error(`net route-all: not enrolled in ${meshId}`);
|
|
104794
|
+
process.exit(1);
|
|
104795
|
+
}
|
|
104796
|
+
const identity = loadMesh(meshId);
|
|
104797
|
+
const state3 = fullTunnelState({
|
|
104798
|
+
platform: process.platform,
|
|
104799
|
+
helperAvailable: await netdAvailable(),
|
|
104800
|
+
helperCode: null,
|
|
104801
|
+
engineAvailable: meshEngineStatus().available,
|
|
104802
|
+
hasBundle: identity?.bundle !== void 0 && identity.bundle.length > 0,
|
|
104803
|
+
networkAllows: bundleGrantsExitNode(identity?.bundle),
|
|
104804
|
+
exitNodes: [],
|
|
104805
|
+
selfIsExitNode: false,
|
|
104806
|
+
pathToExit: "none",
|
|
104807
|
+
claimedBy: ids.find((id) => id !== meshId && readLocal(id)?.fullTunnel === true) ?? null,
|
|
104808
|
+
ownsNode: true
|
|
104809
|
+
});
|
|
104810
|
+
if (!off && !state3.allowed) {
|
|
104811
|
+
console.error(`net route-all: ${state3.reason}`);
|
|
104812
|
+
process.exit(1);
|
|
104813
|
+
}
|
|
104814
|
+
updateLocal(meshId, { fullTunnel: !off });
|
|
104815
|
+
console.log(off ? `${meshId} all traffic no longer routed through this network` : `${meshId} ALL traffic from this machine will go through this network`);
|
|
104816
|
+
for (const w of state3.warnings) console.log(` ${w}`);
|
|
104817
|
+
console.log("Run `tesseract-agent restart` for this to take effect now.");
|
|
104818
|
+
return;
|
|
104819
|
+
}
|
|
103141
104820
|
if (sub === "peers") {
|
|
103142
104821
|
const s = readStatus();
|
|
103143
104822
|
if (!s || s.stale) {
|