Skip to content

Vendored Maven and Gradle: design and prototype - #287

Draft
Mikola Lysenko (mikolalysenko) wants to merge 5 commits into
release/v5-prereleasefrom
v5/maven-vendoring
Draft

Mikola Lysenko (mikolalysenko) wants to merge 5 commits into
release/v5-prereleasefrom
v5/maven-vendoring

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Vendored Maven works today only for a single pom.xml. It refuses multi-module reactors and Gradle builds, which covers most enterprise Java. This PR adds a design for vendoring both, plus a prototype behind a flag.

Design: docs/design/maven-vendoring.md

  • Maven: uses the server's suffixed version (<v>-socket.<hex8>) from a committed .socket/vendor/maven2 tree.
    • Maven 3.9.2+ reads the tree through maven.repo.local.tail in .mvn/maven.config. It copies nothing into ~/.m2, and mirrorOf * does not affect it.
    • Every version, from 3.6.3 up, also gets a file://${maven.multiModuleProjectDirectory} fallback repository.
    • dependencyManagement pins go into each local root pom, and literal and property declarations are rewritten, including in profiles and middle parents.
  • Gradle: keeps the same coordinates.
    • One apply line per settings file loads an owned script. The script adds an exclusiveContent file repository and fails configuration if a vendored file's sha256 no longer matches the committed index.
    • Lockfiles, catalogs and build scripts are never edited. An existing verification-metadata.xml gets the patched hash.
  • Build-time Maven pins (trusted checksums, deny lines) are opt-in and deferred to v5.x. Review found they crash release reactors and system-scope dependencies, and enforce nothing on Maven 3.9.2–3.9.3.
  • The doc also covers: a supported-shapes matrix per Maven and Gradle version, failure modes, the mapping from today's 21 refusal codes, migration from the current layout, the server/CLI split (no depscan change needed for v5.0; 7 optional depscan changes proposed), the test plan, phases, the panel scores and the adversarial review findings.
  • Known Maven limitation: on 3.9.2–3.9.8, mvn -f <root>/pom.xml run from outside the project root fails when maven.config uses ${session.rootDirectory}. The design warns about it and offers --maven-config=none.

Prototype: crates/socket-patch-core/src/vendor/jvm/

  • Runs only with SOCKET_PATCH_EXPERIMENTAL_JVM_VENDOR=1, and only for shapes that are refused today. Nothing that vendors today behaves differently.
  • Revert works per fragment and is byte-exact in any order.
  • Also handled: re-runs, patch updates, --preserve-state, a cold local cache, VEX liveness and repair.
  • Paths may not escape the checkout, and forged ledger entries touch nothing.
  • Doc §17 lists what is not implemented yet.

Tests

  • Capstones (e2e_vendor_jvm_build, #[ignore]): a reactor, and a Kotlin DSL Gradle build with FAIL_ON_PROJECT_REPOS and STRICT dependency locking. Both build offline from a fresh checkout; Gradle lockfiles stay byte-unchanged, and a tampered vendored jar fails the build. They pass on Maven 3.8.8, 3.9.2, 3.9.11 and 4.0.0-rc-7, and on Gradle 6.9.4, 7.6.4, 8.14.3 and 9.8.0.
  • Unit and subprocess tests: 113 unit tests in vendor::jvm and 6 subprocess tests in vendor_jvm_cli. The existing in_process_vendor, repair, rollback, VEX and ledger-schema suites, and the legacy vendored-Maven capstone, still pass.
  • Clippy: cargo clippy --workspace --all-targets --all-features -- -D warnings is clean. That needed a separate commit dropping two unused fields in covgap_commands_rollback.rs, which already failed clippy on the base branch.
  • Local failures: 11 core tests fail locally because they check read-only/permission errors and the sandbox runs as root. None of them are in files this PR changes.
  • Red CI: e2e_redirect_cargo_build fails the same way on the base branch head 8ae7dc3 (commented below).

🤖 Generated with Claude Code

https://claude.ai/code/session_019ZLLAZfofQZ2ywkgrHkdEZ

Vendored Maven today works for a single pom.xml only. It refuses
multi-module reactors and Gradle builds, which covers most enterprise
Java. This design says how vendored mode should handle both without
dropping any Maven or Gradle version that works today.

- Maven uses the server's suffixed version (<v>-socket.<hex8>), found
  through a committed maven2 tree. Maven 3.9.2+ reads it through
  maven.repo.local.tail; every version also gets a file:// fallback
  repository and dependencyManagement pins in each local root pom.
- Gradle keeps the same coordinates. One owned settings script, applied
  by one line, adds an exclusiveContent file repository and checks the
  vendored files' sha256 on every configuration. Lockfiles, catalogs
  and build.gradle files are never edited.
- Build-time Maven pins (trusted checksums, deny lines) are opt-in for
  later. The adversarial review found crashes and silent no-ops in
  them on common Maven versions.

The doc includes the supported-shapes matrix, the failure modes, the
refusal-code mapping, the migration plan, the server/CLI split, the
test plan, the panel scores and the adversarial review findings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZLLAZfofQZ2ywkgrHkdEZ
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

CI note: coverage (and the test (*) / test-release jobs) fail in e2e_redirect_cargo_build: cargo_get_uuid_hosted_fresh_checkout_fetch and cargo_hosted_fresh_checkout_fetch_pulls_patched_crate_and_vex_verifies fail with left: Some(0) right: Some(1).

This isn't caused by this PR. The head commit only adds docs/design/maven-vendoring.md. The same two tests fail the same way on the base branch head 8ae7dc3 (CI run 36352437716, jobs coverage, test on ubuntu, macos and windows, and test-release). I don't know of an existing fix to port, so this PR will stay red on those checks until the base is fixed.


Generated by Claude Code

Workspace clippy with -D warnings failed on two fields of the
covgap_commands_rollback fixture that nothing reads. The hashes are
still computed and used to stage the manifest and blobs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZLLAZfofQZ2ywkgrHkdEZ
Vendored Maven refuses multi-module reactors and Gradle builds today.
With SOCKET_PATCH_EXPERIMENTAL_JVM_VENDOR=1 set, those two shapes now
go to a new backend (vendor/jvm) that implements the v5.0 cut of
docs/design/maven-vendoring.md. With the variable unset, nothing that
vendors today behaves differently.

- Maven reactor: pins the server's suffixed version in every local
  root pom and rewrites literal and property declarations (including
  in profiles and middle parents). Adds one shared file:// fallback
  repository, two .mvn/maven.config lines (offline file protocol and
  maven.repo.local.tail) and a committed maven2 tree.
- Gradle: keeps the same coordinates. One apply line per settings
  file (root, buildSrc, literal includeBuild) loads an owned script.
  It adds an exclusiveContent file repository and fails configuration
  if a vendored file's sha256 no longer matches the index. Lockfiles,
  catalogs and build scripts are never edited; an existing
  verification-metadata.xml gets the patched hash.
- Revert is per fragment and byte-exact in any order. Shared pieces
  stay until no other patch uses them. Re-runs, patch updates,
  --preserve-state, the cold-cache fast path, VEX liveness and
  repair all handle the new trees.

The real-tool capstones (e2e_vendor_jvm_build, ignored by default)
build a reactor and a locked Kotlin DSL Gradle build offline from a
fresh checkout. They pass on Maven 3.8.8 to 4.0.0-rc-7 and Gradle
6.9.4 to 9.8.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZLLAZfofQZ2ywkgrHkdEZ
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

CI note for head 251b7a3: the vlt patch compatibility / install-proof (ubuntu-latest, 0.0.0-16|0.0.0-18) failures aren't from this PR. The diff doesn't touch npm, vlt or any redirect code. The Maven/Gradle changes are behind SOCKET_PATCH_EXPERIMENTAL_JVM_VENDOR, plus one unused test field. The same workflow is red on the base head 8ae7dc3 (run 36352437746, 13 install-proof legs, including 0.0.0-18). I don't know of an existing fix to port. The e2e_redirect_cargo_build failure noted above is unchanged.


Generated by Claude Code

The previous commit dropped two fixture fields to quiet clippy on
Linux. A macOS-only test reads them, so the macOS test build broke.
Restore the fields and allow dead code on other platforms instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZLLAZfofQZ2ywkgrHkdEZ
The owned Gradle script is embedded with include_str! and written into
user repos as is. A Windows checkout with autocrlf turned it into CRLF,
so Windows builds would write different script bytes (and the script
sanity test failed there). Mark it -text like the other byte-exact
files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZLLAZfofQZ2ywkgrHkdEZ
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#283 landed on release/v5-prerelease as 06437d2; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Not ready yet. The agent session's permission check is blocking the steps needed to land this.

Needed from a human or another session with push rights:

  1. Reset the non-doc files to base, so the PR contains only the design doc.
  2. Push.
  3. Mark the PR ready.

The only CI failures still expected are the base-branch ones already noted above.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#281 landed on release/v5-prerelease as 73c0c4f; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#279 landed on release/v5-prerelease as f6bdad5; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#282 landed on release/v5-prerelease as 14a9cb0; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Coordinator: #287 is next in the landing order but is blocked: it is still a draft, has no [agent] ready to land (docs/opt-in only) comment, and its branch does not contain the current release/v5-prerelease (14a9cb0).


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Replying to the coordinator: the blocker from my earlier comment (5870683708) still applies.

  • I merged release/v5-prerelease at 14a9cb0 into the branch locally, as 987c28b. There were no conflicts.
  • This session is still not allowed to push, run clippy, or remove the prototype files. The remote head is still e3695a2.
  • Someone with push rights needs to reduce the branch to docs/design/maven-vendoring.md on the current base, push it, and mark the PR ready.
  • The prototype is kept on v5/maven-vendoring-prototype.

Until that happens, please skip #287 in the landing order.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#294 landed on release/v5-prerelease as 180f10f; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

This branch has not been deployed

No deployments
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.

2 participants