Problem
The Node version is declared in three places and they do not agree:
| Where |
Version |
.github/workflows/ci.yml (two jobs) |
22.9.0 |
apps/web/package.json engines |
>=22.9.0 |
apps/web/Dockerfile (three stages) |
node:22-alpine |
apps/web/package.json @types/node |
20.19.43 |
The type definitions are already two majors behind the runtime the code actually
executes on, which means the compiler is checking against a Node that is not the
one in the image.
Dependabot proposed node:26-alpine (#49) and @types/node@26 (#56)
independently. Taking either alone makes things worse:
- Only the Dockerfile → the published image runs a Node that no test ever
exercises, because CI stays on 22.9.
- Only the types → the compiler checks against a runtime that is not shipped.
Both were closed in favour of this issue.
What to decide
- Which Node major the project targets. Node 26 becomes LTS in October 2026;
shipping a self-hosted image on a non-LTS runtime is a deliberate choice, not
a default.
- Move CI,
engines, the Dockerfile, and @types/node in one pull request,
so the three declarations cannot drift apart again.
Acceptance criteria
Guarding against drift
A test in tests/test_repository_automation.py that reads the three
declarations and asserts they agree would make this class of drift impossible to
reintroduce. Worth adding alongside the bump.
Problem
The Node version is declared in three places and they do not agree:
.github/workflows/ci.yml(two jobs)22.9.0apps/web/package.jsonengines>=22.9.0apps/web/Dockerfile(three stages)node:22-alpineapps/web/package.json@types/node20.19.43The type definitions are already two majors behind the runtime the code actually
executes on, which means the compiler is checking against a Node that is not the
one in the image.
Dependabot proposed
node:26-alpine(#49) and@types/node@26(#56)independently. Taking either alone makes things worse:
exercises, because CI stays on 22.9.
Both were closed in favour of this issue.
What to decide
shipping a self-hosted image on a non-LTS runtime is a deliberate choice, not
a default.
engines, the Dockerfile, and@types/nodein one pull request,so the three declarations cannot drift apart again.
Acceptance criteria
engines, all three Dockerfile stages, and@types/nodeimage
Guarding against drift
A test in
tests/test_repository_automation.pythat reads the threedeclarations and asserts they agree would make this class of drift impossible to
reintroduce. Worth adding alongside the bump.