You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
the node the image installs is a floating major (node_22.x at build time), so the image carries a node below the floors its consumers' lockfiles now declare — and the newest published image is one day short of v22.23.4 #8
The docs-site image installs the docs repo's lockfile on a node that lockfile now declares unsupported. The chain: layer-docs-site requires @github.com/opencharly/layer-nodejs:v2026.272.0322, and that layer's own recorded measurement of its build image is node 22.22.2:
# layer-nodejs's charly.yml, in the comment that records the allowBuilds key-form
# measurement:
# MEASURED in the real build image (Fedora 43, node 22.22.2) against pod-dsh's
# dsh-web profile — opencharly/layer-nodejs#5
The docs repo's lockfile — as of opencharly/docs#187, merged 2026-10-26 — carries a floor of >=22.23.4:
$ python3 -c "import json; pk=json.load(open('package-lock.json'))['packages']; \
print({n: (pk[n]['version'], pk[n].get('engines')) for n in ('node_modules/@astrojs/mdx','node_modules/@astrojs/prism')})}"
{'node_modules/@astrojs/mdx': ('8.1.1', {'node': '>=22.23.4'}),
'node_modules/@astrojs/prism': ('4.1.1', {'node': '>=22.23.4'})}
So the moment the umbrella advances the docs pin, the check-docs bed installs that lockfile in this image, on node 22.22.2, and npm warns twice:
The install still succeeds (npm warns; no engine-strict), so the bed is not red — it is noisy, and a floor this far below the requirement is a defect that surfaces later, at an arbitrary future patch.
Mechanism
The layer installs node from NodeSource's floating node_22.x repository at image build time:
A floating major in an image is a snapshot, not a guarantee: the image carries whatever 22.x was current when it was built. The dates say what that is:
what
when
node it carries
layer-nodejs v2026.272.0322 (the tag layer-docs-site pins)
committed 2026-07-28
22.22.2 (the layer's own measured image)
layer-nodejs v2026.292.2324 (the newest tag)
committed 2026-10-19
22.23.3
v22.23.4 — the release the lockfile requires
released 2026-10-20
—
Even the newest node layer is one day short of the floor. So a pin bump alone does not reach it: the newest published image predates v22.23.4 by a day.
Missed control
The node version in the image is never declared, only floated — so nothing can compare it with a floor, and the image's node drifts with the calendar.
The consumer's check is loose: layer-docs-site asserts only that node reports a parseable major (stdout: matches: "v[0-9]+\\."). "Some node 22" passes for "a node below the floor".
No install-cleanliness gate: the bed's npm ci warnings are not asserted against.
Blast radius
Every consumer of this layer that installs a lockfile with a higher node floor inherits it — the docs site today, and any future consumer of the node layer. The same floating-major mechanism produced the sibling defect in the docs repo itself (opencharly/docs#188): there the floating major was .node-version; here it is NodeSource's node_22.x.
Root fix (proposal)
Declare the node version the image installs, exactly, and assert it.
A declared version constant in layer-nodejs (the node version the image installs), installed from that exact version rather than from the floating node_22.x repository — the same root fix as the sibling: a floor is only enforceable against a declared version.
A check step that asserts node --version equals the declared version, so a drifted image is RED rather than quiet. The layer already has the shape of such a step; what it lacks is the equality assertion.
Then, in producer-first order: a new layer-nodejs release → layer-docs-site bumps its pin (and its image is rebuilt on the new node) → the umbrella advances the layer-docs-site gitlink → the check-docs bed installs the docs lockfile on a node that satisfies its floor.
Note
This issue is filed from the docs scope (opencharly/docs#188's RCA) and is not claimed by this slug: the fix is a change in this repo, with its own build and its own release. It is open for a taker, and the umbrella's docs-pin leg waits on it only for the warning-free bed, not for the merge itself.
Agent: umbrella-prose-truth
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (analysed on a live system)
Activity