From 077fed77d4b19bb8e10bc9967b9f4b713f54f4ce Mon Sep 17 00:00:00 2001 From: Kgothatso Ngako Date: Wed, 12 Aug 2026 12:30:15 +0200 Subject: [PATCH] chore(node): bump Node.js from 20 to v24.19.0 (LTS "Krypton") Upgrade the Node.js toolchain across the repo from Node 20 (20.20.0) to Node 24.19.0, the current Active LTS release (Krypton, released 2026-08-03). Node 20 approaches end-of-life, and Node >= 22 is a prerequisite for upgrading the `invoices` BOLT11 library to >= 6.0.x, which ships security fixes for duplicate payment-hash tagged field parsing (alexbosworth/invoices@b30a012) and related input-validation hardening. Node 24.19.0 also naturally includes the async_hooks stack overflow DoS fix that previously forced the 20.20.0 pin. flake.nix / flake.lock: - Pin the nixpkgs-node input to nixpkgs rev 06a1bc65f61c040137db4529ba74756c2d110da3, the revision that packages nodejs 24.19.0 (flake.lock updated via `nix flake update nixpkgs-node`). - Set expectedNodeVersion = "24.19.0"; the existing assertion keeps guarding against silent version drift on future nixpkgs bumps. - Stop swapping nodejs through the pkgs overlay. The main nixpkgs' npm build plumbing (srcOnly nodejs in the buildNpmPackage and importNpmLock npm-config hooks, pulled in by pkgs.typescript and pkgs.nodePackages.pnpm) cannot consume the newer structured-attrs nodejs derivation and fails evaluation with: "The 'env' attribute set cannot contain any attributes passed to derivation. The following attributes are overlapping: NINJA, NIX_MAIN_PROGRAM" Instead, nodejs24 is a standalone let-binding used only where the repo consumes Node directly: - buck2NativeBuildInputs (buck2 build environment) - devShell nativeBuildInputs (via buck2NativeBuildInputs; the bare `nodejs` entry was removed so the old nodejs no longer shadows node 24 on PATH) - the three installPhase `exec node` substitutions in tscDerivation, nextDerivation and npmDerivation, so packaged binaries run under Node 24 nixpkgs' internal build tooling (typescript, pnpm wrapper) keeps its own Node 20, which is harmless build-time plumbing; pnpm is still taken from nodePackages as before. package.json engines ("node": "20" -> "24"): - package.json (workspace root) - core/api/package.json - apps/admin-panel/package.json - third-party/node/turbo/package.json - third-party/node/rover/package.json CI: - .github/workflows/vendor/nodejs-check-code.yml and nodejs-audit.yml: actions/setup-node node-version 20 -> 24. NOTE: these files are auto-synced from blinkbitcoin/concourse-shared via vendir (ci/vendir.yml); the same change must land upstream or the next vendir sync will revert them. The Concourse pipelines also use a nodejs-concourse registry image built outside this repo, which needs its own Node 24 rebuild. Verification: - nix develop -c node --version -> v24.19.0 (/nix/store/...-nodejs-24.19.0/bin/node) - nix develop -c pnpm --version -> 8.15.5 (unchanged) - nix eval .#packages.x86_64-linux.api.name / .consent.name evaluate cleanly, confirming the expectedNodeVersion assertion passes Follow-ups (not in this commit): - Run the full buck2 build and test suites under Node 24 in CI - Bump @types/node (^20/^22 -> ^24) across the workspace with a pnpm lockfile regen so TypeScript sees the Node 24 API surface - Upgrade core/api `invoices` dependency to >= 6.0.5 (now unblocked) --- .github/workflows/vendor/nodejs-audit.yml | 2 +- .../workflows/vendor/nodejs-check-code.yml | 2 +- apps/admin-panel/package.json | 2 +- core/api/package.json | 2 +- flake.lock | 8 +++---- flake.nix | 22 +++++++++++-------- package.json | 2 +- third-party/node/rover/package.json | 2 +- third-party/node/turbo/package.json | 2 +- 9 files changed, 24 insertions(+), 20 deletions(-) diff --git a/.github/workflows/vendor/nodejs-audit.yml b/.github/workflows/vendor/nodejs-audit.yml index adf381d89a..c29c037d65 100644 --- a/.github/workflows/vendor/nodejs-audit.yml +++ b/.github/workflows/vendor/nodejs-audit.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 20 + node-version: 24 cache: "yarn" - run: yarn install --frozen-lockfile - name: Run audit diff --git a/.github/workflows/vendor/nodejs-check-code.yml b/.github/workflows/vendor/nodejs-check-code.yml index 4efe9f4070..eaf0c21445 100644 --- a/.github/workflows/vendor/nodejs-check-code.yml +++ b/.github/workflows/vendor/nodejs-check-code.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 20 + node-version: 24 cache: "yarn" - run: yarn install --frozen-lockfile - name: Run check code diff --git a/apps/admin-panel/package.json b/apps/admin-panel/package.json index 1ee77509b0..c376cbaf83 100644 --- a/apps/admin-panel/package.json +++ b/apps/admin-panel/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "engines": { - "node": "20" + "node": "24" }, "scripts": { "dev": "next dev -p 3004", diff --git a/core/api/package.json b/core/api/package.json index 1229dda7b9..5aa9b05f8a 100644 --- a/core/api/package.json +++ b/core/api/package.json @@ -36,7 +36,7 @@ "codegen:api-keys": "cd ./src/services/api-keys/proto && buf generate" }, "engines": { - "node": "20" + "node": "24" }, "dependencies": { "@apollo/server": "^4.12.2", diff --git a/flake.lock b/flake.lock index abdbfa7ad3..6c282ff22f 100644 --- a/flake.lock +++ b/flake.lock @@ -89,17 +89,17 @@ }, "nixpkgs-node": { "locked": { - "lastModified": 1769433173, - "narHash": "sha256-Gf1dFYgD344WZ3q0LPlRoWaNdNQq8kSBDLEWulRQSEs=", + "lastModified": 1786528403, + "narHash": "sha256-UpIWBQ4Jze4yny1fioevD8p5Q/P+Un5jh05/bfe8CEw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "13b0f9e6ac78abbbb736c635d87845c4f4bee51b", + "rev": "06a1bc65f61c040137db4529ba74756c2d110da3", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", + "rev": "06a1bc65f61c040137db4529ba74756c2d110da3", "type": "github" } }, diff --git a/flake.nix b/flake.nix index ecc35b54dc..5503e73e84 100644 --- a/flake.nix +++ b/flake.nix @@ -3,7 +3,8 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; - nixpkgs-node.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + # Pinned to a nixpkgs revision that packages nodejs 24.19.0 (Node 24 LTS "Krypton") + nixpkgs-node.url = "github:nixos/nixpkgs/06a1bc65f61c040137db4529ba74756c2d110da3"; nixpkgs-docker.url = "github:nixos/nixpkgs/nixpkgs-unstable"; nixpkgs-tilt.url = "github:nixos/nixpkgs/nixpkgs-unstable"; # reindeer >= 2024.03.29 downloads crates from static.crates.io (CDN) instead of the @@ -38,11 +39,15 @@ dockerPkgs = import nixpkgs-docker {inherit system;}; tiltPkgs = import nixpkgs-tilt {inherit system;}; reindeerPkgs = import nixpkgs-reindeer {inherit system;}; - # CVE: DoS via stack overflow in async_hooks - require nodejs 20.20.0+ - expectedNodeVersion = "20.20.0"; + # Node 24 LTS "Krypton" (24.19.0); includes the async_hooks stack overflow fix. + # Kept out of the pkgs overlay on purpose: the main nixpkgs' npm build + # plumbing (srcOnly in buildNpmPackage/importNpmLock hooks) cannot consume + # the newer structured-attrs nodejs derivation, so only the repo-facing + # toolchain (dev shell, buck2 builds, packaged bins) uses nodejs24. + expectedNodeVersion = "24.19.0"; + nodejs24 = assert nodePkgs.nodejs_24.version == expectedNodeVersion; nodePkgs.nodejs_24; overlays = [ (self: super: { - nodejs = assert nodePkgs.nodejs_20.version == expectedNodeVersion; nodePkgs.nodejs_20; pnpm = super.nodePackages.pnpm; }) (import rust-overlay) @@ -56,7 +61,7 @@ buck2NativeBuildInputs = with pkgs; [ buck2 protobuf - nodejs + nodejs24 pnpm python3 ripgrep @@ -69,7 +74,6 @@ nativeBuildInputs = with pkgs; [ envsubst - nodejs tiltPkgs.tilt typescript bats @@ -158,7 +162,7 @@ substituteInPlace "$out/bin/run" \ --replace "#!${pkgs.coreutils}/bin/env sh" "#!${pkgs.bash}/bin/sh" \ --replace "$(cat build/$name-$system/buck2-deps-path)" "$out/lib" \ - --replace "exec node" "exec ${pkgs.nodejs}/bin/node" + --replace "exec node" "exec ${nodejs24}/bin/node" ''; }; @@ -200,7 +204,7 @@ substituteInPlace "$out/bin/run" \ --replace "#!${pkgs.coreutils}/bin/env sh" "#!${pkgs.bash}/bin/sh" \ --replace "\''${0%/*}/../lib/" "$out/lib/" \ - --replace "exec node" "exec ${pkgs.nodejs}/bin/node" + --replace "exec node" "exec ${nodejs24}/bin/node" ''; }; @@ -261,7 +265,7 @@ npm_bin_source_file=$(cat "$out/bin/$npm_bin_name" | grep "exec" | awk '{print $2}') substituteInPlace "$npm_bin_source_file" \ --replace "$(cat build/$name-$system/buck2-node-modules-path)" "$out/lib" \ - --replace "exec node" "exec ${pkgs.nodejs}/bin/node" \ + --replace "exec node" "exec ${nodejs24}/bin/node" \ --replace " sed " " ${pkgs.gnused}/bin/sed " \ --replace "dirname" "${pkgs.coreutils}/bin/dirname" \ --replace "uname" "${pkgs.coreutils}/bin/uname" diff --git a/package.json b/package.json index d9de33e739..e10085211b 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "whichnode": "which node" }, "engines": { - "node": "20", + "node": "24", "pnpm": "8" }, "resolutions": { diff --git a/third-party/node/rover/package.json b/third-party/node/rover/package.json index de378e36e2..8d15bc6f55 100644 --- a/third-party/node/rover/package.json +++ b/third-party/node/rover/package.json @@ -5,7 +5,7 @@ "@apollo/rover": "^0.21.0" }, "engines": { - "node": "20", + "node": "24", "pnpm": ">=8 <9" }, "packageManager": "pnpm@8.7.6" diff --git a/third-party/node/turbo/package.json b/third-party/node/turbo/package.json index 9c1dbcfb46..3224c6d996 100644 --- a/third-party/node/turbo/package.json +++ b/third-party/node/turbo/package.json @@ -5,7 +5,7 @@ "turbo": "^1.10.3" }, "engines": { - "node": "20", + "node": "24", "pnpm": ">=8 <9" }, "packageManager": "pnpm@8.7.6"