Skip to content

Add in-memory hosted engine and napi addon - #276

Open
Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
mainfrom
feat/napi-hosted-in-memory
Open

Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
mainfrom
feat/napi-hosted-in-memory

Conversation

@mikolalysenko

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

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Summary

Adds a way for a service to run hosted-mode patching in-process, with no working directory and no network calls from the engine. depscan's new autopatch worker streams a repository's lockfiles into it and serves patch lookups straight from the patch database.

  • hosted_memory engine (crates/socket-patch-cli/src/hosted_memory/): takes a map of repository files (text, binary, presence-only, symlinks), detects project roots, looks up patches once across all roots, and returns rewritten files plus per-root redirect ledgers. The rewrite, pnpm trust and npm allow-remote planning, confirmation and ledger-merge stages are copied as pure functions from run_redirect_selected. The disk scan --mode hosted path is unchanged.
  • PatchApi trait (appended in api/client.rs): the five lookups the hosted path makes (batch, by-package, package references, view, artifact download). ApiClient implements it by forwarding to its existing methods.
  • ProjectView seam (lock_inventory/view.rs): lockfile readers work over disk or memory. Disk wrappers call the same readers, so behavior is unchanged.
  • Hidden hosted-bundle command: runs the engine on a JSON bundle from stdin, for debugging.
  • socket-patch-node napi addon (crates/socket-patch-node, napi 3.13): HostedScanSession (pushChunk / endFile / markPresent / finish / cancel), selectHostedScanPaths, and a JS provider callback that implements PatchApi. The JS package is private and lives outside the npm/socket-patch-* release glob.

Scope and limits

Testing

  • 20 parity tests run the real CLI binary with a scrubbed environment and compare changed bytes, ledger bytes and the redirect block against the engine, across npm, pnpm v9, yarn classic and berry, bun.lock, bun.lockb, Rush, uv, requirements, poetry, Pipfile, cargo (including workspaces and [patch] paths), composer, Gemfile, golang and a nested monorepo.
  • Engine tests cover cross-root lookup dedup, determinism, hostile SOCKET_* environments, malformed and 200k-deep inputs, limits, cancellation, timeouts, no proxy fallback on 401, symlinks, a corrupt ledger and vendored takeover refusal.
  • Node smoke test (13 cases) against the built addon: streamed redirect, dry run, provider failures, cancel, limits.
  • cargo clippy --workspace --all-features -- -D warnings passes. The addon has only been built on macOS arm64; Linux and Windows CI builds are the first run there.

🤖 Generated with Claude Code


Note

Medium Risk
Large new hosted redirect path and N-API boundary with org-authenticated lookups; disk scan behavior is mostly shared via extracted logic and parity tests, but any engine drift could affect in-process consumers before the CLI path.

Overview
Introduces an in-memory hosted redirect engine so hosted-mode patching can run without touching the filesystem or spawning the CLI. Callers supply repo files (text, binary, presence-only, symlinks); the engine detects roots, deduplicates patch lookups across roots, and returns rewritten lockfiles plus redirect ledgers aligned with scan --mode hosted --json.

The engine lives under crates/socket-patch-cli/src/hosted_memory/ (discovery, ledger merge, path selection, redirect planning/rewrite). Disk scan --mode hosted is largely unchanged; many helpers in commands/scan/hosted.rs are widened to pub(crate) so the engine can reuse the same pnpm/npm trust and JSON shapes. A hidden hosted-bundle subcommand runs the engine from a JSON stdin bundle for parity/debugging (requires org API token; no public proxy).

Adds socket-patch-node, a private N-API crate exposing HostedScanSession (streamed input), selectHostedScanPaths, and a JS PatchApi provider. Workspace default-members and release builds now target only socket-patch-cli so release artifacts skip the addon; CI gains a node-addon job (build + Node smoke tests) and a dedicated profile.addon for faster addon links.

Reviewed by Cursor Bugbot for commit 1f45298. Configure here.

Let hosts run hosted-mode patching without a working directory or
network access. The new hosted_memory engine takes a map of repository
files, finds every project root, looks up patches once across all roots
through a pluggable PatchApi provider, and returns the rewritten
lockfiles and redirect ledgers.

Lockfile inventory now reads through a ProjectView, so the same parsers
serve disk and in-memory projects; disk behavior is unchanged. The
existing scan --mode hosted path keeps using ApiClient directly, which
also implements PatchApi.

Parity tests compare the engine against the real CLI binary across npm,
pnpm, yarn, bun, pypi, cargo, composer, gem and golang fixtures. A hidden
hosted-bundle command exposes the engine for debugging.

Assisted-by: Claude Code:claude-opus-5-5
Expose the in-memory hosted engine to Node as a native addon, so a
service can stream repository files into a scan session and serve patch
lookups from its own data source instead of the Socket API.

The package lives under crates/socket-patch-node/npm and is private, so
the npm release tooling does not publish it. Release builds now build
only the CLI crate, and a new CI job builds the addon and runs its Node
smoke test.

Assisted-by: Claude Code:claude-opus-5-5
@socket-security

socket-security Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​napi@​3.13.08110093100100
Addedcargo/​napi-build@​2.5.09710093100100
Addedcargo/​napi-derive@​3.6.99910093100100

View full report

@socket-security-staging

socket-security-staging Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​napi@​3.13.08210093100100
Addedcargo/​napi-build@​2.5.09710093100100
Addedcargo/​napi-derive@​3.6.99910093100100

View full report

Comment thread crates/socket-patch-node/src/lib.rs Fixed
Export the scan session as an opaque External handle plus plain
functions, not a napi class. The class wrapper's generated glue unwraps
its native pointer through an FFI out-parameter, which CodeQL reports as
a possible invalid pointer dereference. The public HostedScanSession in
index.js is unchanged; it now calls the handle functions.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review September 27, 2026 00:51

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issues.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 1f45298. Configure here.

let reason = if rush_internal {
Some("rush_internal")
} else if remaining.is_empty() {
Some("cargo_member")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nested Cargo roots over-demoted

Medium Severity

detect_roots treats any Cargo.lock under an ancestor lock as a workspace member and drops that directory as a root, without reading members/exclude. demote_cargo_members later uses real workspace membership and keeps excluded crates, but those crates never become roots, so their lock is never streamed or scanned. Independent nested Cargo projects are left unpatched.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1f45298. Configure here.

socket_patch_core::utils::pipenv::MAJOR_OVERRIDE_ENV
),
});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pipenv warning cites unused PATH

Low Severity

When pipenvMajor is unset, the engine emits redirect_pipenv_installer_unknown telling users to put Pipenv on PATH or set a process env var. The in-memory engine never reads the environment; only the pipenvMajor option is honored. Following that advice cannot change the next scan.

Fix in Cursor Fix in Web

Triggered by learned rule: Remediation advice must be convergent: following it must clear the triggering detection

Reviewed by Cursor Bugbot for commit 1f45298. Configure here.

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