feat(deps): upgrade puppeteer to 25, axios to 1.19, better-sqlite3 to 13; require Node >= 22 - #110
Merged
Merged
Conversation
… 13; require Node >= 22 Final dependency upgrade for the security cleanup in #109: - puppeteer ^25.8.0: drops the vulnerable extract-zip dependency (SNYK-JS-EXTRACTZIP-17660777 has no fixed release; puppeteer 25 replaced extract-zip with modern-tar). Code adapted to the v25 API: executablePath() is now async, browser.isConnected() became the .connected property. - axios ^1.19.0: clears all advisories flagged up to 1.17.x. - js-yaml ^4.3.1 (as planned in #109). - better-sqlite3 ^13.0.3 in root and mcp: 11.x cannot compile on Node >= 26 (uses removed V8 APIs). - Node: puppeteer 25 is ESM-only and needs Node >= 22, so package.json now declares engines.node >= 22 and the Docker image moves from node:20-slim (EOL) to node:26-slim. - mcp: repair the build broken since #62 bumped the MCP SDK to 1.25.3 — capabilities moved to McpServer's options argument, zod ^3.25.0 with an npm override so the SDK no longer nests zod 4 next to the app's zod 3, @qdrant/js-client-rest pinned to ^1.16.2 (1.17+ drops the search method the server relies on). - tests: stub puppeteer.executablePath in the four crawlWebsite tests that run it under fake timers (it does real I/O since v25 and the retry timer was scheduled after the timer advance, hanging the crawl); restore real timers in the crawlWebsite afterEach so a failing test can no longer leak frozen timers into the rest of the block. Verified on Node 26.7.0: root build, mcp build, full vitest suite (723 passed / 8 skipped). npm audit: axios/puppeteer/extract-zip advisories cleared; mcp reports 0 vulnerabilities. Signed-off-by: Denis Jannot <denis.jannot@solo.io>
… base) The package was orphaned and dropped from trixie; it only provided Arabic display fonts, which doc2vec never needs — pages are text-extracted, not rendered to images. Signed-off-by: Denis Jannot <denis.jannot@solo.io>
…atibility The 1.13 client builds an Agent from its bundled undici 5 and passes it as the dispatcher to the global fetch — on Node 26 that's undici 7, whose dispatch-handler protocol differs, so every request dies with 'fetch failed' (cause: InvalidArgumentError: invalid onError method). 1.19.0 ships undici 7.29 and works against a real Qdrant from the image (verified with docker). The root sync code doesn't use the search API that 1.17 removed, so unlike mcp it can take the latest client. Signed-off-by: Denis Jannot <denis.jannot@solo.io>
…mbedding fails A rejected embedding request (e.g. an invalid OpenAI API key) was swallowed at every layer: createEmbeddings caught all errors and returned [], callers logged 'Embedding failed for chunk' per chunk and moved on, and both processChunksForUrl and the GitHub processIssue path deleted the item's existing chunks BEFORE embedding — so a bad key deleted stored chunks, stored nothing back, advanced the sync markers (ETag/lastmod, last-run date), and the run finished green. Now: - createEmbeddings throws FatalEmbeddingError on 401/403 — an auth failure is permanent, so the source aborts instead of degrading every chunk into a logged-and-skipped failure. Transient errors still return []. - FatalEmbeddingError is rethrown through every per-item catch (website page callback + crawl loop, GitHub issue, Zendesk ticket, local dir, S3, code file), so a bad key fails the source on the first chunk. - processChunksForUrl and processIssue embed all chunks BEFORE deleting the old ones; on any embedding failure the existing chunks are kept and the item fails: websites don't store ETag/lastmod (page retried next run), GitHub counts it toward failedChunks (last-run date not advanced), Zendesk counts failedTickets. Tests: 6 new cases covering the fatal 401/403 path, transient-failure tolerance, and that existing chunks are never deleted when embedding fails. Signed-off-by: Denis Jannot <denis.jannot@solo.io>
This was referenced Aug 19, 2026
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.
Final combined dependency upgrade for #109, superseding the remaining Snyk PRs (#86, #97, #90 — will close them once this merges).
Dependency changes
extract-zip(SNYK-JS-EXTRACTZIP-17660777 has no fixed release; v25 replaced it withmodern-tar)1.0.0 – 1.17.0)Node requirement
Puppeteer 25 is ESM-only and requires Node ≥ 22, so:
engines.node >= 22declared in package.json (hence the minor version bump to 2.15.0)node:20-slim(EOL, incompatible with puppeteer 25) tonode:26-slimCode adaptations for puppeteer 25
puppeteer.executablePath()is now async →resolveBrowserExecutablePathawaits itbrowser.isConnected()was removed →.connectedpropertymcp build repair
The mcp package has not compiled since #62 bumped
@modelcontextprotocol/sdkto 1.25.3 (no CI to catch it):capabilitiesmoved toMcpServer's options argument (no longer valid in server info)^3.25 || ^4) with an npmoverridesentry so the SDK no longer gets a nested zod 4 next to the app's zod 3 (that mismatch caused theTS2589errors)@qdrant/js-client-restpinned to ^1.16.2 — 1.17+ drops thesearchmethodserver.tsrelies on (follow-up: migrate to thequeryAPI)Test fixes
Puppeteer 25's async
executablePath()does real I/O; the four crawlWebsite tests that run it under fake timers hung (the retry timer was only scheduled after the timer advance had finished) — those tests now stubexecutablePath, and the crawlWebsiteafterEachrestores real timers so a single failing test can no longer leak frozen timers into the remaining tests of the block.Verification
On Node 26.7.0: root
tscbuild ✅, mcp build ✅, full vitest suite 723 passed / 8 skipped ✅.npm audit: axios/puppeteer/extract-zip advisories cleared; mcp reports 0 vulnerabilities. Remaining root audit findings (~20, in @mozilla/readability, @xmldom/xmldom, fast-xml-parser, nanoid, esbuild-via-vitest…) are the separate final CVE check from #109.Part of #109
🤖 Generated with Claude Code
Also: qdrant client Node 26 compatibility + silent embedding failures
fetch failed(InvalidArgumentError: invalid onError method). Verified against a real Qdrant container from the built image.processChunksForUrl/processIssuehad already deleted the item's existing chunks — destroying data, storing nothing, advancing sync markers, and finishing green. Now all chunks are embedded before old ones are deleted, aFatalEmbeddingError(401/403) aborts the source immediately, and transient failures mark the item failed so sync markers aren't advanced and the next run retries. 6 new tests.