Skip to content

test: assert package.json overrides are enforced in package-lock.json (tests/lockfile-overrides.test.mjs) - #324

Open
kubestellar-hive[bot] wants to merge 1 commit into
mainfrom
quality/test-lockfile-overrides
Open

kubestellar-hive[bot] wants to merge 1 commit into
mainfrom
quality/test-lockfile-overrides

Conversation

@kubestellar-hive

Copy link
Copy Markdown
Contributor

Test Improvement

Adds one test-only file, tests/lockfile-overrides.test.mjs (5 tests),
asserting that the overrides block in package.json is actually enforced by
the resolved tree in package-lock.json.

Files claimed by this PR: tests/lockfile-overrides.test.mjs (new).
Nothing else — no production code, no workflow, no package.json, no
lockfile, no new dependency.

The gap

All 7 overrides exist to hold a transitive dependency at or above a version
that fixes a known advisory. Nothing verifies that they work. npm ci does
not: copying only the two manifests into an empty directory at 00b44df and
running npm ci --ignore-scripts exits 0 even though the lockfile's root
packages[""] entry records no overrides key while package.json declares
all 7. So raising an override floor without regenerating the lockfile leaves CI
installing the vulnerable version, green and silent.

What the 5 tests assert

  1. The lockfile belongs to this package — lockfileVersion >= 3, name and
    version agree, and it lists a non-zero number of packages.
  2. package.json declares a non-empty overrides block, so nothing below can
    pass vacuously if it is dropped or renamed.
  3. Every override selector matches a real package, and every nested
    parent > child override resolves to one — catching a typo'd or stale
    override that pins nothing.
  4. No installed instance of an overridden package sits below its floor.
  5. Every nested override is enforced where its parent resolves it, following
    Node's resolution order (own node_modules, then each enclosing one).

Two deliberate design notes, both to avoid a test that looks strict but is not:

  • Floors, not caret equality. tinyglobby declares picomatch ^4.0.4,
    which ^2.3.2 cannot satisfy, so npm gives it a nested picomatch@4.0.5.
    That is benign — 4.0.5 is above the floor, the advisory intent holds — but an
    equality assertion would be red against main for a dependency that is fine.
    The floor is the invariant the overrides actually encode.
  • Hoist-aware resolution. sockjs > uuid is hoisted to node_modules/uuid
    in the current tree. A test that looked only for
    node_modules/sockjs/node_modules/uuid would find nothing and pass
    vacuously; test 3 fails loudly instead.

semver is not a declared devDependency, so the floor is parsed directly and
any range form the test does not understand fails the run rather than being
skipped.

Verification

Local clone of cncf/endusers at 00b44df after npm ci, node v26.8.2.

  • node --test: 60 pass, 0 fail (55 before; the 5 new tests are the delta).

  • npx prettier --check tests/lockfile-overrides.test.mjs: clean.

  • Mutation-checked — an assertion that cannot fail is not a test. Five
    deliberate breakages, each reverted, each caught by exactly one assertion:

    mutation result
    lock serialize-javascript 7.1.0 → 7.0.1 test 4 fails
    add override joi-typo matching nothing test 3 fails
    sockjs > uuid floor → ^12.0.0 test 5 fails
    delete the overrides block test 2 fails
    override range → latest fails loudly, does not skip

    Baseline re-verified green after each revert.

Disjointness from open PRs

Related Issue

Closes #323


Filed by quality agent (hold-gated mode). Human review required.

— hive: agent=quality backend=copilot model=claude-opus-5

npm ci exits 0 against a lockfile whose root records no overrides, so an
override floor raised in package.json without regenerating the lockfile
silently keeps installing the version the override was added to eliminate.

Adds tests/lockfile-overrides.test.mjs, which asserts every override
selector resolves to a real package and no installed instance sits below
its floor, following Node's nested-then-hoisted resolution order for
nested overrides.

Closes #323

Signed-off-by: kubestellar-hive[bot] <kubestellar-hive@hive.kubestellar.io>
@kubestellar-hive

Copy link
Copy Markdown
Contributor Author

Important

Held for human review by the hive's ACMM level gate.

This PR was opened by the "quality" agent while Hive policy required a human checkpoint for that agent. Non-outreach agents are held at ACMM L3–L5; the outreach agent is always held because it publishes project-facing communication.

Hive will automatically remove the hold label once current policy no longer requires a level hold for "quality". If this is an outreach PR, a human must review it and remove the label.

@kubestellar-hive kubestellar-hive Bot added quality Approved by a Hive merger/owner for auto-merge on green CI testing Approved by a Hive merger/owner for auto-merge on green CI agent/quality Approved by a Hive merger/owner for auto-merge on green CI hive/hosted-available-lke648397-260827-5n31 Approved by a Hive merger/owner for auto-merge on green CI labels Sep 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent/quality Approved by a Hive merger/owner for auto-merge on green CI hive/hosted-available-lke648397-260827-5n31 Approved by a Hive merger/owner for auto-merge on green CI hold quality Approved by a Hive merger/owner for auto-merge on green CI testing Approved by a Hive merger/owner for auto-merge on green CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[quality] overrides in package.json are enforced by no gate; npm ci passes against a lockfile that records none

0 participants