Skip to content

fix(inference): reject unsafe provider replacement - #7763

Merged
apurvvkumaria merged 3 commits into
mainfrom
codex/7746-direct-provider-verification
Jul 28, 2026
Merged

fix(inference): reject unsafe provider replacement#7763
apurvvkumaria merged 3 commits into
mainfrom
codex/7746-direct-provider-verification

Conversation

@prekshivyas

@prekshivyas prekshivyas commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

This follow-up prevents the behavior reported by PR Review Advisor on #7746: OpenShell verified an existing direct provider's old endpoint before NemoClaw replaced it with the requested endpoint. NemoClaw now reuses only the exact direct binding recorded for the sandbox and refuses endpoint replacement that cannot be rolled back.

Related Issue

Follow-up to #7746 (PRA-1); related to #7725.

Changes

  • Compare an existing direct compatible-provider binding with the sandbox registry before route selection.
  • Reuse the provider without mutation when its recorded endpoint and credential environment match the request.
  • Refuse replacement when the requested direct binding differs because OpenShell redacts the previous endpoint required for rollback.
  • Verify newly created direct providers during route selection and remove them when verification fails.
  • Add regressions for verified creation, failed-selection cleanup, existing-binding refusal, and exact recorded-binding reuse.
  • Document the direct-provider restriction while preserving the DNS-backed HTTPS Pin Runtime update and rollback guidance.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification:
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: Codex Desktop exact-head review at 97686155b passed all nine categories with no findings. The change fails before an unverifiable direct-provider mutation; endpoint validation, invocation-local credential handling, mutation locking, and HTTPS Pin Runtime rollback remain intact.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: docs-updated
  • Evidence: docs/inference/switch-providers.mdx; verified direct-provider refusal and exact-binding reuse, absent-provider verification and cleanup, and the unchanged DNS-backed HTTPS Pin Runtime update and rollback guidance. The focused inference tests passed 77/77, including endpoint and credential-binding mismatch regressions; the test-conditional scan passed. npm run docs passed with 0 errors and 2 pre-existing warnings.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit: Not applicable
  • Station profile/scenario: Not applicable
  • Result: Not applicable
  • Supporting evidence: Not applicable

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — npx vitest run --project cli src/lib/actions/inference-set-compatible-provider.test.ts src/lib/actions/inference-set-degraded-state.test.ts src/lib/actions/inference-set-provider-alias.test.ts src/lib/actions/inference-set-provider.test.ts src/lib/actions/inference-set-gateway-route-containment.test.ts: 77 passed; npm run test-conditionals:scan -- --top 25: passed
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — not applicable to this isolated inference correction
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only) — passed with 0 errors and 2 pre-existing warnings
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Prekshi Vyas prekshiv@nvidia.com

Summary by CodeRabbit

  • New Features
    • Improved compatible-provider switching to support model-only changes when the recorded endpoint remains valid.
    • Added safeguards to block endpoint changes for existing direct compatible bindings, requiring re-onboarding when the endpoint changes.
  • Bug Fixes
    • Prevented unnecessary provider update actions when the existing binding details already match.
    • Improved recovery and rollback behavior for compatible-provider failures, including stricter verification behavior and safer cleanup.
  • Documentation
    • Updated compatible-provider switching guidance with clarified endpoint/model reuse and DNS failure/restore behavior.
  • Tests
    • Expanded and adjusted coverage for compatible-provider edge cases using updated provider-capture simulation.

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@prekshivyas prekshivyas added area: docs Documentation, examples, guides, or docs build v0.0.97 labels Jul 28, 2026
@prekshivyas prekshivyas self-assigned this Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Compatible-provider switching now validates recorded direct bindings before mutation, reuses matching providers without updates, cleans up newly created providers after verification failure, and documents endpoint and restoration behavior. Tests add stateful provider lifecycle coverage and updated compatible-provider fixtures.

Changes

Compatible provider binding safeguards

Layer / File(s) Summary
Binding guard and endpoint reuse
src/lib/actions/inference-set.ts, docs/inference/switch-providers.mdx
Direct bindings are compared with recorded provider, endpoint, and credential details. Matching bindings avoid mutation; mismatches are rejected and require onboarding. Documentation describes model-only switching, endpoint reuse, and restoration behavior.
Provider lifecycle test coverage
src/lib/actions/inference-set.test-support.ts, src/lib/actions/inference-set-compatible-provider.test.ts, src/lib/actions/inference-set-degraded-state.test.ts, src/lib/actions/inference-set-provider-alias.test.ts
Test captures model provider presence, versions, creation, updates, and deletion. Tests cover verification defaults, cleanup after route-selection failure, endpoint replacement rejection, provider reuse, and provenance scenarios.

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

Possibly related PRs

  • NVIDIA/NemoClaw#7746: Both changes update direct compatible-provider binding behavior and its test fixtures.

Suggested labels: area: inference

Suggested reviewers: cv, ericksoa

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: rejecting unsafe provider replacement in inference.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/7746-direct-provider-verification

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

@github-actions

Copy link
Copy Markdown
Contributor

@github-code-quality

github-code-quality Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 9768615 in the codex/7746-direct-pr... branch remains at 96%, unchanged from commit c4c020c in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit 9768615 in the codex/7746-direct-pr... branch remains at 81%, unchanged from commit c4c020c in the main branch.

Show a code coverage summary of the most impacted files.
File main c4c020c codex/7746-direct-pr... 9768615 +/-
src/lib/onboard...ndbox-create.ts 83% 33% -50%
src/lib/onboard...-create-plan.ts 88% 75% -13%
src/lib/onboard...ndbox-create.ts 91% 83% -8%
src/lib/actions...test-support.ts 100% 93% -7%
src/lib/actions...nference-set.ts 94% 94% 0%
src/lib/messagi...nnels/policy.ts 100% 100% 0%
src/lib/sandbox...rce-identity.ts 88% 88% 0%
src/lib/state/config-io.ts 93% 93% 0%
src/lib/platform.ts 84% 89% +5%
src/lib/domain/.../connect-env.ts 89% 97% +8%

Updated July 28, 2026 21:36 UTC

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@cjagwani
cjagwani requested a review from apurvvkumaria July 28, 2026 21:11
@apurvvkumaria
apurvvkumaria enabled auto-merge (squash) July 28, 2026 21:11

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/lib/actions/inference-set.ts (1)

644-654: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider moving this pure comparison to the domain layer.

matchesRecordedDirectProviderBinding is a pure decision function (no I/O, no side effects) defined inline in inference-set.ts (an actions module). As per path instructions, src/lib/{actions,domain,adapters,state}/** ownership should keep "pure decisions" in src/lib/domain/** while actions orchestrate. Extracting this comparison into a domain module would keep the layering consistent and make it independently unit-testable.

🤖 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 `@src/lib/actions/inference-set.ts` around lines 644 - 654, Move the pure
comparison implemented by matchesRecordedDirectProviderBinding from the actions
module into an appropriate src/lib/domain module, export it there, and update
the action code to import and use the domain function while preserving the
existing matching behavior.

Source: Path instructions

src/lib/actions/inference-set-compatible-provider.test.ts (1)

301-337: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate mock shape vs. shared createCompatibleProviderCapture.

This inline mock re-implements the provider:get/provider:create/provider:delete cases already in createCompatibleProviderCapture (test-support.ts), only to add a failing inference:set case and drop provider:update. Consider extending the shared helper to accept optional command overrides (e.g., an inference:set failure injector) so this scenario reuses the shared lifecycle mock instead of duplicating it.

🤖 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 `@src/lib/actions/inference-set-compatible-provider.test.ts` around lines 301 -
337, Extend createCompatibleProviderCapture in test-support.ts to accept
optional command overrides, then update the test “removes an absent direct
provider when verified route selection fails (`#7725`)” to use that shared helper
for provider:get/create/delete lifecycle behavior while injecting only the
failing inference:set response and omitting provider:update as needed. Remove
the duplicated inline captureOpenshell mock and preserve the scenario’s existing
assertions and state transitions.
🤖 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 `@src/lib/actions/inference-set.ts`:
- Around line 980-993: Refine the error handling in the direct-provider update
branch around matchesRecordedDirectProviderBinding so the InferenceSetError
message accurately identifies whether the mismatch is in provider, endpointUrl,
or credentialEnv. Preserve the existing rollback guidance for endpoint/provider
replacements, while providing credentialEnv-specific guidance when the endpoint
remains unchanged.

---

Nitpick comments:
In `@src/lib/actions/inference-set-compatible-provider.test.ts`:
- Around line 301-337: Extend createCompatibleProviderCapture in test-support.ts
to accept optional command overrides, then update the test “removes an absent
direct provider when verified route selection fails (`#7725`)” to use that shared
helper for provider:get/create/delete lifecycle behavior while injecting only
the failing inference:set response and omitting provider:update as needed.
Remove the duplicated inline captureOpenshell mock and preserve the scenario’s
existing assertions and state transitions.

In `@src/lib/actions/inference-set.ts`:
- Around line 644-654: Move the pure comparison implemented by
matchesRecordedDirectProviderBinding from the actions module into an appropriate
src/lib/domain module, export it there, and update the action code to import and
use the domain function while preserving the existing matching behavior.
🪄 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: CHILL

Plan: Enterprise

Run ID: b02c1192-933f-4ba5-9b1e-d858ac661f9b

📥 Commits

Reviewing files that changed from the base of the PR and between c4c020c and e8a9f8b.

📒 Files selected for processing (6)
  • docs/inference/switch-providers.mdx
  • src/lib/actions/inference-set-compatible-provider.test.ts
  • src/lib/actions/inference-set-degraded-state.test.ts
  • src/lib/actions/inference-set-provider-alias.test.ts
  • src/lib/actions/inference-set.test-support.ts
  • src/lib/actions/inference-set.ts

Comment thread src/lib/actions/inference-set.ts
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

Advisor assessment: No blocking advisor findings reported
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings match; normalized E2E selections differ; severity counts match.

Nemotron output stays in workflow artifacts and does not change the assessment above.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: inference-routing, network-policy

1 optional E2E recommendation
  • openclaw-inference-switch

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>

@coderabbitai coderabbitai Bot 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.

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 `@src/lib/actions/inference-set-compatible-provider.test.ts`:
- Around line 428-430: Align the parameterized expectations around
prepareInferenceSetProviderBinding with the provider guard’s implemented error
contract: assert the “Refusing to replace provider ... does not match this
sandbox's durable custom-endpoint provenance” message for both cases, or change
the guard to emit the binding-specific diagnostic while preserving the intended
behavior.
🪄 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: CHILL

Plan: Enterprise

Run ID: d8f84383-cf06-4da3-be93-0523f17b227f

📥 Commits

Reviewing files that changed from the base of the PR and between a86b36f and 9768615.

📒 Files selected for processing (3)
  • docs/inference/switch-providers.mdx
  • src/lib/actions/inference-set-compatible-provider.test.ts
  • src/lib/actions/inference-set.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/actions/inference-set.ts
  • docs/inference/switch-providers.mdx

Comment thread src/lib/actions/inference-set-compatible-provider.test.ts
@apurvvkumaria
apurvvkumaria merged commit cf34b72 into main Jul 28, 2026
91 of 101 checks passed
@apurvvkumaria
apurvvkumaria deleted the codex/7746-direct-provider-verification branch July 28, 2026 21:51
@cjagwani cjagwani mentioned this pull request Jul 28, 2026
23 tasks
cv pushed a commit that referenced this pull request Jul 28, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Add the canonical dated changelog entry for NemoClaw v0.0.97 before the
release plan captures `origin/main`.
The entry groups the user-visible and maintainer-facing changes since
v0.0.96 while preserving the Deferred dual-Station status, experimental
runtime-identity boundary, and pending physical IGX validation.

## Changes

- Add `docs/changelog/2026-07-28.mdx` with the parser-safe MDX SPDX
comment and exact `## v0.0.97` heading.
- Summarize the 43 merged PRs in the release range, omitting
internal-only changes from the public entry and linking each grouped
change to its most specific published documentation.
- Keep the experimental Okta reference explicitly opt-in and outside
normal onboarding, keep the two-Station path Deferred, and state that
physical IGX Orin validation remains pending.

### Source summary

- [#7440](#7440),
[#7443](#7443), and
[#7445](#7445) ->
`docs/changelog/2026-07-28.mdx`: Document read-only host readiness
reports and fail-closed platform qualification.
- [#7030](#7030) ->
`docs/changelog/2026-07-28.mdx`: Document the Deferred trusted
two-Station vLLM evaluation.
- [#7265](#7265) ->
`docs/changelog/2026-07-28.mdx`: Document the bounded experimental
direct-runner Okta runtime-identity reference.
- [#7711](#7711) and
[#7648](#7648) ->
`docs/changelog/2026-07-28.mdx`: Document compatible-endpoint reasoning
effort and retired NVIDIA Build model paths.
- [#7746](#7746),
[#7763](#7763), and
[#7681](#7681) ->
`docs/changelog/2026-07-28.mdx`: Document safe compatible-provider
creation, replacement refusal, and narrow OpenShell bridge URL handling.
- [#7641](#7641),
[#7690](#7690),
[#7631](#7631), and
[#7710](#7710) ->
`docs/changelog/2026-07-28.mdx`: Document paused-container recovery,
recreation journaling, pre-mutation uninstall checks, and
source-checkout OpenShell selection.
- [#7624](#7624) and
[#7762](#7762) ->
`docs/changelog/2026-07-28.mdx`: Document Jetson release diagnostics and
bounded render-device group propagation.
- [#7639](#7639),
[#7760](#7760),
[#7721](#7721), and
[#7761](#7761) ->
`docs/changelog/2026-07-28.mdx`: Document Telegram, MCP media-type,
Hermes image-mode, and locked-restart fixes.
- [#7653](#7653) and
[#7680](#7680) ->
`docs/changelog/2026-07-28.mdx`: Document Deep Agents policy tasks and
the bounded Claude Code OAuth path.
- [#7679](#7679) ->
`docs/changelog/2026-07-28.mdx`: Document the checksum-bound libssh2 and
Python HTMLParser backports.
- [#7655](#7655),
[#7651](#7651),
[#7664](#7664),
[#7666](#7666),
[#7670](#7670),
[#7719](#7719), and
[#7741](#7741) ->
`docs/changelog/2026-07-28.mdx`: Document exact candidate E2E evidence,
Launchable selection, diagnostic consolidation, and trusted WSL
validation.

## Type of Change

- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [x] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Quality Gates

- [ ] Tests added or updated for changed behavior
- [x] Existing tests cover changed behavior — justification:
`test/changelog-docs.test.ts` validates the dated changelog contract,
MDX header, heading uniqueness, and release-entry structure.
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `docs-updated`
- Evidence: The committed `docs/changelog/2026-07-28.mdx` blob exactly
matches the reviewed file. Completeness, factual accuracy, link shape,
parser-safe MDX header, one-sentence-per-line style, `.docs-skip`
compliance, and bounded product claims passed.
- Agent: Codex Desktop documentation writer subagent
<!-- docs-review-head-sha: da6aa27 -->
<!-- docs-review-agents-blob-sha: be20a09 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit: Not applicable; this PR changes only the dated
changelog.
- Station profile/scenario: Not applicable.
- Result: Not applicable.
- Supporting evidence: Not applicable.

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — `npx vitest run
test/changelog-docs.test.ts` passed 6/6.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — not applicable to this doc-only release
entry.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only) —
completed with 0 errors and 2 pre-existing Fern warnings.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)
— native changelog entries use the required parser-safe MDX SPDX comment
and intentionally have no frontmatter.

---
Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added improved host readiness reporting and Jetson onboarding
guidance.
* Added controls for reasoning effort with compatible endpoints and
enhanced managed MCP discovery.
  * Improved Deep Agents task publication and preset support.
* **Bug Fixes**
* Hardened provider switching, sandbox recovery, uninstall behavior, and
Telegram connectivity.
* Improved container image integrity checks, media-type handling, and
checksum validation.
  * Enhanced vLLM evaluation behavior and release diagnostics.
* **Documentation**
  * Added the NemoClaw v0.0.97 changelog.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: docs Documentation, examples, guides, or docs build

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants