Skip to content

feat: OA009 stale floor detector#770

Open
sonukapoor wants to merge 20 commits into
mainfrom
feature/issue-730-oa009-stale-floor
Open

feat: OA009 stale floor detector#770
sonukapoor wants to merge 20 commits into
mainfrom
feature/issue-730-oa009-stale-floor

Conversation

@sonukapoor

Copy link
Copy Markdown
Collaborator

Adds OA009 (stale override floor) to the override hygiene auditor - the ninth and final rule in the OA series.

OA009 fires when a >= or ^ range floor in an override is already met by every parent declaration, making the override have no net effect on the resolved version. Safe to remove automatically.

What changed

  • OA009 detector - compares the override's range floor against all parent-declared ranges for the same package; fires when the floor is already covered everywhere
  • Empty container pruning - after removing the last override entry via --fix, the now-empty overrides / pnpm.overrides container is also removed from package.json rather than leaving "overrides": {}
  • projectPath in hint commands - fix commands shown after the findings table now include the scanned path when it is not . (e.g. cve-lite ./apps/web overrides --fix --rule OA009)
  • Path-first argument normalization - cve-lite <path> overrides [flags] now works alongside cve-lite overrides <path> [flags]; both orderings are accepted
  • Docs - OA009 page added; terminal output blocks and fix commands corrected across OA001-OA008; README and getting-started commands fixed to include the required path argument

Closes #730

@sonukapoor sonukapoor requested a review from alamb-hex June 29, 2026 11:06
15 cases covering: fires for >= and ^ floor when all parents meet it,
fires for exact-version and >= parent ranges, silent for partial parent
coverage, empty parents, missing installed version, concrete pins, floating
tags, ~ and > operators (out of scope v1), nested object values, unparseable
parent ranges, and skippedDetectors bypass.
Detects override entries using >= or ^ floor ranges where every parent
package already declares a minimum version meeting or exceeding the floor.
When all parents independently enforce the floor, the override is redundant
and safe to remove. Emits a low-severity finding with an rfc6902 remove
patch and a runnable fix command.

Skips: concrete version pins (OA004 territory), floating tags, ~ and >
operators (out of scope v1), nested object values, missing installed
versions, empty parent declarations, and unparseable parent range specs
(conservative - returns false rather than assuming floor met).
After applying patches, filter applied findings from the terminal table
and remaining-findings check so the output only shows issues still
needing attention. Exit code also now reflects post-fix state.
OA009 was absent from the OA_RULES constant in override-findings-sarif.ts.
SARIF consumers (GitHub Code Scanning, SARIF Multitool) would encounter a
result referencing a rule with no matching entry in the extension component,
breaking validation. Updated the test assertion to cover OA001-OA009.
walkInstalledTree only reads node_modules manifests and never sees the root
package.json. When the root project is the sole direct consumer of an
overridden package (no transitive package also declares it), parentDeclarations
was empty and OA009 skipped the entry. seedRootDeclarations() now seeds
dependencies, devDependencies, optionalDependencies, and peerDependencies from
the root into parentDeclarations before the detectors run. This is also the
correct foundation for PD001/PD002 and DM001 which share the same context.
When the override is ^4.2.0 and a parent declares ^5.0.0, coerceVersion strips
the operator and compareVersions(5.0.0, 4.2.0) returns >= 0, causing OA009 to
fire. But ^4.2.0 means >=4.2.0 <5.0.0 and ^5.0.0 means >=5.0.0 <6.0.0 - the
ranges do not overlap, so removing the override would change the resolved
version from 4.x to 5.x. Added a majorOf() guard: when the override uses ^,
each parent must also be in the same major before it counts as meeting the
floor. Added a test case covering the cross-major non-firing case.
Extends detectors.test.ts to cover OA009 through the real CLI binary. Uses
the existing examples/oa009-stale-floor fixture (build-tool@2.0.0 declares
semver ^7.5.4; override semver >=5.7.2 is therefore redundant). Asserts the
finding fires, package name, severity, and the remove patch. No temp directory
needed - the fixture already has the full node_modules structure.
@sonukapoor sonukapoor force-pushed the feature/issue-730-oa009-stale-floor branch from b318916 to ae9125e Compare June 29, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: detect stale override floors that no longer change the resolved version (OA009)

1 participant