@trillboards/edge-sdk 0.2.21 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/deploy/macos/scripts/setup-litertlm.sh +30 -0
  2. package/deploy/windows/e2e/test-enterprise-trust-store.ps1 +341 -0
  3. package/deploy/windows/setup-litertlm.ps1 +49 -1
  4. package/dist/AudienceAnalyzeClient.d.ts +32 -1
  5. package/dist/AudienceAnalyzeClient.d.ts.map +1 -1
  6. package/dist/AudienceAnalyzeClient.js +34 -5
  7. package/dist/AudienceAnalyzeClient.js.map +1 -1
  8. package/dist/CloudSensingManager.d.ts +30 -0
  9. package/dist/CloudSensingManager.d.ts.map +1 -1
  10. package/dist/CloudSensingManager.js +61 -1
  11. package/dist/CloudSensingManager.js.map +1 -1
  12. package/dist/EdgeAgent.js +1 -1
  13. package/dist/cli.d.ts.map +1 -1
  14. package/dist/cli.js +60 -0
  15. package/dist/cli.js.map +1 -1
  16. package/dist/diagnose.d.ts +37 -4
  17. package/dist/diagnose.d.ts.map +1 -1
  18. package/dist/diagnose.js +155 -6
  19. package/dist/diagnose.js.map +1 -1
  20. package/dist/enterpriseNetwork.d.ts +130 -0
  21. package/dist/enterpriseNetwork.d.ts.map +1 -0
  22. package/dist/enterpriseNetwork.js +568 -0
  23. package/dist/enterpriseNetwork.js.map +1 -0
  24. package/dist/enterpriseProxy.d.ts +73 -0
  25. package/dist/enterpriseProxy.d.ts.map +1 -0
  26. package/dist/enterpriseProxy.js +406 -0
  27. package/dist/enterpriseProxy.js.map +1 -0
  28. package/dist/enterpriseTrust.d.ts +188 -0
  29. package/dist/enterpriseTrust.d.ts.map +1 -0
  30. package/dist/enterpriseTrust.js +615 -0
  31. package/dist/enterpriseTrust.js.map +1 -0
  32. package/dist/index.d.ts +10 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +29 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/localNetworkAccess.d.ts +166 -0
  37. package/dist/localNetworkAccess.d.ts.map +1 -0
  38. package/dist/localNetworkAccess.js +490 -0
  39. package/dist/localNetworkAccess.js.map +1 -0
  40. package/dist/sensingRunMode.d.ts +36 -0
  41. package/dist/sensingRunMode.d.ts.map +1 -1
  42. package/dist/sensingRunMode.js +63 -1
  43. package/dist/sensingRunMode.js.map +1 -1
  44. package/dist/transportFailure.d.ts +118 -0
  45. package/dist/transportFailure.d.ts.map +1 -0
  46. package/dist/transportFailure.js +267 -0
  47. package/dist/transportFailure.js.map +1 -0
  48. package/package.json +1 -1
@@ -0,0 +1,406 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeProxyUrl = normalizeProxyUrl;
4
+ exports.pickWinInetProxy = pickWinInetProxy;
5
+ exports.findBypassRule = findBypassRule;
6
+ exports.parseRegQuery = parseRegQuery;
7
+ exports.parseNetshWinhttp = parseNetshWinhttp;
8
+ exports.parseScutilProxy = parseScutilProxy;
9
+ exports.resolveProxyForUrl = resolveProxyForUrl;
10
+ exports.describeProxy = describeProxy;
11
+ exports.redactProxyUrl = redactProxyUrl;
12
+ const child_process_1 = require("child_process");
13
+ /**
14
+ * enterpriseProxy — find the proxy the MACHINE is already configured to use.
15
+ *
16
+ * The connector's HTTP client is raw `node:https`, and unlike `curl`, `node:https`
17
+ * does NOT honour proxy environment variables implicitly: a proxy requires an
18
+ * explicit agent. Before this module nothing anywhere in the SDK read
19
+ * `HTTPS_PROXY`, `HTTP_PROXY` or `NO_PROXY`, and no `agent:` was ever passed —
20
+ * so on a site where direct egress is blocked and a proxy is mandatory, every
21
+ * call went direct and every call failed.
22
+ *
23
+ * NO NEW CONFIG KEY. This deliberately reads the platform's ACTUAL
24
+ * configuration rather than inventing a `proxyUrl` setting:
25
+ *
26
+ * - a new key would have to be set per install, by the person who least knows
27
+ * the value, on a machine whose browsers already have it;
28
+ * - the connector runs on a customer's PC and must resolve its proxy BEFORE
29
+ * its first network call, so a server-side tunable (`runtime_config`) could
30
+ * not be fetched in time to be useful — the fetch is the thing being fixed;
31
+ * - `HTTPS_PROXY`/`NO_PROXY` is what an IT admin already scripts, and on
32
+ * Windows the GPO-managed WinINET/WinHTTP settings are what the estate
33
+ * actually carries.
34
+ *
35
+ * Resolution order, first hit wins:
36
+ * 1. environment — `HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY` (+ lowercase)
37
+ * 2. Windows — WinINET (HKCU Internet Settings), then WinHTTP
38
+ * macOS — `scutil --proxy`
39
+ * Linux — environment only; there is no other system-wide source
40
+ *
41
+ * PAC / auto-config is DETECTED AND REPORTED, never silently ignored. Evaluating
42
+ * a PAC file means running the site's JavaScript with `dnsResolve`/`myIpAddress`
43
+ * host functions; we do not do that, and the honest outcome is to name the PAC
44
+ * URL in the failure so the operator can ask IT for the literal proxy — not to
45
+ * report "no proxy configured" on a machine that plainly has one.
46
+ */
47
+ /** Wall-clock budget for a proxy-reading subprocess. */
48
+ const PROXY_READ_TIMEOUT_MS = 10000;
49
+ function defaultExec(cmd, args) {
50
+ return (0, child_process_1.spawnSync)(cmd, args, {
51
+ encoding: 'utf-8',
52
+ timeout: PROXY_READ_TIMEOUT_MS,
53
+ maxBuffer: 1024 * 1024,
54
+ windowsHide: true,
55
+ });
56
+ }
57
+ /**
58
+ * Normalise whatever the platform gave us into an absolute proxy URL.
59
+ *
60
+ * WinINET stores `proxy:8080`, or a scheme-keyed list
61
+ * `http=p1:80;https=p2:8080`; `scutil` gives host and port separately; the
62
+ * environment usually has a full URL but is frequently set to a bare host:port.
63
+ * Returns null for anything that cannot be made into a URL, so a malformed
64
+ * setting degrades to DIRECT rather than to a crash on the request path.
65
+ */
66
+ function normalizeProxyUrl(raw) {
67
+ if (!raw)
68
+ return null;
69
+ const value = raw.trim();
70
+ if (!value)
71
+ return null;
72
+ const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(value) ? value : `http://${value}`;
73
+ try {
74
+ const url = new URL(withScheme);
75
+ if (!url.hostname)
76
+ return null;
77
+ // socks is a real thing an admin may set and one we cannot tunnel through
78
+ // without a SOCKS implementation; treat it as unsupported-but-named rather
79
+ // than pretend it is an HTTP proxy.
80
+ if (!/^https?:$/.test(url.protocol) && !/^socks/i.test(url.protocol))
81
+ return null;
82
+ return formatProxyUrl(url);
83
+ }
84
+ catch {
85
+ return null;
86
+ }
87
+ }
88
+ /**
89
+ * Render a proxy URL with its port ALWAYS explicit.
90
+ *
91
+ * `URL.toString()` drops a default port, so `http://p:80` comes back as
92
+ * `http://p` — harmless to reparse and actively confusing in the one line an
93
+ * operator reads to check what their proxy is. Rendering the port every time
94
+ * makes the log line and the customer's IT ticket agree.
95
+ */
96
+ function formatProxyUrl(url) {
97
+ const port = url.port || (url.protocol === 'https:' ? '443' : '80');
98
+ const credentials = url.username ? `${url.username}${url.password ? `:${url.password}` : ''}@` : '';
99
+ return `${url.protocol}//${credentials}${url.hostname}:${port}`;
100
+ }
101
+ /** Pick the `https=` (or `http=`) entry out of a WinINET scheme-keyed list. */
102
+ function pickWinInetProxy(proxyServer, targetProtocol) {
103
+ if (!proxyServer)
104
+ return null;
105
+ if (!proxyServer.includes('='))
106
+ return normalizeProxyUrl(proxyServer);
107
+ const wanted = targetProtocol === 'https:' ? 'https' : 'http';
108
+ const parts = proxyServer.split(';').map((p) => p.trim()).filter(Boolean);
109
+ const map = new Map();
110
+ for (const part of parts) {
111
+ const eq = part.indexOf('=');
112
+ if (eq <= 0)
113
+ continue;
114
+ map.set(part.slice(0, eq).trim().toLowerCase(), part.slice(eq + 1).trim());
115
+ }
116
+ // Fall back to the http entry: an appliance that lists only `http=` almost
117
+ // always accepts CONNECT on the same port, and a wrong-but-named proxy fails
118
+ // LOUDLY as `proxy_rejected`, which is a far better answer than going direct
119
+ // on a network where direct egress is blocked and hanging.
120
+ return normalizeProxyUrl(map.get(wanted) ?? map.get('http') ?? null);
121
+ }
122
+ /**
123
+ * Does a bypass list exempt this host?
124
+ *
125
+ * Accepts both the POSIX `NO_PROXY` vocabulary and the Windows `ProxyOverride`
126
+ * vocabulary, because the same function serves both:
127
+ * `*` — everything
128
+ * `<local>` — Windows: any hostname with no dot in it
129
+ * `.corp.local` — that suffix
130
+ * `corp.local` — that host and its subdomains
131
+ * `*.corp.local` — same, wildcard spelling
132
+ * `10.0.0.7` — that literal address
133
+ * `host:8080` — that host, only on that port
134
+ *
135
+ * Returns the matching entry (so the caller can SAY which rule applied) or null.
136
+ */
137
+ function findBypassRule(host, port, bypassList) {
138
+ if (!host)
139
+ return null;
140
+ const target = host.toLowerCase().replace(/^\[|\]$/g, '');
141
+ // Loopback and link-local ALWAYS bypass, whatever the list says. The connector
142
+ // talks to `127.0.0.1:9379` (the local litert-lm server) on the same global
143
+ // agent as the cloud; routing that through a corporate proxy would break local
144
+ // inference on exactly the machines this change exists to support.
145
+ if (target === 'localhost' ||
146
+ target === '::1' ||
147
+ /^127\./.test(target) ||
148
+ /^169\.254\./.test(target) ||
149
+ /^fe80:/i.test(target)) {
150
+ return 'loopback/link-local (always direct)';
151
+ }
152
+ if (!bypassList)
153
+ return null;
154
+ for (const rawEntry of bypassList.split(/[,;]/)) {
155
+ const entry = rawEntry.trim().toLowerCase();
156
+ if (!entry)
157
+ continue;
158
+ if (entry === '*')
159
+ return rawEntry.trim();
160
+ if (entry === '<local>') {
161
+ if (!target.includes('.'))
162
+ return rawEntry.trim();
163
+ continue;
164
+ }
165
+ let pattern = entry;
166
+ let entryPort;
167
+ const colon = pattern.lastIndexOf(':');
168
+ // Only treat a trailing `:digits` as a port; an IPv6 literal has many colons.
169
+ if (colon > 0 && /^\d+$/.test(pattern.slice(colon + 1))) {
170
+ entryPort = pattern.slice(colon + 1);
171
+ pattern = pattern.slice(0, colon);
172
+ }
173
+ if (entryPort && String(port ?? '') !== entryPort)
174
+ continue;
175
+ if (pattern.startsWith('*.'))
176
+ pattern = pattern.slice(1); // `*.x` -> `.x`
177
+ if (pattern.startsWith('.')) {
178
+ if (target.endsWith(pattern) || target === pattern.slice(1))
179
+ return rawEntry.trim();
180
+ continue;
181
+ }
182
+ if (target === pattern || target.endsWith(`.${pattern}`))
183
+ return rawEntry.trim();
184
+ }
185
+ return null;
186
+ }
187
+ function envProxy(env, protocol) {
188
+ // Uppercase first, then lowercase — both spellings are in the wild, and
189
+ // `http_proxy` (lowercase) is the one convention says is authoritative for
190
+ // plain HTTP because of a historical CGI header-injection hazard.
191
+ const names = protocol === 'https:'
192
+ ? ['HTTPS_PROXY', 'https_proxy', 'ALL_PROXY', 'all_proxy']
193
+ : ['HTTP_PROXY', 'http_proxy', 'ALL_PROXY', 'all_proxy'];
194
+ for (const name of names) {
195
+ const url = normalizeProxyUrl(env[name]);
196
+ if (url)
197
+ return { url, name };
198
+ }
199
+ return { url: null };
200
+ }
201
+ const WININET_KEY = 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings';
202
+ /** Parse `reg.exe query` output into a name -> value map. */
203
+ function parseRegQuery(stdout) {
204
+ const out = {};
205
+ for (const line of (stdout || '').split(/\r?\n/)) {
206
+ // ` ProxyServer REG_SZ proxy.corp:8080`
207
+ const m = line.match(/^\s{2,}(\S+)\s+(REG_[A-Z_]+)\s+(.*)$/);
208
+ if (!m)
209
+ continue;
210
+ out[m[1]] = m[3].trim();
211
+ }
212
+ return out;
213
+ }
214
+ /** Parse `netsh winhttp show proxy` output. */
215
+ function parseNetshWinhttp(stdout) {
216
+ const text = stdout || '';
217
+ if (/direct access/i.test(text))
218
+ return { server: null, bypass: null };
219
+ const server = text.match(/Proxy Server\(s\)\s*:\s*(.+)/i)?.[1]?.trim() || null;
220
+ const bypass = text.match(/Bypass List\s*:\s*(.+)/i)?.[1]?.trim() || null;
221
+ return { server: server && server !== '(none)' ? server : null, bypass };
222
+ }
223
+ /** Parse `scutil --proxy` output into a flat map (arrays are joined with `,`). */
224
+ function parseScutilProxy(stdout) {
225
+ const out = {};
226
+ const exceptions = [];
227
+ let inExceptions = false;
228
+ for (const line of (stdout || '').split(/\r?\n/)) {
229
+ const trimmed = line.trim();
230
+ if (/^ExceptionsList\s*:\s*<array>/.test(trimmed)) {
231
+ inExceptions = true;
232
+ continue;
233
+ }
234
+ if (inExceptions) {
235
+ if (trimmed === '}') {
236
+ inExceptions = false;
237
+ continue;
238
+ }
239
+ const item = trimmed.match(/^\d+\s*:\s*(.+)$/);
240
+ if (item)
241
+ exceptions.push(item[1].trim());
242
+ continue;
243
+ }
244
+ const m = trimmed.match(/^([A-Za-z0-9]+)\s*:\s*(.+)$/);
245
+ if (m)
246
+ out[m[1]] = m[2].trim();
247
+ }
248
+ if (exceptions.length > 0)
249
+ out.ExceptionsList = exceptions.join(',');
250
+ return out;
251
+ }
252
+ function windowsProxy(opts, protocol) {
253
+ const exec = opts.exec ?? defaultExec;
254
+ const warnings = [];
255
+ let autoConfigUrl;
256
+ // WinINET first: it is per-user, it is what browsers use, and it is what a GPO
257
+ // "Configure proxy settings" policy writes.
258
+ const reg = exec('reg.exe', ['query', WININET_KEY]);
259
+ if (reg.error) {
260
+ warnings.push(`WinINET proxy: reg.exe failed (${reg.error.message})`);
261
+ }
262
+ else if (reg.status === 0) {
263
+ const values = parseRegQuery(reg.stdout || '');
264
+ const auto = values.AutoConfigURL;
265
+ if (auto)
266
+ autoConfigUrl = auto;
267
+ const enabled = values.ProxyEnable && /^0x0*[1-9a-f]/i.test(values.ProxyEnable);
268
+ if (enabled && values.ProxyServer) {
269
+ const url = pickWinInetProxy(values.ProxyServer, protocol);
270
+ if (url) {
271
+ return { url, source: 'wininet', bypass: values.ProxyOverride || null, autoConfigUrl, warnings };
272
+ }
273
+ warnings.push(`WinINET proxy: could not parse ProxyServer="${values.ProxyServer}"`);
274
+ }
275
+ }
276
+ // WinHTTP: the machine-wide store, used by services and by anything that never
277
+ // logs a user in. On this product the connector runs as an interactive user,
278
+ // so this is the fallback rather than the primary.
279
+ const netsh = exec('netsh.exe', ['winhttp', 'show', 'proxy']);
280
+ if (netsh.error) {
281
+ warnings.push(`WinHTTP proxy: netsh failed (${netsh.error.message})`);
282
+ }
283
+ else if (netsh.status === 0) {
284
+ const parsed = parseNetshWinhttp(netsh.stdout || '');
285
+ const url = parsed.server ? pickWinInetProxy(parsed.server, protocol) : null;
286
+ if (url)
287
+ return { url, source: 'winhttp', bypass: parsed.bypass, autoConfigUrl, warnings };
288
+ }
289
+ return { url: null, source: 'none', bypass: null, autoConfigUrl, warnings };
290
+ }
291
+ function macProxy(opts, protocol) {
292
+ const exec = opts.exec ?? defaultExec;
293
+ const warnings = [];
294
+ const result = exec('/usr/sbin/scutil', ['--proxy']);
295
+ if (result.error) {
296
+ warnings.push(`macOS proxy: scutil failed (${result.error.message})`);
297
+ return { url: null, source: 'none', bypass: null, warnings };
298
+ }
299
+ if (result.status !== 0) {
300
+ warnings.push(`macOS proxy: scutil exited ${result.status}`);
301
+ return { url: null, source: 'none', bypass: null, warnings };
302
+ }
303
+ const values = parseScutilProxy(result.stdout || '');
304
+ const autoConfigUrl = values.ProxyAutoConfigEnable === '1' ? values.ProxyAutoConfigURLString : undefined;
305
+ const prefix = protocol === 'https:' ? 'HTTPS' : 'HTTP';
306
+ const enabled = values[`${prefix}Enable`] === '1';
307
+ const host = values[`${prefix}Proxy`];
308
+ const port = values[`${prefix}Port`];
309
+ if (enabled && host) {
310
+ return {
311
+ url: normalizeProxyUrl(port ? `${host}:${port}` : host),
312
+ source: 'macos-scutil',
313
+ bypass: values.ExceptionsList || null,
314
+ autoConfigUrl,
315
+ warnings,
316
+ };
317
+ }
318
+ return { url: null, source: 'none', bypass: null, autoConfigUrl, warnings };
319
+ }
320
+ /**
321
+ * The whole decision for one target URL: which proxy (if any), or why not.
322
+ *
323
+ * Pure with respect to its options, so the platform branches are all testable
324
+ * off their native platform — which is the only way the Windows path gets any
325
+ * coverage at all from a Linux CI lane.
326
+ */
327
+ function resolveProxyForUrl(targetUrl, opts = {}) {
328
+ const env = opts.env ?? process.env;
329
+ const platform = opts.platform ?? process.platform;
330
+ const warnings = [];
331
+ let target;
332
+ try {
333
+ target = new URL(targetUrl);
334
+ }
335
+ catch {
336
+ return { proxyUrl: null, source: 'none', warnings: [`unparseable target URL: ${targetUrl}`] };
337
+ }
338
+ const port = target.port ? Number(target.port) : target.protocol === 'https:' ? 443 : 80;
339
+ // NO_PROXY is checked FIRST and against the environment regardless of where
340
+ // the proxy itself came from: an admin who exports NO_PROXY means it.
341
+ const noProxy = env.NO_PROXY ?? env.no_proxy;
342
+ const envBypass = findBypassRule(target.hostname, port, noProxy);
343
+ const fromEnv = envProxy(env, target.protocol);
344
+ if (fromEnv.url) {
345
+ if (envBypass) {
346
+ return { proxyUrl: null, source: 'env', bypassedBy: envBypass, warnings };
347
+ }
348
+ return { proxyUrl: fromEnv.url, source: 'env', warnings };
349
+ }
350
+ let platformResult;
351
+ if (platform === 'win32')
352
+ platformResult = windowsProxy(opts, target.protocol);
353
+ else if (platform === 'darwin')
354
+ platformResult = macProxy(opts, target.protocol);
355
+ else
356
+ platformResult = { url: null, source: 'none', bypass: null, warnings: [] };
357
+ warnings.push(...platformResult.warnings);
358
+ // The loopback rule must hold even when nothing at all is configured, so run
359
+ // the bypass check on the platform list (or an empty one) either way.
360
+ const bypass = envBypass ?? findBypassRule(target.hostname, port, platformResult.bypass);
361
+ if (platformResult.url && !bypass) {
362
+ return {
363
+ proxyUrl: platformResult.url,
364
+ source: platformResult.source,
365
+ autoConfigUrl: platformResult.autoConfigUrl,
366
+ warnings,
367
+ };
368
+ }
369
+ return {
370
+ proxyUrl: null,
371
+ source: platformResult.url ? platformResult.source : 'none',
372
+ ...(bypass ? { bypassedBy: bypass } : {}),
373
+ ...(platformResult.autoConfigUrl ? { autoConfigUrl: platformResult.autoConfigUrl } : {}),
374
+ warnings,
375
+ };
376
+ }
377
+ /** One operator-facing line describing the proxy decision. */
378
+ function describeProxy(resolution) {
379
+ if (resolution.proxyUrl) {
380
+ return `proxy: ${redactProxyUrl(resolution.proxyUrl)} (from ${resolution.source})`;
381
+ }
382
+ if (resolution.bypassedBy) {
383
+ return `proxy: direct — bypass rule "${resolution.bypassedBy}"`;
384
+ }
385
+ if (resolution.autoConfigUrl) {
386
+ return (`proxy: NOT USED — this machine is configured by an auto-config (PAC) script ` +
387
+ `at ${resolution.autoConfigUrl}, which this build cannot evaluate. ` +
388
+ `Set HTTPS_PROXY to the literal proxy that PAC file returns.`);
389
+ }
390
+ return 'proxy: direct (none configured)';
391
+ }
392
+ /** Strip proxy credentials before anything is logged. */
393
+ function redactProxyUrl(proxyUrl) {
394
+ try {
395
+ const url = new URL(proxyUrl);
396
+ if (url.username || url.password) {
397
+ url.username = '***';
398
+ url.password = '';
399
+ }
400
+ return formatProxyUrl(url);
401
+ }
402
+ catch {
403
+ return proxyUrl;
404
+ }
405
+ }
406
+ //# sourceMappingURL=enterpriseProxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enterpriseProxy.js","sourceRoot":"","sources":["../src/enterpriseProxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,188 @@
1
+ import { type SpawnSyncReturns } from 'child_process';
2
+ /**
3
+ * enterpriseTrust — read the MACHINE's trust decision, and add it to ours.
4
+ *
5
+ * WHY THIS EXISTS
6
+ * ---------------
7
+ * Retail and restaurant chains run TLS-inspecting proxies: every outbound
8
+ * HTTPS connection is terminated by an appliance which re-signs it with a
9
+ * private enterprise root. That root is installed on the machine, so every
10
+ * browser on it works. Node does NOT read the platform trust store — it ships
11
+ * its own Mozilla-derived list and consults nothing else — so the connector was
12
+ * the one thing on the machine that could not talk to us.
13
+ *
14
+ * The failure had the worst possible shape. On a fresh install `uv` died first
15
+ * and the installer aborted blaming local AI; on the REPAIR path (where uv and
16
+ * litert-lm are already present, `setup-litertlm.ps1`'s `Test-LitertLmCli`
17
+ * short-circuit) the install COMPLETED and the connector then silently could
18
+ * not reach the API — a background process, no window, on a machine the
19
+ * customer believes is working.
20
+ *
21
+ * WHAT THIS IS NOT
22
+ * ----------------
23
+ * It is not a way to skip verification. There is no `rejectUnauthorized:false`
24
+ * here or anywhere in this tree and there must never be one — a connector that
25
+ * accepts any certificate is strictly worse than one that cannot connect,
26
+ * because it fails silently and in the customer's favour-looking direction.
27
+ * What we do is ADD the roots the machine's owner has already chosen to trust.
28
+ * Node's bundled list is always kept as the base (see `buildCaBundle`), so this
29
+ * can only ever widen trust to what this machine already trusts, never narrow
30
+ * it and never bypass it.
31
+ *
32
+ * RUNTIME RESOLUTION, NOT AN INSTALL-TIME EXPORT
33
+ * ----------------------------------------------
34
+ * The other design on the table was to export the machine roots to a .pem at
35
+ * install time and point `NODE_EXTRA_CA_CERTS` at it from the launcher. That is
36
+ * cheaper and it is wrong, for a reason specific to this product:
37
+ *
38
+ * - The normal order of operations is domain-join, then install, then IT
39
+ * ROTATES the inspection root (annually, or the day the appliance is
40
+ * replaced). An exported bundle is a snapshot: at the next rotation the
41
+ * connector breaks again with the exact same silent symptom.
42
+ * - Nothing would re-export it. There is no auto-update on Windows
43
+ * (cctv-connector-windows-gtm-readiness.md §5 — `install-update.ps1` is the
44
+ * installer's own in-place upgrade path and nothing polls), so a stale
45
+ * bundle would sit on the machine until the customer manually re-downloaded
46
+ * 2.6 GB.
47
+ * - `NODE_EXTRA_CA_CERTS` is read ONCE at process start, so even a correct
48
+ * file cannot be picked up without a restart.
49
+ *
50
+ * So we read the store at runtime, cache it for `TRUST_CACHE_TTL_MS`, and
51
+ * invalidate eagerly the moment a certificate-verification failure is
52
+ * classified (`invalidateTrustAnchorCache`, called from the transport). A root
53
+ * installed by IT while the connector is running is therefore picked up on the
54
+ * next cadence tick without a restart, which is the behaviour an operator on
55
+ * the phone with IT actually needs.
56
+ *
57
+ * `NODE_EXTRA_CA_CERTS` is still honoured — see `readNodeExtraCaCerts`. That
58
+ * matters more than it looks: passing `ca:` to a request REPLACES Node's
59
+ * resolved CA set, which silently disables `NODE_EXTRA_CA_CERTS` for that
60
+ * request. An admin who had already worked around this bug with that variable
61
+ * would have had their workaround broken by the fix. We read it ourselves.
62
+ */
63
+ /** How long a trust-store read is reused before being taken again. */
64
+ export declare const TRUST_CACHE_TTL_MS: number;
65
+ export interface TrustAnchorSource {
66
+ /** Operator-facing name of the store, e.g. `LocalMachine\Root`. */
67
+ name: string;
68
+ /** How many distinct PEM certificates came from it. */
69
+ count: number;
70
+ }
71
+ export interface TrustAnchorResolution {
72
+ /** PEM blocks to ADD to Node's bundled roots. Deduplicated. */
73
+ certs: string[];
74
+ /** Which stores contributed, in read order. */
75
+ sources: TrustAnchorSource[];
76
+ /**
77
+ * Non-fatal problems. A warning here means "one store could not be read", not
78
+ * "trust is broken" — the others still contributed and Node's bundled roots
79
+ * are always present.
80
+ */
81
+ warnings: string[];
82
+ /** Epoch ms this snapshot was taken. It is a snapshot; see the file header. */
83
+ resolvedAtMs: number;
84
+ /** The platform whose stores were read (`process.platform` at read time). */
85
+ platform: NodeJS.Platform;
86
+ }
87
+ /** Injectable seams so the readers are testable off their native platform. */
88
+ export interface TrustAnchorReadOptions {
89
+ platform?: NodeJS.Platform;
90
+ /** Replaces the subprocess runner (Windows/macOS store readers). */
91
+ exec?: (cmd: string, args: string[]) => SpawnSyncReturns<string>;
92
+ /** Replaces file reads (Linux bundles, NODE_EXTRA_CA_CERTS). */
93
+ readFile?: (p: string) => string;
94
+ /** Replaces the environment lookup (NODE_EXTRA_CA_CERTS, SSL_CERT_FILE). */
95
+ env?: NodeJS.ProcessEnv;
96
+ }
97
+ /**
98
+ * Pull the PEM blocks out of arbitrary text.
99
+ *
100
+ * Deliberately a scan and not a parse: `security find-certificate -p` and
101
+ * `/etc/ssl/certs/ca-certificates.crt` both interleave human-readable headers
102
+ * between blocks, and OpenSSL is happy to be handed the blocks alone.
103
+ */
104
+ export declare function extractPemBlocks(text: string): string[];
105
+ export declare function readWindowsTrustAnchors(opts?: TrustAnchorReadOptions): {
106
+ certs: string[];
107
+ sources: TrustAnchorSource[];
108
+ warnings: string[];
109
+ };
110
+ /**
111
+ * Subjects the admin has explicitly set to "Never Trust" in the admin domain.
112
+ *
113
+ * `security find-certificate` lists what is STORED in a keychain, not what is
114
+ * TRUSTED — a certificate the admin has explicitly denied is still returned by
115
+ * it. Promoting one of those to a trust anchor would invert the machine
116
+ * owner's decision, which is the exact opposite of what this module exists to
117
+ * honour. `dump-trust-settings -d` is the admin-domain override list; each
118
+ * entry names a certificate and its result type.
119
+ *
120
+ * Parsed loosely on purpose: an unreadable or absent settings list must mean
121
+ * "no explicit overrides", never "drop everything". Exported for the fixture
122
+ * tests, which drive it with the real command's output shape.
123
+ */
124
+ export declare function parseDeniedTrustSubjects(dump: string): Set<string>;
125
+ export declare function readMacTrustAnchors(opts?: TrustAnchorReadOptions): {
126
+ certs: string[];
127
+ sources: TrustAnchorSource[];
128
+ warnings: string[];
129
+ };
130
+ export declare function readLinuxTrustAnchors(opts?: TrustAnchorReadOptions): {
131
+ certs: string[];
132
+ sources: TrustAnchorSource[];
133
+ warnings: string[];
134
+ };
135
+ /**
136
+ * `NODE_EXTRA_CA_CERTS`, read EXPLICITLY.
137
+ *
138
+ * Node applies this variable to the default secure context. Passing `ca:` on a
139
+ * request replaces that context's CA set, so wiring an agent with `ca:` and
140
+ * nothing else would have silently disabled an admin's existing workaround for
141
+ * this very bug. We therefore read it ourselves and merge it in.
142
+ */
143
+ export declare function readNodeExtraCaCerts(opts?: TrustAnchorReadOptions): {
144
+ certs: string[];
145
+ sources: TrustAnchorSource[];
146
+ warnings: string[];
147
+ };
148
+ /** Read every store this platform has. Uncached — see `resolveTrustAnchors`. */
149
+ export declare function readPlatformTrustAnchors(opts?: TrustAnchorReadOptions): TrustAnchorResolution;
150
+ /**
151
+ * The cached read. Callers on the request path use this; it costs one
152
+ * subprocess per TTL, not one per request.
153
+ *
154
+ * The cache holds ONE snapshot with no key, which is valid exactly while the
155
+ * platform and environment are process-wide constants — true in production, and
156
+ * NOT true when a caller injects them. An injected `platform`/`exec`/`readFile`/
157
+ * `env` therefore bypasses the cache in both directions: it neither reads a
158
+ * snapshot taken under a different environment nor publishes its own for
159
+ * someone else to read. (Same rule, same reason, as `resolveProxyCached`.)
160
+ */
161
+ export declare function resolveTrustAnchors(opts?: TrustAnchorReadOptions): TrustAnchorResolution;
162
+ /**
163
+ * Drop the cache so the next resolve re-reads the store.
164
+ *
165
+ * Called when a certificate-verification failure is classified: the single most
166
+ * likely explanation for one is that IT has just deployed (or is about to
167
+ * deploy) the inspection root, and re-reading is how the connector recovers
168
+ * without the restart nobody is there to perform.
169
+ */
170
+ export declare function invalidateTrustAnchorCache(): void;
171
+ /** For tests: the snapshot currently held, without taking a new one. */
172
+ export declare function peekTrustAnchorCache(): TrustAnchorResolution | null;
173
+ /**
174
+ * The `ca` value to hand to TLS: Node's bundled roots FIRST, then the machine's.
175
+ *
176
+ * Including `tls.rootCertificates` is the load-bearing half. `ca:` REPLACES the
177
+ * default set rather than extending it, so passing only the machine anchors
178
+ * would have made a connector on a normal network stop trusting the public web
179
+ * PKI — turning a corporate-network bug into a fleet-wide outage. Returns
180
+ * `undefined` when there is nothing to add, so the default context is used
181
+ * untouched on the overwhelming majority of hosts.
182
+ */
183
+ export declare function buildCaBundle(anchors: TrustAnchorResolution): string[] | undefined;
184
+ /** One operator-facing line describing what was resolved. */
185
+ export declare function describeTrustAnchors(anchors: TrustAnchorResolution): string;
186
+ /** Platform-appropriate instruction for getting a root INTO the store. */
187
+ export declare function trustStoreInstallHint(platform?: NodeJS.Platform): string;
188
+ //# sourceMappingURL=enterpriseTrust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enterpriseTrust.d.ts","sourceRoot":"","sources":["../src/enterpriseTrust.ts"],"names":[],"mappings":"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"}