chore(deps): refresh dependencies and base image, drop dead deps - #33
Merged
Merged
Conversation
Clears every open advisory reported by `npm audit`: 11 in the full tree (7 high, 2 moderate, 2 low) and 10 in the production tree, down to 0 in both. No manifest range needed widening — all fixes were already in range, notably nanoid 3.3.15 -> 3.3.18, postcss, axios, fast-uri, js-yaml, immutable, qs, brace-expansion and body-parser. tar-stream 3.2.1 started shipping its own type definitions, which take precedence over @types/tar-stream and renamed the entry header interface (`Headers` -> `Header`, with the partial form kept internal as `HeaderArgument`). The upgrade script now derives the header type from `Pack['entry']` so it tracks whichever name the package uses. The same bundled types pull in streamx, whose `Writable.end` is declared as `end(data: unknown)` although the runtime treats a missing argument as "just finish" (streamx index.js:170) and tar-stream itself calls `sink.end()` with no argument. Passing an explicit `undefined` keeps the behaviour identical and satisfies the declaration.
node:24.11.1-alpine3.22 -> node:24.20.0-alpine3.24, and a runtime stage that runs `apk upgrade --no-cache` so alpine releases published after the node image are picked up when the image is built. Trivy on ghcr.io/data-fair/catalogs:1.2.1 reported 60 HIGH/CRITICAL: 21 from the alpine layer (libcrypto3/libssl3 3.5.4-r0 with CVE-2026-31789 CRITICAL, musl, zlib) and 39 from node packages. The new base cuts the alpine layer to libcrypto3/libssl3 3.5.7-r0, and `apk upgrade` takes those to 3.5.8-r0. Only the two final runtime stages derive from the patched stage; the build stages keep using `base` so the extra apk round-trip does not run four more times per build. The bundled npm under /usr/local/lib/node_modules accounts for most of the remaining node-package findings and is the obvious thing to delete, but it has to stay: @data-fair/lib-node-registry spawns `npm rebuild` (index.js:195, reached from the plugin download path at index.js:125) to build native addons of plugins installed at runtime.
… entry - worker: @types/tar-stream is inert since tar-stream 3.2.1 ships its own definitions, which win over the @types fallback under NodeNext. - ui: semver and @types/semver had no reference anywhere in the workspace. - ui: ofetch was imported by src/context.ts but never declared — it only resolved through the hoisted copy that lib-vue and lib-vuetify pull in as a peer. Declared explicitly so it stops depending on hoisting. - ui: 'easymde' in optimizeDeps.include is a leftover from vjsf 3. vjsf 4 has no reference to it and the package is absent from the tree, so vite was being asked to prebundle something that does not exist.
…d worker config 4.4.2 -> 5.0.1. Both consumers import the default export, hand it to assertValid and then mutate it (`rawConfig.tmpDir = ...`), so the resolved values are not the only thing that matters. Compared 4.4.2 and 5.0.1 side by side over api/config and worker/config, in development and production, with and without the environment overrides from custom-environment-variables.mjs: the resolved trees are identical, and so are Object.keys, the JSON round-trip, isFrozen/isSealed and whether the tmpDir assignment sticks. nanoid 3.3.18 -> 6.0.1. Over 200k ids per version: same 21-character default length, same URL-safe alphabet, no collisions, and an explicit size argument still honoured. nanoid has been ESM-only since 4 and both workspaces are already "type": "module". @data-fair/types-catalogs ^0.6.0 -> ^0.7.1 in api, which aligns it with worker and with the local ./types-catalogs the root package.json resolves through relativeDependencies — that checkout is already 0.7.1, so api and ui were the odd ones out.
….7 in ui @vueuse/core ^13.0.0 -> ^14.4.0. lib-vuetify 2.4.3 already requires ^14.0.0, so the workspace was pulling a second copy purely to satisfy its own older range; ui, lib-vue, lib-vuetify and unplugin-auto-import now all dedupe onto 14.4.0. vjsf keeps its own 12.8.2. lib-vue's peer range is ">=10", so it is satisfied either way. unplugin-auto-import 19.3.0 -> 21.1.0 and unplugin-vue-components 28.8.0 -> 32.1.0. Both only generate code at build time, so the check that matters is what they emit. Diffing dts/ before and after: the component list is identical (17), route-map.d.ts is byte-identical, and auto-imports.d.ts gains exactly two entries — getCurrentWatcher and isShallow, both from vue's own preset. Nothing was removed or remapped; the rest of the file diff is a formatting change from bracket to dot access plus new lint-disable headers. @data-fair/types-catalogs ^0.6.0 -> ^0.7.1, matching api and worker.
It landed between @mdi/js and @vitejs/plugin-vue when it was declared, which breaks the scoped-then-unscoped ordering the rest of the file follows. No effect on resolution — the lockfile is unchanged.
simple-directory's login page gained a password visibility toggle whose
aria-label also matches "Mot de passe", so `getByLabel('Mot de passe')`
now resolves to two elements and the e2e login fails in strict mode.
Nothing in this repo changed — CI pulls simple-directory:master fresh,
so it broke on its own.
Selecting on the `name` attribute is what events and agents already do,
and it is indifferent to labels, aria-labels and added controls. The
same breakage is latent in data-fair and processings, which still use
getByLabel here.
The submit button is left on getByRole: it is unambiguous and this repo
runs the directory in French, unlike the English-locale fixtures in
events and agents.
Patching alpine at build time makes an image depend on the day it was built rather than on its commit, which no other project here does. Not worth being the odd one out for it. Only the base image bump remains, and it carries the security result on its own: 6 HIGH and 0 CRITICAL on the built image, against 60 HIGH and 2 CRITICAL on the released 1.2.1. The difference with the stage removed is two findings — libcrypto3 and libssl3 stay at 3.5.7-r0 instead of 3.5.8-r0, which resolves itself whenever the node base image is refreshed again.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refresh every dependency in the monorepo: clear the open advisories, modernise the base image, drop dead declarations, and take the majors that can be proven behaviour-neutral.
Why: routine dependency maintenance — the tree had drifted,
npm auditreported 11 advisories (7 high) and the released image carried 60 HIGH/CRITICAL findings.Security
npm audit(full tree)npm audit --omit=devEvery npm advisory was fixable within the existing semver ranges — no manifest range needed widening. On the image, the alpine layer goes 21 → 2 (openssl only, no CRITICAL) and shipped app dependencies 11 → 0.
What changed
tar-stream@3.2.1now ships its own types, which shadow@types/tar-streamand renameHeaders→Header; the upgrade script derives the type fromPack['entry']instead. Those types also pull in streamx, whoseWritable.endis declaredend(data: unknown)although the runtime treats a missing argument as "just finish" (streamx/index.js:170) and tar-stream itself callssink.end()with none — passing explicitundefinedis equivalent.node:24.11.1-alpine3.22→24.20.0-alpine3.24, a one-line change. It clears the alpine layer on its own: musl 1.2.5-r10 → 1.2.6-r2, zlib 1.3.1-r2 → 1.3.2-r0, openssl 3.5.4-r0 → 3.5.7-r0 (the two remaining HIGH; 3.5.8-r0 will arrive with the next node image refresh). The bundled npm under/usr/local/lib/node_modulesaccounts for the other 4 findings and would be the obvious thing to delete, but it must stay:lib-node-registryspawnsnpm rebuild(index.js:195, reached from the plugin download atindex.js:125).@types/tar-streamand ui'ssemver/@types/semver; declaredofetch, imported byui/src/context.tsbut resolving only through hoisting; removedeasymdefromoptimizeDeps(a vjsf 3 leftover, absent from the tree entirely).How the majors were verified
rawConfig.tmpDir = ...), so resolved values aren't enough. Compared both workspaces × dev/prod × with and without env overrides: identical trees,Object.keys, JSON round-trip,isFrozen/isSealed, and mutation stickiness. Then boot-tested inside the alpine image.route-map.d.tsbyte-identical, components identical (17),auto-imports.d.tsgains exactly two vue-preset symbols. Nothing removed or remapped.^14.Declined, with the blocker
mongodb6 → 7 —@data-fair/lib-nodedeclarespeerDependencies.mongodb: "6", and 2.13.3 still does. Blocked upstream.croner9 → 10 — changes DST fall-back resolution: it picks the first occurrence of an ambiguous repeated local hour where croner 9 picked the second (11/144 in a dedicated DST probe, spring-forward untouched). An affected import fires an hour earlier in UTC, once a year. No CVE or feature driver, so not worth shifting users' schedules. Note croner 10 also rejects numeric-prefix stepping (0/5,2/3), but the scheduling schema only defineshourStepalongsidehour: { const: '*' }, so the only form emitted is*/N, which it accepts — theN/stepbranches intoCRON()are dead code.Unrelated fix carried in this branch
fix(tests): select the login inputs by name attributeis not a dependency change. simple-directory's login page gained a password visibility toggle whose aria-label also matches "Mot de passe", sogetByLabel('Mot de passe')resolves to two elements and every e2e login fails in strict mode. Nothing here caused it — CI pullssimple-directory:masterfresh. The fixture now selects on thenameattribute, which is whateventsandagentsalready do. The same breakage is latent indata-fairandprocessings, which still usegetByLabelthere.