@openclaw/gateway-client 2026.8.1-beta.2 → 2026.8.1

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/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { C as resolveGatewayConnectScopes, D as buildDeviceAuthPayloadV3, E as buildDeviceAuthPayload, O as normalizeDeviceMetadataForAuth, S as buildGatewayConnectAuth, T as shouldRetryGatewayWithDeviceToken, _ as GatewayProtocolRequestError, a as createSessionProjection, b as gatewayOriginScope, c as normalizeSessionProjectionRunId, d as readSessionMessageSequence, f as reconcileSessionProjectionSnapshot, g as GatewayProtocolClient, h as shouldPauseGatewayReconnect, i as resetGatewaySessionMessageSubscriptionCoordinator, l as projectLiveSessionMessage, m as reduceSessionProjectionRunEvent, n as getGatewaySessionMessageSubscriptionCoordinator, o as hasSessionProjectionAcceptedFinal, p as reduceSessionProjection, r as releaseGatewaySessionMessageSubscription, s as isLocallyOptimisticSessionMessage, t as GatewaySessionMessageSubscriptionCoordinator, u as readSessionMessageIdentity, v as GatewayProtocolRequestTimeoutError, w as selectGatewayConnectAuth, x as GatewayBrowserDeviceAuthLifecycle, y as gatewayCredentialScope } from "./session-subscriptions-uKmTyc3P.mjs";
1
+ import { C as buildGatewayConnectAuth, D as buildDeviceAuthPayload, E as shouldRetryGatewayWithDeviceToken, O as buildDeviceAuthPayloadV3, S as GatewayBrowserDeviceAuthLifecycle, T as selectGatewayConnectAuth, _ as GatewayProtocolClient, a as createSessionProjection, b as gatewayCredentialScope, c as projectLiveSessionMessage, d as reduceSessionProjectionRunEvent, f as normalizeSessionProjectionRunId, g as shouldPauseGatewayReconnect, h as isRecord, i as resetGatewaySessionMessageSubscriptionCoordinator, k as normalizeDeviceMetadataForAuth, l as reconcileSessionProjectionSnapshot, m as readSessionMessageSequence, n as getGatewaySessionMessageSubscriptionCoordinator, o as hasSessionProjectionAcceptedFinal, p as readSessionMessageIdentity, r as releaseGatewaySessionMessageSubscription, s as isLocallyOptimisticSessionMessage, t as GatewaySessionMessageSubscriptionCoordinator, u as reduceSessionProjection, v as GatewayProtocolRequestError, w as resolveGatewayConnectScopes, x as gatewayOriginScope, y as GatewayProtocolRequestTimeoutError } from "./session-subscriptions-BxuNBgqH.mjs";
2
2
  import { DEFAULT_GATEWAY_REQUEST_TIMEOUT_MS, DEFAULT_PREAUTH_HANDSHAKE_TIMEOUT_MS, MAX_CONNECT_CHALLENGE_TIMEOUT_MS, MAX_SAFE_TIMEOUT_DELAY_MS, MIN_CONNECT_CHALLENGE_TIMEOUT_MS, addSafeTimeoutDelayGraceMs, clampConnectChallengeTimeoutMs, clearGatewayConnectTimeout, getConnectChallengeTimeoutMsFromEnv, resolveConnectChallengeTimeoutMs, resolveFiniteTimeoutDelayMs, resolvePreauthHandshakeTimeoutMs, resolveSafeTimeoutDelayMs, startGatewayConnectTimeout } from "./timeouts.mjs";
3
3
  import { rawDataToString } from "./websocket-data.mjs";
4
4
  import { n as startGatewayClientWithReadinessWait, r as waitForEventLoopReady, t as startGatewayClientWhenEventLoopReady } from "./readiness-CrWxd4TI.mjs";
@@ -9,29 +9,8 @@ import { resolveGatewayStartupRetryAfterMs } from "@openclaw/gateway-protocol/st
9
9
  import { MIN_CLIENT_PROTOCOL_VERSION, MIN_NODE_PROTOCOL_VERSION, MIN_PROBE_PROTOCOL_VERSION, PROTOCOL_VERSION } from "@openclaw/gateway-protocol/version";
10
10
  import { randomUUID } from "node:crypto";
11
11
  import { WebSocket } from "ws";
12
- //#region \0rolldown/runtime.js
13
- var __create = Object.create;
14
- var __defProp = Object.defineProperty;
15
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
16
- var __getOwnPropNames = Object.getOwnPropertyNames;
17
- var __getProtoOf = Object.getPrototypeOf;
18
- var __hasOwnProp = Object.prototype.hasOwnProperty;
19
- var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
20
- var __copyProps = (to, from, except, desc) => {
21
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
22
- key = keys[i];
23
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
24
- get: ((k) => from[k]).bind(null, key),
25
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
26
- });
27
- }
28
- return to;
29
- };
30
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
31
- value: mod,
32
- enumerable: true
33
- }) : target, mod));
34
- //#endregion
12
+ import ipaddr from "ipaddr.js";
13
+ import { TLSSocket } from "node:tls";
35
14
  //#region packages/normalization-core/src/string-coerce.ts
36
15
  /** Trims string input and returns null for non-strings or empty strings. */
37
16
  function normalizeNullableString(value) {
@@ -52,966 +31,315 @@ function normalizeLowercaseStringOrEmpty(value) {
52
31
  return normalizeOptionalLowercaseString(value) ?? "";
53
32
  }
54
33
  //#endregion
55
- //#region packages/net-policy/src/ip.ts
56
- var import_ipaddr = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
57
- (function(root) {
58
- "use strict";
59
- const ipv4Part = "(0?\\d+|0x[a-f0-9]+)";
60
- const ipv4Regexes = {
61
- fourOctet: new RegExp(`^${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}$`, "i"),
62
- threeOctet: new RegExp(`^${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}$`, "i"),
63
- twoOctet: new RegExp(`^${ipv4Part}\\.${ipv4Part}$`, "i"),
64
- longValue: new RegExp(`^${ipv4Part}$`, "i")
65
- };
66
- const octalRegex = new RegExp(`^0[0-7]+$`, "i");
67
- const hexRegex = new RegExp(`^0x[a-f0-9]+$`, "i");
68
- const zoneIndex = "%[0-9a-z]{1,}";
69
- const ipv6Part = "(?:[0-9a-f]+::?)+";
70
- const ipv6Regexes = {
71
- zoneIndex: new RegExp(zoneIndex, "i"),
72
- "native": new RegExp(`^(::)?(${ipv6Part})?([0-9a-f]+)?(::)?(${zoneIndex})?$`, "i"),
73
- deprecatedTransitional: new RegExp(`^(?:::)(${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}(${zoneIndex})?)$`, "i"),
74
- transitional: new RegExp(`^((?:${ipv6Part})|(?:::)(?:${ipv6Part})?)${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}(${zoneIndex})?$`, "i")
75
- };
76
- function expandIPv6(string, parts) {
77
- if (string.indexOf("::") !== string.lastIndexOf("::")) return null;
78
- let colonCount = 0;
79
- let lastColon = -1;
80
- let zoneId = (string.match(ipv6Regexes.zoneIndex) || [])[0];
81
- let replacement, replacementCount;
82
- if (zoneId) {
83
- zoneId = zoneId.substring(1);
84
- string = string.replace(/%.+$/, "");
85
- }
86
- while ((lastColon = string.indexOf(":", lastColon + 1)) >= 0) colonCount++;
87
- if (string.substr(0, 2) === "::") colonCount--;
88
- if (string.substr(-2, 2) === "::") colonCount--;
89
- if (colonCount > parts) return null;
90
- replacementCount = parts - colonCount;
91
- replacement = ":";
92
- while (replacementCount--) replacement += "0:";
93
- string = string.replace("::", replacement);
94
- if (string[0] === ":") string = string.slice(1);
95
- if (string[string.length - 1] === ":") string = string.slice(0, -1);
96
- parts = (function() {
97
- const ref = string.split(":");
98
- const results = [];
99
- for (let i = 0; i < ref.length; i++) results.push(parseInt(ref[i], 16));
100
- return results;
101
- })();
34
+ //#region packages/net-policy/src/redact-sensitive-url.ts
35
+ const SENSITIVE_URL_QUERY_PARAM_NAMES = /* @__PURE__ */ new Set([
36
+ "token",
37
+ "key",
38
+ "api_key",
39
+ "apikey",
40
+ "secret",
41
+ "access_token",
42
+ "auth_token",
43
+ "password",
44
+ "pass",
45
+ "passwd",
46
+ "auth",
47
+ "jwt",
48
+ "session",
49
+ "id_token",
50
+ "code",
51
+ "client_secret",
52
+ "app_secret",
53
+ "hook_token",
54
+ "refresh_token",
55
+ "signature",
56
+ "x_amz_signature",
57
+ "x_amz_security_token",
58
+ "private_key",
59
+ "credential",
60
+ "authorization",
61
+ "sig",
62
+ "x_api_key",
63
+ "x_access_token",
64
+ "x_auth_token"
65
+ ]);
66
+ const URL_QUERY_NAME_SEPARATOR_RE = /[\p{C}\p{Z}\u115F\u1160\u3164\uFFA0+]/gu;
67
+ const SUFFIXED_OR_SCOPED_TOKEN_QUERY_PARAM_RE = /(?:^|_)token(?:_[a-f0-9]{16,})?$/u;
68
+ const TELEGRAM_BOT_TOKEN_PATH_RE = /\/bot\d{6,}(?::|%3[aA])[A-Za-z0-9_-]{20,}(?=\/|$)/giu;
69
+ const MAX_NESTED_URL_REDACTION_DEPTH = 8;
70
+ const URL_SCHEME_RE = /(?:^|[^a-z\d+.-])[a-z][a-z\d+.-]{0,31}:/iu;
71
+ const SPECIAL_SCHEME_AUTHORITY_RE = /\b(?:https?|wss?|ftp):[\\/]{0,2}[^\\/?#\s]*/giu;
72
+ const SPECIAL_SCHEME_SPILLED_USERINFO_RE = /\b(?:https?|wss?|ftp):[\\/]{0,2}[^\s]*@[^\\/?#\s]*/giu;
73
+ const PROTOCOL_RELATIVE_AUTHORITY_RE = /[\\/]{2,}[^\\/?#\s]*/gu;
74
+ function redactSensitiveUrlPath(value) {
75
+ return value.replace(TELEGRAM_BOT_TOKEN_PATH_RE, "/bot***");
76
+ }
77
+ function normalizeUrlQueryParamName(name) {
78
+ let current = name.replace(URL_QUERY_NAME_SEPARATOR_RE, "");
79
+ for (let depth = 0; depth <= MAX_NESTED_URL_REDACTION_DEPTH; depth += 1) {
80
+ let decoded;
81
+ try {
82
+ decoded = decodeURIComponent(current).replace(URL_QUERY_NAME_SEPARATOR_RE, "");
83
+ } catch {
102
84
  return {
103
- parts,
104
- zoneId
85
+ value: normalizeLowercaseStringOrEmpty(current).replaceAll("-", "_"),
86
+ unresolvedEncoding: current.includes("%")
105
87
  };
106
88
  }
107
- function matchCIDR(first, second, partSize, cidrBits) {
108
- if (first.length !== second.length) throw new Error("ipaddr: cannot match CIDR for objects with different lengths");
109
- let part = 0;
110
- let shift;
111
- while (cidrBits > 0) {
112
- shift = partSize - cidrBits;
113
- if (shift < 0) shift = 0;
114
- if (first[part] >> shift !== second[part] >> shift) return false;
115
- cidrBits -= partSize;
116
- part += 1;
117
- }
118
- return true;
89
+ if (decoded === current) return {
90
+ value: normalizeLowercaseStringOrEmpty(current).replaceAll("-", "_"),
91
+ unresolvedEncoding: false
92
+ };
93
+ current = decoded;
94
+ }
95
+ return {
96
+ value: normalizeLowercaseStringOrEmpty(current).replaceAll("-", "_"),
97
+ unresolvedEncoding: current.includes("%")
98
+ };
99
+ }
100
+ function looksLikeNestedUrlValue(value) {
101
+ if (URL_SCHEME_RE.test(value)) return true;
102
+ const forwardAuthorityIndex = value.indexOf("//");
103
+ const backwardAuthorityIndex = value.indexOf("\\\\");
104
+ const authorityIndex = forwardAuthorityIndex < 0 ? backwardAuthorityIndex : backwardAuthorityIndex < 0 ? forwardAuthorityIndex : Math.min(forwardAuthorityIndex, backwardAuthorityIndex);
105
+ if (authorityIndex >= 0 && value.includes("@", authorityIndex + 2)) return true;
106
+ const queryIndex = value.search(/[?&]/u);
107
+ if (queryIndex >= 0 && value.includes("=", queryIndex + 1)) return true;
108
+ const fragmentIndex = value.indexOf("#");
109
+ if (fragmentIndex >= 0 && value.includes("=", fragmentIndex + 1)) return true;
110
+ return /%[\da-f]{2}/iu.test(value);
111
+ }
112
+ /** True for auth-like URL query parameter names that should be redacted. */
113
+ function isSensitiveUrlQueryParamName$1(name) {
114
+ const normalized = normalizeUrlQueryParamName(name);
115
+ return normalized.unresolvedEncoding || SENSITIVE_URL_QUERY_PARAM_NAMES.has(normalized.value) || SUFFIXED_OR_SCOPED_TOKEN_QUERY_PARAM_RE.test(normalized.value);
116
+ }
117
+ function redactDirectSensitiveUrl(value) {
118
+ try {
119
+ const parsed = new URL(value);
120
+ let mutated = false;
121
+ const redactedPath = redactSensitiveUrlPath(parsed.pathname);
122
+ if (redactedPath !== parsed.pathname) {
123
+ parsed.pathname = redactedPath;
124
+ mutated = true;
119
125
  }
120
- function parseIntAuto(string) {
121
- if (hexRegex.test(string)) return parseInt(string, 16);
122
- if (string[0] === "0" && !isNaN(parseInt(string[1], 10))) {
123
- if (octalRegex.test(string)) return parseInt(string, 8);
124
- throw new Error(`ipaddr: cannot parse ${string} as octal`);
125
- }
126
- return parseInt(string, 10);
126
+ if (parsed.username || parsed.password) {
127
+ parsed.username = parsed.username ? "***" : "";
128
+ parsed.password = parsed.password ? "***" : "";
129
+ mutated = true;
127
130
  }
128
- function padPart(part, length) {
129
- while (part.length < length) part = `0${part}`;
130
- return part;
131
+ for (const key of Array.from(parsed.searchParams.keys())) if (isSensitiveUrlQueryParamName$1(key)) {
132
+ parsed.searchParams.set(key, "***");
133
+ mutated = true;
131
134
  }
132
- const ipaddr = {};
133
- ipaddr.IPv4 = (function() {
134
- function IPv4(octets) {
135
- if (octets.length !== 4) throw new Error("ipaddr: ipv4 octet count should be 4");
136
- let i, octet;
137
- for (i = 0; i < octets.length; i++) {
138
- octet = octets[i];
139
- if (!(0 <= octet && octet <= 255)) throw new Error("ipaddr: ipv4 octet should fit in 8 bits");
140
- }
141
- this.octets = octets;
142
- }
143
- IPv4.prototype.SpecialRanges = {
144
- unspecified: [[new IPv4([
145
- 0,
146
- 0,
147
- 0,
148
- 0
149
- ]), 8]],
150
- broadcast: [[new IPv4([
151
- 255,
152
- 255,
153
- 255,
154
- 255
155
- ]), 32]],
156
- multicast: [[new IPv4([
157
- 224,
158
- 0,
159
- 0,
160
- 0
161
- ]), 4]],
162
- linkLocal: [[new IPv4([
163
- 169,
164
- 254,
165
- 0,
166
- 0
167
- ]), 16]],
168
- loopback: [[new IPv4([
169
- 127,
170
- 0,
171
- 0,
172
- 0
173
- ]), 8]],
174
- carrierGradeNat: [[new IPv4([
175
- 100,
176
- 64,
177
- 0,
178
- 0
179
- ]), 10]],
180
- "private": [
181
- [new IPv4([
182
- 10,
183
- 0,
184
- 0,
185
- 0
186
- ]), 8],
187
- [new IPv4([
188
- 172,
189
- 16,
190
- 0,
191
- 0
192
- ]), 12],
193
- [new IPv4([
194
- 192,
195
- 168,
196
- 0,
197
- 0
198
- ]), 16]
199
- ],
200
- reserved: [
201
- [new IPv4([
202
- 192,
203
- 0,
204
- 0,
205
- 0
206
- ]), 24],
207
- [new IPv4([
208
- 192,
209
- 0,
210
- 2,
211
- 0
212
- ]), 24],
213
- [new IPv4([
214
- 192,
215
- 88,
216
- 99,
217
- 0
218
- ]), 24],
219
- [new IPv4([
220
- 198,
221
- 18,
222
- 0,
223
- 0
224
- ]), 15],
225
- [new IPv4([
226
- 198,
227
- 51,
228
- 100,
229
- 0
230
- ]), 24],
231
- [new IPv4([
232
- 203,
233
- 0,
234
- 113,
235
- 0
236
- ]), 24],
237
- [new IPv4([
238
- 240,
239
- 0,
240
- 0,
241
- 0
242
- ]), 4]
243
- ],
244
- as112: [[new IPv4([
245
- 192,
246
- 175,
247
- 48,
248
- 0
249
- ]), 24], [new IPv4([
250
- 192,
251
- 31,
252
- 196,
253
- 0
254
- ]), 24]],
255
- amt: [[new IPv4([
256
- 192,
257
- 52,
258
- 193,
259
- 0
260
- ]), 24]]
261
- };
262
- IPv4.prototype.kind = function() {
263
- return "ipv4";
264
- };
265
- IPv4.prototype.match = function(other, cidrRange) {
266
- let ref;
267
- if (cidrRange === void 0) {
268
- ref = other;
269
- other = ref[0];
270
- cidrRange = ref[1];
271
- }
272
- if (other.kind() !== "ipv4") throw new Error("ipaddr: cannot match ipv4 address with non-ipv4 one");
273
- return matchCIDR(this.octets, other.octets, 8, cidrRange);
274
- };
275
- IPv4.prototype.prefixLengthFromSubnetMask = function() {
276
- let cidr = 0;
277
- let stop = false;
278
- const zerotable = {
279
- 0: 8,
280
- 128: 7,
281
- 192: 6,
282
- 224: 5,
283
- 240: 4,
284
- 248: 3,
285
- 252: 2,
286
- 254: 1,
287
- 255: 0
288
- };
289
- let i, octet, zeros;
290
- for (i = 3; i >= 0; i -= 1) {
291
- octet = this.octets[i];
292
- if (octet in zerotable) {
293
- zeros = zerotable[octet];
294
- if (stop && zeros !== 0) return null;
295
- if (zeros !== 8) stop = true;
296
- cidr += zeros;
297
- } else return null;
298
- }
299
- return 32 - cidr;
300
- };
301
- IPv4.prototype.range = function() {
302
- return ipaddr.subnetMatch(this, this.SpecialRanges);
303
- };
304
- IPv4.prototype.toByteArray = function() {
305
- return this.octets.slice(0);
306
- };
307
- IPv4.prototype.toIPv4MappedAddress = function() {
308
- return ipaddr.IPv6.parse(`::ffff:${this.toString()}`);
309
- };
310
- IPv4.prototype.toNormalizedString = function() {
311
- return this.toString();
312
- };
313
- IPv4.prototype.toString = function() {
314
- return this.octets.join(".");
315
- };
316
- return IPv4;
317
- })();
318
- ipaddr.IPv4.broadcastAddressFromCIDR = function(string) {
319
- try {
320
- const cidr = this.parseCIDR(string);
321
- const ipInterfaceOctets = cidr[0].toByteArray();
322
- const subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray();
323
- const octets = [];
324
- let i = 0;
325
- while (i < 4) {
326
- octets.push(parseInt(ipInterfaceOctets[i], 10) | parseInt(subnetMaskOctets[i], 10) ^ 255);
327
- i++;
328
- }
329
- return new this(octets);
330
- } catch (e) {
331
- throw new Error("ipaddr: the address does not have IPv4 CIDR format");
332
- }
333
- };
334
- ipaddr.IPv4.isIPv4 = function(string) {
335
- return this.parser(string) !== null;
336
- };
337
- ipaddr.IPv4.isValid = function(string) {
338
- try {
339
- new this(this.parser(string));
340
- return true;
341
- } catch (e) {
342
- return false;
343
- }
344
- };
345
- ipaddr.IPv4.isValidCIDR = function(string) {
346
- try {
347
- this.parseCIDR(string);
348
- return true;
349
- } catch (e) {
350
- return false;
351
- }
352
- };
353
- ipaddr.IPv4.isValidFourPartDecimal = function(string) {
354
- if (ipaddr.IPv4.isValid(string) && string.match(/^(0|[1-9]\d*)(\.(0|[1-9]\d*)){3}$/)) return true;
355
- else return false;
356
- };
357
- ipaddr.IPv4.isValidCIDRFourPartDecimal = function(string) {
358
- const match = string.match(/^(.+)\/(\d+)$/);
359
- if (!ipaddr.IPv4.isValidCIDR(string) || !match) return false;
360
- return ipaddr.IPv4.isValidFourPartDecimal(match[1]);
361
- };
362
- ipaddr.IPv4.networkAddressFromCIDR = function(string) {
363
- let cidr, i, ipInterfaceOctets, octets, subnetMaskOctets;
364
- try {
365
- cidr = this.parseCIDR(string);
366
- ipInterfaceOctets = cidr[0].toByteArray();
367
- subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray();
368
- octets = [];
369
- i = 0;
370
- while (i < 4) {
371
- octets.push(parseInt(ipInterfaceOctets[i], 10) & parseInt(subnetMaskOctets[i], 10));
372
- i++;
373
- }
374
- return new this(octets);
375
- } catch (e) {
376
- throw new Error("ipaddr: the address does not have IPv4 CIDR format");
377
- }
378
- };
379
- ipaddr.IPv4.parse = function(string) {
380
- const parts = this.parser(string);
381
- if (parts === null) throw new Error("ipaddr: string is not formatted like an IPv4 Address");
382
- return new this(parts);
383
- };
384
- ipaddr.IPv4.parseCIDR = function(string) {
385
- let match;
386
- if (match = string.match(/^(.+)\/(\d+)$/)) {
387
- const maskLength = parseInt(match[2]);
388
- if (maskLength >= 0 && maskLength <= 32) {
389
- const parsed = [this.parse(match[1]), maskLength];
390
- Object.defineProperty(parsed, "toString", { value: function() {
391
- return this.join("/");
392
- } });
393
- return parsed;
394
- }
395
- }
396
- throw new Error("ipaddr: string is not formatted like an IPv4 CIDR range");
397
- };
398
- ipaddr.IPv4.parser = function(string) {
399
- let match, part, value;
400
- if (match = string.match(ipv4Regexes.fourOctet)) return (function() {
401
- const ref = match.slice(1, 6);
402
- const results = [];
403
- for (let i = 0; i < ref.length; i++) {
404
- part = ref[i];
405
- results.push(parseIntAuto(part));
406
- }
407
- return results;
408
- })();
409
- else if (match = string.match(ipv4Regexes.longValue)) {
410
- value = parseIntAuto(match[1]);
411
- if (value > 4294967295 || value < 0) throw new Error("ipaddr: address outside defined range");
412
- return (function() {
413
- const results = [];
414
- let shift;
415
- for (shift = 0; shift <= 24; shift += 8) results.push(value >> shift & 255);
416
- return results;
417
- })().reverse();
418
- } else if (match = string.match(ipv4Regexes.twoOctet)) return (function() {
419
- const ref = match.slice(1, 4);
420
- const results = [];
421
- value = parseIntAuto(ref[1]);
422
- if (value > 16777215 || value < 0) throw new Error("ipaddr: address outside defined range");
423
- results.push(parseIntAuto(ref[0]));
424
- results.push(value >> 16 & 255);
425
- results.push(value >> 8 & 255);
426
- results.push(value & 255);
427
- return results;
428
- })();
429
- else if (match = string.match(ipv4Regexes.threeOctet)) return (function() {
430
- const ref = match.slice(1, 5);
431
- const results = [];
432
- value = parseIntAuto(ref[2]);
433
- if (value > 65535 || value < 0) throw new Error("ipaddr: address outside defined range");
434
- results.push(parseIntAuto(ref[0]));
435
- results.push(parseIntAuto(ref[1]));
436
- results.push(value >> 8 & 255);
437
- results.push(value & 255);
438
- return results;
439
- })();
440
- else return null;
441
- };
442
- ipaddr.IPv4.subnetMaskFromPrefixLength = function(prefix) {
443
- prefix = parseInt(prefix);
444
- if (prefix < 0 || prefix > 32) throw new Error("ipaddr: invalid IPv4 prefix length");
445
- const octets = [
446
- 0,
447
- 0,
448
- 0,
449
- 0
450
- ];
451
- let j = 0;
452
- const filledOctetCount = Math.floor(prefix / 8);
453
- while (j < filledOctetCount) {
454
- octets[j] = 255;
455
- j++;
135
+ return mutated ? parsed.toString() : value;
136
+ } catch {
137
+ return value;
138
+ }
139
+ }
140
+ function redactQueryString(value, depth) {
141
+ const params = new URLSearchParams(value);
142
+ const entries = Array.from(params.entries());
143
+ const redactedEntries = [];
144
+ const seenSensitiveKeys = /* @__PURE__ */ new Set();
145
+ let mutated = false;
146
+ for (const [key, entryValue] of entries) {
147
+ if (isSensitiveUrlQueryParamName$1(key)) {
148
+ mutated = true;
149
+ if (!seenSensitiveKeys.has(key)) {
150
+ seenSensitiveKeys.add(key);
151
+ redactedEntries.push([key, "***"]);
456
152
  }
457
- if (filledOctetCount < 4) octets[filledOctetCount] = Math.pow(2, prefix % 8) - 1 << 8 - prefix % 8;
458
- return new this(octets);
153
+ continue;
154
+ }
155
+ const redactedKey = redactNestedUrlValue(key, depth + 1);
156
+ const redactedValue = redactNestedUrlValue(entryValue, depth + 1);
157
+ if (redactedKey !== key || redactedValue !== entryValue) mutated = true;
158
+ redactedEntries.push([redactedKey, redactedValue]);
159
+ }
160
+ if (!mutated) return value;
161
+ const redactedParams = new URLSearchParams();
162
+ for (const [key, entryValue] of redactedEntries) redactedParams.append(key, entryValue);
163
+ return redactedParams.toString();
164
+ }
165
+ function redactUrlLikeFallback(value) {
166
+ return redactSensitiveUrlPath(redactEmbeddedUrlUserInfo(value).replace(/([?&])([^=&]+)=([^&]*)/g, (match, prefix, key) => isSensitiveUrlQueryParamName$1(key) ? `${prefix}${key}=***` : match));
167
+ }
168
+ function redactAuthorityUserInfo(candidate, authorityStart) {
169
+ const authority = candidate.slice(authorityStart);
170
+ const userInfoEnd = authority.lastIndexOf("@");
171
+ if (userInfoEnd < 0) return candidate;
172
+ return `${candidate.slice(0, authorityStart)}***:***@${authority.slice(userInfoEnd + 1)}`;
173
+ }
174
+ function redactEmbeddedUrlUserInfo(value) {
175
+ return value.replace(SPECIAL_SCHEME_AUTHORITY_RE, (candidate) => {
176
+ let authorityStart = candidate.indexOf(":") + 1;
177
+ while (authorityStart < candidate.length && (candidate[authorityStart] === "/" || candidate[authorityStart] === "\\")) authorityStart += 1;
178
+ return redactAuthorityUserInfo(candidate, authorityStart);
179
+ }).replace(SPECIAL_SCHEME_SPILLED_USERINFO_RE, (candidate) => {
180
+ let authorityStart = candidate.indexOf(":") + 1;
181
+ while (authorityStart < candidate.length && (candidate[authorityStart] === "/" || candidate[authorityStart] === "\\")) authorityStart += 1;
182
+ const userInfoEnd = candidate.lastIndexOf("@");
183
+ const firstReservedDelimiter = candidate.slice(authorityStart).search(/[\\/?#]/u);
184
+ if (userInfoEnd < 0 || firstReservedDelimiter < 0) return candidate;
185
+ const absoluteReservedDelimiter = authorityStart + firstReservedDelimiter;
186
+ if (absoluteReservedDelimiter >= userInfoEnd) return candidate;
187
+ const credentialSeparator = candidate.indexOf(":", authorityStart);
188
+ if (credentialSeparator < 0 || credentialSeparator > absoluteReservedDelimiter) return candidate;
189
+ const authorityPrefix = candidate.slice(authorityStart, absoluteReservedDelimiter);
190
+ const possiblePort = candidate.slice(credentialSeparator + 1, absoluteReservedDelimiter);
191
+ if (/^\d+$/u.test(possiblePort) || /^\[[^\]]+\](?::\d+)?$/u.test(authorityPrefix)) return candidate;
192
+ return `${candidate.slice(0, authorityStart)}***:***@${candidate.slice(userInfoEnd + 1)}`;
193
+ }).replace(PROTOCOL_RELATIVE_AUTHORITY_RE, (candidate) => {
194
+ let authorityStart = 0;
195
+ while (authorityStart < candidate.length && (candidate[authorityStart] === "/" || candidate[authorityStart] === "\\")) authorityStart += 1;
196
+ return redactAuthorityUserInfo(candidate, authorityStart);
197
+ });
198
+ }
199
+ function hasUnresolvedEmbeddedUrlUserInfo(value) {
200
+ for (const match of value.matchAll(/(?:\b(?:https?|wss?|ftp):[\\/]{0,2}|[\\/]{2,})/giu)) {
201
+ const remainder = value.slice((match.index ?? 0) + match[0].length);
202
+ const userInfoEnd = remainder.search(/(?<!\*\*\*:\*\*\*)@/u);
203
+ const authorityEnd = remainder.search(/[\\/?#]/u);
204
+ const pathBeforeAt = remainder.slice(authorityEnd + 1, userInfoEnd);
205
+ if (userInfoEnd >= 0 && (authorityEnd < 0 || userInfoEnd <= authorityEnd || remainder[authorityEnd] === "/" && (pathBeforeAt.includes(":") || /^[^/?#\s]+\.[^/?#\s]+(?:[/?#]|$)/u.test(remainder.slice(userInfoEnd + 1))))) return true;
206
+ }
207
+ return false;
208
+ }
209
+ function redactRelativeUrlFragment(value, depth) {
210
+ const fragmentIndex = value.indexOf("#");
211
+ if (fragmentIndex < 0) return value;
212
+ const fragment = value.slice(fragmentIndex + 1);
213
+ const redactedFragment = redactFragment(fragment, depth + 1);
214
+ return redactedFragment === fragment ? value : `${value.slice(0, fragmentIndex + 1)}${redactedFragment}`;
215
+ }
216
+ function redactFragment(value, depth) {
217
+ if (!value) return value;
218
+ if (depth > MAX_NESTED_URL_REDACTION_DEPTH && looksLikeNestedUrlValue(value)) return "***";
219
+ const wholeUrl = redactSensitiveUrlAtDepth(value, depth);
220
+ if (wholeUrl.parsedWholeUrl) return redactUrlLikeFallback(wholeUrl.value);
221
+ const candidate = value;
222
+ const firstQueryDelimiter = candidate.search(/[?&]/u);
223
+ const firstEquals = candidate.indexOf("=");
224
+ if (firstEquals >= 0 && (firstQueryDelimiter < 0 || firstEquals < firstQueryDelimiter)) return redactQueryString(candidate, depth);
225
+ const hashRouterQueryIndex = candidate.indexOf("?");
226
+ if (hashRouterQueryIndex >= 0) {
227
+ const redactedQuery = redactQueryString(candidate.slice(hashRouterQueryIndex + 1), depth);
228
+ return `${redactEncodedUrlLikeString(redactUrlLikeFallback(candidate.slice(0, hashRouterQueryIndex + 1)), depth + 1)}${redactedQuery}`;
229
+ }
230
+ const fallback = redactUrlLikeFallback(candidate);
231
+ if (!looksLikeNestedUrlValue(fallback)) return fallback;
232
+ let decoded;
233
+ try {
234
+ decoded = decodeURIComponent(fallback);
235
+ } catch {
236
+ return "***";
237
+ }
238
+ if (decoded === fallback) return fallback;
239
+ const redactedDecoded = redactFragment(decoded, depth + 1);
240
+ return redactedDecoded === decoded ? fallback : encodeURIComponent(redactedDecoded);
241
+ }
242
+ function redactEncodedNestedUrlPath(value, depth) {
243
+ if (!looksLikeNestedUrlValue(value)) return value;
244
+ if (depth > MAX_NESTED_URL_REDACTION_DEPTH) return "***";
245
+ let decoded;
246
+ try {
247
+ decoded = decodeURIComponent(value);
248
+ } catch {
249
+ return "***";
250
+ }
251
+ if (decoded === value) return value;
252
+ const direct = redactSensitiveUrlLikeStringAtDepth(decoded, depth);
253
+ if (direct.value !== decoded || hasUnresolvedEmbeddedUrlUserInfo(decoded)) return direct.value !== decoded ? direct.value : "***";
254
+ if (direct.parsedWholeUrl) return value;
255
+ const nested = redactEncodedNestedUrlPath(decoded, depth + 1);
256
+ return nested === decoded ? value : nested;
257
+ }
258
+ function redactSensitiveUrlAtDepth(value, depth) {
259
+ try {
260
+ const directRedaction = redactDirectSensitiveUrl(value);
261
+ const parsed = new URL(directRedaction);
262
+ if (depth > MAX_NESTED_URL_REDACTION_DEPTH) return {
263
+ value: "***",
264
+ parsedWholeUrl: true
459
265
  };
460
- ipaddr.IPv6 = (function() {
461
- function IPv6(parts, zoneId) {
462
- let i, part;
463
- if (parts.length === 16) {
464
- this.parts = [];
465
- for (i = 0; i <= 14; i += 2) this.parts.push(parts[i] << 8 | parts[i + 1]);
466
- } else if (parts.length === 8) this.parts = parts;
467
- else throw new Error("ipaddr: ipv6 part count should be 8 or 16");
468
- for (i = 0; i < this.parts.length; i++) {
469
- part = this.parts[i];
470
- if (!(0 <= part && part <= 65535)) throw new Error("ipaddr: ipv6 part should fit in 16 bits");
471
- }
472
- if (zoneId) this.zoneId = zoneId;
473
- }
474
- IPv6.prototype.SpecialRanges = {
475
- unspecified: [new IPv6([
476
- 0,
477
- 0,
478
- 0,
479
- 0,
480
- 0,
481
- 0,
482
- 0,
483
- 0
484
- ]), 128],
485
- linkLocal: [new IPv6([
486
- 65152,
487
- 0,
488
- 0,
489
- 0,
490
- 0,
491
- 0,
492
- 0,
493
- 0
494
- ]), 10],
495
- multicast: [new IPv6([
496
- 65280,
497
- 0,
498
- 0,
499
- 0,
500
- 0,
501
- 0,
502
- 0,
503
- 0
504
- ]), 8],
505
- loopback: [new IPv6([
506
- 0,
507
- 0,
508
- 0,
509
- 0,
510
- 0,
511
- 0,
512
- 0,
513
- 1
514
- ]), 128],
515
- uniqueLocal: [new IPv6([
516
- 64512,
517
- 0,
518
- 0,
519
- 0,
520
- 0,
521
- 0,
522
- 0,
523
- 0
524
- ]), 7],
525
- ipv4Mapped: [new IPv6([
526
- 0,
527
- 0,
528
- 0,
529
- 0,
530
- 0,
531
- 65535,
532
- 0,
533
- 0
534
- ]), 96],
535
- deprecatedSiteLocal: [new IPv6([
536
- 65216,
537
- 0,
538
- 0,
539
- 0,
540
- 0,
541
- 0,
542
- 0,
543
- 0
544
- ]), 10],
545
- discard: [new IPv6([
546
- 256,
547
- 0,
548
- 0,
549
- 0,
550
- 0,
551
- 0,
552
- 0,
553
- 0
554
- ]), 64],
555
- rfc6145: [new IPv6([
556
- 0,
557
- 0,
558
- 0,
559
- 0,
560
- 65535,
561
- 0,
562
- 0,
563
- 0
564
- ]), 96],
565
- rfc6052: [[new IPv6([
566
- 100,
567
- 65435,
568
- 0,
569
- 0,
570
- 0,
571
- 0,
572
- 0,
573
- 0
574
- ]), 96], [new IPv6([
575
- 100,
576
- 65435,
577
- 1,
578
- 0,
579
- 0,
580
- 0,
581
- 0,
582
- 0
583
- ]), 48]],
584
- "6to4": [new IPv6([
585
- 8194,
586
- 0,
587
- 0,
588
- 0,
589
- 0,
590
- 0,
591
- 0,
592
- 0
593
- ]), 16],
594
- teredo: [new IPv6([
595
- 8193,
596
- 0,
597
- 0,
598
- 0,
599
- 0,
600
- 0,
601
- 0,
602
- 0
603
- ]), 32],
604
- benchmarking: [new IPv6([
605
- 8193,
606
- 2,
607
- 0,
608
- 0,
609
- 0,
610
- 0,
611
- 0,
612
- 0
613
- ]), 48],
614
- amt: [new IPv6([
615
- 8193,
616
- 3,
617
- 0,
618
- 0,
619
- 0,
620
- 0,
621
- 0,
622
- 0
623
- ]), 32],
624
- as112v6: [[new IPv6([
625
- 8193,
626
- 4,
627
- 274,
628
- 0,
629
- 0,
630
- 0,
631
- 0,
632
- 0
633
- ]), 48], [new IPv6([
634
- 9760,
635
- 79,
636
- 32768,
637
- 0,
638
- 0,
639
- 0,
640
- 0,
641
- 0
642
- ]), 48]],
643
- deprecatedOrchid: [new IPv6([
644
- 8193,
645
- 16,
646
- 0,
647
- 0,
648
- 0,
649
- 0,
650
- 0,
651
- 0
652
- ]), 28],
653
- orchid2: [new IPv6([
654
- 8193,
655
- 32,
656
- 0,
657
- 0,
658
- 0,
659
- 0,
660
- 0,
661
- 0
662
- ]), 28],
663
- droneRemoteIdProtocolEntityTags: [new IPv6([
664
- 8193,
665
- 48,
666
- 0,
667
- 0,
668
- 0,
669
- 0,
670
- 0,
671
- 0
672
- ]), 28],
673
- segmentRouting: [new IPv6([
674
- 24320,
675
- 0,
676
- 0,
677
- 0,
678
- 0,
679
- 0,
680
- 0,
681
- 0
682
- ]), 16],
683
- reserved: [
684
- [new IPv6([
685
- 8193,
686
- 0,
687
- 0,
688
- 0,
689
- 0,
690
- 0,
691
- 0,
692
- 0
693
- ]), 23],
694
- [new IPv6([
695
- 8193,
696
- 3512,
697
- 0,
698
- 0,
699
- 0,
700
- 0,
701
- 0,
702
- 0
703
- ]), 32],
704
- [new IPv6([
705
- 16383,
706
- 0,
707
- 0,
708
- 0,
709
- 0,
710
- 0,
711
- 0,
712
- 0
713
- ]), 20]
714
- ]
715
- };
716
- IPv6.prototype.isIPv4MappedAddress = function() {
717
- return this.range() === "ipv4Mapped";
266
+ let mutated = directRedaction !== value;
267
+ const redactedNestedPath = redactEmbeddedUrlUserInfo(redactEncodedNestedUrlPath(parsed.pathname, depth + 1));
268
+ if (redactedNestedPath !== parsed.pathname) {
269
+ const originalPath = parsed.pathname;
270
+ parsed.pathname = redactedNestedPath;
271
+ if (parsed.pathname === originalPath) return {
272
+ value: directRedaction,
273
+ parsedWholeUrl: false
718
274
  };
719
- IPv6.prototype.kind = function() {
720
- return "ipv6";
721
- };
722
- IPv6.prototype.match = function(other, cidrRange) {
723
- let ref;
724
- if (cidrRange === void 0) {
725
- ref = other;
726
- other = ref[0];
727
- cidrRange = ref[1];
728
- }
729
- if (other.kind() !== "ipv6") throw new Error("ipaddr: cannot match ipv6 address with non-ipv6 one");
730
- return matchCIDR(this.parts, other.parts, 16, cidrRange);
731
- };
732
- IPv6.prototype.prefixLengthFromSubnetMask = function() {
733
- let cidr = 0;
734
- let stop = false;
735
- const zerotable = {
736
- 0: 16,
737
- 32768: 15,
738
- 49152: 14,
739
- 57344: 13,
740
- 61440: 12,
741
- 63488: 11,
742
- 64512: 10,
743
- 65024: 9,
744
- 65280: 8,
745
- 65408: 7,
746
- 65472: 6,
747
- 65504: 5,
748
- 65520: 4,
749
- 65528: 3,
750
- 65532: 2,
751
- 65534: 1,
752
- 65535: 0
753
- };
754
- let part, zeros;
755
- for (let i = 7; i >= 0; i -= 1) {
756
- part = this.parts[i];
757
- if (part in zerotable) {
758
- zeros = zerotable[part];
759
- if (stop && zeros !== 0) return null;
760
- if (zeros !== 16) stop = true;
761
- cidr += zeros;
762
- } else return null;
763
- }
764
- return 128 - cidr;
765
- };
766
- IPv6.prototype.range = function() {
767
- return ipaddr.subnetMatch(this, this.SpecialRanges);
768
- };
769
- IPv6.prototype.toByteArray = function() {
770
- let part;
771
- const bytes = [];
772
- const ref = this.parts;
773
- for (let i = 0; i < ref.length; i++) {
774
- part = ref[i];
775
- bytes.push(part >> 8);
776
- bytes.push(part & 255);
777
- }
778
- return bytes;
779
- };
780
- IPv6.prototype.toFixedLengthString = function() {
781
- const addr = (function() {
782
- const results = [];
783
- for (let i = 0; i < this.parts.length; i++) results.push(padPart(this.parts[i].toString(16), 4));
784
- return results;
785
- }).call(this).join(":");
786
- let suffix = "";
787
- if (this.zoneId) suffix = `%${this.zoneId}`;
788
- return addr + suffix;
789
- };
790
- IPv6.prototype.toIPv4Address = function() {
791
- if (!this.isIPv4MappedAddress()) throw new Error("ipaddr: trying to convert a generic ipv6 address to ipv4");
792
- const ref = this.parts.slice(-2);
793
- const high = ref[0];
794
- const low = ref[1];
795
- return new ipaddr.IPv4([
796
- high >> 8,
797
- high & 255,
798
- low >> 8,
799
- low & 255
800
- ]);
801
- };
802
- IPv6.prototype.toNormalizedString = function() {
803
- const addr = (function() {
804
- const results = [];
805
- for (let i = 0; i < this.parts.length; i++) results.push(this.parts[i].toString(16));
806
- return results;
807
- }).call(this).join(":");
808
- let suffix = "";
809
- if (this.zoneId) suffix = `%${this.zoneId}`;
810
- return addr + suffix;
811
- };
812
- IPv6.prototype.toRFC5952String = function() {
813
- const regex = /((^|:)(0(:|$)){2,})/g;
814
- const string = this.toNormalizedString();
815
- let bestMatchIndex = 0;
816
- let bestMatchLength = -1;
817
- let match;
818
- while (match = regex.exec(string)) if (match[0].length > bestMatchLength) {
819
- bestMatchIndex = match.index;
820
- bestMatchLength = match[0].length;
821
- }
822
- if (bestMatchLength < 0) return string;
823
- return `${string.substring(0, bestMatchIndex)}::${string.substring(bestMatchIndex + bestMatchLength)}`;
824
- };
825
- IPv6.prototype.toString = function() {
826
- return this.toRFC5952String();
827
- };
828
- return IPv6;
829
- })();
830
- ipaddr.IPv6.broadcastAddressFromCIDR = function(string) {
831
- try {
832
- const cidr = this.parseCIDR(string);
833
- const ipInterfaceOctets = cidr[0].toByteArray();
834
- const subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray();
835
- const octets = [];
836
- let i = 0;
837
- while (i < 16) {
838
- octets.push(parseInt(ipInterfaceOctets[i], 10) | parseInt(subnetMaskOctets[i], 10) ^ 255);
839
- i++;
840
- }
841
- return new this(octets);
842
- } catch (e) {
843
- throw new Error(`ipaddr: the address does not have IPv6 CIDR format (${e})`);
844
- }
845
- };
846
- ipaddr.IPv6.isIPv6 = function(string) {
847
- return this.parser(string) !== null;
848
- };
849
- ipaddr.IPv6.isValid = function(string) {
850
- if (typeof string === "string" && string.indexOf(":") === -1) return false;
851
- try {
852
- const addr = this.parser(string);
853
- new this(addr.parts, addr.zoneId);
854
- return true;
855
- } catch (e) {
856
- return false;
857
- }
858
- };
859
- ipaddr.IPv6.isValidCIDR = function(string) {
860
- if (typeof string === "string" && string.indexOf(":") === -1) return false;
861
- try {
862
- this.parseCIDR(string);
863
- return true;
864
- } catch (e) {
865
- return false;
866
- }
867
- };
868
- ipaddr.IPv6.networkAddressFromCIDR = function(string) {
869
- let cidr, i, ipInterfaceOctets, octets, subnetMaskOctets;
870
- try {
871
- cidr = this.parseCIDR(string);
872
- ipInterfaceOctets = cidr[0].toByteArray();
873
- subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray();
874
- octets = [];
875
- i = 0;
876
- while (i < 16) {
877
- octets.push(parseInt(ipInterfaceOctets[i], 10) & parseInt(subnetMaskOctets[i], 10));
878
- i++;
879
- }
880
- return new this(octets);
881
- } catch (e) {
882
- throw new Error(`ipaddr: the address does not have IPv6 CIDR format (${e})`);
883
- }
884
- };
885
- ipaddr.IPv6.parse = function(string) {
886
- const addr = this.parser(string);
887
- if (addr.parts === null) throw new Error("ipaddr: string is not formatted like an IPv6 Address");
888
- return new this(addr.parts, addr.zoneId);
889
- };
890
- ipaddr.IPv6.parseCIDR = function(string) {
891
- let maskLength, match, parsed;
892
- if (match = string.match(/^(.+)\/(\d+)$/)) {
893
- maskLength = parseInt(match[2]);
894
- if (maskLength >= 0 && maskLength <= 128) {
895
- parsed = [this.parse(match[1]), maskLength];
896
- Object.defineProperty(parsed, "toString", { value: function() {
897
- return this.join("/");
898
- } });
899
- return parsed;
900
- }
901
- }
902
- throw new Error("ipaddr: string is not formatted like an IPv6 CIDR range");
903
- };
904
- ipaddr.IPv6.parser = function(string) {
905
- let addr, i, match, octet, octets, zoneId;
906
- if (match = string.match(ipv6Regexes.deprecatedTransitional)) return this.parser(`::ffff:${match[1]}`);
907
- if (ipv6Regexes.native.test(string)) return expandIPv6(string, 8);
908
- if (match = string.match(ipv6Regexes.transitional)) {
909
- zoneId = match[6] || "";
910
- addr = match[1];
911
- if (!match[1].endsWith("::")) addr = addr.slice(0, -1);
912
- addr = expandIPv6(addr + zoneId, 6);
913
- if (addr.parts) {
914
- octets = [
915
- parseInt(match[2]),
916
- parseInt(match[3]),
917
- parseInt(match[4]),
918
- parseInt(match[5])
919
- ];
920
- for (i = 0; i < octets.length; i++) {
921
- octet = octets[i];
922
- if (!(0 <= octet && octet <= 255)) return null;
923
- }
924
- addr.parts.push(octets[0] << 8 | octets[1]);
925
- addr.parts.push(octets[2] << 8 | octets[3]);
926
- return {
927
- parts: addr.parts,
928
- zoneId: addr.zoneId
929
- };
930
- }
931
- }
932
- return null;
933
- };
934
- ipaddr.IPv6.subnetMaskFromPrefixLength = function(prefix) {
935
- prefix = parseInt(prefix);
936
- if (prefix < 0 || prefix > 128) throw new Error("ipaddr: invalid IPv6 prefix length");
937
- const octets = [
938
- 0,
939
- 0,
940
- 0,
941
- 0,
942
- 0,
943
- 0,
944
- 0,
945
- 0,
946
- 0,
947
- 0,
948
- 0,
949
- 0,
950
- 0,
951
- 0,
952
- 0,
953
- 0
954
- ];
955
- let j = 0;
956
- const filledOctetCount = Math.floor(prefix / 8);
957
- while (j < filledOctetCount) {
958
- octets[j] = 255;
959
- j++;
960
- }
961
- if (filledOctetCount < 16) octets[filledOctetCount] = Math.pow(2, prefix % 8) - 1 << 8 - prefix % 8;
962
- return new this(octets);
963
- };
964
- ipaddr.fromByteArray = function(bytes) {
965
- const length = bytes.length;
966
- if (length === 4) return new ipaddr.IPv4(bytes);
967
- else if (length === 16) return new ipaddr.IPv6(bytes);
968
- else throw new Error("ipaddr: the binary input is neither an IPv6 nor IPv4 address");
969
- };
970
- ipaddr.isValid = function(string) {
971
- return ipaddr.IPv6.isValid(string) || ipaddr.IPv4.isValid(string);
972
- };
973
- ipaddr.isValidCIDR = function(string) {
974
- return ipaddr.IPv6.isValidCIDR(string) || ipaddr.IPv4.isValidCIDR(string);
975
- };
976
- ipaddr.parse = function(string) {
977
- if (ipaddr.IPv6.isValid(string)) return ipaddr.IPv6.parse(string);
978
- else if (ipaddr.IPv4.isValid(string)) return ipaddr.IPv4.parse(string);
979
- else throw new Error("ipaddr: the address has neither IPv6 nor IPv4 format");
980
- };
981
- ipaddr.parseCIDR = function(string) {
982
- try {
983
- return ipaddr.IPv6.parseCIDR(string);
984
- } catch (e) {
985
- try {
986
- return ipaddr.IPv4.parseCIDR(string);
987
- } catch (e2) {
988
- throw new Error("ipaddr: the address has neither IPv6 nor IPv4 CIDR format");
989
- }
990
- }
991
- };
992
- ipaddr.process = function(string) {
993
- const addr = this.parse(string);
994
- if (addr.kind() === "ipv6" && addr.isIPv4MappedAddress()) return addr.toIPv4Address();
995
- else return addr;
275
+ mutated = true;
276
+ }
277
+ const redactedQuery = redactQueryString(parsed.search.slice(1), depth);
278
+ if (redactedQuery !== parsed.search.slice(1)) {
279
+ parsed.search = redactedQuery;
280
+ mutated = true;
281
+ }
282
+ const fragment = parsed.hash.slice(1);
283
+ const redactedHash = redactFragment(fragment, depth + 1);
284
+ if (redactedHash !== fragment) {
285
+ parsed.hash = redactedHash;
286
+ mutated = true;
287
+ }
288
+ return {
289
+ value: mutated ? parsed.toString() : value,
290
+ parsedWholeUrl: true
996
291
  };
997
- ipaddr.subnetMatch = function(address, rangeList, defaultName) {
998
- let i, rangeName, rangeSubnets, subnet;
999
- if (defaultName === void 0 || defaultName === null) defaultName = "unicast";
1000
- for (rangeName in rangeList) if (Object.prototype.hasOwnProperty.call(rangeList, rangeName)) {
1001
- rangeSubnets = rangeList[rangeName];
1002
- if (rangeSubnets[0] && !(rangeSubnets[0] instanceof Array)) rangeSubnets = [rangeSubnets];
1003
- for (i = 0; i < rangeSubnets.length; i++) {
1004
- subnet = rangeSubnets[i];
1005
- if (address.kind() === subnet[0].kind() && address.match.apply(address, subnet)) return rangeName;
1006
- }
1007
- }
1008
- return defaultName;
292
+ } catch {
293
+ return {
294
+ value,
295
+ parsedWholeUrl: false
1009
296
  };
1010
- if (typeof module !== "undefined" && module.exports) module.exports = ipaddr;
1011
- else root.ipaddr = ipaddr;
1012
- })(exports);
1013
- })))(), 1);
1014
- import_ipaddr.default.IPv4.parse("198.18.0.0");
297
+ }
298
+ }
299
+ function redactSensitiveUrlLikeStringAtDepth(value, depth) {
300
+ const redactedUrl = redactSensitiveUrlAtDepth(value, depth);
301
+ if (redactedUrl.parsedWholeUrl) return redactedUrl;
302
+ return {
303
+ value: redactEncodedUrlLikeString(redactRelativeUrlFragment(redactUrlLikeFallback(redactedUrl.value), depth), depth + 1),
304
+ parsedWholeUrl: false
305
+ };
306
+ }
307
+ function redactEncodedUrlLikeString(value, depth) {
308
+ if (!looksLikeNestedUrlValue(value)) return value;
309
+ if (depth > MAX_NESTED_URL_REDACTION_DEPTH) return "***";
310
+ let decoded;
311
+ try {
312
+ decoded = decodeURIComponent(value);
313
+ } catch {
314
+ return "***";
315
+ }
316
+ if (decoded === value) return value;
317
+ const redactedDecoded = redactSensitiveUrlLikeStringAtDepth(decoded, depth + 1);
318
+ if (redactedDecoded.value !== decoded || redactedDecoded.parsedWholeUrl) return redactedDecoded.value === decoded ? value : redactedDecoded.value;
319
+ return hasUnresolvedEmbeddedUrlUserInfo(decoded) ? "***" : value;
320
+ }
321
+ function redactNestedUrlValue(value, depth) {
322
+ if (!looksLikeNestedUrlValue(value)) return value;
323
+ if (depth > MAX_NESTED_URL_REDACTION_DEPTH) return "***";
324
+ const direct = redactSensitiveUrlLikeStringAtDepth(value, depth);
325
+ if (direct.value !== value) return direct.value;
326
+ if (hasUnresolvedEmbeddedUrlUserInfo(value)) return "***";
327
+ if (direct.parsedWholeUrl) return value;
328
+ let decoded;
329
+ try {
330
+ decoded = decodeURIComponent(value);
331
+ } catch {
332
+ return "***";
333
+ }
334
+ if (decoded === value || !looksLikeNestedUrlValue(decoded)) return value;
335
+ const redactedDecoded = redactNestedUrlValue(decoded, depth + 1);
336
+ return redactedDecoded === decoded ? value : encodeURIComponent(redactedDecoded);
337
+ }
338
+ /** Redacts sensitive URL-looking substrings even when the full value is not a valid URL. */
339
+ function redactSensitiveUrlLikeString(value) {
340
+ return redactSensitiveUrlLikeStringAtDepth(value, 0).value;
341
+ }
342
+ ipaddr.IPv4.parse("198.18.0.0");
1015
343
  function stripIpv6Brackets(value) {
1016
344
  if (value.startsWith("[") && value.endsWith("]")) return value.slice(1, -1);
1017
345
  return value;
@@ -1034,7 +362,7 @@ function normalizeIpParseInput(raw) {
1034
362
  function parseCanonicalIpAddress(raw) {
1035
363
  const normalized = normalizeIpParseInput(raw);
1036
364
  if (!normalized) return;
1037
- return import_ipaddr.default.IPv4.isValidFourPartDecimal(normalized) || import_ipaddr.default.IPv6.isValid(normalized) ? import_ipaddr.default.parse(normalized) : void 0;
365
+ return ipaddr.IPv4.isValidFourPartDecimal(normalized) || ipaddr.IPv6.isValid(normalized) ? ipaddr.parse(normalized) : void 0;
1038
366
  }
1039
367
  /** Normalizes canonical IP literals and maps IPv4-mapped IPv6 addresses to IPv4 text. */
1040
368
  function normalizeIpAddress(raw) {
@@ -1056,8 +384,12 @@ function normalizeGatewayErrorText(value) {
1056
384
  function isSensitiveUrlQueryParamName(key) {
1057
385
  return /(?:token|password|secret|key|auth|credential)/iu.test(key);
1058
386
  }
1059
- function normalizeFingerprint(fingerprint) {
1060
- return (fingerprint ?? "").replaceAll(":", "").trim().toLowerCase();
387
+ const SHA256_HEX_FINGERPRINT = /^[a-fA-F0-9]{64}$/u;
388
+ const SHA256_COLON_FINGERPRINT = /^(?:[a-fA-F0-9]{2}:){31}[a-fA-F0-9]{2}$/u;
389
+ function normalizeTlsFingerprint(fingerprint) {
390
+ const value = (fingerprint ?? "").trim().replace(/^sha256:/iu, "");
391
+ if (SHA256_HEX_FINGERPRINT.test(value)) return value.toLowerCase();
392
+ return SHA256_COLON_FINGERPRINT.test(value) ? value.replaceAll(":", "").toLowerCase() : "";
1061
393
  }
1062
394
  function parseHostForAddressChecks(host) {
1063
395
  if (!host) return null;
@@ -1153,6 +485,7 @@ function isSecureWebSocketUrl(rawUrl, options) {
1153
485
  }
1154
486
  }
1155
487
  var GatewayWebSocketTransportConfigurationError = class extends Error {};
488
+ var GatewayWebSocketTlsPinError = class extends Error {};
1156
489
  function resolveGatewayWebSocketTransport(params) {
1157
490
  const usesTls = isWssUrl(params.url);
1158
491
  if (params.tlsFingerprint && !usesTls) throw new GatewayWebSocketTransportConfigurationError("gateway tls fingerprint requires wss:// gateway url");
@@ -1164,32 +497,41 @@ function resolveGatewayWebSocketTransport(params) {
1164
497
  } catch {}
1165
498
  throw new GatewayWebSocketTransportConfigurationError(`SECURITY ERROR: Cannot connect to "${displayHost}" over plaintext ws://. Both credentials and chat data would be exposed to network interception. Use wss:// for remote URLs. Safe defaults: keep gateway.bind=loopback and connect via SSH tunnel (ssh -N -L 18789:127.0.0.1:18789 user@gateway-host), or use Tailscale Serve/Funnel. ` + (allowPrivateWs ? "" : "Break-glass (trusted private networks only): set OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1. ") + "Run `openclaw doctor --fix` for guidance.");
1166
499
  }
1167
- const normalize = params.normalizeTlsFingerprint ?? normalizeFingerprint;
500
+ const normalize = params.normalizeTlsFingerprint ?? normalizeTlsFingerprint;
501
+ const expectedFingerprint = params.tlsFingerprint ? normalizeTlsFingerprint(params.tlsFingerprint) : void 0;
502
+ if (params.tlsFingerprint && !expectedFingerprint) throw new GatewayWebSocketTransportConfigurationError("gateway tls fingerprint must be a SHA-256 fingerprint");
1168
503
  const options = { ...params.options };
1169
- if (usesTls && params.tlsFingerprint) {
1170
- options.rejectUnauthorized = false;
1171
- options.checkServerIdentity = (_hostValue, cert) => {
1172
- const fingerprintValue = typeof cert === "object" && cert && "fingerprint256" in cert ? cert.fingerprint256 ?? "" : "";
1173
- const fingerprint = normalize(typeof fingerprintValue === "string" ? fingerprintValue : "");
1174
- const expected = normalize(params.tlsFingerprint);
1175
- if (!expected) return;
1176
- if (!fingerprint) return /* @__PURE__ */ new Error("Missing server TLS fingerprint");
1177
- if (fingerprint !== expected) return /* @__PURE__ */ new Error("Server TLS fingerprint mismatch");
1178
- };
1179
- }
1180
- return {
1181
- options,
1182
- validateSocket: (socket) => {
1183
- if (!params.tlsFingerprint) return null;
1184
- const expected = normalize(params.tlsFingerprint);
1185
- if (!expected) return /* @__PURE__ */ new Error("gateway tls fingerprint missing");
1186
- const rawSocket = socket["_socket"];
1187
- if (!rawSocket || typeof rawSocket.getPeerCertificate !== "function") return /* @__PURE__ */ new Error("gateway tls fingerprint unavailable");
1188
- const cert = rawSocket.getPeerCertificate();
1189
- const fingerprint = normalize(cert?.fingerprint256 ?? "");
1190
- if (!fingerprint) return /* @__PURE__ */ new Error("gateway tls fingerprint unavailable");
1191
- return fingerprint === expected ? null : /* @__PURE__ */ new Error("gateway tls fingerprint mismatch");
1192
- }
504
+ if (usesTls && expectedFingerprint) applyGatewayWebSocketTlsPin(options, expectedFingerprint, normalize);
505
+ return { options };
506
+ }
507
+ function applyGatewayWebSocketTlsPin(options, expectedFingerprint, normalize = normalizeTlsFingerprint) {
508
+ options.rejectUnauthorized = false;
509
+ const headers = { ...options.headers };
510
+ const deferredHeaders = Object.entries(headers).filter(([key]) => key.toLowerCase() === "expect");
511
+ for (const [key] of deferredHeaders) delete headers[key];
512
+ options.headers = headers;
513
+ options.finishRequest = (request) => {
514
+ request.once("socket", (socket) => {
515
+ if (!(socket instanceof TLSSocket)) {
516
+ request.destroy(new GatewayWebSocketTlsPinError("gateway tls fingerprint unavailable"));
517
+ return;
518
+ }
519
+ const validatePin = () => {
520
+ if (request.destroyed) return;
521
+ const canonicalFingerprint = normalizeTlsFingerprint(socket.getPeerCertificate()?.fingerprint256);
522
+ const fingerprint = canonicalFingerprint ? normalize(canonicalFingerprint) : "";
523
+ if (!fingerprint || fingerprint !== normalize(expectedFingerprint)) {
524
+ request.destroy(new GatewayWebSocketTlsPinError(fingerprint ? "gateway tls fingerprint mismatch" : "gateway tls fingerprint unavailable"));
525
+ return;
526
+ }
527
+ for (const [key, value] of deferredHeaders) if (value !== void 0) request.setHeader(key, value);
528
+ request.end();
529
+ };
530
+ if (socket.secureConnecting) {
531
+ socket.once("secureConnect", validatePin);
532
+ request.once("close", () => socket.off("secureConnect", validatePin));
533
+ } else validatePin();
534
+ });
1193
535
  };
1194
536
  }
1195
537
  //#endregion
@@ -1210,7 +552,7 @@ const DEFAULT_HOST_DEPS = {
1210
552
  logDebug: () => {},
1211
553
  logError: () => {},
1212
554
  redactForLog: (message) => message,
1213
- normalizeTlsFingerprint: normalizeFingerprint
555
+ normalizeTlsFingerprint
1214
556
  };
1215
557
  function resolveHostDeps(overrides) {
1216
558
  return Object.fromEntries(Object.entries(DEFAULT_HOST_DEPS).map(([key, fallback]) => [key, overrides?.[key] ?? fallback]));
@@ -1370,6 +712,11 @@ var GatewayClient = class {
1370
712
  },
1371
713
  notifyStoppedClose: true,
1372
714
  onConnectError: (error) => this.notifyConnectError(error),
715
+ onReconnectStopped: (error) => this.notifyReconnectPaused({
716
+ code: 1008,
717
+ reason: error.message,
718
+ detailCode: null
719
+ }),
1373
720
  onParseError: (error) => this.logDebug(`gateway client parse error: ${formatGatewayClientErrorForLog(error)}`),
1374
721
  onEvent: (event) => this.opts.onEvent?.(event),
1375
722
  onGap: (info) => this.opts.onGap?.(info),
@@ -1416,6 +763,9 @@ var GatewayClient = class {
1416
763
  }
1417
764
  createSocket(handlers) {
1418
765
  const url = this.opts.url ?? DEFAULT_GATEWAY_CLIENT_URL;
766
+ const configuredEdgeAuthHeaders = this.opts.edgeAuthHeaders;
767
+ const edgeAuthHeaders = configuredEdgeAuthHeaders && Object.keys(configuredEdgeAuthHeaders).length > 0 ? configuredEdgeAuthHeaders : void 0;
768
+ if (edgeAuthHeaders && new URL(url).protocol !== "wss:") throw new GatewayWebSocketTransportConfigurationError("edge auth headers require a wss:// Gateway URL");
1419
769
  const handshakeTimeoutMs = resolvePreauthHandshakeTimeoutMs({
1420
770
  env: this.opts.env,
1421
771
  configuredTimeoutMs: this.opts.preauthHandshakeTimeoutMs
@@ -1428,7 +778,11 @@ var GatewayClient = class {
1428
778
  options: {
1429
779
  maxPayload: 25 * 1024 * 1024,
1430
780
  handshakeTimeout: handshakeTimeoutMs,
1431
- ...this.opts.origin ? { origin: this.opts.origin } : {}
781
+ ...this.opts.origin ? { origin: this.opts.origin } : {},
782
+ ...edgeAuthHeaders ? {
783
+ followRedirects: false,
784
+ headers: edgeAuthHeaders
785
+ } : {}
1432
786
  }
1433
787
  });
1434
788
  this.deps.beforeConnect();
@@ -1451,14 +805,8 @@ var GatewayClient = class {
1451
805
  this.transportValidated = false;
1452
806
  let upgradeError;
1453
807
  ws.on("open", () => {
1454
- handlers.open();
1455
- const tlsError = transport.validateSocket(ws);
1456
- if (tlsError) {
1457
- handlers.error(tlsError);
1458
- ws.close(1008, tlsError.message);
1459
- return;
1460
- }
1461
808
  this.transportValidated = true;
809
+ handlers.open();
1462
810
  });
1463
811
  ws.on("message", (data) => handlers.message(rawDataToString(data)));
1464
812
  ws.on("close", (code, reason) => {
@@ -1470,13 +818,26 @@ var GatewayClient = class {
1470
818
  ws.on("unexpected-response", (request, response) => {
1471
819
  readUpgradeErrorBody(response).then((body) => {
1472
820
  const statusCode = response.statusCode;
821
+ let gatewayError;
822
+ try {
823
+ const parsed = JSON.parse(body);
824
+ const parsedError = isRecord(parsed) ? parsed.error : void 0;
825
+ gatewayError = isRecord(parsedError) ? parsedError : void 0;
826
+ } catch {}
827
+ const rawLocation = response.headers.location;
828
+ const location = rawLocation ? redactSensitiveUrlLikeString(Array.isArray(rawLocation) ? rawLocation[0] ?? "" : rawLocation) : void 0;
1473
829
  upgradeError = new GatewayClientRequestError({
1474
830
  code: "UNAVAILABLE",
1475
831
  message: `gateway rejected websocket upgrade (HTTP ${statusCode ?? "unknown"})${body ? `: ${body}` : ""}`,
1476
832
  retryable: true,
1477
833
  details: {
1478
834
  reason: "websocket-upgrade-rejected",
1479
- ...statusCode === void 0 ? {} : { httpStatus: statusCode }
835
+ ...statusCode === void 0 ? {} : { httpStatus: statusCode },
836
+ ...location ? { location } : {},
837
+ ...typeof gatewayError?.type === "string" ? {
838
+ gatewayErrorType: gatewayError.type,
839
+ ...typeof gatewayError.message === "string" ? { gatewayErrorMessage: gatewayError.message } : {}
840
+ } : {}
1480
841
  }
1481
842
  });
1482
843
  handlers.error(upgradeError);
@@ -1734,6 +1095,7 @@ var GatewayClient = class {
1734
1095
  closeReason: "connect retry"
1735
1096
  };
1736
1097
  }
1098
+ this.nodeProtocolTransitionPending = false;
1737
1099
  const role = this.opts.role ?? "operator";
1738
1100
  const detailCode = error instanceof GatewayClientRequestError ? readConnectErrorDetailCode(error.details) : null;
1739
1101
  const shouldRetryWithDeviceToken = shouldRetryGatewayWithDeviceToken({
@@ -1813,7 +1175,7 @@ var GatewayClient = class {
1813
1175
  const details = context.connectFailure?.error instanceof GatewayClientRequestError ? context.connectFailure.error.details : void 0;
1814
1176
  if (context.code === 1013 && context.connectFailure?.reconnectDelayMs !== void 0) return {
1815
1177
  retry: true,
1816
- notify: false,
1178
+ notify: this.opts.notifyOnStartupRetry === true,
1817
1179
  reconnectDelayMs: context.connectFailure.reconnectDelayMs
1818
1180
  };
1819
1181
  if (info.transientPreHelloCleanClose && this.suppressedTransientPreHelloCleanCloses < MAX_SUPPRESSED_TRANSIENT_PRE_HELLO_CLEAN_CLOSES) {
@@ -1834,6 +1196,7 @@ var GatewayClient = class {
1834
1196
  details,
1835
1197
  deviceTokenRetryPending: this.pendingDeviceTokenRetry,
1836
1198
  tokenMismatchIsTerminal: true,
1199
+ protocolMismatchIsTerminal: !this.nodeProtocolTransitionPending,
1837
1200
  clientVersionMismatchIsTerminal: true
1838
1201
  })) {
1839
1202
  this.notifyReconnectPaused({
@@ -1969,4 +1332,15 @@ function createGatewayRequestAbortError(method) {
1969
1332
  return err;
1970
1333
  }
1971
1334
  //#endregion
1972
- export { DEFAULT_GATEWAY_REQUEST_TIMEOUT_MS, DEFAULT_PREAUTH_HANDSHAKE_TIMEOUT_MS, GatewayBrowserDeviceAuthLifecycle, GatewayClient, GatewayClientRequestError, GatewayClientRequestTimeoutError, GatewayScopeUpgrade, GatewaySessionMessageSubscriptionCoordinator, MAX_CONNECT_CHALLENGE_TIMEOUT_MS, MAX_SAFE_TIMEOUT_DELAY_MS, MIN_CONNECT_CHALLENGE_TIMEOUT_MS, addSafeTimeoutDelayGraceMs, buildDeviceAuthPayload, buildDeviceAuthPayloadV3, buildGatewayConnectAuth, clampConnectChallengeTimeoutMs, clearGatewayConnectTimeout, createSessionProjection, gatewayCredentialScope, gatewayOriginScope, getConnectChallengeTimeoutMsFromEnv, getGatewaySessionMessageSubscriptionCoordinator, hasSessionProjectionAcceptedFinal, isGatewayConnectAssemblyError, isLocallyOptimisticSessionMessage, normalizeDeviceMetadataForAuth, normalizeSessionProjectionRunId, projectLiveSessionMessage, readSessionMessageIdentity, readSessionMessageSequence, reconcileSessionProjectionSnapshot, reduceSessionProjection, reduceSessionProjectionRunEvent, releaseGatewaySessionMessageSubscription, resetGatewaySessionMessageSubscriptionCoordinator, resolveConnectChallengeTimeoutMs, resolveFiniteTimeoutDelayMs, resolveGatewayConnectScopes, resolvePreauthHandshakeTimeoutMs, resolveSafeTimeoutDelayMs, selectGatewayConnectAuth, shouldRetryGatewayWithDeviceToken, startGatewayClientWhenEventLoopReady, startGatewayClientWithReadinessWait, startGatewayConnectTimeout, waitForEventLoopReady };
1335
+ //#region packages/gateway-client/src/cloudflare-access.ts
1336
+ const CF_ACCESS_CLIENT_ID_HEADER = "CF-Access-Client-Id";
1337
+ const CF_ACCESS_CLIENT_SECRET_HEADER = "CF-Access-Client-Secret";
1338
+ /** Build only the two headers Cloudflare Access defines for service-token auth. */
1339
+ function buildCloudflareAccessHeaders(credentials) {
1340
+ return {
1341
+ [CF_ACCESS_CLIENT_ID_HEADER]: credentials.clientId,
1342
+ [CF_ACCESS_CLIENT_SECRET_HEADER]: credentials.clientSecret
1343
+ };
1344
+ }
1345
+ //#endregion
1346
+ export { CF_ACCESS_CLIENT_ID_HEADER, CF_ACCESS_CLIENT_SECRET_HEADER, DEFAULT_GATEWAY_REQUEST_TIMEOUT_MS, DEFAULT_PREAUTH_HANDSHAKE_TIMEOUT_MS, GatewayBrowserDeviceAuthLifecycle, GatewayClient, GatewayClientRequestError, GatewayClientRequestTimeoutError, GatewayScopeUpgrade, GatewaySessionMessageSubscriptionCoordinator, MAX_CONNECT_CHALLENGE_TIMEOUT_MS, MAX_SAFE_TIMEOUT_DELAY_MS, MIN_CONNECT_CHALLENGE_TIMEOUT_MS, addSafeTimeoutDelayGraceMs, buildCloudflareAccessHeaders, buildDeviceAuthPayload, buildDeviceAuthPayloadV3, buildGatewayConnectAuth, clampConnectChallengeTimeoutMs, clearGatewayConnectTimeout, createSessionProjection, gatewayCredentialScope, gatewayOriginScope, getConnectChallengeTimeoutMsFromEnv, getGatewaySessionMessageSubscriptionCoordinator, hasSessionProjectionAcceptedFinal, isGatewayConnectAssemblyError, isLocallyOptimisticSessionMessage, normalizeDeviceMetadataForAuth, normalizeSessionProjectionRunId, projectLiveSessionMessage, readSessionMessageIdentity, readSessionMessageSequence, reconcileSessionProjectionSnapshot, reduceSessionProjection, reduceSessionProjectionRunEvent, releaseGatewaySessionMessageSubscription, resetGatewaySessionMessageSubscriptionCoordinator, resolveConnectChallengeTimeoutMs, resolveFiniteTimeoutDelayMs, resolveGatewayConnectScopes, resolvePreauthHandshakeTimeoutMs, resolveSafeTimeoutDelayMs, selectGatewayConnectAuth, shouldRetryGatewayWithDeviceToken, startGatewayClientWhenEventLoopReady, startGatewayClientWithReadinessWait, startGatewayConnectTimeout, waitForEventLoopReady };