[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.
Kind: bug. Source: new finding, register E55; child of #715 (E10).
Problem
Vendored Maven decides "is this a reactor?" twice, with two different predicates of the same name:
vendor/jvm/mod.rs#L219-L227 detect routes through maven_reactor::declares_modules. It parses the pom into a `Doc` and counts only `<modules>` / `<subprojects>` whose parent is the project or a profile. Plugin configuration, comments and CDATA don't count, and the test [`plugin_configuration_modules_do_not_make_a_reactor`](https://github.com/SocketDev/socket-patch/blob/045d7ec783d788bf3c5a1310724b51e09fb6505d/crates/socket-patch-core/src/vendor/jvm/maven_reactor.rs#L3783-L3792``) pins that a maven-ear-plugin <configuration><modules> is Shape::Other.
Shape::Other then falls through to the legacy single-pom path. maven_prelude calls the legacy maven_repo::declares_modules,`` which only strips comments and looks for any <modules open tag anywhere, and refuses with `vendor_maven_multimodule_unsupported`.
So every input where the two disagree is refused. A real reactor never reaches the legacy check, because jvm_shape takes it first (vendor_maven L308; the existing test missing_reactor_module_is_refused_without_writes gets vendor_jvm_shape_unsupported, not the legacy code). The legacy refusal fires only on false positives:
<modules> inside plugin <configuration>, as in every maven-ear-plugin project (<packaging>ear</packaging>);
<modules> inside a CDATA section, for example in a <description>.
Proof by execution (a unit probe in maven_repo::tests using the existing fixture / run_vendor helpers, run twice on 045d7ec, not committed). The pom is a single-module EAR project:
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId><artifactId>app</artifactId><version>1.0.0</version>
<packaging>ear</packaging>
<build><plugins><plugin><artifactId>maven-ear-plugin</artifactId><configuration>
<modules><jarModule><groupId>x</groupId><artifactId>y</artifactId></jarModule></modules>
</configuration></plugin></plugins></build>
</project>
PROBE jvm::detect = Other
PROBE reactor::declares_modules = false
PROBE legacy declares_modules = true
PROBE vendor refused vendor_maven_multimodule_unsupported: the root pom.xml declares <modules> (a multi-module aggregator); ...
Symptoms
None filed. Impact: vendor (and scan --mode vendored) refuses every EAR-packaged project with a misleading "multi-module aggregator" error, although neither JVM path treats it as one. The fix is small and removes code.
Proposed change
- Delete the legacy
declares_modules, strip_xml_comments and real_open_tag from vendor/maven_repo.rs (about 45 production lines), along with the vendor_maven_multimodule_unsupported refusal branch in maven_prelude, which is unreachable once the false positives are gone. If a guard is still wanted, call super::jvm::maven_reactor::declares_modules (one predicate).
- Update
CLI_CONTRACT.md (the maven row of the vendored table) to say that aggregators route to the JVM reactor backend, instead of naming the dead code.
Size and scope
vendor/maven_repo.rs and its tests, CLI_CONTRACT.md. About −45 production lines and +30 test lines. Out of scope: the other pom scanners (#715).
Acceptance criteria
Dependencies
None. First child of #715. #690 also edits maven_repo.rs (not this function).
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.
Kind: bug. Source: new finding, register E55; child of #715 (E10).
Problem
Vendored Maven decides "is this a reactor?" twice, with two different predicates of the same name:
vendor/jvm/mod.rs#L219-L227detectroutes throughmaven_reactor::declares_modules.It parses the pom into a `Doc` and counts only `<modules>` / `<subprojects>` whose parent is the project or a profile. Plugin configuration, comments and CDATA don't count, and the test [`plugin_configuration_modules_do_not_make_a_reactor`](https://github.com/SocketDev/socket-patch/blob/045d7ec783d788bf3c5a1310724b51e09fb6505d/crates/socket-patch-core/src/vendor/jvm/maven_reactor.rs#L3783-L3792``) pins that amaven-ear-plugin<configuration><modules>isShape::Other.Shape::Otherthen falls through to the legacy single-pom path.maven_preludecalls the legacymaven_repo::declares_modules,`` which only strips comments and looks for any<modulesopen tag anywhere, and refuses with `vendor_maven_multimodule_unsupported`.So every input where the two disagree is refused. A real reactor never reaches the legacy check, because
jvm_shapetakes it first (vendor_mavenL308; the existing testmissing_reactor_module_is_refused_without_writesgetsvendor_jvm_shape_unsupported, not the legacy code). The legacy refusal fires only on false positives:<modules>inside plugin<configuration>, as in everymaven-ear-pluginproject (<packaging>ear</packaging>);<modules>inside a CDATA section, for example in a<description>.Proof by execution (a unit probe in
maven_repo::testsusing the existingfixture/run_vendorhelpers, run twice on045d7ec, not committed). The pom is a single-module EAR project:Symptoms
None filed. Impact:
vendor(andscan --mode vendored) refuses every EAR-packaged project with a misleading "multi-module aggregator" error, although neither JVM path treats it as one. The fix is small and removes code.Proposed change
declares_modules,strip_xml_commentsandreal_open_tagfromvendor/maven_repo.rs(about 45 production lines), along with thevendor_maven_multimodule_unsupportedrefusal branch inmaven_prelude, which is unreachable once the false positives are gone. If a guard is still wanted, callsuper::jvm::maven_reactor::declares_modules(one predicate).CLI_CONTRACT.md(the maven row of the vendored table) to say that aggregators route to the JVM reactor backend, instead of naming the dead code.Size and scope
vendor/maven_repo.rsand its tests,CLI_CONTRACT.md. About −45 production lines and +30 test lines. Out of scope: the other pom scanners (#715).Acceptance criteria
vendor_maven_multimodule_unsupported), and a pom with<modules>inside a CDATA<description>behaves the samemissing_reactor_module_is_refused_without_writes,commented_modules_do_not_refuseandplugin_configuration_modules_do_not_make_a_reactorstay greendeclares_modulestests (declares_modules_boundary_and_comment_discipline,declares_modules_fail_closed_edges) are deleted or moved onto the reactor predicategrep -rn 'fn declares_modules' cratesfinds one definitionDependencies
None. First child of #715. #690 also edits
maven_repo.rs(not this function).