Conversation
…RCE) (#342) * docs: add project rules for claude code * fix(security): add module whitelist to prevent arbitrary code injection via /use endpoint The /use endpoint accepts a module name from the HTTP query string and passes it directly to importlib.import_module() with only lowercase/strip normalization. This allows an attacker to load arbitrary Python modules by sending crafted requests, potentially achieving remote code execution. Add an ALLOWED_MODULES frozenset whitelist that restricts dynamic imports to the 10 known service modules (chat, clients, data, dropper, pipe, profiler, remote, services, task, task_http). Requests for any other module name now raise ValueError, returning a 400 response. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add language identifier to markdown code fence Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(security): require authentication for profiler endpoints All 5 profiler endpoints (/profile, /profile/start, /profile/stop, /profile/status, /profile/report) were registered with public=True, bypassing the AuthMiddleware entirely. This allows unauthenticated users to start/stop profiling and read performance reports that expose internal function names, call counts, and timing data. Remove public=True from all profiler route registrations so they require authentication like other protected endpoints. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: correct HTTP method in profiler docs (PUT → POST) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: remove claude.md from version control This file is project-specific AI tooling configuration and should not be tracked in git. Added to .gitignore instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(security): add tests for ALLOWED_MODULES allowlist validation Verify that: - ALLOWED_MODULES is an immutable frozenset with the expected 10 entries - use() rejects non-allowlisted modules and path traversal attempts - use() accepts valid modules and calls initModule correctly - use() normalizes module names (lower + strip) - use() skips already-loaded modules without re-importing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(security): address CodeRabbit review feedback on test_server.py - Fix S104: change stub host from 0.0.0.0 to 127.0.0.1 - Add return type annotation to _make_server() -> WebServer - Track injected sys.modules mocks and clean up in teardown_module() - Assert cached module's initModule is not re-called in reload test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: minor changes --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: stepmik <stepmikhaylov@yandex.ru>
…tore (#355) * fix(security): prevent filter expression injection in Milvus vector store Add _escape_milvus_str() helper to sanitize user-controlled values before interpolation into Milvus filter expressions. Escapes single quotes and backslashes to prevent filter injection attacks across all query construction points in the Milvus store implementation. * fix: address review feedback on Milvus filter injection PR - Remove unnecessary tuple wrappers on append calls - Fix isTable filter using wrong field (docFilter.nodeId -> docFilter.isTable) - Use unquoted boolean for isTable filter (matches isDeleted pattern) - Add type annotation and docstring to _escape_milvus_str * fix: move test to nodes/test/ per project conventions
* fix(security): use secure temporary file creation in task engine Replace insecure predictable temp file path with tempfile.mkstemp() to prevent information disclosure and symlink attacks. _write_task_file previously wrote pipeline config (which may contain API keys and resolved env vars) to /tmp/<task-id>.json with default 0644 permissions. This was vulnerable to: - World-readable files exposing sensitive pipeline configuration - Symlink attacks due to predictable path based on task ID - TOCTOU races from lack of O_EXCL exclusive creation mkstemp() creates the file atomically with O_EXCL, uses a random suffix making the path unpredictable, and defaults to 0600 permissions (owner read/write only). Uses await asyncio.to_thread(os.write, ...) for async compatibility. Tests use asyncio.run() instead of deprecated get_event_loop(). * fix: address CodeRabbit findings on temp file PR - Use os.fdopen + f.write instead of os.write to prevent partial writes - Remove unused tempfile import in tests - Add @skipIf(os.name == 'nt') on POSIX-specific tests * chore: minor changes --------- Co-authored-by: stepmik <stepmikhaylov@yandex.ru>
…pe HTML output (#362) * fix(security): require authentication for profiler endpoints and escape HTML output Remove public=True from all 5 profiler routes so they require authentication via AuthMiddleware, and HTML-escape the profile report output to prevent XSS. * fix: improve profiler XSS tests to verify actual endpoint output * fix: revert conftest.py changes, scope mocks to test file Remove depends and rocketride mocks from conftest.py (they break other tests per asclearuc). Move stubs into the profiler test file where they're needed, scoped locally.
Co-authored-by: Dmitrii Karataev <dmitriikarataev@Dmitriis-MacBook-Pro.local>
* fix(client-ts): correct ConnectErrorCallback type signature The callback type expected (message: string) => Promise<void> but the implementation passes Error objects and callers may return void instead of Promise<void>. Updated to accept Error | string and return void | Promise<void>. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(client-ts): use ConnectionException in ConnectErrorCallback type Address maintainer feedback: - Replace Error | string with ConnectionException from exceptions module - Pass ConnectionException object directly to callback instead of extracting message string - Keep void | Promise<void> return type as approved - Fix invocation site in client.ts to construct ConnectionException when needed Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(apps): migrate onConnectError handlers to accept ConnectionException Update three call sites to match the new ConnectErrorCallback type signature that accepts ConnectionException instead of a plain string. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore(client-ts): revert formatting changes --------- Co-authored-by: NIHAL NIHALANI <nihal.nihalani@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: stepmik <stepmikhaylov@yandex.ru>
…odes (#531) All LLM node IGlobal classes assigned the Chat instance to `self._chat` in `beginGlobal`, but `endGlobal` cleared `self.chat` (no underscore) — a different attribute that was never set. This meant `endGlobal` was a no-op: the Chat object was never explicitly released when a pipeline stopped. Fixed in 12 nodes: llm_anthropic, llm_bedrock, llm_deepseek, llm_gemini, llm_ibm_watson, llm_mistral, llm_ollama, llm_openai, llm_perplexity, llm_qwen, llm_vertex, llm_xai. llm_vision_ollama and llm_vision_mistral were already correct.
Adds a new LLM node for GMI Cloud (api.gmi-serving.com), an OpenAI-compatible inference platform hosting 100+ models including DeepSeek, GPT, Claude, Gemini, Llama 4, and Qwen3 on owned H100/H200 GPU infrastructure. ## Profiles Two model tiers are supported: Shared (always-on) — API key only required: DeepSeek V3.2, V3, R1, R1 Distill 32B & 1.5B, Prover V2 GPT-5.2, 5.1, 5, 4o Claude Opus 4.5, Sonnet 4.5 Gemini 3 Pro, Gemini 3 Flash Deploy-on-demand — endpoint URL + API key required (deploy first at console.gmicloud.ai, then paste the provided endpoint URL): Llama 4 Scout, Llama 4 Maverick Qwen3 235B, 32B, 30B, Coder 480B A custom profile allows specifying any model name and endpoint URL manually.
…580) Replace fragile str().startswith() path traversal checks with Path.is_relative_to() in chat and dropper modules. The string prefix comparison could be bypassed with crafted paths like /app/static/chat-evil/. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…proach (#577) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ogger (#578) The redactSensitiveFields function only checked for auth-key, token-key, and apikey patterns. This missed commonly used sensitive fields like password, secret, authorization, bearer, credential, access_token, refresh_token, and private_key, which could be logged unredacted. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Establish baseline community guidelines for inclusive collaboration. Intentionally kept lightweight to be expanded over time. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…etplace rejects SVGs
…nfigs (#359) * fix(security): restrict environment variable expansion in pipeline configs Add an allowlist of permitted env var prefixes (ROCKETRIDE_, PIPELINE_, NODE_, ROCKET_) to _resolve_pipeline(). All other ${VAR} references are replaced with <REDACTED> to prevent exfiltration of sensitive environment variables (AWS keys, DB URLs, tokens) via pipeline configuration. * chore(ai): allow ROCKETRIDE_ prefixed variables * chore(ai): check json injection --------- Co-authored-by: stepmik <stepmikhaylov@yandex.ru>
The URL API silently strips ports that are default-for-scheme (e.g. :443 on https), so url.port is empty for both "no port given" and "scheme-default port given". This caused normalizeUri to always overwrite with the default 5565 port, breaking connections through ngrok/Cloudflare tunnels and custom reverse proxies. Check the raw input string for an explicit port pattern before deciding whether to apply the default port. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update connection.py * cr
…#504) * deprecation pathway * coderabbit suggestions * add tests * cr * fix build * fix build * Update conftest.py * Update conftest.py * Update conftest.py * Update conftest.py * simplify * simplify
* add latest openai model profiles * coderabbit fixes * fix typo (we didn't introduce) * don't change default * Update services.json * Update services.json
* remove gemini 3 pro (deprecated), gemini 2 * code rabbit response * coderabbit * Update services.json * Update services.json
…TOWER HACKATHON] (#386) * Add Exa search node and stable pipeline * Harden Exa search node runtime handling * Fix Exa fallback question parsing * Fix Exa mock credential test wiring * Assert Exa mock request contract * Tighten Exa API exception types * Document Exa node lifecycle hooks * Handle unsafe Exa result URLs per item * Clean up Exa backend from endpoint bag * Unpin Exa node requests dependency * Add comments to Exa service definition * Add Exa search docstrings * Parse Exa boolean config defensively * Guard Exa error payload parsing * revert: remove Exa node test changes * revert: restore base test framework behavior * chore: drop test framework whitespace diff --------- Co-authored-by: Kaushik Sivakumar <kaushik.siva88@gmail.com>
* feat(vscode): improve stop button feedback in Pipeline Observability screen Handle TASK_STATE.STOPPING in the control button to show "Stopping..." with a disabled state and distinct orange styling, preventing duplicate clicks and giving immediate visual feedback during pipeline shutdown. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(vscode): register canvas-played pipelines in sidebar menu The PIPELINES sidebar failed to track pipelines started from the canvas because source-component detection relied solely on config.mode being set to "Source". The canvas editor never writes that field — only the C++ engine adds it at execution time — so freshly saved .pipe files from the canvas had zero recognised source components. Three changes fix the issue: 1. PipelineFileParser.getSourceComponents now accepts an optional service catalog and also checks each component's provider classType array for "source", matching the same logic the canvas uses to decide which nodes get a Run button. 2. SidebarFilesProvider passes the cached service catalog to the parser when loading/re-parsing files, and re-parses all files when the catalog first arrives (servicesUpdated) so that files parsed before connect are retroactively enriched. 3. handleEvent now handles the "restart" apaevt_task action, which the server sends instead of "begin" when a pipeline is restarted. Without this, restarted pipelines silently dropped out of the active set. Closes #396 #Hack-with-bay-2 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tests (#561) The stress test (4 pipelines x 32 cycles) used a 30s hard-coded timeout that was too tight for CI runners, causing both Jest timeout errors and "Connection closed" failures under load. Several other concurrent tests had the same issue. Test teardown could also hang indefinitely if a WebSocket connection failed to close cleanly. Root causes addressed: - Hard-coded 30s timeouts on concurrent tests replaced with TEST_CONFIG.timeout (120s) matching the rest of the suite - Added single-retry with backoff in the stress test to handle transient "Connection closed" errors from server-side frame drops under load - Added bounded timeouts to all afterEach teardown blocks so cleanup never hangs the runner - Added forceExit to jest.config.js so Jest exits even with leaked handles - Added pytest-timeout (120s default) in pyproject.toml to prevent individual Python tests from hanging indefinitely - Removed deprecated event_loop fixture from conftest.py (replaced by pytest-asyncio auto mode) - Added asyncio_mode = "auto" to pyproject.toml for consistent async test handling Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…urrent state (#575) - Rename idle label from "Play" to "Run Pipeline" for clearer intent - Add STOPPING state with "Stopping..." disabled button to prevent double-clicks and provide immediate visual feedback during shutdown - Widen hover expansion to accommodate longer label text - Smooth CSS transitions with easing functions for polished UX Closes #398 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Top-level `permissions: { contents: write, packages: write, id-token: write }`
on nightly.yaml granted every job in the workflow the union of all writes
any one job needed, including jobs that only consume read-only inputs. The
Scorecard `TokenPermissionsID` rule flags this as the most severe form of
over-grant because top-level writes propagate to every reuse-called
workflow as the upper bound.
Drop the top-level to `contents: read` and raise per-job only where the
job actually writes:
- build: contents: read, packages: write
(forwarded to _build.yaml for NuGet/vcpkg writes
to ghcr.io via VCPKG_BINARY_SOURCES=...readwrite)
- cleanup-prereleases: contents: write
(git push origin --delete <tag> and gh release
delete; the tag deletion requires repo write)
- prerelease: contents: write, id-token: write
(forwarded to _release.yaml for tag push +
gh release create + Sigstore keyless signing)
- docker: contents: read, packages: write
(forwarded to _docker.yaml for ghcr image push;
matches release.yaml's docker job pattern)
- init: no override, inherits top-level read
(_init.yaml is read-only — extracts versions
from package.json via jq and stamps github.sha)
The grants mirror the canonical pattern already in place in release.yaml
(committed in the prior TokenPermissionsID cleanup pass that closed #513
and #515 on _build.yaml and _init.yaml).
Closes Scorecard TokenPermissionsID alerts #566 (topLevel contents:write)
and #567 (topLevel packages:write).
The remaining 10 TokenPermissionsID alerts on this repo (#451, #452, #454,
#455, #489, #490, #604, #635, #649, #650) flag job-level writes that are
required for the job's function (ghcr image push, GitHub release publish,
artifact cleanup, model-sync commits). Those are being dismissed
separately with "won't fix" + per-alert justification — Scorecard
penalizes any write, including the unavoidable kind.
…933) Closes the 9 mechanically-fixable Scorecard `PinnedDependenciesID` alerts on this repo. Mutable tag references (`@v4`, `:tag`) become immutable hash references; Dependabot will continue to bump the SHAs as new versions ship. GitHub Actions (7 alerts): sync-models.yml actions/checkout v4 → 34e1148... #599 actions/setup-python v5 → a26af69... #600 actions/cache v4 → 0057852... #601 peter-evans/create-pull-req. v7 → 22a9089... #602 discord-discussions.yml actions/checkout v4 → 34e1148... #644 discord-issues.yml actions/checkout v4 → 34e1148... #645 discord-pr.yml actions/checkout v4 → 34e1148... #646 Docker base images (2 alerts): docker/Dockerfile.engine ubuntu:jammy-20240808 → @sha256:adbb90115a21969d2fe6fa7f9af4253e16d45f8d4c1e930182610c4731962658 #561 docker/Dockerfile.mcp python:3.12-slim → @sha256:9d3abd9fc11d06998ccdbdd93b4dd49b5ad7d67fcbbc11c016eb0eb2c2194891 #471 Both digests are the OCI image index (multi-platform manifest list), so platform resolution still happens at build time. `jammy-20240808` is already a date-pinned snapshot tag; `3.12-slim` is a floating upstream tag and was pinned at the digest current as of 2026-05-20. The remaining 6 `PinnedDependenciesID` alerts (#465, #466, #467, #468, #472, #603) flag pip/npm install commands with already-exact version pins (`twine==6.1.0`, `@vscode/vsce@3.7.1`, `ovsx@0.10.9`, etc.). Scorecard wants `pip install --require-hashes` or lockfile-driven installs for these; the ergonomics of doing that for one-shot workflow installs (and for the `./client-python` local-path install in Dockerfile.mcp, which can't be hash-pinned at all) outweigh the incremental supply-chain hardening over an already-exact version constraint. Those alerts are being dismissed separately with "won't fix" + per-alert justification.
…934) Closes 3 Dependabot alerts on the python backend's transitive cryptography dependency. The two per-node files that pull cryptography directly (db_mysql/requirements.txt, text_output/requirements.txt) are already at cryptography==46.0.7, but the baseline file at nodes/src/nodes/ requirements.txt — which Dependabot scans against — left cryptography unmentioned, so the transitive version resolution was unpinned and fell to whatever requests/urllib3/httpx pulled in. Pinning the baseline closes: GHSA-r6ph-v2qm-q3c2 (high) #64 Vulnerable to a Subgroup Attack Due to Missing Subgroup Validation for SECT Curves. Fix: 46.0.5. GHSA-m959-cc7f-wv43 (low) #65 Incomplete DNS name constraint enforcement on peer names. Fix: 46.0.6. GHSA-p423-j2cm-9vmq (medium) #66 Buffer overflow if non-contiguous buffers were passed to APIs. Fix: 46.0.7. Bounded range (>=46.0.7,<47) matches the repo convention for security-driven dependency floors (handlebars: ">=4.7.9 <5"; protobufjs: ">=7.5.5 <8"; the npm overrides set on root package.json).
Closes Dependabot alert #164 (GHSA-58qx-3vcg-4xpx, medium) — ws is vulnerable to uninitialized memory disclosure on a crafted Sec- WebSocket-Protocol header that overflows the parsing buffer. Affects all 8.x lines below 8.20.1. ws → >=8.20.1 <9 was 8.18.0 + 8.20.1 co-existing in the tree; forces the 8.18.0 caller chain to 8.20.1+ Post-install resolves to ws@8.20.1 only — the 8.18.0 instance is gone. ws has no direct entry in any package.json on this repo; it's pulled transitively (typical sources: socket.io adapters, dev-server stacks, websocket utilities in @rspack/core / vite plugin chains). The override approach matches how we handled the previous transitive overrides cluster (#914, #915, #916, #917). Bounded range (>=fix <next-major) matches the existing repo convention.
The npm-development group bump in PR #921 broke `vsce package` on all three Build matrix runners: ::error::@types/vscode ^1.120.0 greater than engines.vscode ^1.99.3. Consider upgrade engines.vscode or use an older @types/vscode version vsce enforces @types/vscode ≤ engines.vscode at build time so the shipped extension doesn't describe APIs the declared minimum VS Code can't provide. apps/vscode/package.json's engines.vscode floor is ^1.99.3 — that floor is a product/UX choice, not something Dependabot should ratchet up automatically through a routine group bump. Add @types/vscode to the root npm ignores so the npm-development group stops trying to bump it. Future @types/vscode updates land when the team raises engines.vscode in a deliberate PR. Matches the existing precedent for @rsbuild/*, @rslib/*, @rspack/* (added after PR #866 tried to downgrade rsbuild across seven workspaces because Dependabot harmonised to the older per-app pin). Companion to the fix commit on PR #921 (dependabot/npm_and_yarn/ npm-development-a42da78f69) which pins apps/vscode/package.json's @types/vscode to ~1.99.0 so pnpm stops floating it forward across the 1.x line.
…938) CodeQL js/incomplete-multi-character-sanitization (#476) flagged the single-pass regex strip in firstSentence as leaving residual `<script` after one substitution on inputs like `<scri<x>pt>` — the inner `<x>` gets consumed but the outer pair re-forms a `<script>` tag. In practice today the output of this function lands in a JSON catalog file (.rocketride/services-catalog.json) via JSON.stringify, so any residual HTML would be JSON-escaped before write and not rendered. But the consumer surface may grow (the catalog could be sourced into a webview tooltip, an LLM context window, or a markdown preview), and loop-stripping until idempotent is cheap defense-in-depth that closes the SAST signal at the source. Pattern: loop the same regex until `stripped === prev`. Each pass removes a complete `<...>` span; nested or malformed tags need at most O(depth) passes (typically 2-3, always terminates because the output is monotonically shorter on each non-fixed-point iteration). Closes CodeQL alert #476.
#939) CodeQL py/stack-trace-exposure (alerts #5 and #6) flagged the authentication error path returning str(e) directly to the HTTP client via HTMLResponse / PlainTextResponse. The exception text can leak library internals — JWT verifier specifics, cryptography binding errors, file paths in some edge cases — which is information an attacker probing the auth endpoint can use to fingerprint the stack and pivot. Three call sites in _authenticate_credential_inner returned (code, str(e)): - PermissionError from a registered authenticator (401) - Generic Exception from a registered authenticator (400) - Generic Exception from the built-in account fallback (400) Now each site: 1. Logs the actual exception via debug() — operators still see the full text in server logs for triage 2. Returns a generic message to the client — "Authentication failed" for 401, "Bad request" for 400 The downstream _format_error helper that wraps the message into the HTML/text/JSON response is unchanged; only the message contents flowing into it are sanitized at the source. The 'No authorization provided' and 'Invalid authorization provided' branches were already generic and stay as-is. Closes CodeQL alerts #5 and #6.
) * fix(scripts): guard state.js dot-paths against prototype pollution CodeQL js/prototype-pollution-utility (alert #274) flagged setState's walk loop in scripts/lib/state.js: it splits a dot-notation key into parts, walks them creating empty objects as needed, then assigns the value at the leaf. Without a guard, a caller passing setState('__proto__.polluted', 'x') would set Object.prototype.polluted for the entire process — and updateState has the same shape. Callers in this codebase are all in-repo build scripts (not network input), so this is defense-in-depth rather than a live exploit. But state.js is a shared utility used by every build/deploy script, and guarding once at the entry of the two write paths is far cheaper than auditing every call site. Implementation: a single assertSafePath(parts) helper at the top of the module, called at the entry of setState and updateState. Throws synchronously if any path segment is one of __proto__, constructor, prototype. The error message names the offending segment to make debugging obvious if a legitimate caller ever stumbles into it. deleteKeyAndPrune isn't guarded directly because it's only reachable through setState/updateState (both now guarded). getState (read path) is also not guarded — reads of __proto__/constructor return objects the caller already has access to, so no pollution risk. Closes CodeQL alert #274. * fix(scripts): coerce path segments with String() before forbidden-key check CodeRabbit caught an edge case in the assertSafePath guard from the initial commit: FORBIDDEN_KEYS is a Set, and Set.has() uses identity equality. A caller passing a String *wrapper object* (e.g. new String('__proto__')) would fail the .has() check (different identity from the primitive '__proto__') but still coerce to the string '__proto__' when used as a bracket-access key — re-opening the prototype-pollution path. Verified locally: setState('__proto__.x', 1) → throws (primitive blocked) setState([new String('__proto__'), 'x'], 1) → BYPASS on previous commit; throws after this commit Fix: String(rawPart) inside the loop normalizes wrappers, numbers, and other coercible values to the same string form that property access uses. Symbols would TypeError on String(); that's acceptable behavior — Symbol keys never reach Object.prototype anyway, and the TypeError surfaces the misuse synchronously. Addresses CodeRabbit review feedback on PR #940.
…ases (#955) PR #929 (per-job permissions scoping on nightly.yaml) missed id-token: write on the docker job. _docker.yaml's docker job declares: permissions: contents: read packages: write id-token: write ← for cosign keyless Sigstore signing GitHub validates at workflow-start that the caller's permissions cover every permission the reusable job declares. The missing id-token: write produced a workflow-level `startup_failure` on every nightly run after #929 merged at 2026-05-20T21:45 — the workflow couldn't even instantiate jobs (gh run view returns `jobs: []`, log-not-found), and 13 consecutive runs against develop have been failing the same way. Mirror was modelled on release.yaml's docker job which ALSO omits id-token: write — that's a latent bug in release.yaml too, but it hasn't bitten because release.yaml's docker job is gated by `if: server_tag_exists == 'false'` and only fires on fresh release tags, so the misconfiguration only surfaces on a real release cut. Should be fixed in a follow-up pass. Comment in-file explains the constraint so the next person editing this block doesn't drop it again.
Brings 24 develop commits into stage in preparation for tomorrow's VS Code release. Highlights: - security cleanup batch (#933, #934, #936, #937, #938, #939, #940) - nightly workflow id-token fix (#955) - shell injection fix in _build.yaml (#928) - nightly per-job permission scoping (#929) - vscode sidebar polish + env vars + autocomplete + startup fixes (#932) - Helm chart for production deployment (#510) - persistent cross-session memory node with Redis backend (#547) - Cohere Rerank pipeline node (#898) - Rsbuild upgrade + build config modernization (#905) - engine management restructure with ioControl (#922) Preserves 3 stage-unique commits (gdg-fixes #904, version bump, prior develop→stage merge #907). Follows pattern of #907.
…957) Same latent bug as the one that broke nightly.yaml in PR #929 and was hotfixed in #955: release.yaml's docker job omits id-token: write even though the reusable _docker.yaml job declares it (required for cosign keyless Sigstore signing). Hasn't surfaced as a startup_failure because the docker job here is gated by: if: needs.init.outputs.server_tag_exists == 'false' So the docker job is only instantiated when a fresh release tag is being created — meaning GitHub's start-time permission-coverage validation only runs the docker job's check on a real release cut. Every release.yaml dispatch where the tag already exists skips the docker job entirely and the misconfiguration is invisible. If left in place, the next fresh release (server-vX where the tag doesn't yet exist) would fail with startup_failure the same way nightly did. Fixing preemptively rather than waiting for the cut. Comment in-file references the nightly outage so the next person editing release.yaml has the breadcrumb.
* fix(builder): prevent deadlock when conditional skips a dedup branch (#925) ## Summary - `builder test` could deadlock on `tika:submodule-build` when the source tree was already locally compiled (`serverReady=true`, `serverDownloaded=false`). The `whenNot ready` branch in `server:build-core` was pre-built with the parent's shared `seen` set, so the build-time-dedup stub referenced from `tika:submodule-test`'s pipeline waited on a completion promise whose resolver lived inside the never-executed `then`-branch. - `buildWhenTask` now clones the `seen` set when pre-building each `when`/`whenNot` branch, so conditional-branch contents no longer pollute the parent's dedup state. If the same action is referenced both inside a conditional branch and elsewhere, both locations now build their own real subtree; runtime `completedActions` and the process-global `getOrCreateCompletion` still ensure exactly one execution. ## Type fix ## Testing - [ ] Tests added or updated - [ ] Tested locally - [ ] `./builder test` passes Reproduction: run `builder build` once on a clean tree, then re-run `builder test` against the same unchanged tree. Before the fix this would hang at `Waiting for: tika:submodule-build`. After the fix, the test pipeline completes. ## Checklist - [x] Commit messages follow [conventional commits](https://www.conventionalcommits.org/) - [x] No secrets or credentials included - [ ] Wiki updated (if applicable) - [ ] Breaking changes documented (if applicable) ## Linked Issue Fixes # * fix(qdrant): correct score-space mismatch and isDeleted filter (#958) * fix(qdrant): correct score-space mismatch and isDeleted filter Three bugs fixed: 1. Score-space mismatch: threshold_search is a [0,1] value but was passed directly to Qdrant as score_threshold, which Qdrant applies against raw cosine scores in [-1,1]. The (score+1)/2 rescaling only happened afterwards in _convertToDocs, so every non-zero category ("Related", "Strongly Related", etc.) had an effective bar far higher than intended — causing zero results. Fix: inverse-transform the threshold before the API call for Cosine similarity. 2. Hardcoded score floor: _convertToDocs filtered score < 0.20 regardless of user config. Replaced with self.threshold_search. 3. isDeleted filter too strict: MatchValue(False) alone excluded documents where the field is null or absent (e.g. documents indexed before soft-delete existed). Fix: nested should-filter covering isDeleted=False, isDeleted=null, and isDeleted missing. Mock updated to mirror the real filter semantics (exclude only when isDeleted is explicitly True). 11 new tests covering all three fixes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(qdrant): drop unavailable IsNull/IsEmpty filter and engine-side score_threshold - isDeleted: replace should[MatchValue(False), IsNullCondition, IsEmptyCondition] with must_not[MatchValue(True)]. IsNullCondition is not available in the installed qdrant_client and broke CI; must_not covers False/null/absent. - score: stop passing score_threshold to query_points (Qdrant filters it in raw space while threshold_search is rescaled [0,1]); the cut stays in base _addDoc. - name the 0.20 relevance floor as MIN_RELEVANCE_SCORE. - trim tests to honest guards (engine never receives score_threshold). --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Ariel Vernaza <ariel@lazyracoon.tech> * fix(crewai): patch async compatibility issues for CrewAI 1.14.x hierarchical crews (#951) Two runtime crashes when running hierarchical crews on the shared asyncio daemon loop: (1) planning calls execute_sync() from inside the loop → RuntimeError, fixed by offloading _handle_crew_planning to a ThreadPoolExecutor worker; (2) delegation tools lack _arun/_aexecute async variants, fixed by patching BaseAgentTool, DelegateWorkTool, and AskQuestionTool. Also cleans planning prompt token noise via _CrewTool.__repr__ and delegates task description interpolation to CrewAI's native _interpolate_inputs() mechanism. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(template): route RAG chat query through embedding before vector store chat_1 questions were wired directly to store_1, bypassing the embedding step. Queries must be embedded before vector similarity search so they exist in the same space as the stored document vectors. Reuses the existing embedding_transformer_1 node on the ingestion path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Alexandru Sclearuc <asclearuc@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Ariel Vernaza <ariel@lazyracoon.tech>
* fix(ocr): support img2table 2.0 OCRInstance API rewrite ## Summary - img2table 2.0.0 (2026-05-10) moved `OCRInstance` out of `img2table.ocr.base` and replaced the `content` / `to_ocr_dataframe` contract with a single `of()` returning `OCRData`, breaking the OCR node with `No module named 'img2table.ocr.base'`. - Make `ModelServerOCR` in `nodes/src/nodes/ocr/IGlobal.py` version-aware: try `img2table.ocr._types.OCRInstance` first (v2), fall back to `img2table.ocr.base.OCRInstance` (v1). - Implement `of()` so it builds an `OCRData(records=…)` on v2 and defers to the base class on v1 (which still drives the existing `content` + `to_ocr_dataframe`); add `_format_to_v2_records` helper producing the v2 word-record dict shape. - Add `nodes/test/ocr/test_model_server_ocr.py` covering both branches: 4 pure-helper tests, 3 v2-only `of()` tests, 1 v1-only `of()` test, 1 `content()` test on both. Loads `IGlobal.py` via `spec_from_file_location` inside a `_scoped_stubs()` context manager so `sys.modules` is snapshotted/restored — no leakage into peer tests in the same `pytest-xdist` session. ## Type fix ## Testing - [x] Tests added (`nodes/test/ocr/test_model_server_ocr.py` — 8 active, 1 version-skipped) - [x] Tested locally — `./builder.cmd nodes:test --pytest-pattern=ocr --verbose` → 10 passed, 1 skipped - [ ] `./builder test` passes ## Checklist - [x] Commit messages follow [conventional commits](https://www.conventionalcommits.org/) - [x] No secrets or credentials included - [ ] Wiki updated (if applicable) - [ ] Breaking changes documented (if applicable) ## Linked Issue Fixes #913
|
Important Review skippedIgnore keyword(s) in the title. ⛔ Ignored keywords (5)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
No description provided. |
…signore (#972) Unblocks the gitleaks check on PR #971 (release: stage to main). The finding flagged a placeholder credential in nodes/src/nodes/tool_exa_search/services.json at line 138 of commit fd6b61d — the test fixture of the Exa search node (#509, 2026-04-21). The file's inline comment two lines above the value already documents the intent: the field is a placeholder for config-validation testing, not a live key. The test block has since been refactored on stage to use a cases array, so the value no longer appears in the current file. But gitleaks scans the full main..stage commit range on PR #971 (227 commits — main hasn't moved since 2026-03-29), so the historical commit's content is what's flagged. A later refactor doesn't clear a historical match — only an allowlist entry does. Fingerprint format <commit>:<path>:<rule>:<line> — gitleaks matches this exact occurrence only, so this doesn't silence future findings. Two known gitleaks config inconsistencies worth a follow-up (NOT blocking this release): - The pipe-file-api-key rule has paths = '\.pipe(\.json)?$' which shouldn't match services.json, yet gitleaks attributed the finding to that rule. - The services-json-api-key rule has a 16-char minimum which an 8-char placeholder wouldn't trigger. Neither rule should have fired given the documented config; one of them did. Investigate after the release lands.
- Register rocketride.sidebar.documentation.open command via vscode.env.openExternal → https://docs.rocketride.org/ - Update SF hackathon announcement title, date (June 5), and Luma link - Remove stale RocketRide 2.4, NYC Meetup, and RAG template announcements - Rename Community spotlight → Connect with us with updated Discord URL Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
anandray
left a comment
There was a problem hiding this comment.
LGTM — composition verified, security cleanup work all lands cleanly.
Verification summary
12 security PRs from this week's cleanup batch are all in stage and composed correctly:
| PR | Verified in stage |
|---|---|
| #928 _build.yaml shell-injection guard | commit 5181f0ed |
| #929 nightly.yaml per-job permissions | commit 3cf1937f |
| #933 GHA + Docker SHA pins | commit a0f305ce |
| #934 cryptography baseline pin | cryptography>=46.0.7,<47 present in nodes/src/nodes/requirements.txt |
| #936 ws override | "ws": ">=8.20.1 <9" in root package.json |
| #937 @types/vscode dependabot ignore | present in .github/dependabot.yml |
| #938 services.ts loop-strip sanitize | commit 95db6137 |
| #939 server.py generic auth errors | commit 6edbb671 |
| #940 state.js proto-pollution guard | commit 0c61de13 |
#955 nightly docker id-token: write |
verified in stage's nightly.yaml |
#957 release docker id-token: write |
verified in stage's release.yaml |
Critical: #957's release.yaml docker fix is in stage. Without it, the release.yaml dispatch this merge triggers would have hit startup_failure on the docker job (same bug that broke nightly last week). The explicit "Merge develop (pick up #957 release-docker id-token fix)" commit (14c26b66) shows the deliberate hotfix pull-forward worked.
Workflow self-check on release.yaml path
Since this PR's merge fires release.yaml, I verified the workflow itself is healthy in stage:
release.yamldocker job grantscontents: read, packages: write, id-token: write✓_release.yamlrelease job declared permissions match the caller's grant ✓_docker.yamldocker job declared permissions match the caller's grant ✓
No startup_failure mode is reachable on the release publish.
Gitleaks finding — false positive, resolved via #972
The gitleaks failure on initial CI was a historical false-positive: a literal placeholder credential in the test-fixture block of nodes/src/nodes/tool_exa_search/services.json from PR #509 (Charlie's Exa search node, April 21). The file's own inline comment two lines above the value documents it as a placeholder for config-validation testing, not a live key. The string was refactored away in a later stage commit (now uses a cases array), so it only appears in the historical commit when gitleaks scans the full main..stage range.
PR #972 (merged at 19:42 UTC) added the fingerprint to .gitleaksignore to unblock this scan. CI on this PR has re-run and gitleaks now passes.
Two latent gitleaks config inconsistencies surfaced in the investigation — the pipe-file-api-key rule's paths filter doesn't appear to be applied, and the services-json-api-key rule's 16-char minimum should have suppressed the 8-char placeholder. Worth a follow-up ticket after this release lands; not blocking.
Also picked up at cut time
#975 (Ryan's sidebar docs-link wiring + announcements update, +5/-5 across 2 files) — landed on stage after the initial PR cut. Scope is VS Code UX only, no impact on the security composition above. CI re-ran on the new HEAD 98e5b498 and the Build matrix is green across all 3 platforms.
Known deferrals
- #961 (diff jsdiff DoS override) — merged to develop after the stage cutoff. LOW severity, transitive in
mocha(dev-only). Safe to defer to next stage sync, no impact on customer-facing artifacts. - #910 / #948 / #949 (openai/cohere/redis major bumps) — held off develop intentionally for a 24h prerelease soak before next release. Already approved, will land staggered over the next 3 days post-release.
Net
7/7 explicit team thumbs in the EU/US Dev sync + composition verified + release.yaml path proven healthy + gitleaks now clean + Build matrix green on 98e5b498. Approve.
Summary
VS Code release per Rod's noon-PT ask in EU/US Dev sync today. Merges current
stageHEAD intomain, which firesrelease.yamlautomatically (init → build → release → docker).Stage HEAD
3e98006d fix(ocr): support img2table 2.0 OCRInstance API rewrite (#969) (#970)Highlights of what ships
Sign-off
Team responses gathered in EU/US Dev sync today:
Cutting per Rod's noon-PT call with 6/7 explicit thumbs.