From 1fba3d9f957c8b4c76111ab0f1a96740d2d090ba Mon Sep 17 00:00:00 2001 From: implementer Date: Mon, 31 Aug 2026 00:26:34 +0000 Subject: [PATCH] docs(adr): record Node.js 24 LTS runtime decision as ADR-002 --- docs/adr/ADR-002-node-24-lts-runtime.md | 87 +++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 docs/adr/ADR-002-node-24-lts-runtime.md diff --git a/docs/adr/ADR-002-node-24-lts-runtime.md b/docs/adr/ADR-002-node-24-lts-runtime.md new file mode 100644 index 0000000..082237e --- /dev/null +++ b/docs/adr/ADR-002-node-24-lts-runtime.md @@ -0,0 +1,87 @@ +# ADR-002: Node.js 24 LTS runtime + +- Status: Accepted +- Date: 2026-08-31 +- Deciders: platform stream +- References: ADR index (section 70), Technology stack wiki (sections 5.2, 6, 7, 8), ADR-001 + +## Context + +EPPP is a greenfield personal blogging platform (ADR-001) whose runtime is a +single modular-monolith application plus an optional worker, deployed as one +or more containers of one image. The whole platform — public server, admin +API, rendering pipeline, extension runtime, core services and background +jobs — executes on one runtime, so the runtime choice is a platform-wide, +hard-to-reverse decision with security, tooling and operational reach. + +The workspace is a pnpm monorepo (pnpm 11.23.0) whose root manifest already +declares `engines.node: ">=24.0.0 <25.0.0"` with `engineStrict: true`, and +the CI pipeline installs and runs on Node 24 (E00-S01-T08). The technology +stack wiki classifies Node.js as support class A — a fixed upstream EOL date +— and pins the golden compatibility tuple to Node 24.19.0 LTS (Krypton), with +`node:24.19.0-bookworm-slim` as the application container base image. + +## Decision + +EPPP runs on the **Node.js 24 LTS** runtime line, exact-pinned to Node 24.19.0 +LTS (Krypton) in the golden compatibility tuple and the container image. The +workspace root manifest restricts the engine to 24.x +(`engines.node: ">=24.0.0 <25.0.0"`), pnpm enforces it at install time +(`engineStrict: true`), and CI installs and runs on Node 24. The runtime is a +class A dependency: its upstream EOL (2028-04-30) drives the upgrade +schedule, and a move to a later major line (for example Node 26) is only +evaluated once that line is LTS and the compatibility suite passes, and then +only as a deliberate, ADR-recorded change. The decision text — **Node.js 24 +LTS runtime** — matches the ADR index entry (ADR-002, section 70). + +## Alternatives + +- **Node 22 LTS (Jod)** — rejected: it is the previous LTS line and reaches + EOL before Node 24 (2027-04-30), shortening the runway for a platform whose + v1.1 boundary contracts (ADR-027 to ADR-032) extend past that date. +- **Node 26 (current, non-LTS at decision time)** — rejected: not LTS when + the decision was made; running a non-LTS line contradicts the class A + support posture (fixed EOL, security patching on an LTS cadence). +- **Node 24 with no exact pin (floating latest 24.x)** — rejected: a floating + minor would break the reproducibility of the golden compatibility tuple and + the container image; the line is pinned and minors move deliberately. +- **Node 24 LTS, exact-pinned 24.19.0** — chosen: an LTS major with a fixed + EOL, exact-pinned in the image and tuple, engine-restricted in the + manifest, and enforced in CI. + +## Consequences + +- Positive: an LTS line with a fixed upstream EOL (2028-04-30) gives a + predictable security-patching and upgrade horizon; the exact pin makes + builds and containers reproducible; the engine restriction rejects + unsupported Node versions at install time instead of failing at runtime. +- Negative: Node 24 API and behaviour become the platform floor — anything + needing a newer Node feature waits for the deliberate, ADR-recorded major + upgrade; minor upgrades inside 24.x still need the weekly dependency sweep + and full CI. +- Neutral: the runtime is shared by every module, so a future extraction + (ADR-001) keeps running on the same Node line until that module's runtime + needs diverge. + +## Operational impact + +- Application and worker containers run `node:24.19.0-bookworm-slim`; release + automation records the immutable image digest in the SBOM/release manifest. +- The supported runtime is enforced at install (`engineStrict: true` fails + installs on unsupported Node) and at test time (the node-engine suite + asserts the current runtime satisfies the 24.x range). +- CI installs and runs every stage on Node 24, so the committed pipeline is + the operational proof that the platform runs on the chosen line. +- Node 24 is patched on the LTS cadence; security-emergency updates go + through the focused lane (immediate, full CI), and the EOL date is the + deadline for the next major-line ADR. + +## Revisit trigger + +- Revisit when Node 26 becomes LTS and passes the compatibility suite, per + the LTS strategy — the decision to move majors is a new ADR, not a patch. +- Revisit on a security-emergency or patch-lane event that forces a minor + upgrade outside the weekly sweep, or if upstream announces a change to the + Node 24 support horizon. +- Revisit if a module's runtime needs (ADR-001 extraction) diverge from the + shared Node line and a second runtime enters the platform.