Repository navigation
Fix Bun patches keyed by a rewired resolution (#1019) - #1699
Merged
Mikola Lysenko (mikolalysenko) merged 5 commits intoOct 23, 2026
Merged
Mikola Lysenko (mikolalysenko) merged 5 commits into
Mikola Lysenko (mikolalysenko) merged 5 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
A bun patch made after socket-patch rewired a package is keyed by the tarball it resolves to, such as @s/p@.socket/vendor/npm/<uuid>/@s/p-1.0.0.tgz. The consent gate split that key at its last @, which sits inside the path for a scoped package, so the package went unprotected. Split at the first @ past the scope, as Bun does. Refs #1019 Assisted-by: Claude Code:claude-opus-5-5
Bun 1.4 keys a bun patch made after a rewire by the package's current resolution. A superseding hosted re-run, a takeover or a vendored re-run moved the entry and orphaned that key, so the user's patch silently stopped applying, even with --allow-patch-conflicts. The bun guard now matches those keys and leaves the package where the patch applies (a key for the URL this run would pin anyway is no conflict). Rollback, remove and vendor --revert still go ahead, but now warn that such a patch stops applying. Refs #1019 Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
force-pushed
the
agent/fix-bun-patched-dependency-resolution-key
branch
from
October 23, 2026 20:00
8e3c884 to
cef3ad4
Compare
Rollback, remove and vendor --revert warned about any tarball-keyed bun patch for a package, even a stale key the lock no longer resolved to, or one the revert put back in force (a pre-v5 vendored revert that returns the lock to its hosted URL). They now compare the keys the lock resolves to before and after the write and warn only for the ones it took out, so a revert followed by a hosted unwind no longer warns twice. Refs #1019 Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 23, 2026 20:54
Collaborator
Author
|
BugBot review Generated by Claude Code |
The unwind's Bun patch check opened bun.lockb with a bare read, so a FIFO or device at that path could hang rollback, remove and vendor --revert. It now reads the lock the way the rest of the Bun backend does. Refs #1019 Assisted-by: Claude Code:claude-opus-5-5
Collaborator
Author
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 979f3db. Configure here.
Collaborator
Author
|
Burn-down agent: labeled Ready for review.
Generated by Claude Code |
Collaborator
Author
|
Burn-down agent: labeled Ready for review.
Generated by Claude Code |
Tanmay Singla (Tanmay182003)
approved these changes
Oct 23, 2026
Mikola Lysenko (mikolalysenko)
deleted the
agent/fix-bun-patched-dependency-resolution-key
branch
October 23, 2026 22:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1019
Summary
On Bun 1.4, a
bun patchmade after socket-patch rewired a package is keyed by the package's current resolution. That isname@https://patch.socket.dev/…/name-1.0.0.tgzwhen hosted, orname@.socket/vendor/npm/<uuid>/name-1.0.0.tgzwhen vendored. Bun applies the patch only while the lock still resolves the package there. Before this PR, any socket-patch run that moved the entry orphaned the key, and the user's own patch silently stopped applying on every install, with exit 0 and no warning. Those runs were a superseding hosted re-run, a hosted⇄vendored takeover, a vendored re-run onto a new uuid,rollback/remove, andvendor --revert.What changes for users:
bun patchis keyed by a hosted URL or vendored path stays where it is, and the run warnsredirect_bun_patched_dependency_skipped(hosted) or refusesvendor_lock_entry_unsupported(vendored), naming the key. That covers the superseding re-run, both takeovers (the takeover keeps the existing wiring:redirect_takeover_kept_vendored, or the hosted lock untouched), and vendored re-runs.--allow-patch-conflictsdoes not lift this, just as it doesn't for the Hosted and vendored Bun rewiring silently discards the project's ownbun patch(patchedDependencies): fresh frozen installs drop the user's patch with exit 0 #367 registry key. A key for the URL or path the run would pin anyway (an in-sync re-run at the same uuid) is no conflict, so those runs stay quiet and VEX still attests.vendor --revert: these still restore the registry entry the user asked for. A wet run that takes out of the lock the tarball a patch is keyed by now warnsredirect_bun_patched_dependency_dropped(hosted unwind) orvendor_bun_patched_dependency_dropped(vendored revert), naming the key and how to re-create the patch. Each unwind compares the keys the lock resolves to before and after it writes, so a stale key, or one the unwind puts back in force, stays silent.user_patch_conflict) split apatchedDependencieskey at its last@. For a scoped package's resolution key, that@sits inside the URL or path (…/npm/@s/p/…), so the key named no package and the scoped package went unprotected. It now splits at the first@past the scope, as Bun does.Root cause
Both places that recognize a project-owned Bun patch assumed the key is
name@<semver or range>:vendor::bun_lock_text::patched_dependency_key, the Hosted and vendored Bun rewiring silently discards the project's ownbun patch(patchedDependencies): fresh frozen installs drop the user's patch with exit 0 #367 backend guard shared by the hosted text and binary rewriters, the in-memory hosted engine, and the vendored text and binary backends. It matched onlyname@versionand a barename. It now also matchesname@<…>/<leaf>-<version>.tgz, the package's own tarball, unless that is the resolution this run writes (dep.artifact_urlfor hosted,<uuid_dir_rel>/<leaf>-<version>.tgzfor vendored). For the unwind warnings,vendor::bun_lock::live_user_patch_keysreads the keys whosename@resolutionis a current lock entry spec (textbun.lock, orbun.lockb). The hosted unwind andrevert_bun_optswarn for the keys that leave that set.patch::user_patches::split_selectorsplit at the last@.Test evidence
Red→green: each new test below fails on
mainand passes on this branch. To check, I putmain's sources back with the new tests kept.patch::user_patches::tests::bun_resolution_keys_protect_scoped_and_unscoped_packagesvendor::bun_lock_text::tests::patched_dependency_key_matches_rewired_resolutionspatch::redirect::tests::bun_lock_patch_keyed_by_hosted_url_survives_superseding_rerunvendor::bun_lock::tests::user_bun_patch_keyed_by_resolution_refuses_before_any_write--allow-patch-conflictsin_process_vendor_bun_takeoveruser_patch::bun_patch_keyed_by_hosted_url_survives_a_superseding_rerunuser_patch::bun_patch_keyed_by_hosted_url_blocks_the_vendored_takeoveruser_patch::bun_patch_keyed_by_vendored_path_blocks_the_hosted_takeoverrollbackwarnsredirect_bun_patched_dependency_droppeduser_patch::bun_rollback_warns_that_a_patch_keyed_by_the_hosted_url_stops_applyingvendor --revertwarnsvendor_bun_patched_dependency_droppeduser_patch::bun_vendor_revert_warns_that_a_patch_keyed_by_the_vendored_path_stops_applyingThe issue's matrix maps onto these as follows: hosted superseding re-run (text lock) → rewriter + CLI re-run tests;
bun.lockbhosted re-run → same guard via the in-memory engine andrewrite_bun_binarycallers (skip_bun_user_patched); hosted→vendored and vendored→hosted takeovers → the two CLI takeover tests; vendored superseding re-run → vendored unit test (the guard runs inpreflight_packagefor every entry state);rollback→ CLI rollback test;vendor --revert→ CLI revert test.Local runs:
cargo fmt --all -- --check: cleancargo clippy --workspace --all-features -- -D warnings: cleancargo test -p socket-patch-core --all-features: 6704 passed, 4 failed. The 4 also fail onmain's sources in this sandbox, because they are permission tests that break when run as root:wire_failure_rolls_back_already_written_files,wire_write_failure_maps_error_and_leaves_lock_untouched,relax_loop_must_not_traverse_symlinked_root,an_unremovable_hidden_lock_keeps_every_store_entry.cargo test -p socket-patch-cli --all-features, the suites this touches:--lib933,in_process_vendor_bun_takeover45,rollback122,scan245,user_patches27,in_process_rollback_vendored22,vendor_eject_bun_lockb10, all passing.in_process_redirectis 148 passed and 3 failed; the 3 write-failure tests also fail onmainas root. The whole CLI crate doesn't fit in this sandbox's disk allowance, so CI runs the rest.SOCKET_PATCH_BUN_E2E_REQUIRED=1 … -- --include-ignored:e2e_redirect_bun_build38,e2e_vendor_bun_build40,mode_migration_bun35, all passing.Notes
bun patch --commitafter a rewire.patch::redirect::vlt_heal::tests::an_unremovable_hidden_lock_keeps_every_store_entryfails locally onmaintoo, because this sandbox runs as root. It's unrelated.npm/,pypi/,gem/) changes are needed: this is all Rust-side lock logic./code-review highfindings:bun_purlsfilter inhosted_unwind.UserPatchIndexalready treats a selector it can't parse as protecting every version of the name (fix(cli)!: require consent before patching user-patched packages #1646's "unknown ranges protect every version" rule). A resolution key falls under that rule for scoped and unscoped packages alike. This PR only makes scoped keys reach it.?query/#fragment/\\spellings. socket-patch's own hosted URLs and vendored paths, which are the keys Bun writes after one of our rewires, never carry them, andbun.lockuses/.live_user_patch_keysreturns after readingpackage.jsonand the text lock when no key names a tarball. A revert already reads and writes the same lock.CHANGELOG.mdis untouched.https://claude.ai/code/session_014dTNrFC4Epo2YKb7Ydxm7c
Generated by Claude Code