Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: SocketDev/socket-patch
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: SocketDev/socket-patch
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: feat/apply-mismatch-warning
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 14 commits
  • 38 files changed
  • 2 contributors

Commits on Jun 11, 2026

  1. fix(purl): percent-decode purl components from the API

    The patches API serves scoped purls percent-encoded
    (pkg:npm/%40scope/name@1.0.0) and scan stores them verbatim as manifest
    keys, but neither the npm crawler nor the vendor coordinate parser
    decoded them — so apply/vendor reported scoped packages as 'package not
    installed', and detect_prunable saw every encoded entry as prunable.
    
    - utils/purl.rs: percent_decode_purl_component (strict, all-or-nothing,
      fail-safe passthrough), normalize_purl + purl_eq (compare/display
      only, never path construction)
    - npm_crawler parse_purl_components, vendor parse_npm_purl (NpmCoords
      now owns decoded name/version; base_purl stays verbatim for ledger/
      manifest key parity), parse_jsr_purl: decode AFTER /-and-@ splits,
      BEFORE the is_safe_* guards — %2e%2e/%2f cannot smuggle traversal
    - detect_prunable + purl_matches_identifier compare normalized forms
    - human output shows the decoded purl; JSON keeps verbatim keys
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    42e95be View commit details
    Browse the repository at this point in the history
  2. feat(vendor): auto-force staging on content mismatch + correct alread…

    …y-applied events
    
    The vendor stage is a private copy and every apply write path is
    hash-gated to exactly afterHash, so a beforeHash mismatch (a patch built
    against different bytes than the installed artifact, or a package
    already patched in place by apply) no longer fails the vendor: the
    stage is overwritten with the verified patched content and the
    overwrite surfaces as a vendor_content_mismatch_overwritten warning
    event. Missing patch-target files still fail closed without --force
    (force's silent NotFound skip would pack an artifact without the fix).
    
    - shared force_apply_staged / missing_existing_patch_files /
      mismatch_overwrite_warnings policy helpers in vendor/mod.rs, used by
      all npm flavors (via stage_patch_pack) + cargo/composer/gem/pypi/
      golang backends; dry runs predict the same outcome
    - vendor.rs: gate the already_vendored rewrite on entry.is_none() — the
      first vendor of an in-place-applied package now emits Applied (it
      packed + rewired this run) instead of a miscounted skip
    - scan --vendor: pre-prompt baseline check annotates mismatched
      packages before the confirm prompt (best-effort, read-only)
    - --force narrowed to missing-file tolerance + variant-probe bypass;
      CLI_CONTRACT.md documents the new warning code
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    c3c012f View commit details
    Browse the repository at this point in the history
  3. feat(vendor): take over exact-version override pins (pnpm + yarn berry)

    A user-authored override/resolution that pins the package to exactly
    the version being vendored (Flowise: pnpm.overrides 'tar-fs': '3.1.0')
    no longer refuses with vendor_override_conflict. The pin's key is kept
    (its spelling and quoting preserved on both pnpm surfaces — pnpm
    hard-requires the package.json and lock override maps to agree), its
    VALUE is rewritten to the file:.socket/vendor/... spec, and the pinned
    value is recorded as the wiring original so every revert path (--revert,
    reconcile, remove) restores the user's pin verbatim.
    
    - pnpm: classify_pkg_override (Insert / Ours / Takeover) replaces the
      boolean conflict checks; effective key threads through EditCtx,
      apply_pkg_override and edit_overrides; revert restores originals in
      place instead of deleting. Ranges, different versions, parent>child
      selector chains, and duplicate same-name keys still refuse, now with
      a hint that exact pins are taken over.
    - yarn berry: bare-name resolutions pin equal to the version is taken
      over symmetrically (KIND_RESOLUTION records the original).
    - npm/yarn-classic/bun wire the lock only (no override surface), so
      no conflict exists there to take over.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    7363c65 View commit details
    Browse the repository at this point in the history
  4. feat(scan): prune lifecycle for vendored packages

    scan --prune previously blanket-exempted vendored purls, so nothing
    ever cleaned unused vendored state: dropped patches kept their
    artifacts and overrides forever, removed dependencies stayed redirected,
    and orphan uuid dirs were only swept by vendor --revert.
    
    The prune pass now runs a vendored-state GC first (under the apply
    lock; contention degrades to a skip, never a scan failure):
    
    (a) entries whose patch is gone from the manifest are reverted
        (same stale test as the vendor flows' reconcile_dropped);
    (b) entries whose dependency left the lockfile graph are reverted and
        their manifest entries dropped, feeding the same pass's blob sweep.
        Per-flavor in-use probes: pnpm scans packages:/snapshots: blocks
        for the artifact (the mirrored overrides: declaration alone is not
        usage); package-lock/yarn/bun probe the lock text for the uuid dir
        (those flavors wire resolutions into the lock itself). None =
        cannot determine = keep, fail-safe; detached entries are exempt
        (lockfile-invisible by design);
    (c) orphan .socket/vendor/<eco>/<uuid> dirs are swept (extracted from
        run_revert into a shared sweep_orphan_vendor_dirs).
    
    JSON gc gains revertedVendoredEntries/removedVendorOrphanDirs (wet)
    and revertableVendoredEntries/vendorOrphanDirs (preview, which also
    mirrors the wet pass's manifest drops so blob counts agree); human
    output gains a GC summary line. CLI_CONTRACT.md updated.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    adc5179 View commit details
    Browse the repository at this point in the history
  5. test: e2e coverage for encoded scoped purls, mismatch annotation, pru…

    …ne lifecycle
    
    - scan_vendor_e2e: full pipeline with the API's percent-encoded scoped
      purl form (download -> vendor lookup against node_modules/@scope ->
      lock rewiring -> prune exemption); interactive pre-prompt baseline
      annotation + auto-force warning; scan --prune reverting an unused
      vendored entry (ledger + manifest + artifact + lock all reconciled)
    - clippy: too_many_arguments allow on stage_patch_pack, JsrPurlParts
      type alias
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    7042cbc View commit details
    Browse the repository at this point in the history
  6. feat(vendor): lockfile inventory module for npm-family locks

    Read-only inventories of the dependency set a lockfile resolves,
    independent of what is installed: name/version/purl plus the lock's
    artifact URL and content verifier (typed LockIntegrity: SRI, yarn sha1
    fragment, berry cache-zip checksum, sha256 hex, go.sum h1 — the latter
    two for the ecosystems that follow). Powers scan's lockfile supplement
    and vendor's missing-package fetch.
    
    Covers all five npm flavors via detect_npm_lock_flavor (package-lock/
    shrinkwrap, pnpm v9, yarn classic, yarn berry, bun). Fail-soft per
    entry, fail-closed per value (names/versions path-guarded; git/file/
    link/workspace specs and our own vendored entries excluded; duplicate
    instances dedup preferring a verifier). lookup() bridges percent-
    encoded manifest purls. Reuses the wiring backends' parsers via
    pub(super) visibility bumps.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    1a2dc4a View commit details
    Browse the repository at this point in the history
  7. feat(vendor): registry_fetch — verified pristine-artifact fetching

    Downloads the artifact a lockfile entry resolves (lock-recorded URL,
    else the conventional npm registry URL; SOCKET_NPM_REGISTRY override),
    verifies it against the lock-recorded integrity FAIL-CLOSED before any
    disk write (strongest hash of a multi-hash SRI; yarn sha1 fragment;
    sha256 hex), and extracts to a private tempdir the vendor pipeline can
    stage from. Entries with no verifier are refused without any network
    I/O (Unverifiable).
    
    Hardening: http(s)-only, download/decompression/entry-count/entry-size
    caps, regular-files-only extraction with first-component strip +
    is_safe_relative_subpath (fail-closed on traversal-bearing tarballs,
    nothing half-extracts), exec bits preserved so the deterministic
    re-pack keeps bin scripts executable.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    9c93b90 View commit details
    Browse the repository at this point in the history
  8. feat(vendor,scan): auto-fetch missing packages + lockfile/ledger disc…

    …overy
    
    vendor: a manifest patch whose package has no installed copy is now
    satisfied automatically (no flag) instead of failing with
    package_not_installed:
    - already-vendored purls stage from their own committed artifact,
      sha256-verified against the vendor ledger (fresh-clone re-vendor and
      in-sync runs work offline, no registry traffic);
    - otherwise the lockfile-resolved pristine artifact is fetched
      (lock-recorded URL else conventional registry URL), verified against
      the lock's integrity FAIL-CLOSED, and staged from a private tempdir —
      the project tree is never touched.
    Reason codes: vendor_fetched_missing (skip-warning beside the Applied
    event), vendor_fetch_failed (distinct Failed, suppresses the duplicate
    not-installed skip), vendor_fetch_unverifiable (no lock integrity →
    calm skip). --offline keeps the calm skip and names the lockfile as
    the would-be source.
    
    scan: discovery now supplements the installed-tree crawl with
    (a) lockfile-only dependencies — warned '[NOT INSTALLED]' in the table
        + a stderr note, JSON lockfileOnlyPackages + packages[].notInstalled,
        counted as scanned so a wiped node_modules no longer prunes
        lockfile-listed entries, partitioned out of --apply BEFORE download
        (calm skipped/package_not_installed records, exit 0, no manifest
        writes) while --vendor passes them to the auto-fetch; and
    (b) vendored-ledger entries — the committed artifact IS the dependency,
        so updates[] detection and scan --vendor keep working on a fresh
        clone before any install.
    
    scan --json --vendor now vendors a completely fresh clone end-to-end
    (e2e-proven, second run already_vendored).
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    18822dc View commit details
    Browse the repository at this point in the history
  9. feat(vendor): yarn berry checksum-verified fetch + ledger artifact st…

    …aging tests
    
    Berry locks never hash the tarball — the checksum is sha512 of the
    deterministic cache zip. The fetch rebuilds that zip from the fetched
    bytes via the same spike-pinned berry_zip recipe the wiring uses and
    compares the 10c0/<hex> value fail-closed (foreign cacheKeys are
    Unverifiable). Plus unit coverage for stage_local_artifact's
    ledger-sha256 gate.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    430145a View commit details
    Browse the repository at this point in the history
  10. feat(vendor): cargo + golang lockfile inventory and verified fetch

    - Cargo.lock [[package]] inventory: crates.io-sourced entries carry
      their sha256 .crate checksum (Sha256Hex); workspace members skipped,
      git/custom-registry sources discovery-only. Fetch from
      static.crates.io (SOCKET_CRATES_REGISTRY override), verify, extract
      ({name}-{version}/ top dir) — feeds vendor_cargo_crate's pristine_src.
    - go.sum inventory: module-zip h1: lines (the /go.mod manifests-only
      lines skipped). Fetch from the module proxy (SOCKET_GOPROXY, else the
      standard GOPROXY's first non-direct element, else proxy.golang.org)
      with Go's !uppercase path escaping; verify the dirhash Hash1/HashZip
      in memory BEFORE extraction (algorithm validated against a live
      sum.golang.org lookup for golang.org/x/text@v0.14.0); extract with
      the explicit module@version/ prefix (module paths contain slashes, so
      a first-component strip would be wrong) — feeds vendor_go_module.
    - lookup() generalized across ecosystems; inventory_project() returns
      the union the scan supplement and vendor auto-fetch consume.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    16e7e54 View commit details
    Browse the repository at this point in the history
  11. feat(vendor): composer + gem + pypi lockfile inventory and verified f…

    …etch
    
    - composer.lock packages[]/packages-dev[]: zip dists with their sha1
      shasum (frequently empty → discovery-only); names lowercased to the
      packagist form, pretty leading v dropped; path dists (ours) excluded.
      Fetch verifies sha1 and strips the variable zipball top dir.
    - Gemfile.lock GEM/specs + bundler 2.6 CHECKSUMS sha256 (older locks
      discovery-only); the GEM remote drives the /downloads/<gem> URL.
      Platform-suffixed specs skipped (unsupported for vendoring). The
      fetched .gem (plain tar) is sha256-verified whole, then data.tar.gz
      extracts at the root (no prefix strip).
    - pypi: uv.lock registry packages with a pure py3-none-any wheel carry
      a fetchable URL + sha256; poetry.lock and ==-pinned requirements.txt
      contribute discovery-only entries (PEP 503-normalized names). The
      unzipped wheel is a site-packages-shaped stage for the pypi backend.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    b5e9f63 View commit details
    Browse the repository at this point in the history
  12. feat(scan): all-ecosystem lockfile supplement + docs

    scan's lockfile supplement now consumes inventory_project (npm-family,
    Cargo.lock, go.sum, composer.lock, Gemfile.lock, uv/poetry/requirements)
    with per-ecosystem counts; the vendor auto-fetch pass likewise serves
    every inventoried ecosystem. CLI_CONTRACT.md gains the lockfile-
    supplement and vendor-auto-fetch sections + the three reason codes;
    README notes the fresh-clone flow; the exact-shape empty-scan contract
    test pins the additive lockfileOnlyPackages field; the cargo build e2e
    scrubs ambient CARGO_TARGET_DIR from child builds.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    772f98d View commit details
    Browse the repository at this point in the history
  13. feat(apply): beforeHash mismatch warns and applies the full blob by d…

    …efault; --strict restores the hard error
    
    A file whose on-disk content matches NEITHER the patch's beforeHash nor
    its afterHash previously hard-failed the in-place apply (the flatted
    case: a patch built against non-registry bytes made plain apply
    unusable). The default now overwrites such files with the FULL verified
    patched content and continues:
    
    - core: apply_package_patch's force bool becomes MismatchPolicy
      {Warn (default) | Strict | Force}. Warn promotes HashMismatch to
      Ready keeping the warning signature (expected/current hashes); the
      diff strategy self-disables on a wrong base (partial patches are
      skipped, as they must be) and the archive/blob writes stay hash-gated
      to exactly afterHash — a tolerated mismatch lands verified patched
      bytes or fails, never silent corruption. Missing pre-existing files
      still fail closed (only Force skips them).
    - CLI: global --strict (env SOCKET_STRICT) restores the fail-closed
      behavior across apply/get/scan --apply/the hook/go redirects
      (--force overrides it); plumbed through DownloadParams into the
      nested applies. Vendor staging is unaffected (already auto-forces
      into its private stage).
    - Each overwrite logs a content_mismatch_overwritten warning to stderr
      and rides the JSON envelope as a Skipped warning event beside the
      package's Applied event.
    - Since the full content lives in the afterHash blob and the default
      --download-mode diff may not have staged it, a pre-apply pass probes
      for mismatches and downloads the missing blobs by hash (offline runs
      warn and let those files fail).
    
    Live-verified: pristine flatted@3.3.1 + its bad-baseline patch now
    applies 6/6 files via blob with per-file warnings (exit 0);
    apply --strict exits 1 with the old error and leaves files untouched.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    0426e0b View commit details
    Browse the repository at this point in the history
  14. polish(apply): decode percent-encoded purls in human output

    The 'Patched packages' summary and the no-matching-installed-package
    warning printed manifest keys verbatim (pkg:npm/%40scope/...); show the
    decoded form like the scan/vendor output does. JSON keeps verbatim keys.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    mikolalysenko and claude committed Jun 11, 2026
    Configuration menu
    Copy the full SHA
    64c59f1 View commit details
    Browse the repository at this point in the history
Loading