GeezerVison is showing github.com — fix(manifest): record every resolved Maven dependency edge by jfblaa · Pull Request #1711 · SocketDev/socket-cli
Conversation
Heads up, reviewer
We have been missing maven edges in dynamic SBOMs as the APIs for some reason only report dependencies as children of the first parent in the tree/graph rather than all the parents.
LLM Description written by Claude Code:claude-opus-5-5
Maven Socket facts now include every dependency edge Maven resolves, as Gradle and sbt facts already do. Before, an edge onto a dependency Maven kept elsewhere was dropped: jetty-io -> jetty-util when jetty-util is also a direct dependency, or an edge Maven mediated to another version. Dependency chains therefore missed paths to a package.
What changes
- The extension wraps Maven's own graph transformer, records each node's children before conflict resolution, and points every edge at the node Maven kept for that conflict. No version choice is made outside Maven.
- Roots are shaped like Gradle's runtime and test classpaths: the test root is the module's whole resolution, the compile root the nodes Maven kept with a prod scope. An edge from a prod node onto a
provided one is kept, and the provided dependency stays dev.
- Prod/dev now follows the scope Maven kept a node with, replacing the reachability split from fix(manifest): keep Maven components reachable from their root #1549. A dependency Maven widens to compile under a test parent is prod, as it is on Maven's runtime classpath.
- A module whose conflict resolution fails (unsatisfiable hard version ranges) is reported unscannable and emits and fetches nothing. It used to emit the half-resolved candidates, including several versions of one package.
No facts format, assembler or Coana change.
Verification
- Maven compat matrix 3.2.5, 3.6.3, 3.8.8, 3.9.9, 4.0.0-rc-6 green. New fixture cases (edge onto a direct dependency, mediated edge, prod onto provided, unsolvable conflict) all fail with the
v1.x extension.
- Records are identical with and without
aether.conflictResolver.verbose.
socket fix --dynamic-sbom-inference on a Maven reactor with a vulnerable package reached both directly and transitively gives the same fix as before.
🤖 Generated with Claude Code
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Maven facts only had the edges that survive conflict resolution, so an
edge onto a dependency Maven kept elsewhere (a direct dependency, or a
mediated version) was missing, unlike Gradle and sbt facts. The Maven
extension now records each node's children before conflict resolution
and points every edge at the node Maven kept.
Roots follow Gradle's runtime and test classpaths: the test root is the
module's whole resolution, the compile root the nodes Maven kept with a
prod scope. A dependency Maven widens to compile under a test parent is
therefore prod, matching Maven's runtime classpath.
A module whose conflict resolution fails has no resolved graph, so it is
reported unscannable and contributes no dependencies.
cursor
Bot
commented
Nov 12, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
PR Summary
Medium Risk
Changes core Maven dependency graph emission used by reachability and dynamic SBOM inference; behavior shifts for scope conflicts and failed resolution, though compat matrix and assertion tests guard regressions.
Overview
Maven Socket facts now record the full resolved dependency graph and classify prod vs dev like Gradle/sbt, aligning reachability and SBOM inference with Maven’s actual classpath.
The Maven extension wraps resolution with an EdgeRecorder that snapshots children before conflict resolution and rewrites edges to the winner Maven kept. That restores edges that were previously dropped (duplicate direct deps, mediated versions, prod → provided). Compile/test roots are reshaped: compile holds nodes Maven kept with a prod scope; test holds the full resolution with all edges.
Prod/dev labeling no longer follows reachability from direct prod deps—it uses the effective scope Maven kept on each node (so compile-scoped artifacts under a test parent count as prod). Modules where conflict resolution fails entirely are marked unscannable with no partial nodes or jar fetches.
Coverage adds compat smoke cases (dup-io/dup-util, mediated edges, container-lib → provided API, unsolvable conflicts) and expands assert-records.py / Vitest fixtures.
Reviewed by Cursor Bugbot for commit 25c8a4f. Configure here.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[agent] A simplification review (reuse, simplification, efficiency, altitude), not a bug hunt. The approach is at the right depth: recording edges fixes what the reachability-based prod/dev split was working around, the new root layout matches Gradle's runtime/test classpaths, and the assembler needs no Maven-specific code. The inline comments are mostly about how much machinery EdgeRecorder needs.
Looked at and not flagged:
- The
copies map: it only saves memory, but it keeps the pre-walk linear.
- The per-module session copy: microseconds.
- Prod records appearing in both roots: this is the intended Gradle-shaped contract. Buffering every record until the run ends predates this PR, though the PR doubles what that buffer holds.
- Follow-up idea, older than this PR: store a sibling module's jar and test-jar under their own ids and let the assembler collapse them, the way it does for Gradle variants. That would remove the jar/test-jar caveats in
visit.
- Dead code: none.
NODE_DATA_CONFLICT_WINNER, ArrayDeque and Deque are all still used.
The new unsolvable-conflict smoke test follows the existing one-script-per-failure-fixture pattern.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Holding for a pending review
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Build the resolved edges inside the transformer, so a broken assumption
about Maven's graph becomes a collection error that marks only that
module unscannable. A module whose graph never passed through the
recorder is now reported instead of emitting nothing silently.
Walk each artifact once again before touching its node, leave self-edges
to the assembler, and exclude libdep from mid's lib dependency so the
fixture catches a walk keyed by the shared jar/test-jar id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Nov 12, 2026
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
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.
|