Merge reviewed candidate 20260919T204043Z-web-product (pulse 698d08d2e9)

Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot] 2026-09-19 22:09:10 +01:00
commit 22fd851e72
4 changed files with 52 additions and 9 deletions

View file

@ -2366,6 +2366,17 @@ artifact-selection behaviour.
`scripts/trigger-release.sh` and `scripts/trigger-stable-patch.sh` must send
the exact remote candidate SHA they already verified; branch ancestry or a
later branch tip is not equivalent release admission.
18. Keep the frontend type-surface dependency and its compiler lib aligned.
`frontend-modern/package.json` and `frontend-modern/package-lock.json` must
pin a single `@types/node` line at or above the reviewed floor with its
`undici-types` companion resolved consistently, and
`frontend-modern/tsconfig.json` must declare the `ES2022` lib whenever the
source uses `Array.prototype.at()`/`String.prototype.at()`. `@types/node`
before 26 shipped an `.at()` compatibility polyfill that masked the missing
lib; a bump that removes it must keep
`frontend-modern/src/security/__tests__/dependencySecurity.test.ts` proving
the manifest range, the locked `@types/node`/`undici-types` versions and the
`ES2022` lib declaration stay in step.
## Current State

View file

@ -22,7 +22,7 @@
"@solidjs/testing-library": "^0.8.5",
"@tailwindcss/typography": "^0.5.19",
"@testing-library/jest-dom": "^6.5.0",
"@types/node": "^20.10.0",
"@types/node": "^26.5.1",
"@types/qrcode": "^1.5.6",
"@typescript-eslint/eslint-plugin": "^8.24.0",
"@typescript-eslint/parser": "^8.24.0",
@ -1969,13 +1969,13 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "20.19.43",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
"integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
"version": "26.5.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.5.1.tgz",
"integrity": "sha512-CzNm2FezW4VR/LjG6yUdiEgLE/rAQ9Slj5gCu/C2VrdcW7I0ahNZ8DRbHT7zOZ6r3ONgd/bsQIeSaoDGrd1C6g==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
"undici-types": "~8.9.0"
}
},
"node_modules/@types/qrcode": {
@ -6473,9 +6473,9 @@
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz",
"integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==",
"dev": true,
"license": "MIT"
},

View file

@ -73,7 +73,7 @@
"@solidjs/testing-library": "^0.8.5",
"@tailwindcss/typography": "^0.5.19",
"@testing-library/jest-dom": "^6.5.0",
"@types/node": "^20.10.0",
"@types/node": "^26.5.1",
"@types/qrcode": "^1.5.6",
"@typescript-eslint/eslint-plugin": "^8.24.0",
"@typescript-eslint/parser": "^8.24.0",

View file

@ -20,6 +20,13 @@ const lock = JSON.parse(
readFileSync(new URL('../../../package-lock.json', import.meta.url), 'utf8'),
) as PackageLock;
const tsconfig = readFileSync(new URL('../../../tsconfig.json', import.meta.url), 'utf8');
const libMatch = /"lib"\s*:\s*\[([^\]]*)\]/.exec(tsconfig);
const declaredLib = (libMatch?.[1] ?? '')
.split(',')
.map((entry) => entry.trim().replace(/^"|"$/g, ''))
.filter(Boolean);
const parseVersion = (version: string): [number, number, number] => {
const [major = 0, minor = 0, patch = 0] = version
.split('-', 1)[0]
@ -139,4 +146,29 @@ describe('frontend dependency security floors', () => {
expect(atLeast(version, [4, 28, 7]), `browserslist ${version} is vulnerable`).toBe(true);
}
});
it('keeps @types/node and its undici-types companion aligned with the declared ES2022 lib', () => {
// @types/node 20 shipped an .at() compatibility polyfill that masked the
// missing ES2022 lib; 26 drops it, so tsconfig must declare ES2022 itself
// (Dependabot #2099). Keep the manifest range, the lock and the lib in step.
const range = manifest.devDependencies['@types/node'];
expect(/^\^26\.\d+\.\d+$/.test(range), `unexpected @types/node range ${range}`).toBe(true);
expect(atLeast(range.slice(1), [26, 5, 1])).toBe(true);
const nodeTypes = lockedVersions('@types/node');
expect(nodeTypes).toHaveLength(1);
expect(nodeTypes[0]).not.toContain('-');
expect(
atLeast(nodeTypes[0], [26, 5, 1]),
`@types/node ${nodeTypes[0]} is below the reviewed floor`,
).toBe(true);
const undici = lockedVersions('undici-types');
expect(undici).not.toHaveLength(0);
for (const version of undici) {
expect(
atLeast(version, [8, 9, 0]),
`undici-types ${version} must satisfy @types/node 26`,
).toBe(true);
}
expect(declaredLib).toContain('ES2022');
});
});