Skip to content

fix: fail closed on event sanitizer errors#482

Merged
rapids-bot[bot] merged 6 commits into
NVIDIA:release/0.6from
willkill07:fix/relay-517-event-sanitizer-fail-closed
Jul 20, 2026
Merged

fix: fail closed on event sanitizer errors#482
rapids-bot[bot] merged 6 commits into
NVIDIA:release/0.6from
willkill07:fix/relay-517-event-sanitizer-fail-closed

Conversation

@willkill07

@willkill07 willkill07 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Overview

Fail closed when event sanitizer callbacks cannot produce valid sanitized fields, preventing unsanitized observability data from reaching exporters.

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.
  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Details

  • Return empty event fields when Python or Node sanitizer callbacks raise, return invalid values, or otherwise fail conversion.
  • Apply the same fail-closed fallback to raw C FFI callbacks, native dynamic plugins, and worker dynamic plugins, covering Go and other FFI consumers.
  • Add regressions for Python, Node, FFI malformed and null callback results, Go sanitizer callback marshalling failures, and native/worker plugin callback failures.

Where should the reviewer start?

Start with crates/core/src/plugin/dynamic/native.rs and crates/core/src/plugin/dynamic/worker.rs, where callback failures now clear observable event fields; the FFI API test records the externally visible contract.

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

  • Closes RELAY-517

Summary by CodeRabbit

  • Bug Fixes

    • Event sanitizers now fail closed across JS, Python, FFI, and native flows: when sanitizer callbacks throw/return invalid values, or when serialization/deserialization/marshaling fails, sanitization returns default fields and clears observability data (data/metadata and related fields) instead of preserving original values.
    • Callback errors are still recorded.
  • Tests

    • Updated existing expectations from “fails open” to “fails closed” for invalid results and sanitizer exceptions.
    • Added coverage for marshal/deserialization and callback error scenarios, including Go/native integration cases asserting cleared observability fields.

Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07
willkill07 requested a review from a team as a code owner July 20, 2026 12:24
@github-actions github-actions Bot added size:S PR is small Bug issue describes bug; PR fixes bug lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code labels Jul 20, 2026
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: c01fdf83-ac88-45b0-8f3c-3822a0f940e3

📥 Commits

Reviewing files that changed from the base of the PR and between 0b5bd21 and aa419ad.

📒 Files selected for processing (2)
  • crates/node/src/api/mod.rs
  • crates/node/tests/event_sanitizers_tests.mjs
📜 Recent review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (13)
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/node/src/api/mod.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/node/src/api/mod.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/tests/event_sanitizers_tests.mjs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/node/src/api/mod.rs
**/*.{rs,go,js,ts}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding // comment form.

Files:

  • crates/node/src/api/mod.rs
{crates/python/src/py_api/mod.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go,crates/node/src/api/**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update the language-native bindings for every exposed surface in Python, Go, and Node.js.

Files:

  • crates/node/src/api/mod.rs
{crates/**/src/**/*.rs,python/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not add tests under src; Rust tests belong in crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/node/src/api/mod.rs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/tests/event_sanitizers_tests.mjs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

Files:

  • crates/node/src/api/mod.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/node/src/api/mod.rs
crates/{python,ffi,node}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/tests/event_sanitizers_tests.mjs
crates/node/**/*.{js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use camelCase for Node.js public APIs.

Files:

  • crates/node/tests/event_sanitizers_tests.mjs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/node/tests/event_sanitizers_tests.mjs
🔇 Additional comments (3)
crates/node/src/api/mod.rs (2)

1353-1353: LGTM!

Also applies to: 1384-1384


2385-2387: LGTM!

Also applies to: 2867-2869

crates/node/tests/event_sanitizers_tests.mjs (1)

25-30: LGTM!

Also applies to: 106-123, 161-181, 192-211, 279-296


Walkthrough

Event sanitizer failure paths across Node.js, Python, FFI, and native plugin integrations now return default cleared fields instead of original input fields. Tests verify that invalid, failed, or unmarshalable sanitizer results clear observability data.

Changes

Event sanitizer failure handling

Layer / File(s) Summary
Language binding fail-closed handling
crates/node/src/{api/mod.rs,callable.rs}, crates/node/tests/event_sanitizers_tests.mjs, crates/python/src/py_callable.rs, crates/python/tests/coverage/..., python/tests/test_event_sanitizers.py, crates/ffi/src/callable.rs, crates/ffi/tests/unit/{callable_tests.rs,api/registry_tests.rs}
Node.js, Python, and FFI sanitizer wrappers now return default fields for conversion, callback, serialization, and invalid-result failures. Binding tests expect cleared observability fields.
Core callback fallback handling
crates/core/src/plugin/dynamic/{native.rs,worker.rs}
Native plugin and worker sanitizer callbacks now use default fields when sanitization fails instead of preserving incoming fields.
Cross-runtime failure coverage
crates/core/tests/fixtures/native_plugin/src/lib.rs, crates/core/tests/integration/native_plugin_tests.rs, crates/core/tests/unit/dynamic_worker_tests.rs, go/nemo_relay/event_sanitizers_test.go
Native fixture callbacks and integration tests, worker tests, and Go tests verify that sanitizer failures clear event data, metadata, and category profile fields.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • NVIDIA/NeMo-Relay#478: Modifies the related Node.js event-sanitizer middleware error-handling path with a different fallback behavior.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows Conventional Commits and accurately summarizes the fail-closed sanitizer change.
Description check ✅ Passed The description includes all required sections, checklist items, reviewer guidance, and a related issue reference.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@willkill07 willkill07 self-assigned this Jul 20, 2026
@willkill07 willkill07 added this to the 0.6 milestone Jul 20, 2026
Signed-off-by: Will Killian <wkillian@nvidia.com>
@github-actions github-actions Bot added the lang:go PR changes/introduces Go code label Jul 20, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/ffi/src/callable.rs`:
- Line 837: Update the sanitizer callback handling in the native plugin path so
deserialization or callback errors discard the original fields and return the
default redacted set. Replace the fallback that preserves fields with the
established fail-closed default behavior, while leaving successful sanitizer
results unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 15c30d2c-104a-4243-8c8f-e09c092eee2d

📥 Commits

Reviewing files that changed from the base of the PR and between c276a9f and 91f30e7.

📒 Files selected for processing (3)
  • crates/ffi/src/callable.rs
  • crates/ffi/tests/unit/callable_tests.rs
  • go/nemo_relay/event_sanitizers_test.go
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (20)
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • crates/ffi/src/callable.rs
crates/ffi/**

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Rebuild the FFI crate in release mode so the shared library and header stay in sync when making changes to crates/ffi

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • crates/ffi/src/callable.rs
crates/ffi/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/ffi, also use test-ffi-surface for validation

Use C FFI export names prefixed with nemo_relay_ in the raw C FFI layer.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • crates/ffi/src/callable.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • crates/ffi/src/callable.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • crates/ffi/src/callable.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • go/nemo_relay/event_sanitizers_test.go
  • crates/ffi/src/callable.rs
**/*.{rs,go,js,ts}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding // comment form.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • go/nemo_relay/event_sanitizers_test.go
  • crates/ffi/src/callable.rs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • go/nemo_relay/event_sanitizers_test.go
  • crates/ffi/src/callable.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • go/nemo_relay/event_sanitizers_test.go
  • crates/ffi/src/callable.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • go/nemo_relay/event_sanitizers_test.go
  • crates/ffi/src/callable.rs
crates/{python,ffi,node}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • crates/ffi/src/callable.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/ffi/tests/unit/callable_tests.rs
  • go/nemo_relay/event_sanitizers_test.go
go/nemo_relay/**/*.go

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

go/nemo_relay/**/*.go: Format changed Go packages with cd go/nemo_relay && go fmt ./...
Run Go tests with just test-go to build and test the NeMo Relay Go binding
Use just build-go when you want an explicit build-only pass or need the artifact for other work
Use just ci=true test-go when you need the CI-style coverage and JUnit path
On macOS, set DYLD_LIBRARY_PATH to the ../../target/release directory before running the raw go test command directly

Use PascalCase for public Go APIs.

Files:

  • go/nemo_relay/event_sanitizers_test.go
**/*.go

📄 CodeRabbit inference engine (CONTRIBUTING.md)

When changing the experimental Go binding, format Go code with gofmt and keep go vet ./... passing.

Files:

  • go/nemo_relay/event_sanitizers_test.go
{crates/python/src/py_api/mod.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go,crates/node/src/api/**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update the language-native bindings for every exposed surface in Python, Go, and Node.js.

Files:

  • go/nemo_relay/event_sanitizers_test.go
{python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update language wrapper helpers such as Python wrapper modules, Python type stubs, and Go shorthand packages when the new behavior belongs in those helper layers.

Files:

  • go/nemo_relay/event_sanitizers_test.go
**/*.{py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/maintain-observability/SKILL.md)

Keep Python, Go, and Node.js config objects and subscriber/exporter methods aligned so all bindings expose the same logical knobs and semantics.

Files:

  • go/nemo_relay/event_sanitizers_test.go
go/nemo_relay/**

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep shared plugin helpers in go/nemo_relay aligned with plugin registration, composition, and lifecycle behavior.

Files:

  • go/nemo_relay/event_sanitizers_test.go
go/nemo_relay/**/*

⚙️ CodeRabbit configuration file

go/nemo_relay/**/*: Review Go binding changes for cgo memory ownership, race safety, callback cleanup, idiomatic exported APIs, and parity with Rust/FFI behavior.
Any API change should include focused Go tests and consider race-test behavior.

Files:

  • go/nemo_relay/event_sanitizers_test.go
{crates/**/src/**/*.rs,python/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not add tests under src; Rust tests belong in crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/ffi/src/callable.rs
🔇 Additional comments (2)
crates/ffi/tests/unit/callable_tests.rs (1)

556-564: LGTM!

go/nemo_relay/event_sanitizers_test.go (1)

41-53: 🔒 Security & Privacy

Drop the category-profile setup suggestion. EmitEvent in go/nemo_relay only accepts parent, data, metadata, and timestamp options, so this test cannot seed a category profile through the Go API.

			> Likely an incorrect or invalid review comment.

Comment thread crates/ffi/src/callable.rs
@github-actions

Copy link
Copy Markdown

Signed-off-by: Will Killian <wkillian@nvidia.com>
@github-actions github-actions Bot added size:M PR is medium and removed size:S PR is small labels Jul 20, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/core/tests/integration/native_plugin_tests.rs`:
- Around line 772-776: Update the subscriber setup in the native event sanitizer
test to call NativePluginTestCleanup::mark_subscriber_registered after
register_subscriber succeeds, ensuring Drop can deregister it during unwinding.
Preserve the existing explicit cleanup behavior and subscriber registration
flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 1d01a665-bdf2-4eb3-aeaa-9e86349db29e

📥 Commits

Reviewing files that changed from the base of the PR and between 91f30e7 and abda3a6.

📒 Files selected for processing (6)
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/ffi/tests/unit/api/registry_tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (22)
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
crates/ffi/**

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Rebuild the FFI crate in release mode so the shared library and header stay in sync when making changes to crates/ffi

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
crates/ffi/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/ffi, also use test-ffi-surface for validation

Use C FFI export names prefixed with nemo_relay_ in the raw C FFI layer.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
**/*.{rs,go,js,ts}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding // comment form.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
crates/{python,ffi,node}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/ffi/tests/unit/api/registry_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
{crates/core/src/plugin/dynamic/**,crates/plugin/**,crates/worker/**,crates/worker-proto/**,crates/types/**,python/plugin/**,examples/rust-native-plugin/**,examples/python-grpc-worker-plugin/**,docs/build-plugins/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Keep the stable boundary explicit: native plugins cross a C ABI, and worker plugins cross grpc-v1.

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
{crates/core/src/plugin/dynamic/**/*.rs,examples/rust-native-plugin/**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not pass Rust runtime types, trait objects, futures, or allocator-owned strings across the native dynamic-library boundary.

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
{crates/**/src/**/*.rs,python/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not add tests under src; Rust tests belong in crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
{crates/core/src/plugin/dynamic/**,examples/rust-native-plugin/**,examples/python-grpc-worker-plugin/**,docs/build-plugins/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Native and worker plugins are trusted extensions; document that native plugins are in-process and unsandboxed, and worker plugins provide process isolation but not a security sandbox.

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
{crates/core/src/plugin/dynamic/**/*.rs,crates/plugin/**/*.rs,crates/worker/**/*.rs,crates/worker-proto/**/*.rs,python/plugin/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Manifest validation must cover kind, compatibility, load contract, integrity, capability mismatch, and disabled-plugin behavior.

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
crates/core/src/plugin/dynamic/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

The native loader must keep libraries alive until registered callbacks are cleared and must deregister plugin kinds before unload.

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
🔇 Additional comments (2)
crates/core/src/plugin/dynamic/native.rs (1)

1500-1500: 📐 Maintainability & Code Quality

Verify the required Rust, core, and FFI validation matrix before handoff.

  • crates/core/src/plugin/dynamic/native.rs#L1500-L1500: run the Rust checks plus core-runtime validation.
  • crates/core/src/plugin/dynamic/worker.rs#L1063-L1068: run the Rust checks plus core-runtime validation.
  • crates/core/tests/fixtures/native_plugin/src/lib.rs#L422-L437: run the Rust checks plus core-runtime validation.
  • crates/core/tests/integration/native_plugin_tests.rs#L749-L797: run the Rust checks plus core-runtime validation.
  • crates/core/tests/unit/dynamic_worker_tests.rs#L1044-L1045: run the Rust checks plus core-runtime validation.
  • crates/ffi/tests/unit/api/registry_tests.rs#L338-L339: run FFI surface validation and rebuild the FFI crate in release mode.

Please attach results for cargo fmt --all, cargo clippy --workspace --all-targets -- -D warnings, just test-rust, cargo deny check, validate-change, the full Rust/Python/Go/Node matrix, test-ffi-surface, and uv run pre-commit run --all-files. Also confirm dependent skills/docs were updated if they document sanitizer fallback semantics.

As per coding guidelines, Rust changes require formatting, Clippy, and Rust tests; crates/core requires broader validation; crates/ffi requires FFI surface validation and release rebuilding; and handoff requires full pre-commit validation.

Source: Coding guidelines

crates/core/tests/unit/dynamic_worker_tests.rs (1)

1044-1044: LGTM!

Also applies to: 1119-1121, 1142-1145

Comment thread crates/core/tests/integration/native_plugin_tests.rs

@mnajafian-nv mnajafian-nv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

…vent-sanitizer-fail-closed

Signed-off-by: Will Killian <wkillian@nvidia.com>

# Conflicts:
#	crates/node/src/api/mod.rs
#	crates/node/src/callable.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
crates/node/tests/event_sanitizers_tests.mjs (1)

89-111: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Assert that all event fields are cleared.

These fail-closed tests only inspect data. Include non-null metadata (and a category-profile fixture where applicable), then assert every emitted sanitizer field is cleared in the direct, thread-safe, and plugin-owned failure cases. Otherwise, a regression leaking unsanitized metadata can pass.

As per path instructions, tests should cover the behavior promised by the changed API surface, including error paths.

Also applies to: 137-167, 167-187, 245-268

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/node/tests/event_sanitizers_tests.mjs` around lines 89 - 111, Expand
the fail-closed sanitizer tests around the invalid-results cases and the
corresponding thread-safe and plugin-owned failure cases to provide non-null
metadata, including a category-profile fixture where applicable. Assert that
every emitted sanitizer field is cleared, not just events.at(-1).data, while
preserving the existing callback-error assertions and coverage of each failure
path.

Source: Path instructions

crates/node/src/api/mod.rs (1)

2383-2386: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Align both event-sanitizer documentation blocks with fail-closed behavior.

  • crates/node/src/api/mod.rs#L2383-L2386: update the global event-sanitizer docs to say callback, serialization, conversion, and invalid-result failures clear event fields and record the error.
  • crates/node/src/api/mod.rs#L2864-L2867: apply the same fail-closed wording to scope-local event sanitizers.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/node/src/api/mod.rs` around lines 2383 - 2386, Update the
documentation blocks for global and scope-local event sanitizers in
crates/node/src/api/mod.rs at lines 2383-2386 and 2864-2867 to consistently
describe fail-closed behavior: callback, serialization, conversion, and
invalid-result failures clear event fields and record the error for
getLastCallbackError(). Apply the same wording to both sites; no implementation
changes are needed.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/node/src/api/mod.rs`:
- Around line 2383-2386: Update the documentation blocks for global and
scope-local event sanitizers in crates/node/src/api/mod.rs at lines 2383-2386
and 2864-2867 to consistently describe fail-closed behavior: callback,
serialization, conversion, and invalid-result failures clear event fields and
record the error for getLastCallbackError(). Apply the same wording to both
sites; no implementation changes are needed.

In `@crates/node/tests/event_sanitizers_tests.mjs`:
- Around line 89-111: Expand the fail-closed sanitizer tests around the
invalid-results cases and the corresponding thread-safe and plugin-owned failure
cases to provide non-null metadata, including a category-profile fixture where
applicable. Assert that every emitted sanitizer field is cleared, not just
events.at(-1).data, while preserving the existing callback-error assertions and
coverage of each failure path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 49c36f37-3400-4a1a-bf18-7022fa8263e0

📥 Commits

Reviewing files that changed from the base of the PR and between abda3a6 and 0b5bd21.

📒 Files selected for processing (6)
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/node/tests/event_sanitizers_tests.mjs
  • crates/node/tests/scope_tests.mjs
  • crates/node/tests/tools_tests.mjs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (17)
crates/node/**/*.{js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use camelCase for Node.js public APIs.

Files:

  • crates/node/tests/scope_tests.mjs
  • crates/node/tests/tools_tests.mjs
  • crates/node/tests/event_sanitizers_tests.mjs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.

Files:

  • crates/node/tests/scope_tests.mjs
  • crates/node/tests/tools_tests.mjs
  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/node/tests/event_sanitizers_tests.mjs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/node/tests/scope_tests.mjs
  • crates/node/tests/tools_tests.mjs
  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/node/tests/event_sanitizers_tests.mjs
crates/{python,ffi,node}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/node/tests/scope_tests.mjs
  • crates/node/tests/tools_tests.mjs
  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/node/tests/event_sanitizers_tests.mjs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/node/tests/scope_tests.mjs
  • crates/node/tests/tools_tests.mjs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/node/tests/event_sanitizers_tests.mjs
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/core/tests/integration/native_plugin_tests.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/core/tests/integration/native_plugin_tests.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/core/tests/integration/native_plugin_tests.rs
**/*.{rs,go,js,ts}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding // comment form.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/core/tests/integration/native_plugin_tests.rs
{crates/python/src/py_api/mod.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go,crates/node/src/api/**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update the language-native bindings for every exposed surface in Python, Go, and Node.js.

Files:

  • crates/node/src/api/mod.rs
{crates/**/src/**/*.rs,python/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not add tests under src; Rust tests belong in crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/core/tests/integration/native_plugin_tests.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/core/tests/integration/native_plugin_tests.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/integration/native_plugin_tests.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Files:

  • crates/core/tests/integration/native_plugin_tests.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

Files:

  • crates/core/tests/integration/native_plugin_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/integration/native_plugin_tests.rs
🔇 Additional comments (9)
crates/core/tests/integration/native_plugin_tests.rs (1)

777-777: 📐 Maintainability & Code Quality

Run the required Rust validation before handoff.

The cleanup fix is correctly placed. Because this is a Rust change, verify cargo fmt --all, cargo clippy --workspace --all-targets -- -D warnings, just test-rust, and uv run pre-commit run --all-files were run successfully.

Source: Coding guidelines

crates/node/src/api/mod.rs (4)

1333-1390: 📐 Maintainability & Code Quality

Run the required Rust and Node validation before handoff.

Run just test-rust, cargo fmt --all, cargo clippy --workspace --all-targets -- -D warnings, the Node test target covering the changed sanitizer tests, and uv run pre-commit run --all-files.

As per coding guidelines, any Rust change must run the required Rust test, formatting, lint, and pre-commit commands before review or handoff.

Source: Coding guidelines


81-81: LGTM!

Also applies to: 567-600, 721-725, 765-769, 805-811, 853-859, 899-905, 986-992, 1115-1121, 1273-1305, 1333-1390, 1526-1527


2434-2440: LGTM!

Also applies to: 2456-2457, 2473-2474, 2491-2504, 2525-2533, 2548-2548, 2612-2628, 2643-2659, 2673-2687, 2707-2726


2925-2935: LGTM!

Also applies to: 2953-2954, 2971-2972, 2987-3005, 3032-3043, 3061-3061, 3138-3157, 3178-3197, 3217-3235, 3260-3284

crates/node/src/callable.rs (2)

17-17: LGTM!

Also applies to: 41-41, 88-95, 122-185, 213-238, 243-266, 270-292, 329-364, 392-426, 431-455, 459-481, 592-662


97-120: 🩺 Stability & Availability

Sync middleware callbacks are sync-only

This wrapper is used only for guardrails/intercepts that are documented to accept synchronous callbacks. Promise-returning callbacks are handled by the separate PromiseAwareFn/*_async APIs, so this is not a bug on this path.

			> Likely an incorrect or invalid review comment.
crates/node/tests/scope_tests.mjs (1)

336-339: LGTM!

Also applies to: 341-343

crates/node/tests/tools_tests.mjs (1)

30-31: LGTM!

Also applies to: 299-314, 526-564, 566-590, 678-700, 756-756

@willkill07
willkill07 requested a review from mnajafian-nv July 20, 2026 17:34
Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07

Copy link
Copy Markdown
Member Author

/merge

@rapids-bot
rapids-bot Bot merged commit fd2ff6c into NVIDIA:release/0.6 Jul 20, 2026
69 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug issue describes bug; PR fixes bug lang:go PR changes/introduces Go code lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code size:M PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants