[agent] Filed by Claude Code on behalf of Mikola Lysenko (@mikolalysenko) while adding Maven patch SBOM annotations to depscan. Repro artifacts were produced with real Maven and a stub patch API.
Summary
Maven patch records are keyed differently depending on the consumer:
- Vendored mode (
vendor, scan/get --mode vendored) treats record file keys as jar member paths (META-INF/NOTICE.txt, org/…/Foo.class). It extracts the cached jar, applies the patch to the members, and re-zips.
- Agent mode (
apply) resolves the keys relative to the version directory (~/.m2/repository/<g>/<a>/<v>/<key>) and never opens the jar.
So one API record cannot serve both modes. The Socket patch backend builds Maven patches as jar-member overlays: depscan's maven repacker applies the record's files as jar entries at the archive root. Every such patch therefore fails in agent mode.
Impact
Agent mode (scan --sync, get + apply) is unusable for real Socket Maven patches. It fails with apply_failed: … File not found, and the jar in ~/.m2 stays unpatched. The docker e2e only passes because its record uses a version-directory key (package/commons-lang3-3.12.0.pom).
Repro
Stage one record in .socket/manifest.json with a blob, keyed META-INF/NOTICE.txt (git-sha256 before/after of the member, exactly like e2e_vendor_maven_build::stage_manifest). MAVEN_REPO_LOCAL holds Central's commons-lang3 3.12.0 jar and pom.
socket-patch apply --json --offline
-> exit 1 {"status":"partialFailure","events":[{"action":"failed","errorCode":"apply_failed",
"error":"Cannot apply patch: META-INF/NOTICE.txt - File not found"}]}
~/.m2 jar: PRISTINE
socket-patch vendor --json --offline (same manifest)
-> exit 0 {"events":[{"action":"applied","files":[{"path":"META-INF/NOTICE.txt","verified":true,"appliedVia":"blob"}]}]}
Expected vs actual
- Expected: agent-mode
apply handles Maven records whose keys are not version-directory files by patching the jar's members in place. It could reuse the vendored stage_local_jar / member-apply path, rewriting the jar and its .sha1, and keeping the rollback before-blob as the original jar. Alternatively it refuses Maven member-keyed records up front with a clear code that recommends --mode hosted/vendored.
- Actual: a generic "File not found" failure.
CLI revision
3efdc31d
Suggested fix
- Share the vendored jar-member application with
apply, keyed off "the record key is not a file in the version directory, but is an entry in <a>-<v>[-<classifier>].jar".
- Add a docker/e2e case with a member-keyed record.
- Rollback and VEX (
vex_consumed maven copies) need to agree on the after-hash semantics: member hash vs. whole-jar hash.
File refs (at 3efdc31)
crates/socket-patch-core/src/patch/apply.rs (no jar/zip handling; see the classifier comment near l.350)
crates/socket-patch-core/src/vendor/maven_repo.rs:153-420 (vendor_maven: member-level apply + deterministic re-zip)
crates/socket-patch-cli/tests/docker_e2e_maven.rs:109-116 (version-dir keys only)
[agent] Filed by Claude Code on behalf of Mikola Lysenko (@mikolalysenko) while adding Maven patch SBOM annotations to depscan. Repro artifacts were produced with real Maven and a stub patch API.
Summary
Maven patch records are keyed differently depending on the consumer:
vendor,scan/get --mode vendored) treats record file keys as jar member paths (META-INF/NOTICE.txt,org/…/Foo.class). It extracts the cached jar, applies the patch to the members, and re-zips.apply) resolves the keys relative to the version directory (~/.m2/repository/<g>/<a>/<v>/<key>) and never opens the jar.So one API record cannot serve both modes. The Socket patch backend builds Maven patches as jar-member overlays: depscan's maven repacker applies the record's files as jar entries at the archive root. Every such patch therefore fails in agent mode.
Impact
Agent mode (
scan --sync,get+apply) is unusable for real Socket Maven patches. It fails withapply_failed: … File not found, and the jar in~/.m2stays unpatched. The docker e2e only passes because its record uses a version-directory key (package/commons-lang3-3.12.0.pom).Repro
Stage one record in
.socket/manifest.jsonwith a blob, keyedMETA-INF/NOTICE.txt(git-sha256 before/after of the member, exactly likee2e_vendor_maven_build::stage_manifest).MAVEN_REPO_LOCALholds Central's commons-lang3 3.12.0 jar and pom.Expected vs actual
applyhandles Maven records whose keys are not version-directory files by patching the jar's members in place. It could reuse the vendoredstage_local_jar/ member-apply path, rewriting the jar and its.sha1, and keeping the rollback before-blob as the original jar. Alternatively it refuses Maven member-keyed records up front with a clear code that recommends--mode hosted/vendored.CLI revision
3efdc31dSuggested fix
apply, keyed off "the record key is not a file in the version directory, but is an entry in<a>-<v>[-<classifier>].jar".vex_consumedmaven copies) need to agree on the after-hash semantics: member hash vs. whole-jar hash.File refs (at 3efdc31)
crates/socket-patch-core/src/patch/apply.rs(no jar/zip handling; see the classifier comment near l.350)crates/socket-patch-core/src/vendor/maven_repo.rs:153-420(vendor_maven: member-level apply + deterministic re-zip)crates/socket-patch-cli/tests/docker_e2e_maven.rs:109-116(version-dir keys only)