Skip to content

fix(inference): accept onboard provider aliases + guide dcode users (#6321) - #6378

Merged
cv merged 13 commits into
mainfrom
fix/inference-set-provider-alias-dcode-6321
Jul 7, 2026
Merged

fix(inference): accept onboard provider aliases + guide dcode users (#6321)#6378
cv merged 13 commits into
mainfrom
fix/inference-set-provider-alias-dcode-6321

Conversation

@yanyunl1991

@yanyunl1991 yanyunl1991 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

nemoclaw inference set was unusable in the three ways #6321 reports. This PR fixes all three, each verified end-to-end on a real test sandbox onboarded against an internal-resolving Inference Hub endpoint. Facet 2 is served by guidance, not by accepting a re-supplied internal endpoint: inference set never skips the DNS-pinning SSRF guard for a supplied --endpoint-url (trusting the recorded registry value would be self-authorizing, since inference set itself persists it), and instead guides the user to omit --endpoint-url to reuse the endpoint onboarding established. A different internal endpoint is likewise blocked. See the PR #6378 review thread.

  • Facet 1 — provider-name drift. onboard accepts installer-style keys (anthropicCompatible, build, openai, …); inference set only accepted the OpenShell names. Normalize the installer alias to its OpenShell name before validation.
  • Facet 2 — SSRF guard vs onboard. inference set --endpoint-url <internal-hub> was blocked by the DNS-pinning SSRF guard while onboard accepted the same URL. The guard is correct and stays, and inference set never skips it for a supplied --endpoint-url. Rather than accept a re-supplied internal endpoint, the fix turns the dead-end into guidance: on a same-provider sandbox, omit --endpoint-url to switch only the model (the gateway keeps the route onboard established). A different internal endpoint stays blocked.
  • Facet 3 — Deep Agents (dcode) refused with no next step. dcode bakes its model at image-build time, so it has no runtime inference-set path. Keep the refusal, append an actionable re-onboard hint.

Refs #6321.

Facet 2 — guidance, not a guard bypass (security-reviewed)

inference set never repoints the OpenShell gateway (openshellInferenceSetArgs passes only provider + model), so a same-provider model switch does not need --endpoint-url at all — the gateway keeps the endpoint onboarding established. The DNS-pinning SSRF guard therefore stays fully authoritative for every supplied --endpoint-url; when it blocks an internal URL on a same-provider sandbox, the error appends actionable guidance: drop --endpoint-url to switch only the model, or re-onboard to change the endpoint.

An earlier revision of this PR accepted the exact recorded endpoint via a string-equality identity match against entry.endpointUrl (skipping the guard on a match). That was removed in review (PR #6378): entry.endpointUrl is not exclusively onboarding-provenanced — this same inference set action persists it — so trusting the recorded string to skip the guard would be self-authorizing (a value this command wrote could later authorize an internal-resolving switch). No provenance marker was added because the bypass is gone entirely rather than gated.

Two facts shape the safe fix:

  1. inference set never repoints the OpenShell gateway (openshellInferenceSetArgs passes only provider + model); the endpoint is fixed at onboard time.
  2. A same-provider model switch therefore does not need --endpoint-url at all — the gateway keeps the route onboard established.

So the guard is unchanged. When it blocks an internal --endpoint-url and the sandbox is already on that provider, the error now appends: drop --endpoint-url to switch only the model (reuses the established route), and re-onboard/rebuild to actually change the endpoint. A genuinely new internal endpoint, or a switch to a different provider, still errors with no bypass.

Reproduction + Verification (real test machine)

Test host: Ubuntu 24.04 x86_64 (no GPU). inference-api.nvidia.com resolves to an internal 10.48.x.x address there (same condition as the reporter's network), so the SSRF path is exercised for real. Fresh sandboxes onboarded via NEMOCLAW_PROVIDER=custom (openclaw infra-6321) and --agent dcode (dcode-6321).

Before (v0.0.74, real sandboxes):

# Facet 1
$ nemoclaw infra-6321 inference set --provider anthropicCompatible --model <m>
Unsupported provider 'anthropicCompatible'. Supported providers: ...
$ echo $?
2
$ nemoclaw infra-6321 inference set --provider custom --model <m>
Unsupported provider 'custom'. ...          (exit 2)

# Facet 2  (same Hub URL onboard just accepted; resolves to 10.48.203.205)
$ nemoclaw infra-6321 inference set --provider compatible-endpoint --endpoint-url https://inference-api.nvidia.com/v1 --model <m>
endpoint-url is not allowed: URL hostname "inference-api.nvidia.com" resolves to private/internal address "10.48.203.205". ...   (exit 2, dead-end)

# Facet 3
$ nemoclaw dcode-6321 inference set --provider nvidia-prod --model <m>
nemoclaw inference set supports OpenClaw and Hermes sandboxes; 'dcode-6321' uses 'langchain-deepagents-code'.   (exit 2, no next step)

After (this branch, same real sandboxes):

# Facet 1 — installer name accepted; same-provider switch succeeds
$ nemoclaw infra-6321 inference set --provider custom --model <m>
  Setting OpenShell inference route: compatible-endpoint / <m>
  Inference route synced for 'infra-6321': ...   (exit 0)

# Facet 2 — guard still fires, now with guidance
$ nemoclaw infra-6321 inference set --provider compatible-endpoint --endpoint-url https://inference-api.nvidia.com/v1 --model <m>
endpoint-url is not allowed: ... resolves to private/internal address "10.48.203.205". ...
  This sandbox is already configured for 'compatible-endpoint'. To switch only the model, omit --endpoint-url — inference set reuses the endpoint onboarding already established ... To point the sandbox at a different endpoint, re-run onboarding or rebuild.   (exit 2)
# ... and the guided path works:
$ nemoclaw infra-6321 inference set --provider compatible-endpoint --model <m>   (no --endpoint-url)
  Inference route synced for 'infra-6321': ...   (exit 0)

# Facet 3 — refusal now actionable
$ nemoclaw dcode-6321 inference set --provider nvidia-prod --model <m>
nemoclaw inference set supports OpenClaw and Hermes sandboxes; 'dcode-6321' uses 'langchain-deepagents-code'. Deep Agents Code bakes its model into the sandbox image at build time, so it has no runtime inference-set path. To change the model, re-onboard with the new selection: `nemoclaw onboard --agent dcode --name 'dcode-6321' --fresh` ...   (exit 2)

Changes

  • src/lib/actions/inference-set.ts:
    • normalizeInferenceSetProvider + INSTALLER_PROVIDER_ALIASES — accept the installer provider vocabulary onboard uses (facet 1); persists the canonical OpenShell name.
    • dcode branch of the unsupported-agent refusal appends a re-onboard hint (facet 3); the target sandbox name is shellQuoted.
    • explicitCustomProviderMetadata catches the SSRF-guard error and, for a same-provider sandbox, appends the omit---endpoint-url guidance (facet 2). The guard is unchanged.
  • src/lib/actions/inference-set-provider-alias.test.ts (new): 13 cases — alias normalization + case/trim + passthrough + drift guard + parity vs onboard's getEffectiveProviderName; anthropicCompatible accepted end-to-end; dcode hint present / absent-for-other-agents; SSRF guard still fires + guidance appended + omit-flag path succeeds + no hint on provider switch.

Type of Change

  • Code change (feature, bug fix, or refactor)

Verification

  • npx vitest run --project cli src/lib/actions/inference-set-provider-alias.test.ts — 13/13.
  • Full src/lib/actions/inference-set*.test.ts — 101/101 (no regressions).
  • npm run build:cli passes; npx prek run … --stage pre-commit clean (Biome + repository-checks).
  • End-to-end on a real test sandbox against an internal-resolving endpoint (transcripts above): facet 1 switch succeeds, facet 2 guard-holds + guidance + omit-flag works, facet 3 hint present.
  • No secrets, API keys, or credentials committed.

AI Disclosure

  • AI-assisted — tool: Claude Code

Signed-off-by: Yanyun Liao yanyunl@nvidia.com

Summary by CodeRabbit

  • New Features
    • Installer-style provider names are now accepted for inference-set provider selection and automatically normalized to the canonical provider.
  • Bug Fixes
    • Same-provider model-only switches can omit --endpoint-url; when endpoint URLs are blocked, the error now guides users to omit --endpoint-url.
    • Deep Agents Code incompatibility errors now include a more specific re-onboarding remediation hint.
  • Documentation
    • Added an “Installer Provider Aliases” section and clarified endpoint URL omission behavior for model-only changes.
  • Tests
    • Added regression and parity checks to prevent provider alias/name drift and validate error-message behavior.

…6321)

Two of the three defects reported in #6321 (the SSRF-guard facet is a
security trust-model decision deferred to a separate maintainer review):

Facet 1 — provider-name drift. `nemoclaw onboard` accepts installer-style
provider keys (`anthropicCompatible`, `build`, `openai`, …) while
`inference set` only accepted the OpenShell provider names
(`compatible-anthropic-endpoint`, `nvidia-prod`, `openai-api`, …), so a
sandbox onboarded with `NEMOCLAW_PROVIDER=anthropicCompatible` could not be
switched with `inference set --provider anthropicCompatible` — the two
commands used different vocabularies for the same provider. Add
`normalizeInferenceSetProvider`, which maps the installer alias to its
OpenShell provider name before validation (OpenShell names and unknown
values pass through unchanged, so genuinely unsupported providers still
error). The alias table mirrors REMOTE_PROVIDER_CONFIG[key].providerName /
getEffectiveProviderName() in src/lib/onboard/providers.ts; a sync test
asserts every alias resolves to a SUPPORTED_PROVIDER_NAMES entry so the two
lists cannot drift. The normalized name is what gets persisted, keeping the
registry canonical.

Facet 3 — Deep Agents (dcode) refusal. `inference set` on a
langchain-deepagents-code sandbox refused with a blunt "supports OpenClaw
and Hermes" message and no next step. dcode bakes its model into the
sandbox image at build time (ARG NEMOCLAW_MODEL → ~/.deepagents/config.toml),
so it genuinely has no runtime inference-set path. Keep the refusal (the
safety contract is correct) but append an actionable hint pointing dcode
users at the only supported way to change the model: re-onboard with a new
selection. The hint fires only for langchain-deepagents-code; other
unsupported agents keep the original message.

Regression coverage in inference-set-provider-alias.test.ts (9 cases):
alias normalization + case/trim + passthrough + drift guard;
runInferenceSet accepts `anthropicCompatible` end-to-end and persists the
canonical name; genuinely-unsupported providers still rejected; dcode
refusal carries the re-onboard hint while other agents do not.

Fixes #6321

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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
📝 Walkthrough

Walkthrough

inference set now normalizes installer provider aliases before validation, preserves the canonical provider in sandbox state, and adjusts endpoint-url and Deep Agents Code error messages. The docs and tests were updated to cover alias parity, provider acceptance, and the new guidance paths.

Changes

Provider normalization and inference-set guidance

Layer / File(s) Summary
Provider alias map and normalization
src/lib/actions/inference-set.ts
Adds installer alias normalization, exports the supported provider names and alias map, and adds a stable prefix for endpoint-url validation errors.
Provider wiring and error guidance
src/lib/actions/inference-set.ts
Normalizes the requested provider before downstream validation, adds Deep Agents Code-specific re-onboarding text, and augments endpoint-url validation errors when the sandbox is already on the target provider.
Alias and provider acceptance tests
src/lib/actions/inference-set-provider-alias.test.ts
Adds tests for installer alias normalization, canonical provider passthrough, unknown-provider rejection, persistence of the normalized provider value, and the Deep Agents Code and SSRF guidance paths.
Inference-set docs updates
docs/inference/switch-inference-providers.mdx
Documents installer provider aliases and model-only switching guidance for compatible endpoints.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

Suggested labels: bug-fix, area: cli, area: providers

Suggested reviewers: ericksoa, jyaunches, prekshivyas

🚥 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 clearly summarizes the main changes: accepting onboard provider aliases and adding guidance for dcode users.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/inference-set-provider-alias-dcode-6321

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

@github-code-quality

github-code-quality Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the fix/inference-set-pr... branch is 96%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main fix/inference-set-pr... cb87b89 +/-
nemoclaw/src/se...cret-scanner.ts 100%
nemoclaw/src/commands/slash.ts 100%
nemoclaw/src/li...bprocess-env.ts 100%
nemoclaw/src/bl...eprint/state.ts 98%
nemoclaw/src/onboard/config.ts 98%
nemoclaw/src/bl...int/snapshot.ts 97%
nemoclaw/src/bl...print/runner.ts 95%
nemoclaw/src/co...ration-state.ts 94%
nemoclaw/src/bl...ate-networks.ts 94%
nemoclaw/src/index.ts 94%

TypeScript / code-coverage/cli

The overall coverage in the fix/inference-set-pr... branch is 75%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main fix/inference-set-pr... cb87b89 +/-
src/lib/shields...nsition-lock.ts 85%
src/lib/onboard/preflight.ts 83%
src/lib/actions...all/run-plan.ts 81%
src/lib/state/o...oard-session.ts 80%
src/lib/actions...licy-channel.ts 79%
src/lib/state/sandbox.ts 75%
src/lib/onboard...er-gpu-patch.ts 69%
src/lib/policy/index.ts 66%
src/lib/shields/index.ts 61%
src/lib/onboard.ts 28%

Updated July 07, 2026 18:26 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Changes requested

Merge posture: Do not merge yet
Primary next action: Fix PRA-1: SSRF bypass eliminated — all supplied endpoints go through DNS-pinning guard; then add or justify PRA-T1.
Open items: 5 required · 5 warnings · 1 suggestion · 3 test follow-ups
Since last review: 0 prior items resolved · 0 still apply · 10 new items found

Action checklist

  • PRA-1 Fix: SSRF bypass eliminated — all supplied endpoints go through DNS-pinning guard in src/lib/actions/inference-set.ts:336
  • PRA-2 Fix: Trust boundary correctly narrow — only host.openshell.internal over HTTP on unprivileged ports exempted in src/lib/actions/inference-set.ts:321
  • PRA-9 Fix: Facet 2 acceptance met — docs state SSRF guard always validates, omit flag for model-only switch in docs/inference/switch-inference-providers.mdx:45
  • PRA-10 Fix: Facet 1 acceptance met — docs show installer aliases work in docs/inference/switch-inference-providers.mdx:36
  • PRA-11 Fix: Facet 3 acceptance met — dcode hint provides actionable re-onboard command in src/lib/actions/inference-set.ts:543
  • PRA-3 Resolve or justify: shellQuote defense-in-depth relies on untested validateName restriction in src/lib/actions/inference-set-provider-alias.test.ts:266
  • PRA-4 Resolve or justify: Provider alias maps duplicated between onboard and inference-set — drift guard test mitigates but window exists in src/lib/onboard/providers.ts:33
  • PRA-5 Resolve or justify: Provider normalization ordering correct — unrecognized aliases pass through for validation in src/lib/actions/inference-set.ts:500
  • PRA-6 Resolve or justify: dcode hint uses shellQuote correctly for copy-paste safety in src/lib/actions/inference-set.ts:543
  • PRA-7 Resolve or justify: Test file monolith — 563 lines mixing 5 distinct test concerns in src/lib/actions/inference-set-provider-alias.test.ts:1
  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-8 In-scope improvement: Provider alias map duplicated from onboard — extract to shared module in src/lib/actions/inference-set.ts:258

Findings index

ID Severity Category Location Required action
PRA-1 Required security src/lib/actions/inference-set.ts:336 No change required — the fix is correct and tests verify the guard is consulted for re-supplied identical URLs and that no mutation occurs on rejection.
PRA-2 Required security src/lib/actions/inference-set.ts:321 No change required — trust boundary is correctly maintained.
PRA-3 Resolve/justify security src/lib/actions/inference-set-provider-alias.test.ts:266 Add a comment or test linking the `validateName` restriction to this defense-in-depth claim, or add an integration test that attempts a metacharacter sandbox name through the full CLI path to confirm it's rejected before the hint.
PRA-4 Resolve/justify security src/lib/onboard/providers.ts:33 Consider a shared source of truth (e.g., a JSON/TS config file imported by both) to eliminate duplication. For now, the drift-guard test is an adequate safety net.
PRA-5 Resolve/justify correctness src/lib/actions/inference-set.ts:500 No change required — behavior is correct and tested.
PRA-6 Resolve/justify correctness src/lib/actions/inference-set.ts:543 No change required.
PRA-7 Resolve/justify architecture src/lib/actions/inference-set-provider-alias.test.ts:1 Split the test file into focused modules before merge: `normalize-provider.test.ts`, `provider-alias-e2e.test.ts`, `dcode-hint.test.ts`, `ssrf-guidance.test.ts`, `alias-drift-guard.test.ts`.
PRA-8 Improvement correctness src/lib/actions/inference-set.ts:258 Extract provider alias mappings to a shared config file (e.g., `src/lib/inference/provider-aliases.ts`) imported by both onboard/providers.ts and inference-set.ts. This is a follow-up refactor, not a blocker for this PR.
PRA-9 Required acceptance docs/inference/switch-inference-providers.mdx:45 No change required — docs accurately reflect the fix.
PRA-10 Required acceptance docs/inference/switch-inference-providers.mdx:36 No change required.
PRA-11 Required acceptance src/lib/actions/inference-set.ts:543 No change required.

🚨 Required before merge

Address these before merging unless a maintainer explicitly overrides the advisor with rationale.

PRA-1 Required — SSRF bypass eliminated — all supplied endpoints go through DNS-pinning guard

  • Location: src/lib/actions/inference-set.ts:336
  • Category: security
  • Problem: The `normalizeCustomEndpointUrl` function now unconditionally calls `rewriteConfigUrlsWithDnsPinning` for every supplied `--endpoint-url`, eliminating the prior string-equality bypass that would have allowed a recorded internal-resolving URL to be re-authorized. The catch block in `explicitCustomProviderMetadata` (lines 379-397) correctly augments only SSRF/DNS-pinning rejections (identified by `ENDPOINT_URL_NOT_ALLOWED_PREFIX`) with same-provider omit-flag guidance, while leaving other endpoint errors (missing URL, malformed URL) untouched.
  • Impact: Prevented a potential SSRF bypass where re-supplying an onboard-recorded internal endpoint would skip the guard, enabling access to internal services.
  • Required action: No change required — the fix is correct and tests verify the guard is consulted for re-supplied identical URLs and that no mutation occurs on rejection.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run the test `re-supplying the SAME onboard-recorded internal endpoint is rejected with omit-guidance (no bypass)` at line 199-220 in inference-set-provider-alias.test.ts — it asserts the guard is called and `expectNoInferenceMutation` passes.
  • Missing regression test: Already covered by the test at line 199-220 in inference-set-provider-alias.test.ts
  • Done when: The required change is committed and verification passes: Run the test `re-supplying the SAME onboard-recorded internal endpoint is rejected with omit-guidance (no bypass)` at line 199-220 in inference-set-provider-alias.test.ts — it asserts the guard is called and `expectNoInferenceMutation` passes.
  • Evidence: Lines 336 (guard call), 379-397 (catch block with ENDPOINT_URL_NOT_ALLOWED_PREFIX check), and test at lines 199-220

PRA-2 Required — Trust boundary correctly narrow — only host.openshell.internal over HTTP on unprivileged ports exempted

  • Location: src/lib/actions/inference-set.ts:321
  • Category: security
  • Problem: The `ALLOWED_PRIVATE_CUSTOM_ENDPOINT_HOSTS` trust boundary remains correctly narrow: only `host.openshell.internal` over HTTP on unprivileged ports (≥1024) is exempted from the DNS-pinning guard. The comment explicitly forbids extending to HTTPS, localhost, RFC1918 literals, or arbitrary internal DNS names.
  • Impact: Maintains the sandbox-to-host bridge security model; no relaxation of SSRF protection for internal endpoints.
  • Required action: No change required — trust boundary is correctly maintained.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read lines 315-330 in inference-set.ts — the exemption logic and its restrictive comments are intact.
  • Missing regression test: No new test needed; existing SSRF guard tests cover this boundary.
  • Done when: The required change is committed and verification passes: Read lines 315-330 in inference-set.ts — the exemption logic and its restrictive comments are intact.
  • Evidence: Lines 315-330 in inference-set.ts

PRA-9 Required — Facet 2 acceptance met — docs state SSRF guard always validates, omit flag for model-only switch

  • Location: docs/inference/switch-inference-providers.mdx:45
  • Category: acceptance
  • Problem: Documentation now explicitly states: "Any `--endpoint-url` you do pass is always validated by the host-side SSRF guard, so a URL that resolves to a private or internal address is rejected even if it is the same one onboarding recorded; omit the flag to keep the established endpoint." This matches the code behavior and the acceptance criteria for facet 2.
  • Impact: Users correctly understand the guard behavior and the correct workaround (omit --endpoint-url).
  • Required action: No change required — docs accurately reflect the fix.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read the Compatible Endpoints section in the docs file (lines 45-48).
  • Missing regression test: N/A — documentation.
  • Done when: The required change is committed and verification passes: Read the Compatible Endpoints section in the docs file (lines 45-48).
  • Evidence: Lines 45-48 in switch-inference-providers.mdx

PRA-10 Required — Facet 1 acceptance met — docs show installer aliases work

  • Location: docs/inference/switch-inference-providers.mdx:36
  • Category: acceptance
  • Problem: Documentation adds "Installer Provider Aliases" section showing both `anthropicCompatible` and `compatible-anthropic-endpoint` work. This matches facet 1 acceptance.
  • Impact: Users discover they can use the same provider name they used during onboarding.
  • Required action: No change required.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read the Find the Provider Name section (lines 36-44) in switch-inference-providers.mdx.
  • Missing regression test: N/A — documentation.
  • Done when: The required change is committed and verification passes: Read the Find the Provider Name section (lines 36-44) in switch-inference-providers.mdx.
  • Evidence: Lines 36-44 in switch-inference-providers.mdx

PRA-11 Required — Facet 3 acceptance met — dcode hint provides actionable re-onboard command

  • Location: src/lib/actions/inference-set.ts:543
  • Category: acceptance
  • Problem: The dcode hint includes the re-onboard command with `--fresh` flag and references `NEMOCLAW_PROVIDER` / `NEMOCLAW_MODEL` env vars. This matches facet 3 acceptance: actionable next step instead of dead-end refusal.
  • Impact: Deep Agents users get a concrete path to change their model instead of a blunt refusal.
  • Required action: No change required.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read the error message construction at lines 543-546 in inference-set.ts.
  • Missing regression test: Covered by dcode hint tests at lines 158-182 and 258-280.
  • Done when: The required change is committed and verification passes: Read the error message construction at lines 543-546 in inference-set.ts.
  • Evidence: Lines 543-546 in inference-set.ts; tests at lines 158-182, 258-280
Review findings by urgency: 5 required fixes, 5 items to resolve/justify, 1 in-scope improvement

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-3 Resolve/justify — shellQuote defense-in-depth relies on untested validateName restriction

  • Location: src/lib/actions/inference-set-provider-alias.test.ts:266
  • Category: security
  • Problem: The `shellQuote` defense-in-depth test (lines 258-280) correctly verifies that metacharacters (spaces, quotes, semicolons, `$()`, backticks) are contained within single quotes. However, `validateName` (which restricts sandbox names to metacharacter-free shapes) is not tested here — the test assumes it blocks bad names before the hint path. If `validateName` were ever loosened, the shellQuote layer would be the only protection.
  • Impact: If sandbox name validation is weakened in the future, a malicious sandbox name could break out of the shell-quoted hint command.
  • Recommended action: Add a comment or test linking the `validateName` restriction to this defense-in-depth claim, or add an integration test that attempts a metacharacter sandbox name through the full CLI path to confirm it's rejected before the hint.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search for `validateName` in the codebase and verify its character restrictions.
  • Missing regression test: Integration test: attempt `onboard --name "a;b"` and confirm rejection before inference-set hint path.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search for `validateName` in the codebase and verify its character restrictions.
  • Evidence: Test at lines 258-280 in inference-set-provider-alias.test.ts; shellQuote implementation at src/lib/core/shell-quote.ts

PRA-4 Resolve/justify — Provider alias maps duplicated between onboard and inference-set — drift guard test mitigates but window exists

  • Location: src/lib/onboard/providers.ts:33
  • Category: security
  • Problem: The `NON_INTERACTIVE_PROVIDER_ALIASES` in onboard/providers.ts uses camelCase keys (e.g., `anthropiccompatible`, `hermesProvider`) while `inference-set.ts` uses lowercase keys (e.g., `anthropiccompatible`, `hermesprovider`). The drift-guard test (lines 303-342) imports onboard's config and calls `getEffectiveProviderName` to verify parity, which catches drift at test time. However, the two maps are maintained separately — a future onboard change could add an alias that inference-set doesn't know about, or vice versa. The test will fail, but the window exists until CI runs.
  • Impact: Potential drift between onboard and inference-set provider vocabularies, leading to user-facing 'unsupported provider' errors for valid onboard names.
  • Recommended action: Consider a shared source of truth (e.g., a JSON/TS config file imported by both) to eliminate duplication. For now, the drift-guard test is an adequate safety net.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run the test `installer alias parity with onboard provider config — facet 1 drift guard` at line 303-342 — it exercises the full onboard key set against inference-set's map.
  • Missing regression test: Already covered by the drift-guard test at line 303-342.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run the test `installer alias parity with onboard provider config — facet 1 drift guard` at line 303-342 — it exercises the full onboard key set against inference-set's map.
  • Evidence: NON_INTERACTIVE_PROVIDER_ALIASES at line 33 in onboard/providers.ts vs INSTALLER_PROVIDER_ALIASES at line 258 in inference-set.ts; drift guard test at lines 303-342

PRA-5 Resolve/justify — Provider normalization ordering correct — unrecognized aliases pass through for validation

  • Location: src/lib/actions/inference-set.ts:500
  • Category: correctness
  • Problem: The `normalizeInferenceSetProvider` function is called early in `runInferenceSetWithoutHostLock` (line 500), before `assertSupportedProvider`. This means an unrecognized provider alias (e.g., `totally-made-up`) passes through unchanged and is then rejected by `assertSupportedProvider` with the correct error message showing the original user input.
  • Impact: Good UX — error messages show what the user typed, not a normalized form.
  • Recommended action: No change required — behavior is correct and tested.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Test `passes an unrecognized provider through unchanged (validation still rejects it later)` at line 55 in inference-set-provider-alias.test.ts.
  • Missing regression test: Already covered.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Test `passes an unrecognized provider through unchanged (validation still rejects it later)` at line 55 in inference-set-provider-alias.test.ts.
  • Evidence: Line 500 (normalizeInferenceSetProvider call), line 501 (assertSupportedProvider), test at line 55

PRA-6 Resolve/justify — dcode hint uses shellQuote correctly for copy-paste safety

  • Location: src/lib/actions/inference-set.ts:543
  • Category: correctness
  • Problem: The dcode hint uses `shellQuote(sandboxName)` but the error message is thrown as a plain string, not passed through a shell. The hint is for copy-paste by the user, so shell quoting is appropriate. The test at line 273-274 verifies the quoted form appears in the error message and the bare name does not.
  • Impact: User gets a safe, copy-pasteable re-onboard command with properly quoted sandbox name.
  • Recommended action: No change required.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Test `shell-quotes the sandbox name in the dcode re-onboard hint` at line 258 in inference-set-provider-alias.test.ts.
  • Missing regression test: Already covered.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Test `shell-quotes the sandbox name in the dcode re-onboard hint` at line 258 in inference-set-provider-alias.test.ts.
  • Evidence: Lines 543-546 (hint construction), test at lines 258-280

PRA-7 Resolve/justify — Test file monolith — 563 lines mixing 5 distinct test concerns

  • Location: src/lib/actions/inference-set-provider-alias.test.ts:1
  • Category: architecture
  • Problem: New test file is 563 lines — a monolith growth flagged by drift context. It mixes unit tests for `normalizeInferenceSetProvider`, integration-style tests for `runInferenceSet`, SSRF guard behavior tests, dcode hint tests, and a drift-guard test that imports onboard's CJS module. This could be split into separate files for maintainability.
  • Impact: Reduced maintainability; harder to navigate and run focused test subsets; mixed test fixtures create coupling.
  • Recommended action: Split the test file into focused modules before merge: `normalize-provider.test.ts`, `provider-alias-e2e.test.ts`, `dcode-hint.test.ts`, `ssrf-guidance.test.ts`, `alias-drift-guard.test.ts`.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Review the test file structure — five distinct `describe` blocks with different concerns (normalization, e2e alias, dcode hint, SSRF guidance, drift guard).
  • Missing regression test: N/A — this is a test organization concern.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Review the test file structure — five distinct `describe` blocks with different concerns (normalization, e2e alias, dcode hint, SSRF guidance, drift guard).
  • Evidence: Test file has 5 describe blocks spanning 563 lines; drift context flagged monolith growth

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

PRA-8 Improvement — Provider alias map duplicated from onboard — extract to shared module

  • Location: src/lib/actions/inference-set.ts:258
  • Category: correctness
  • Problem: The `INSTALLER_PROVIDER_ALIASES` map duplicates provider alias mappings that exist in `onboard/providers.ts` (`NON_INTERACTIVE_PROVIDER_ALIASES` and `getEffectiveProviderName`). The comment acknowledges this and explains the `@ts-nocheck` onboard module isn't imported into the hot path. The drift-guard test mitigates divergence, but a shared config would be cleaner.
  • Impact: Maintenance burden; risk of drift despite test guard; violates DRY.
  • Suggested action: Extract provider alias mappings to a shared config file (e.g., `src/lib/inference/provider-aliases.ts`) imported by both onboard/providers.ts and inference-set.ts. This is a follow-up refactor, not a blocker for this PR.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare `INSTALLER_PROVIDER_ALIASES` (line 258) with `NON_INTERACTIVE_PROVIDER_ALIASES` and `getEffectiveProviderName` in onboard/providers.ts.
  • Missing regression test: Drift-guard test covers this.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: INSTALLER_PROVIDER_ALIASES at lines 258-285 in inference-set.ts; NON_INTERACTIVE_PROVIDER_ALIASES at line 33 and getEffectiveProviderName at line 103 in onboard/providers.ts
Simplification opportunities: 2 possible cuts, net -28 lines possible

These are safe simplification checks only. Do not remove validation, security controls, data-loss prevention, or required tests.

  • PRA-7 shrink (src/lib/actions/inference-set-provider-alias.test.ts:1): Split inference-set-provider-alias.test.ts into 5 focused test files by concern
    • Replacement: normalize-provider.test.ts, provider-alias-e2e.test.ts, dcode-hint.test.ts, ssrf-guidance.test.ts, alias-drift-guard.test.ts
    • Net: 0 lines
    • Safety boundary: All existing test coverage preserved; no behavior change
  • PRA-8 shrink (src/lib/actions/inference-set.ts:258): Duplicate INSTALLER_PROVIDER_ALIASES map (28 lines)
    • Replacement: Import from shared src/lib/inference/provider-aliases.ts
    • Net: -28 lines
    • Safety boundary: Drift-guard test ensures parity; shared module used by both hot path and onboard
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Integration test: metacharacter sandbox name rejection before inference-set hint path (verify validateName blocks before dcode hint). The changed behavior involves sandbox mutation, gateway calls, and DNS-pinning guard — all require real sandbox integration tests. Unit tests mock rewriteConfigUrlsWithDnsPinning; a real integration test against an internal-resolving endpoint would validate the full stack.
  • PRA-T2 Runtime validation — Integration test: full inference-set flow against real internal-resolving endpoint (exercises DNS-pinning guard, guidance, omit-flag path). The changed behavior involves sandbox mutation, gateway calls, and DNS-pinning guard — all require real sandbox integration tests. Unit tests mock rewriteConfigUrlsWithDnsPinning; a real integration test against an internal-resolving endpoint would validate the full stack.
  • PRA-T3 Runtime validation — Integration test: provider alias normalization end-to-end with real onboard + inference-set sequence. The changed behavior involves sandbox mutation, gateway calls, and DNS-pinning guard — all require real sandbox integration tests. Unit tests mock rewriteConfigUrlsWithDnsPinning; a real integration test against an internal-resolving endpoint would validate the full stack.
Since last review details

Current findings, using the urgency labels above:

PRA-1 Required — SSRF bypass eliminated — all supplied endpoints go through DNS-pinning guard

  • Location: src/lib/actions/inference-set.ts:336
  • Category: security
  • Problem: The `normalizeCustomEndpointUrl` function now unconditionally calls `rewriteConfigUrlsWithDnsPinning` for every supplied `--endpoint-url`, eliminating the prior string-equality bypass that would have allowed a recorded internal-resolving URL to be re-authorized. The catch block in `explicitCustomProviderMetadata` (lines 379-397) correctly augments only SSRF/DNS-pinning rejections (identified by `ENDPOINT_URL_NOT_ALLOWED_PREFIX`) with same-provider omit-flag guidance, while leaving other endpoint errors (missing URL, malformed URL) untouched.
  • Impact: Prevented a potential SSRF bypass where re-supplying an onboard-recorded internal endpoint would skip the guard, enabling access to internal services.
  • Required action: No change required — the fix is correct and tests verify the guard is consulted for re-supplied identical URLs and that no mutation occurs on rejection.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run the test `re-supplying the SAME onboard-recorded internal endpoint is rejected with omit-guidance (no bypass)` at line 199-220 in inference-set-provider-alias.test.ts — it asserts the guard is called and `expectNoInferenceMutation` passes.
  • Missing regression test: Already covered by the test at line 199-220 in inference-set-provider-alias.test.ts
  • Done when: The required change is committed and verification passes: Run the test `re-supplying the SAME onboard-recorded internal endpoint is rejected with omit-guidance (no bypass)` at line 199-220 in inference-set-provider-alias.test.ts — it asserts the guard is called and `expectNoInferenceMutation` passes.
  • Evidence: Lines 336 (guard call), 379-397 (catch block with ENDPOINT_URL_NOT_ALLOWED_PREFIX check), and test at lines 199-220

PRA-2 Required — Trust boundary correctly narrow — only host.openshell.internal over HTTP on unprivileged ports exempted

  • Location: src/lib/actions/inference-set.ts:321
  • Category: security
  • Problem: The `ALLOWED_PRIVATE_CUSTOM_ENDPOINT_HOSTS` trust boundary remains correctly narrow: only `host.openshell.internal` over HTTP on unprivileged ports (≥1024) is exempted from the DNS-pinning guard. The comment explicitly forbids extending to HTTPS, localhost, RFC1918 literals, or arbitrary internal DNS names.
  • Impact: Maintains the sandbox-to-host bridge security model; no relaxation of SSRF protection for internal endpoints.
  • Required action: No change required — trust boundary is correctly maintained.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read lines 315-330 in inference-set.ts — the exemption logic and its restrictive comments are intact.
  • Missing regression test: No new test needed; existing SSRF guard tests cover this boundary.
  • Done when: The required change is committed and verification passes: Read lines 315-330 in inference-set.ts — the exemption logic and its restrictive comments are intact.
  • Evidence: Lines 315-330 in inference-set.ts

PRA-3 Resolve/justify — shellQuote defense-in-depth relies on untested validateName restriction

  • Location: src/lib/actions/inference-set-provider-alias.test.ts:266
  • Category: security
  • Problem: The `shellQuote` defense-in-depth test (lines 258-280) correctly verifies that metacharacters (spaces, quotes, semicolons, `$()`, backticks) are contained within single quotes. However, `validateName` (which restricts sandbox names to metacharacter-free shapes) is not tested here — the test assumes it blocks bad names before the hint path. If `validateName` were ever loosened, the shellQuote layer would be the only protection.
  • Impact: If sandbox name validation is weakened in the future, a malicious sandbox name could break out of the shell-quoted hint command.
  • Recommended action: Add a comment or test linking the `validateName` restriction to this defense-in-depth claim, or add an integration test that attempts a metacharacter sandbox name through the full CLI path to confirm it's rejected before the hint.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search for `validateName` in the codebase and verify its character restrictions.
  • Missing regression test: Integration test: attempt `onboard --name "a;b"` and confirm rejection before inference-set hint path.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search for `validateName` in the codebase and verify its character restrictions.
  • Evidence: Test at lines 258-280 in inference-set-provider-alias.test.ts; shellQuote implementation at src/lib/core/shell-quote.ts

PRA-4 Resolve/justify — Provider alias maps duplicated between onboard and inference-set — drift guard test mitigates but window exists

  • Location: src/lib/onboard/providers.ts:33
  • Category: security
  • Problem: The `NON_INTERACTIVE_PROVIDER_ALIASES` in onboard/providers.ts uses camelCase keys (e.g., `anthropiccompatible`, `hermesProvider`) while `inference-set.ts` uses lowercase keys (e.g., `anthropiccompatible`, `hermesprovider`). The drift-guard test (lines 303-342) imports onboard's config and calls `getEffectiveProviderName` to verify parity, which catches drift at test time. However, the two maps are maintained separately — a future onboard change could add an alias that inference-set doesn't know about, or vice versa. The test will fail, but the window exists until CI runs.
  • Impact: Potential drift between onboard and inference-set provider vocabularies, leading to user-facing 'unsupported provider' errors for valid onboard names.
  • Recommended action: Consider a shared source of truth (e.g., a JSON/TS config file imported by both) to eliminate duplication. For now, the drift-guard test is an adequate safety net.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run the test `installer alias parity with onboard provider config — facet 1 drift guard` at line 303-342 — it exercises the full onboard key set against inference-set's map.
  • Missing regression test: Already covered by the drift-guard test at line 303-342.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run the test `installer alias parity with onboard provider config — facet 1 drift guard` at line 303-342 — it exercises the full onboard key set against inference-set's map.
  • Evidence: NON_INTERACTIVE_PROVIDER_ALIASES at line 33 in onboard/providers.ts vs INSTALLER_PROVIDER_ALIASES at line 258 in inference-set.ts; drift guard test at lines 303-342

PRA-5 Resolve/justify — Provider normalization ordering correct — unrecognized aliases pass through for validation

  • Location: src/lib/actions/inference-set.ts:500
  • Category: correctness
  • Problem: The `normalizeInferenceSetProvider` function is called early in `runInferenceSetWithoutHostLock` (line 500), before `assertSupportedProvider`. This means an unrecognized provider alias (e.g., `totally-made-up`) passes through unchanged and is then rejected by `assertSupportedProvider` with the correct error message showing the original user input.
  • Impact: Good UX — error messages show what the user typed, not a normalized form.
  • Recommended action: No change required — behavior is correct and tested.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Test `passes an unrecognized provider through unchanged (validation still rejects it later)` at line 55 in inference-set-provider-alias.test.ts.
  • Missing regression test: Already covered.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Test `passes an unrecognized provider through unchanged (validation still rejects it later)` at line 55 in inference-set-provider-alias.test.ts.
  • Evidence: Line 500 (normalizeInferenceSetProvider call), line 501 (assertSupportedProvider), test at line 55

PRA-6 Resolve/justify — dcode hint uses shellQuote correctly for copy-paste safety

  • Location: src/lib/actions/inference-set.ts:543
  • Category: correctness
  • Problem: The dcode hint uses `shellQuote(sandboxName)` but the error message is thrown as a plain string, not passed through a shell. The hint is for copy-paste by the user, so shell quoting is appropriate. The test at line 273-274 verifies the quoted form appears in the error message and the bare name does not.
  • Impact: User gets a safe, copy-pasteable re-onboard command with properly quoted sandbox name.
  • Recommended action: No change required.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Test `shell-quotes the sandbox name in the dcode re-onboard hint` at line 258 in inference-set-provider-alias.test.ts.
  • Missing regression test: Already covered.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Test `shell-quotes the sandbox name in the dcode re-onboard hint` at line 258 in inference-set-provider-alias.test.ts.
  • Evidence: Lines 543-546 (hint construction), test at lines 258-280

PRA-7 Resolve/justify — Test file monolith — 563 lines mixing 5 distinct test concerns

  • Location: src/lib/actions/inference-set-provider-alias.test.ts:1
  • Category: architecture
  • Problem: New test file is 563 lines — a monolith growth flagged by drift context. It mixes unit tests for `normalizeInferenceSetProvider`, integration-style tests for `runInferenceSet`, SSRF guard behavior tests, dcode hint tests, and a drift-guard test that imports onboard's CJS module. This could be split into separate files for maintainability.
  • Impact: Reduced maintainability; harder to navigate and run focused test subsets; mixed test fixtures create coupling.
  • Recommended action: Split the test file into focused modules before merge: `normalize-provider.test.ts`, `provider-alias-e2e.test.ts`, `dcode-hint.test.ts`, `ssrf-guidance.test.ts`, `alias-drift-guard.test.ts`.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Review the test file structure — five distinct `describe` blocks with different concerns (normalization, e2e alias, dcode hint, SSRF guidance, drift guard).
  • Missing regression test: N/A — this is a test organization concern.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Review the test file structure — five distinct `describe` blocks with different concerns (normalization, e2e alias, dcode hint, SSRF guidance, drift guard).
  • Evidence: Test file has 5 describe blocks spanning 563 lines; drift context flagged monolith growth

PRA-8 Improvement — Provider alias map duplicated from onboard — extract to shared module

  • Location: src/lib/actions/inference-set.ts:258
  • Category: correctness
  • Problem: The `INSTALLER_PROVIDER_ALIASES` map duplicates provider alias mappings that exist in `onboard/providers.ts` (`NON_INTERACTIVE_PROVIDER_ALIASES` and `getEffectiveProviderName`). The comment acknowledges this and explains the `@ts-nocheck` onboard module isn't imported into the hot path. The drift-guard test mitigates divergence, but a shared config would be cleaner.
  • Impact: Maintenance burden; risk of drift despite test guard; violates DRY.
  • Suggested action: Extract provider alias mappings to a shared config file (e.g., `src/lib/inference/provider-aliases.ts`) imported by both onboard/providers.ts and inference-set.ts. This is a follow-up refactor, not a blocker for this PR.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare `INSTALLER_PROVIDER_ALIASES` (line 258) with `NON_INTERACTIVE_PROVIDER_ALIASES` and `getEffectiveProviderName` in onboard/providers.ts.
  • Missing regression test: Drift-guard test covers this.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: INSTALLER_PROVIDER_ALIASES at lines 258-285 in inference-set.ts; NON_INTERACTIVE_PROVIDER_ALIASES at line 33 and getEffectiveProviderName at line 103 in onboard/providers.ts

PRA-9 Required — Facet 2 acceptance met — docs state SSRF guard always validates, omit flag for model-only switch

  • Location: docs/inference/switch-inference-providers.mdx:45
  • Category: acceptance
  • Problem: Documentation now explicitly states: "Any `--endpoint-url` you do pass is always validated by the host-side SSRF guard, so a URL that resolves to a private or internal address is rejected even if it is the same one onboarding recorded; omit the flag to keep the established endpoint." This matches the code behavior and the acceptance criteria for facet 2.
  • Impact: Users correctly understand the guard behavior and the correct workaround (omit --endpoint-url).
  • Required action: No change required — docs accurately reflect the fix.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read the Compatible Endpoints section in the docs file (lines 45-48).
  • Missing regression test: N/A — documentation.
  • Done when: The required change is committed and verification passes: Read the Compatible Endpoints section in the docs file (lines 45-48).
  • Evidence: Lines 45-48 in switch-inference-providers.mdx

PRA-10 Required — Facet 1 acceptance met — docs show installer aliases work

  • Location: docs/inference/switch-inference-providers.mdx:36
  • Category: acceptance
  • Problem: Documentation adds "Installer Provider Aliases" section showing both `anthropicCompatible` and `compatible-anthropic-endpoint` work. This matches facet 1 acceptance.
  • Impact: Users discover they can use the same provider name they used during onboarding.
  • Required action: No change required.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read the Find the Provider Name section (lines 36-44) in switch-inference-providers.mdx.
  • Missing regression test: N/A — documentation.
  • Done when: The required change is committed and verification passes: Read the Find the Provider Name section (lines 36-44) in switch-inference-providers.mdx.
  • Evidence: Lines 36-44 in switch-inference-providers.mdx

PRA-11 Required — Facet 3 acceptance met — dcode hint provides actionable re-onboard command

  • Location: src/lib/actions/inference-set.ts:543
  • Category: acceptance
  • Problem: The dcode hint includes the re-onboard command with `--fresh` flag and references `NEMOCLAW_PROVIDER` / `NEMOCLAW_MODEL` env vars. This matches facet 3 acceptance: actionable next step instead of dead-end refusal.
  • Impact: Deep Agents users get a concrete path to change their model instead of a blunt refusal.
  • Required action: No change required.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read the error message construction at lines 543-546 in inference-set.ts.
  • Missing regression test: Covered by dcode hint tests at lines 158-182 and 258-280.
  • Done when: The required change is committed and verification passes: Read the error message construction at lines 543-546 in inference-set.ts.
  • Evidence: Lines 543-546 in inference-set.ts; tests at lines 158-182, 258-280

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: openclaw-inference-switch, hermes-inference-switch, inference-routing
Optional E2E: ubuntu-repo-cloud-langchain-deepagents-code, cloud-inference

Dispatch hint: openclaw-inference-switch,hermes-inference-switch,inference-routing

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • openclaw-inference-switch (high): Required because runInferenceSet is changed on the OpenClaw live route-switch path. This job onboards an OpenClaw sandbox, runs nemoclaw inference set, verifies the OpenShell route, OpenClaw config/hash, registry/session state, inference.local, and a real OpenClaw agent turn.
  • hermes-inference-switch (high): Required because the same inference-set implementation is used for Hermes route and in-sandbox config synchronization, including compatible endpoint and API-family behavior. This job validates Hermes runtime inference switching end to end.
  • inference-routing (medium): Required as the closest existing E2E coverage for inference routing security boundaries and custom endpoint fail-closed behavior. The PR changes endpoint URL validation/error handling before route mutation, so an existing live inference-routing security lane should run even though more targeted inference-set SSRF coverage is still missing.

Optional E2E

  • ubuntu-repo-cloud-langchain-deepagents-code (high): Optional adjacent confidence for the Deep Agents Code guidance change: the new inference-set refusal points users at re-onboarding, and this typed target exercises the DCode cloud onboarding/re-onboarding path, but it does not directly assert the new inference-set refusal message.
  • cloud-inference (medium): Optional broad sanity check that a hosted OpenClaw sandbox still reaches inference.local after the inference docs and command behavior changes; less targeted than the switch-specific jobs.

New E2E recommendations

  • inference provider alias compatibility (high): Existing live switch jobs appear to pass canonical provider IDs such as compatible-anthropic-endpoint, not installer aliases such as anthropicCompatible. Add a live OpenClaw inference-set case that onboards/configures a compatible Anthropic route, runs nemoclaw inference set --provider anthropicCompatible, and asserts OpenShell/registry/session store the canonical provider.
    • Suggested test: Add an openclaw-inference-switch matrix mode or focused live test for installer-provider-alias inference set.
  • inference-set SSRF pre-mutation boundary (high): The PR relies on unit coverage for the subtle security contract that every supplied --endpoint-url still hits DNS-pinning, same-provider SSRF rejection happens before OpenShell/registry/config mutation, and omitting --endpoint-url succeeds for a model-only switch. Existing inference-routing E2E covers adjacent endpoint fail-closed behavior but not this inference-set path.
    • Suggested test: Add a live or hermetic E2E for same-provider compatible-endpoint nemoclaw inference set --endpoint-url <internal-resolving URL> rejection with no persisted/gateway side effects, followed by a successful model-only switch without --endpoint-url.
  • Deep Agents Code inference-set refusal (medium): The changed dcode user-facing path is currently covered by unit tests and adjacent re-onboarding E2E, but no existing E2E appears to invoke nemoclaw inference set against a live langchain-deepagents-code sandbox and assert the actionable re-onboard hint.
    • Suggested test: Extend the DCode cloud target checks with a negative nemoclaw inference set invocation that asserts the re-onboard guidance and no sandbox mutation.

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: openclaw-inference-switch,hermes-inference-switch,inference-routing

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: openclaw-inference-switch
Optional E2E targets: hermes-inference-switch, docs-validation

Dispatch required E2E targets:

  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=openclaw-inference-switch

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • openclaw-inference-switch: The PR changes src/lib/actions/inference-set.ts, including provider-name normalization, custom endpoint/SSRF error handling, and inference-set registry/session mutation behavior. The openclaw-inference-switch free-standing live job is the smallest wired E2E path that runs nemoclaw inference set against a live OpenClaw sandbox and validates route, config/hash, registry/session, inference.local, and agent-turn behavior.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=openclaw-inference-switch

Optional E2E targets

  • hermes-inference-switch: Adjacent coverage for the same inference-set action on Hermes. Useful because the changed provider normalization and explicit custom-provider metadata flow are shared, while Hermes has separate in-sandbox config and runtime assertions.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=hermes-inference-switch
  • docs-validation: Optional validation for the updated inference-provider documentation in docs/inference/switch-inference-providers.mdx.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=docs-validation

Relevant changed files

  • docs/inference/switch-inference-providers.mdx
  • src/lib/actions/inference-set.ts

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings

Merge posture: No blocking advisor findings
Primary next action: Add or justify PRA-T1 and any related test follow-ups.
Open items: 0 required · 0 warnings · 1 suggestion · 3 test follow-ups
Top item: Remove the stale identity-match comment fragment

Action checklist

  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-1 In-scope improvement: Remove the stale identity-match comment fragment in src/lib/actions/inference-set.ts:552

Findings index

ID Severity Category Location Required action
PRA-1 Improvement docs src/lib/actions/inference-set.ts:552 Delete the stale fragment or replace it with a complete comment that only describes the current prefix-based SSRF guidance behavior.
Review findings by urgency: 0 required fixes, 0 items to resolve/justify, 1 in-scope improvement

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

  • None.

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

PRA-1 Improvement — Remove the stale identity-match comment fragment

  • Location: src/lib/actions/inference-set.ts:552
  • Category: docs
  • Problem: A dangling comment line, `// Canonical equality of an operator-supplied endpoint URL against the trusted,`, remains immediately before `ENDPOINT_URL_NOT_ALLOWED_PREFIX`. The identity-match bypass described by that fragment has been removed, while the following comment correctly documents the SSRF rejection prefix.
  • Impact: Readers auditing this trust-boundary code may spend time reconciling a removed equality-bypass design with the current behavior that validates every supplied endpoint URL.
  • Suggested action: Delete the stale fragment or replace it with a complete comment that only describes the current prefix-based SSRF guidance behavior.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Read `src/lib/actions/inference-set.ts` around `normalizeEndpointUrlShape()` and `ENDPOINT_URL_NOT_ALLOWED_PREFIX` and confirm there is no remaining incomplete identity-match comment.
  • Missing regression test: No new automated regression is needed for this comment-only cleanup; existing tests in `src/lib/actions/inference-set-provider-alias.test.ts` already verify same recorded internal endpoints are still DNS-guarded and rejected.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: The diff removes the same-endpoint bypass behavior, but the changed file still contains the incomplete comment immediately before `export const ENDPOINT_URL_NOT_ALLOWED_PREFIX = "endpoint-url is not allowed:";`.
Simplification opportunities: 1 possible cut, net -2 lines possible

These are safe simplification checks only. Do not remove validation, security controls, data-loss prevention, or required tests.

  • PRA-1 delete (src/lib/actions/inference-set.ts:552): The stale `// Canonical equality ... trusted,` comment fragment and its blank separator.
    • Replacement: Keep only the current `ENDPOINT_URL_NOT_ALLOWED_PREFIX` explanation, or replace the fragment with a complete current-behavior comment.
    • Net: -2 lines
    • Safety boundary: Do not remove the endpoint URL shape validation, DNS-pinning call, prefix constant, or SSRF negative tests.
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Runtime/integration: same-provider `compatible-endpoint` model switch without `--endpoint-url` preserves the existing gateway endpoint and updates only the selected model/registry/config.. Unit coverage is strong for the changed branches and security negatives, but the code mutates live OpenShell routes, sandbox registry state, and in-sandbox config, so one targeted runtime validation remains useful for confidence in the real gateway boundary.
  • PRA-T2 Runtime validation — Runtime/integration: explicit re-supply of an internal-resolving recorded endpoint rejects before OpenShell route mutation, registry update, config write, session update, audit append, or gateway restart.. Unit coverage is strong for the changed branches and security negatives, but the code mutates live OpenShell routes, sandbox registry state, and in-sandbox config, so one targeted runtime validation remains useful for confidence in the real gateway boundary.
  • PRA-T3 Runtime validation — Runtime/integration: `--provider anthropicCompatible` reaches OpenShell as `compatible-anthropic-endpoint` and persists the canonical provider name.. Unit coverage is strong for the changed branches and security negatives, but the code mutates live OpenShell routes, sandbox registry state, and in-sandbox config, so one targeted runtime validation remains useful for confidence in the real gateway boundary.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

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

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

141-155: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Keep installer aliases aligned with the onboard provider config

src/lib/actions/inference-set.ts: this local alias map duplicates src/lib/onboard/providers.ts, so it can drift when a provider name or alias changes. Derive it from the onboard config or add a parity check that covers both keys and values.

🤖 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 141 - 155, The local
INSTALLER_PROVIDER_ALIASES map in inference-set.ts is duplicating the onboard
provider aliases and can drift from the source of truth. Update the alias
handling in inference-set to derive from the onboard provider config in
providers.ts, or add a parity check that validates both keys and mapped values
stay in sync with that config. Use the INSTALLER_PROVIDER_ALIASES symbol and the
onboarding provider mapping as the single reference point for future alias
changes.

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.

Nitpick comments:
In `@src/lib/actions/inference-set.ts`:
- Around line 141-155: The local INSTALLER_PROVIDER_ALIASES map in
inference-set.ts is duplicating the onboard provider aliases and can drift from
the source of truth. Update the alias handling in inference-set to derive from
the onboard provider config in providers.ts, or add a parity check that
validates both keys and mapped values stay in sync with that config. Use the
INSTALLER_PROVIDER_ALIASES symbol and the onboarding provider mapping as the
single reference point for future alias changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c7cf92c1-f221-4e26-9a64-eb746fee87c5

📥 Commits

Reviewing files that changed from the base of the PR and between 34ed8fd and 069db65.

📒 Files selected for processing (2)
  • src/lib/actions/inference-set-provider-alias.test.ts
  • src/lib/actions/inference-set.ts

…facet 2)

Real-environment verification of the earlier identity-match attempt showed
it never fired: after a normal onboard the endpoint URL is NOT persisted to
the sandbox registry entry (entry.endpointUrl is null), the single
onboard-session.json is overwritten by the next onboard, and OpenShell does
not expose the gateway provider's registered base-URL value — so there is no
readable, per-sandbox durable endpoint to identity-match against. (The unit
tests passed only because they set entry.endpointUrl explicitly, masking the
gap.)

Replace the identity-match plumbing with guidance that does NOT weaken the
SSRF guard. Two facts make this the right shape:
  - `inference set` never repoints the OpenShell gateway (openshellInferenceSetArgs
    passes only provider + model); the endpoint is fixed at onboard time.
  - A same-provider model switch therefore does not need --endpoint-url at
    all — the gateway keeps the route onboard established.

So when normalizeCustomEndpointUrl's DNS-pinning guard blocks an internal
--endpoint-url AND the sandbox is already on that provider, append an
actionable hint: drop --endpoint-url to switch only the model (which reuses
the established route), and re-onboard/rebuild to actually change the
endpoint. The guard itself is unchanged — a genuinely new internal endpoint,
or a switch to a different provider, still errors with no bypass.

Verified end-to-end on a real test sandbox onboarded against an
internal-resolving Inference Hub endpoint:
  - facet 1: `inference set --provider custom` now switches the model
    (was "Unsupported provider 'custom'"); `anthropicCompatible` no longer
    rejected as unsupported.
  - facet 2: the same internal --endpoint-url is still blocked but now
    carries the omit-the-flag guidance; dropping the flag switches the model.
  - facet 3: dcode refusal carries the re-onboard hint.

Refs #6321

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
Comment thread src/lib/actions/inference-set-provider-alias.test.ts Fixed

@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.ts`:
- Around line 651-679: The same-provider hint is being appended to all
InferenceSetError cases from normalizeCustomEndpointUrl, which can produce
contradictory guidance for non-SSRF failures like the custom-metadata required
error. Update the catch in inference-set.ts so the extra “omit --endpoint-url”
message is only added for the SSRF/blocked-endpoint case, not every
InferenceSetError, by checking the specific error content or type before
wrapping it and leaving other normalizeCustomEndpointUrl errors 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: CHILL

Plan: Enterprise

Run ID: 1b30b96e-7990-4961-8927-94ff02b73326

📥 Commits

Reviewing files that changed from the base of the PR and between 069db65 and db0423a.

📒 Files selected for processing (2)
  • src/lib/actions/inference-set-provider-alias.test.ts
  • src/lib/actions/inference-set.ts

Comment thread src/lib/actions/inference-set.ts
…6321)

Rework the facet-2 test double and the alias-parity test to satisfy CI:

- The stand-in DNS-pinning guard now parses new URL(value).hostname and
  checks Set membership instead of a whole-URL substring match, so CodeQL
  no longer flags it as incomplete URL sanitization (a substring like
  "inference-api.nvidia.com" could otherwise appear anywhere in the URL).
- Replace the two `if` statements (the guard stub and the parity loop's
  skip guard) with a ternary and a .map().filter() chain so changed test
  files add no `if` statements, satisfying codebase-growth-guardrails.

No behavioral change to the fix under test; the 13 cases still pass.

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
…6321)

The catch in explicitCustomProviderMetadata augmented every InferenceSetError
from normalizeCustomEndpointUrl with the "omit --endpoint-url to switch only
the model" guidance. That helper also throws "endpoint-url is required for
custom-compatible metadata." when --credential-env or --inference-api is passed
without --endpoint-url on a same-provider sandbox, producing a self-
contradictory message ("endpoint-url is required ... omit --endpoint-url").

Gate the augmentation to the SSRF/DNS-pinning rejection only, via a shared
ENDPOINT_URL_NOT_ALLOWED_PREFIX constant, and add a test locking in that the
missing-URL error is left unaugmented (and the guard is never consulted).

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The safe alias/guidance change does not resolve the explicit same-URL provider switch that #6321 reports, so the PR should not claim to close every facet. Re-scope Closes to Refs and track durable endpoint identity separately rather than weakening SSRF. Correct the message that suggests a plain rebuild can choose another endpoint (rebuild has no endpoint flag and normally reuses recorded/session state), document the new aliases/recovery behavior, and add exact anthropicCompatible plus shell-metacharacter quoting tests. Rerun the Review Advisor afterward.

…x hint (#6321)

Address maintainer review on #6378:

- Correct the same-provider SSRF guidance message: re-running onboarding is
  what points a sandbox at a different endpoint; rebuild has no endpoint flag
  and reuses the recorded endpoint/session state, so it cannot change the
  endpoint. Update the user-facing message and the accompanying comment.
- Document the new installer provider aliases (e.g. anthropicCompatible ->
  compatible-anthropic-endpoint) and the same-provider model-switch recovery
  (omit --endpoint-url) in docs/inference/switch-inference-providers.mdx.
- Add tests: the installer alias is normalized to the exact canonical OpenShell
  provider name before it reaches the gateway argv, and the dcode re-onboard
  hint shell-quotes the sandbox name (defense-in-depth over name validation).

Refs #6321

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

@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-provider-alias.test.ts`:
- Around line 218-227: The test is treating the result of runInferenceSet as an
Error | InferenceSetResult union, so error.message is not safe to access
directly. Update the test to explicitly narrow the caught value from
runInferenceSet with an instanceof Error check (or equivalent type guard) before
asserting on message, using the runInferenceSet call and the error variable in
inference-set-provider-alias.test.ts as the key locations.
🪄 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: 986b4b8b-4771-42ca-9c45-11ae7ce09cee

📥 Commits

Reviewing files that changed from the base of the PR and between 7832449 and ad5205a.

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

Comment thread src/lib/actions/inference-set-provider-alias.test.ts Outdated
#6321)

Use rejects.toThrow(substring) instead of catching the promise: runInferenceSet
resolves to InferenceSetResult, so `.catch(... as Error)` typed the value as
`Error | InferenceSetResult` and `.message` failed strict typecheck. toThrow
does the same substring assertion without the union.

Refs #6321

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
…6321)

Address the Review Advisor follow-ups (PRA-1..3) on #6378:

- Add the structured design annotation (invalidState / sourceBoundary /
  whyNotSourceFix / regressionTest / removalCondition) to the facet-2 SSRF
  guidance branch, documenting why the fix is guidance rather than a source fix
  and the exact condition under which it should be replaced (a trusted,
  durable per-sandbox endpoint identity).
- Widen tests: the same-URL SSRF branch on the anthropicCompatible provider
  family (reporter's exact case) still hits the guard and emits guidance;
  assert no sandbox/config mutation occurs after the rejection; and assert the
  dcode hint's shellQuote layer neutralizes spaces, quotes, ';', '$()' and
  backticks (defense-in-depth over name validation).

Refs #6321

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
…ion (#6321)

Address Review Advisor PRA-2: add an expectNoInferenceMutation(deps.calls)
helper and use it in both same-provider SSRF-guidance tests, asserting none of
captureOpenshell, updateSandbox, writeSandboxConfig, recomputeSandboxConfigHash,
updateSession, appendAuditEntry, or restartSandboxGateway run after the guard
rejects — proving the security boundary leaves no half-applied state.

Refs #6321

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
…ity match (#6321)

Turn facet 2 from guidance into a real fix. Onboarding persists the endpoint it
established into the host-owned sandbox registry entry (entry.endpointUrl); that
is a trusted, per-sandbox, durable baseline the sandbox cannot forge.

explicitCustomProviderMetadata now canonically compares the operator-supplied
--endpoint-url against that trusted endpoint (passed only when the sandbox is
already on this provider). On a match it accepts the URL WITHOUT the DNS-pinning
SSRF guard — re-validating the exact route onboarding already established adds no
protection. Any mismatch, including a different internal endpoint, still runs the
full guard, and a same-provider sandbox still gets the omit---endpoint-url
guidance. Both sides are shape-normalized (no DNS); credentialed / non-http(s)
URLs never match and fall through to the guard.

Verified end-to-end on a real internal-resolving sandbox: re-supplying the
recorded internal URL now switches the model; a different internal URL is still
rejected; and the no-endpoint model switch still works.

Also refresh the docs note and add identity-match + different-internal-endpoint
regression tests.

Closes #6321

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
…explicit (#6321)

Address Review Advisor PRA-1/PRA-2 on the same-endpoint SSRF bypass: document,
in code beside the bypass, that the SSRF guard's threat model is the untrusted
sandbox agent; that the trusted `entry.endpointUrl` lives in the host-owned
registry the sandbox cannot write and is populated only by host onboarding/
rebuild (provider-recovery merely re-reads it, no sandbox-reachable writer); and
that host-level registry tampering is an accepted, out-of-threat-model risk (such
an attacker could call `inference set` directly), so no provenance marker is
warranted. Records the regression tests and the removal condition (a
sandbox-reachable or non-onboarding writer for endpointUrl would require one).

Refs #6321

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
@yanyunl1991

Copy link
Copy Markdown
Contributor Author

Thanks for the review — all points addressed, and facet 2 is now a real fix rather than guidance.

Review points

  • Closes vs Refs: moved to Refs initially per your note; facet 2 is now genuinely resolved (below), so the PR is back to Closes #6321.
  • Misleading rebuild message: corrected — re-running onboarding is what points a sandbox at a different endpoint; rebuild has no endpoint flag and reuses the recorded endpoint/session state. Message and comment updated.
  • Docs: documented the installer provider aliases (e.g. anthropicCompatible -> compatible-anthropic-endpoint) and the same-provider endpoint behavior in docs/inference/switch-inference-providers.mdx.
  • Tests: added exact alias normalization at the gateway boundary (the installer alias never reaches the openshell inference set argv), dcode-hint shell-quoting, no-mutation-after-rejection across all mutation/side-effect deps, and identity-match + different-internal-endpoint cases.

Facet 2 — now a durable-identity fix, no separate follow-up needed
The durable per-sandbox endpoint identity already exists: onboarding persists the established endpoint into the host-owned sandbox registry entry (entry.endpointUrl). explicitCustomProviderMetadata now canonically compares the supplied --endpoint-url against that value (only when the sandbox is already on the provider): an exact match is accepted without re-running the DNS-pinning guard, while any different endpoint — including a different internal one — still goes through the full guard. The earlier "entry.endpointUrl is null after onboard" observation was made against a checkout predating the registry-persistence change; on current main it is persisted, which is what makes the identity match sound.

Verified end-to-end on a real internal-resolving sandbox: re-supplying the recorded internal URL now switches the model; a different internal URL is still rejected; a no-endpoint model switch still works. The trust boundary — host-owned registry the sandbox cannot write, populated only by onboarding/rebuild, with host-level registry tampering explicitly out of the SSRF guard's threat model — is documented in code next to the bypass.

Re-ran the Review Advisor after each change (down to 0 required fixes).

@prekshivyas prekshivyas self-assigned this Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28884929483
Workflow ref: fix/inference-set-provider-alias-dcode-6321
Requested targets: (default — all supported)
Requested jobs: openclaw-inference-switch,hermes-inference-switch
Summary: 2 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-inference-switch ✅ success
openclaw-inference-switch ✅ success

@prekshivyas
prekshivyas requested a review from cv July 7, 2026 17:25
@prekshivyas

Copy link
Copy Markdown
Collaborator

@cv — maintainer follow-up confirming which of your requested changes the author has since implemented (verified against the current head dd4cea269e, not just the PR description):

  • Misleading "rebuild can choose another endpoint" message — ✅ fixed. inference-set.ts:734-735 now reads "To point the sandbox at a different endpoint, re-run onboarding with the new endpoint (rebuild reuses the recorded endpoint and cannot change it)", and the guidance hint at :520 matches.
  • Document new aliases / recovery behavior — ✅ added in docs/inference/switch-inference-providers.mdx.
  • Exact anthropicCompatible + shell-metacharacter quoting tests — ✅ present in inference-set-provider-alias.test.ts (13 anthropicCompatible assertions + a shellQuote metacharacter test on the dcode re-onboard hint, :219).
  • Track durable endpoint identity rather than weakening SSRF — ✅ addressed as you suggested. matchesTrustedEndpoint() (:558-571) shape-normalizes and accepts --endpoint-url only when it canonically equals the endpoint the host-owned registry recorded for this sandbox; a credentialed / non-http(s) / different URL never matches and still goes through the full DNS-pinning SSRF guard. The guard is not weakened for untrusted input — only the exact host-recorded endpoint is re-accepted, with a SOURCE_OF_TRUTH_REVIEW block (:679-706) and a regression test ("accepts the SAME endpoint … rejects a different internal one"). This is the advisor's PRA-1 item, and I consider it justified at that boundary (the registry is written only by onboarding/rebuild; registry tampering is already outside the SSRF guard's threat model).
  • Rerun the Review Advisor — ✅ done; re-ran on the current head (merge_after_fixes, PRA-1 now Resolve/justify).
  • Recommended live E2E — ✅ dispatched and passed: openclaw-inference-switch + hermes-inference-switch.

One open item is a genuine disagreement, not missing work: you asked to re-scope Closes #6321Refs; the author kept Closes, arguing Facet 2 is now a real fix (canonical-identity match) rather than only guidance. That is your call — if you still want Refs, I'll flip it.

If the above resolves your concerns, could you re-review / clear the change request? Everything else (CI, E2E, advisors) is green.

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

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Current-head rereview on dd4cea269e: the alias normalization, dcode quoting/guidance, no-side-effect rejection coverage, and onboarding-vs-rebuild wording are fixed, but the core SSRF request remains unresolved. matchesTrustedEndpoint() proves only normalized URL-string equality (inference-set.ts:552-571), and an exact match then skips normalizeCustomEndpointUrl/DNS pinning (:710-716). The trusted value is an untagged nullable registry string (selection.ts:47-66), and the comment claiming only onboarding/rebuild can populate it is factually false because this same inference-set action persists endpointUrl at inference-set.ts:948-969. The new test at inference-set-provider-alias.test.ts:350-388 explicitly locks in that the guard is never called. Please either remove this bypass while preserving the safe omit---endpoint-url guidance, or add machine-checkable onboarding provenance plus missing/mismatched-provenance negative tests. Also update the stale PR body, which currently contradicts the implemented bypass.

@github-actions github-actions Bot mentioned this pull request Jul 7, 2026
21 tasks
@wscurran wscurran added area: cli Command line interface, flags, terminal UX, or output area: providers Inference provider integrations and provider behavior bug-fix PR fixes a bug or regression integration: dcode LangChain Deep Code integration behavior security labels Jul 7, 2026
…pplied endpoints (#6321)

PR #6378 review (cv): the Facet-2 same-endpoint acceptance trusted a
registry endpoint string that inference set itself persists (not solely
onboarding/rebuild), so a string-equality match skipping DNS pinning was
self-authorizing — a value this command wrote could later authorize an
internal-resolving switch. Remove matchesTrustedEndpoint entirely; every
supplied --endpoint-url now goes through the host DNS-pinning SSRF guard.

The reporter's model-only switch is served by the safe path that already
exists: omit --endpoint-url to reuse the established endpoint (the guard's
rejection is turned into that guidance). Updated the locking test to assert
a re-supplied internal URL is rejected with omit-guidance and the guard runs,
and corrected the doc that claimed a re-supplied internal endpoint is accepted.

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@prekshivyas

prekshivyas commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

@cv — you were right, and my earlier confirmation was wrong: I repeated the author's "endpointUrl is populated ONLY by host-side onboarding/rebuild" justification without verifying it. It's false — this same inference set action persists endpointUrl (registryFieldsupdateSandbox), so the string-equality match was self-authorizing, exactly as you said. Thanks for the careful re-review.

Implemented your option (a) on head 4f005be22:

  • Removed the bypass entirely — deleted matchesTrustedEndpoint() and the trustedEndpointUrl plumbing. Every supplied --endpoint-url now goes through normalizeCustomEndpointUrl → the DNS-pinning SSRF guard, with no string-equality shortcut. (−111 lines.)
  • Preserved the safe path: omit --endpoint-url to reuse the established route for a model-only switch, and the SSRF rejection still turns into that actionable guidance.
  • Flipped the locking test (inference-set-provider-alias.test.ts): it now asserts a re-supplied internal URL is rejected with omit-guidance and the guard IS consulted (was: "accepts … guard never called").
  • Corrected the doc (switch-inference-providers.mdx) that claimed a re-supplied internal endpoint is accepted.
  • PR body: ClosesRefs #6321, and Facet 2 reframed as guidance rather than acceptance.
  • Recommended live E2E (openclaw-inference-switch, hermes-inference-switch) re-dispatched on the new head.

No provenance marker was added because the bypass is gone rather than gated. If you'd prefer to keep re-supply working via machine-checkable onboarding provenance instead, say so and I'll implement that path; otherwise this closes the SSRF concern outright. Could you re-review?

…moval (#6321)

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

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28888246145
Workflow ref: fix/inference-set-provider-alias-dcode-6321
Requested targets: (default — all supported)
Requested jobs: openclaw-inference-switch,hermes-inference-switch
Summary: 2 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-inference-switch ✅ success
openclaw-inference-switch ✅ success

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28889178520
Workflow ref: fix/inference-set-provider-alias-dcode-6321
Requested targets: (default — all supported)
Requested jobs: openclaw-inference-switch
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
openclaw-inference-switch ✅ success

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved exact head cb87b89. The prior string-equality SSRF bypass is removed, every supplied endpoint remains DNS/SSRF guarded, the linked issue acceptance has been corrected, CodeRabbit has no unresolved findings, and the primary PR Review Advisor is merge_as_is. All attached CI is green, and the required hosted and Anthropic-compatible OpenClaw inference-switch E2Es both passed in run 28889178520. The remaining stale-comment cleanup is nonblocking and can be handled separately without invalidating this exact-head evidence.

@cv
cv merged commit 376ebe2 into main Jul 7, 2026
121 checks passed
@cv
cv deleted the fix/inference-set-provider-alias-dcode-6321 branch July 7, 2026 19:12
@prekshivyas
prekshivyas requested a review from cv July 7, 2026 19:28
apurvvkumaria added a commit that referenced this pull request Jul 8, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Prepares the user-facing documentation for NemoClaw v0.0.76 and closes
the release-prep documentation gate. It adds the release highlights,
documents the arm64 Local NIM warning and expanded image cleanup
behavior, and fixes agent-specific command headings in generated guides.

## Changes

- Add the v0.0.76 release-notes section and move the shared-gateway
route containment entry out of the v0.0.74 history where it was
incorrectly placed.
- Document the advisory Linux arm64 Local NIM manifest warning in the
canonical platform matrix and local-inference guidance.
- Document that `gc` scans both gateway-built and locally prebuilt
sandbox image repositories.
- Keep OpenClaw and Hermes session headings out of the generated Deep
Agents command guide.
- Add a focused variant regression test for the agent-specific session
headings.

### Source summary

| Merged sources | Documentation coverage |
| --- | --- |
| [#6414](#6414),
[#6418](#6418),
[#6416](#6416),
[#6344](#6344) | v0.0.76 release
notes and the Deep Agents quickstart/inference routes |
| [#6340](#6340) | v0.0.76
release notes and existing Deep Agents observability guidance |
| [#6338](#6338),
[#6378](#6378),
[#6297](#6297) | v0.0.76 release
notes and existing inference/troubleshooting guidance |
| [#6362](#6362) | v0.0.76
release notes and existing lifecycle, command, and credential guidance |
| [#6330](#6330),
[#6307](#6307),
[#6008](#6008) | v0.0.76 release
notes and existing security, troubleshooting, and command guidance |
| [#6382](#6382) | v0.0.76
release notes and existing MCP/command guidance |
| [#6326](#6326),
[#5868](#5868),
[#5539](#5539) | v0.0.76 release
notes, platform matrix, inference options, and local-inference guidance
|
| [#6396](#6396),
[#6390](#6390),
[#6007](#6007) | v0.0.76 release
notes and existing messaging guidance |
| [#5388](#5388),
[#6249](#6249),
[#6303](#6303),
[#6306](#6306) | v0.0.76 release
notes and command/lifecycle guidance |

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] 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:

## Verification

- [x] PR description includes the DCO sign-off declaration 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 --project integration
test/generate-platform-docs.test.ts test/agent-variant-docs.test.ts
test/sync-agent-variant-docs.test.ts` (3 files, 29 tests passed)
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [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)

---
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


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

## Summary by CodeRabbit

* **Documentation**
* Added v0.0.76 release notes content, and removed an older conflicting
bullet from the surrounding release history.
* Expanded Local NVIDIA NIM guidance across inference/provider docs,
including an advisory for Linux arm64 DGX Spark/DGX Station hosts when a
matching `linux/arm64` image manifest is unavailable.
* Updated the command reference for correct session-section rendering
and clarified `gc` image cleanup sources.
* **Tests**
* Added coverage ensuring Deep Agents omits sessions headings while
Hermes includes them.
* **CI**
* Refreshed Local NVIDIA NIM provider notes used in the platform matrix.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
…VIDIA#6321) (NVIDIA#6378)

<!-- markdownlint-disable MD041 -->
## Summary
`nemoclaw inference set` was unusable in the three ways NVIDIA#6321 reports.
This PR fixes all three, each verified end-to-end on a real test sandbox
onboarded against an internal-resolving Inference Hub endpoint. Facet 2
is served by guidance, not by accepting a re-supplied internal endpoint:
`inference set` never skips the DNS-pinning SSRF guard for a supplied
`--endpoint-url` (trusting the recorded registry value would be
self-authorizing, since `inference set` itself persists it), and instead
guides the user to omit `--endpoint-url` to reuse the endpoint
onboarding established. A different internal endpoint is likewise
blocked. See the PR NVIDIA#6378 review thread.

- **Facet 1 — provider-name drift.** `onboard` accepts installer-style
keys (`anthropicCompatible`, `build`, `openai`, …); `inference set` only
accepted the OpenShell names. Normalize the installer alias to its
OpenShell name before validation.
- **Facet 2 — SSRF guard vs onboard.** `inference set --endpoint-url
<internal-hub>` was blocked by the DNS-pinning SSRF guard while onboard
accepted the same URL. The guard is correct and stays, and `inference
set` never skips it for a supplied `--endpoint-url`. Rather than accept
a re-supplied internal endpoint, the fix turns the dead-end into
guidance: on a same-provider sandbox, omit `--endpoint-url` to switch
only the model (the gateway keeps the route onboard established). A
different internal endpoint stays blocked.
- **Facet 3 — Deep Agents (dcode) refused with no next step.** dcode
bakes its model at image-build time, so it has no runtime inference-set
path. Keep the refusal, append an actionable re-onboard hint.

Refs NVIDIA#6321.

## Facet 2 — guidance, not a guard bypass (security-reviewed)
`inference set` never repoints the OpenShell gateway
(`openshellInferenceSetArgs` passes only provider + model), so a
same-provider **model** switch does not need `--endpoint-url` at all —
the gateway keeps the endpoint onboarding established. The DNS-pinning
SSRF guard therefore stays fully authoritative for every supplied
`--endpoint-url`; when it blocks an internal URL on a same-provider
sandbox, the error appends actionable guidance: drop `--endpoint-url` to
switch only the model, or re-onboard to change the endpoint.

> An earlier revision of this PR accepted the exact recorded endpoint
via a string-equality identity match against `entry.endpointUrl`
(skipping the guard on a match). **That was removed in review (PR
NVIDIA#6378):** `entry.endpointUrl` is not exclusively onboarding-provenanced
— this same `inference set` action persists it — so trusting the
recorded string to skip the guard would be self-authorizing (a value
this command wrote could later authorize an internal-resolving switch).
No provenance marker was added because the bypass is gone entirely
rather than gated.

Two facts shape the safe fix:
1. `inference set` never repoints the OpenShell gateway
(`openshellInferenceSetArgs` passes only provider + model); the endpoint
is fixed at onboard time.
2. A same-provider model switch therefore does **not** need
`--endpoint-url` at all — the gateway keeps the route onboard
established.

So the guard is unchanged. When it blocks an internal `--endpoint-url`
**and** the sandbox is already on that provider, the error now appends:
drop `--endpoint-url` to switch only the model (reuses the established
route), and re-onboard/rebuild to actually change the endpoint. A
genuinely new internal endpoint, or a switch to a different provider,
still errors with no bypass.

## Reproduction + Verification (real test machine)
Test host: Ubuntu 24.04 x86_64 (no GPU). `inference-api.nvidia.com`
resolves to an internal `10.48.x.x` address there (same condition as the
reporter's network), so the SSRF path is exercised for real. Fresh
sandboxes onboarded via `NEMOCLAW_PROVIDER=custom` (openclaw
`infra-6321`) and `--agent dcode` (`dcode-6321`).

**Before (v0.0.74, real sandboxes):**
```
# Facet 1
$ nemoclaw infra-6321 inference set --provider anthropicCompatible --model <m>
Unsupported provider 'anthropicCompatible'. Supported providers: ...
$ echo $?
2
$ nemoclaw infra-6321 inference set --provider custom --model <m>
Unsupported provider 'custom'. ...          (exit 2)

# Facet 2  (same Hub URL onboard just accepted; resolves to 10.48.203.205)
$ nemoclaw infra-6321 inference set --provider compatible-endpoint --endpoint-url https://inference-api.nvidia.com/v1 --model <m>
endpoint-url is not allowed: URL hostname "inference-api.nvidia.com" resolves to private/internal address "10.48.203.205". ...   (exit 2, dead-end)

# Facet 3
$ nemoclaw dcode-6321 inference set --provider nvidia-prod --model <m>
nemoclaw inference set supports OpenClaw and Hermes sandboxes; 'dcode-6321' uses 'langchain-deepagents-code'.   (exit 2, no next step)
```

**After (this branch, same real sandboxes):**
```
# Facet 1 — installer name accepted; same-provider switch succeeds
$ nemoclaw infra-6321 inference set --provider custom --model <m>
  Setting OpenShell inference route: compatible-endpoint / <m>
  Inference route synced for 'infra-6321': ...   (exit 0)

# Facet 2 — guard still fires, now with guidance
$ nemoclaw infra-6321 inference set --provider compatible-endpoint --endpoint-url https://inference-api.nvidia.com/v1 --model <m>
endpoint-url is not allowed: ... resolves to private/internal address "10.48.203.205". ...
  This sandbox is already configured for 'compatible-endpoint'. To switch only the model, omit --endpoint-url — inference set reuses the endpoint onboarding already established ... To point the sandbox at a different endpoint, re-run onboarding or rebuild.   (exit 2)
# ... and the guided path works:
$ nemoclaw infra-6321 inference set --provider compatible-endpoint --model <m>   (no --endpoint-url)
  Inference route synced for 'infra-6321': ...   (exit 0)

# Facet 3 — refusal now actionable
$ nemoclaw dcode-6321 inference set --provider nvidia-prod --model <m>
nemoclaw inference set supports OpenClaw and Hermes sandboxes; 'dcode-6321' uses 'langchain-deepagents-code'. Deep Agents Code bakes its model into the sandbox image at build time, so it has no runtime inference-set path. To change the model, re-onboard with the new selection: `nemoclaw onboard --agent dcode --name 'dcode-6321' --fresh` ...   (exit 2)
```

## Changes
- `src/lib/actions/inference-set.ts`:
- `normalizeInferenceSetProvider` + `INSTALLER_PROVIDER_ALIASES` —
accept the installer provider vocabulary onboard uses (facet 1);
persists the canonical OpenShell name.
- dcode branch of the unsupported-agent refusal appends a re-onboard
hint (facet 3); the target sandbox name is `shellQuote`d.
- `explicitCustomProviderMetadata` catches the SSRF-guard error and, for
a same-provider sandbox, appends the omit-`--endpoint-url` guidance
(facet 2). The guard is unchanged.
- `src/lib/actions/inference-set-provider-alias.test.ts` (new): 13 cases
— alias normalization + case/trim + passthrough + drift guard + **parity
vs onboard's `getEffectiveProviderName`**; `anthropicCompatible`
accepted end-to-end; dcode hint present / absent-for-other-agents; SSRF
guard still fires + guidance appended + omit-flag path succeeds + no
hint on provider switch.

## Type of Change
- [x] Code change (feature, bug fix, or refactor)

## Verification
- [x] `npx vitest run --project cli
src/lib/actions/inference-set-provider-alias.test.ts` — 13/13.
- [x] Full `src/lib/actions/inference-set*.test.ts` — 101/101 (no
regressions).
- [x] `npm run build:cli` passes; `npx prek run … --stage pre-commit`
clean (Biome + repository-checks).
- [x] End-to-end on a real test sandbox against an internal-resolving
endpoint (transcripts above): facet 1 switch succeeds, facet 2
guard-holds + guidance + omit-flag works, facet 3 hint present.
- [x] No secrets, API keys, or credentials committed.

## AI Disclosure
- [x] AI-assisted — tool: Claude Code

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>


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

* **New Features**
* Installer-style provider names are now accepted for inference-set
provider selection and automatically normalized to the canonical
provider.
* **Bug Fixes**
* Same-provider model-only switches can omit `--endpoint-url`; when
endpoint URLs are blocked, the error now guides users to omit
`--endpoint-url`.
* Deep Agents Code incompatibility errors now include a more specific
re-onboarding remediation hint.
* **Documentation**
* Added an “Installer Provider Aliases” section and clarified endpoint
URL omission behavior for model-only changes.
* **Tests**
* Added regression and parity checks to prevent provider alias/name
drift and validate error-message behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Prepares the user-facing documentation for NemoClaw v0.0.76 and closes
the release-prep documentation gate. It adds the release highlights,
documents the arm64 Local NIM warning and expanded image cleanup
behavior, and fixes agent-specific command headings in generated guides.

## Changes

- Add the v0.0.76 release-notes section and move the shared-gateway
route containment entry out of the v0.0.74 history where it was
incorrectly placed.
- Document the advisory Linux arm64 Local NIM manifest warning in the
canonical platform matrix and local-inference guidance.
- Document that `gc` scans both gateway-built and locally prebuilt
sandbox image repositories.
- Keep OpenClaw and Hermes session headings out of the generated Deep
Agents command guide.
- Add a focused variant regression test for the agent-specific session
headings.

### Source summary

| Merged sources | Documentation coverage |
| --- | --- |
| [NVIDIA#6414](NVIDIA#6414),
[NVIDIA#6418](NVIDIA#6418),
[NVIDIA#6416](NVIDIA#6416),
[NVIDIA#6344](NVIDIA#6344) | v0.0.76 release
notes and the Deep Agents quickstart/inference routes |
| [NVIDIA#6340](NVIDIA#6340) | v0.0.76
release notes and existing Deep Agents observability guidance |
| [NVIDIA#6338](NVIDIA#6338),
[NVIDIA#6378](NVIDIA#6378),
[NVIDIA#6297](NVIDIA#6297) | v0.0.76 release
notes and existing inference/troubleshooting guidance |
| [NVIDIA#6362](NVIDIA#6362) | v0.0.76
release notes and existing lifecycle, command, and credential guidance |
| [NVIDIA#6330](NVIDIA#6330),
[NVIDIA#6307](NVIDIA#6307),
[NVIDIA#6008](NVIDIA#6008) | v0.0.76 release
notes and existing security, troubleshooting, and command guidance |
| [NVIDIA#6382](NVIDIA#6382) | v0.0.76
release notes and existing MCP/command guidance |
| [NVIDIA#6326](NVIDIA#6326),
[NVIDIA#5868](NVIDIA#5868),
[NVIDIA#5539](NVIDIA#5539) | v0.0.76 release
notes, platform matrix, inference options, and local-inference guidance
|
| [NVIDIA#6396](NVIDIA#6396),
[NVIDIA#6390](NVIDIA#6390),
[NVIDIA#6007](NVIDIA#6007) | v0.0.76 release
notes and existing messaging guidance |
| [NVIDIA#5388](NVIDIA#5388),
[NVIDIA#6249](NVIDIA#6249),
[NVIDIA#6303](NVIDIA#6303),
[NVIDIA#6306](NVIDIA#6306) | v0.0.76 release
notes and command/lifecycle guidance |

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] 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:

## Verification

- [x] PR description includes the DCO sign-off declaration 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 --project integration
test/generate-platform-docs.test.ts test/agent-variant-docs.test.ts
test/sync-agent-variant-docs.test.ts` (3 files, 29 tests passed)
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [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)

---
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


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

## Summary by CodeRabbit

* **Documentation**
* Added v0.0.76 release notes content, and removed an older conflicting
bullet from the surrounding release history.
* Expanded Local NVIDIA NIM guidance across inference/provider docs,
including an advisory for Linux arm64 DGX Spark/DGX Station hosts when a
matching `linux/arm64` image manifest is unavailable.
* Updated the command reference for correct session-section rendering
and clarified `gc` image cleanup sources.
* **Tests**
* Added coverage ensuring Deep Agents omits sessions headings while
Hermes includes them.
* **CI**
* Refreshed Local NVIDIA NIM provider notes used in the platform matrix.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output area: providers Inference provider integrations and provider behavior bug-fix PR fixes a bug or regression integration: dcode LangChain Deep Code integration behavior

Projects

None yet

5 participants