Skip to content

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

Merged
Mikola Lysenko (mikolalysenko) merged 5 commits into
mainfrom
feat/napi-hosted-in-memory
Sep 27, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 5 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), backed by an opaque External handle rather than a napi class (the class glue tripped CodeQL's invalid-pointer rule), 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.

Comment thread crates/socket-patch-cli/src/hosted_memory/roots.rs Outdated
Comment thread crates/socket-patch-cli/src/hosted_memory/redirect.rs
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Claude (@claude) review

Keep every directory with its own Cargo.lock as a project root during
path selection. Whether a nested lock belongs to an enclosing workspace
depends on that workspace's members and exclude lists, which only the
engine can read. Crates the workspace excludes are independent projects
and are now scanned; real members still have their unused lock ignored.

Point the in-memory Pipenv warning at the pipenvMajor option, the only
input the engine reads, instead of PATH or an environment variable.

Assisted-by: Claude Code:claude-opus-5-5
Bring in the concurrent scan work from #257. The Cargo member walk keeps
the tree abstraction the in-memory engine needs, and its disk tree reads
manifests through the new parse memo; the memory tree parses directly.
The in-memory Cargo.lock reader adopts the memoized Arc<DocumentMut>
that read_lock now returns.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) merged commit afa7253 into main Sep 27, 2026
413 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the feat/napi-hosted-in-memory branch September 27, 2026 14:32
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Sep 27, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Sep 27, 2026
#276 moved the lock inventory onto `ProjectView` (disk or the in-memory
hosted engine's `MemoryProject`). The requirements.txt reader keeps the
rewired-line fix on main's new signature, so it reaches the in-memory
engine through the same function; the redirected-lines test now also
reads the file through a `ProjectView::Memory` and expects the same
packages. The order and js7 fixes touch `get` and vendored staging,
neither of which the hosted-only in-memory engine copies.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Sep 27, 2026
Brings in #276 (the in-memory hosted engine and its napi addon) and
wires vlt into it:

- vlt-lock.json is a project-root marker.
- The lock inventory and the in-memory flavor probe read vlt through
  the new ProjectView.
- The in-memory rewrite passes bun.lockb presence and the vlt
  withholding to the rewriters, and confirms vlt deps the way the disk
  flow does.
- The in-memory ledger merge rebases vlt edits like the disk merge.
- The engine has no network for the vlt artifact preflight, so it
  judges every in-scope vlt artifact as --offline does: the dep is
  withheld (redirect_vlt_artifact_unverifiable), never pinned. The disk
  and memory preflights share one judge. The node_modules/.vlt-lock.json
  entry is only an install-state sentinel, as on disk.

The lock-inventory conflicts are resolved onto #276's ProjectView
readers, and REBASE_KINDS keeps the vlt kind now that it is shared.

Assisted-by: Claude Code:claude-opus-5-5
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.

3 participants