Skip to content

npm ci FAILS on development (lockfile is missing @gouvfr/dsfr peer deps), and the docs/ lockfile that actually ships is unscanned #246

Description

@rubenvdlinde

Two findings from a full-tree audit today. Both are invisible to CI, for different reasons.

1. npm ci cannot install this repo

On origin/development, npm 11.13.0, Node 22.22.0:

npm error code EUSAGE
npm error `npm ci` can only install packages when your package.json and
npm error package-lock.json or npm-shrinkwrap.json are in sync.
npm error Missing: @gouvfr/dsfr-token@ from lock file
npm error Missing: @gouvfr/dsfr-weave@ from lock file

Both are peerDependencies of @gouvfr/dsfr-nexus, which the lockfile carries but their entries do not:

peerDependencies :: node_modules/@gouvfr/dsfr-nexus -> @gouvfr/dsfr-token  *
peerDependencies :: node_modules/@gouvfr/dsfr-weave -> @gouvfr/dsfr-weave  *

It is specifically the peer set, not the runtime tree. Walking every dependencies entry in package-lock.json and resolving it the way npm does (own node_modules/, then each ancestor) gives 0 unresolved runtime deps — so the lock is internally consistent for dependencies and incomplete only for peers. That is the known npm-11 lockfile-peer-pruning shape: a lock generated by an npm that pruned peers, replayed by an npm that requires them.

Fix: regenerate with npm install on npm 11 and commit the lock. Worth also pinning the npm version CI uses, so the lock is always written and replayed by the same major.

Why nothing reported it

.github/workflows/code-quality.yml contains no npm ci or npm install of its own — the install happens inside the shared workflow. Whatever it does there evidently still succeeds, so the repo has a lockfile that a developer (and the hydra-gates checkers) cannot install from, while CI stays green.

Concretely: it made gate-22 (manifest-validation) and gate-53 (effective-manifest-crossref) unrunnable in a full-tree audit — both refuse to run fail-open when ajv is not resolvable, which is correct behaviour and reported honestly:

[gate-22] manifest-validation: FAIL — SCHEMA VALIDATION DID NOT HAPPEN — Ajv is not resolvable ...
[gate-53] effective-manifest-crossref: FAIL — ajv not resolvable ... refusing to run fail-open

With ajv supplied via NODE_PATH from a scratch install, both PASS. So they are not findings — but they were also not measurable in this repo without working around the lockfile.

2. The docs lockfile that actually ships is unscanned

Dependabot scans the default branch, which is main. main still has docusaurus/; development moved it to docs/ in 11048b7. So all 43 npm alerts name docusaurus/package-lock.json — a path deleted on development — and zero name docs/package-lock.json, which is the tree that ships.

docs/package-lock.json on development carries the same packages, several at older versions than the ones the open dependabot PR is trying to bump:

package docs/ on development note
fast-uri 3.1.0 #144 bumps docusaurus/ 3.1.2 → 3.1.4 (2 advisories)
js-yaml 3.14.2, 4.1.1 2 high + 2 medium on the scanned copy
shell-quote 1.8.3 1 critical on the scanned copy
websocket-driver 0.7.4 1 critical on the scanned copy
dompurify 3.3.1 5 medium + 4 low
webpack-dev-server 5.2.3 6 medium
postcss 8.5.6 1 high
serialize-javascript 6.0.2 1 high
brace-expansion 1.1.12 2 high
svgo 1 high

Fix: add a dependabot.yml entry for directory: /docs (npm), and bump docs/package-lock.json on development. Until then the alert list describes a directory on its way out and says nothing about the one that ships.

Root package-lock.json also has 13 open alerts — 5 high on fast-uri, 2 high postcss, 1 high each js-yaml / flatted / brace-expansion — with no open PR against it either.

Context

Found while measuring nldesign's gates full-tree (no --scope-to-diff) at origin/development 7b0fade. Blocker notes left on #144; #102 and #104 closed as superseded.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions