@plannotator/pi-extension 0.28.32 → 0.28.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/README.md +4 -2
- package/index.ts +4 -0
- package/package.json +3 -4
- package/plannotator.html +2 -2
- package/review-editor.html +2 -2
- package/runtime-tls.ts +93 -0
package/runtime-tls.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One quiet warning when Pi runs on a runtime without the October 2026 TLS
|
|
3
|
+
* fixes (the compromised eMudhra certificate authority): Node 22.23.4,
|
|
4
|
+
* 24.22.1 and 26.12.1 (NSS 3.131.1 roots, chains with blocked keys rejected,
|
|
5
|
+
* nodejs/node#66871), Bun 1.4.4.
|
|
6
|
+
*
|
|
7
|
+
* This replaces the package's `engines.node` floor (#902): npm passes over a
|
|
8
|
+
* release whose engines the running Node misses when it resolves a bare name
|
|
9
|
+
* or a range, so Pi on an older Node silently stayed on an old Plannotator,
|
|
10
|
+
* with no gain (the old version runs on the same Node). Updates must always
|
|
11
|
+
* install; the warning says what to fix instead.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
type Triple = readonly [number, number, number];
|
|
15
|
+
|
|
16
|
+
/** The first fixed release on each Node line that has one. 20 and older, 23 and 25 have none. */
|
|
17
|
+
const NODE_FIXED: readonly Triple[] = [
|
|
18
|
+
[22, 23, 4],
|
|
19
|
+
[24, 22, 1],
|
|
20
|
+
[26, 12, 1],
|
|
21
|
+
];
|
|
22
|
+
const BUN_FIXED: Triple = [1, 4, 4];
|
|
23
|
+
|
|
24
|
+
function parse(version: string | undefined): Triple | null {
|
|
25
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(version ?? "");
|
|
26
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function atLeast(a: Triple, b: Triple): boolean {
|
|
30
|
+
for (let i = 0; i < 3; i++) {
|
|
31
|
+
if (a[i]! !== b[i]!) return a[i]! > b[i]!;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function nodeFixed(v: Triple): boolean {
|
|
37
|
+
const last = NODE_FIXED[NODE_FIXED.length - 1]!;
|
|
38
|
+
if (v[0] > last[0]) return true;
|
|
39
|
+
const line = NODE_FIXED.find((fixed) => fixed[0] === v[0]);
|
|
40
|
+
return !!line && atLeast(v, line);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Whether this process is a Bun-compiled program (Pi's standalone binary)
|
|
45
|
+
* rather than the `bun` executable running Pi: a compiled program's execPath
|
|
46
|
+
* is the program itself. Its Bun comes with it, so the fix is a newer Pi.
|
|
47
|
+
*/
|
|
48
|
+
function bunCompiled(execPath: string): boolean {
|
|
49
|
+
const name = execPath.split(/[\\/]/).pop()?.toLowerCase() ?? "";
|
|
50
|
+
return !/^bun(-debug)?(\.exe)?$/.test(name);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The warning for this runtime, or null when it has the fixes (or its version
|
|
55
|
+
* can't be read). Bun is checked first: it reports a Node-compatible
|
|
56
|
+
* `process.versions.node` but brings its own TLS and root store.
|
|
57
|
+
*/
|
|
58
|
+
export function runtimeTlsWarning(
|
|
59
|
+
versions: Partial<Record<string, string>> = process.versions,
|
|
60
|
+
execPath: string = process.execPath,
|
|
61
|
+
): string | null {
|
|
62
|
+
if (versions.bun) {
|
|
63
|
+
const bun = parse(versions.bun);
|
|
64
|
+
if (!bun || atLeast(bun, BUN_FIXED)) return null;
|
|
65
|
+
return bunCompiled(execPath)
|
|
66
|
+
? `Plannotator: this Pi build runs on Bun v${versions.bun}, which is missing the October 2026 TLS fixes (a compromised certificate authority); update Pi to a build with Bun 1.4.4 or later.`
|
|
67
|
+
: `Plannotator: your Bun v${versions.bun} is missing the October 2026 TLS fixes (a compromised certificate authority); update Bun to 1.4.4 or later.`;
|
|
68
|
+
}
|
|
69
|
+
const node = parse(versions.node);
|
|
70
|
+
if (!node || nodeFixed(node)) return null;
|
|
71
|
+
return `Plannotator: your Node v${versions.node} is missing the October 2026 TLS fixes (a compromised certificate authority); update to 22.23.4, 24.22.1 or 26.12.1 or later.`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const WARNED = Symbol.for("plannotator.pi.runtimeTlsWarned");
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Show the warning at most once per Pi start: the latch lives on globalThis,
|
|
78
|
+
* so a `/reload` (which imports the extension again) or a new session does not
|
|
79
|
+
* repeat it. Returns whether it was shown.
|
|
80
|
+
*/
|
|
81
|
+
export function warnRuntimeTlsOnce(
|
|
82
|
+
notify: (message: string) => void,
|
|
83
|
+
versions: Partial<Record<string, string>> = process.versions,
|
|
84
|
+
execPath: string = process.execPath,
|
|
85
|
+
): boolean {
|
|
86
|
+
const store = globalThis as Record<symbol, unknown>;
|
|
87
|
+
if (store[WARNED]) return false;
|
|
88
|
+
const warning = runtimeTlsWarning(versions, execPath);
|
|
89
|
+
if (!warning) return false;
|
|
90
|
+
store[WARNED] = true;
|
|
91
|
+
notify(warning);
|
|
92
|
+
return true;
|
|
93
|
+
}
|