Skip to content

fix(onboard): gate the packaged gateway service on the version window - #8098

Merged
senthilr-nv merged 16 commits into
mainfrom
fix/gateway-service-version-gate-8094
Aug 4, 2026
Merged

fix(onboard): gate the packaged gateway service on the version window#8098
senthilr-nv merged 16 commits into
mainfrom
fix/gateway-service-version-gate-8094

Conversation

@yanyunl1991

@yanyunl1991 yanyunl1991 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Linux onboarding now adopts the package-managed OpenShell gateway only when the effective binary selected by systemd is compatible with the blueprint version window.
It declines a known incompatible or untrusted package service, rechecks the version before changing service state, and continues through the marked-service or standalone fallback instead of pairing a supported CLI with an unsupported gateway.
Existing sandboxes can recover through a transactional rebuild when that compatibility decision moves NemoClaw-managed authority from the recorded package service to the standalone service; other authority changes remain fail-closed.

Related Issue

Closes #8094.
Closes #8103.

Changes

  • Read the trusted effective systemd ExecStart, probe that binary, and compare its version with min_openshell_version and max_openshell_version.
  • Reject positive evidence of an untrusted upstream unit or executable before version gating, then continue to the marked-service or standalone fallback.
  • Preserve above-maximum development builds when NEMOCLAW_OPENSHELL_CHANNEL=dev; keep an undetermined version eligible to preserve existing behavior.
  • Recheck the effective gateway version after systemctl --user daemon-reload and identity validation, before stop, enable, or restart; this resolves advisor finding PRA-1 and is protected by the startup race regression test.
  • Add regression coverage for below-minimum, above-maximum, in-window, development-channel, unknown-version, both-binary, untrusted-identity, marked-service fallback, warn-once, and pre-start version-change behavior.
  • Permit only the NemoClaw-managed packaged-service to standalone transition at the transactional rebuild journal, before managed MCP teardown, provider mutation, or sandbox deletion.
  • Keep credential mutation, ordinary gateway teardown, declarations, the reverse transition, target changes, and all other authority drift fail-closed.
  • Update docs/reference/architecture.mdx and docs/deployment/gateway-lifecycle-authority.mdx with the adoption, pre-start validation, fallback, and recovery contracts.
  • Product-scope approval: approved for revision 6737a54e5081449e4af06d3af3311cc9120307b4 on base a5562015029fd8cdbebdce5664e8b8bfda9d6ba8. This fixes the existing supported Linux onboarding and managed recovery paths accepted in DGX Spark Playbook: [NemoClaw] express onboarding fails when a different OpenShell is already installed (aborts at inference setup; should detect/align/coexist) #8094 and [DGX Spark][Sandbox] rebuild throws uncaught 'Gateway lifecycle authority changed' and deadlocks all recovery for a sandbox onboarded across the gateway-service migration #8103. It creates no new integration, recipe, image, third-party stack, or supported product surface. Existing NemoClaw ownership, OpenShell compatibility bounds, security validation, transactional rebuild, and managed MCP preservation remain the support boundary.

Type of Change

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

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification:
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: Security review completed for revision 6737a54e5081449e4af06d3af3311cc9120307b4 on base a5562015029fd8cdbebdce5664e8b8bfda9d6ba8; all nine categories pass with no findings. Trusted systemd paths bound version probing, the pre-start check runs before service-state mutation, and the recovery migration is one-way with complete owner equality apart from the source discriminator.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: docs-updated
  • Evidence: Updated docs/reference/architecture.mdx and docs/deployment/gateway-lifecycle-authority.mdx; independently reviewed all nine changed files against the writing guide, controlled terms, security meaning, and current base. npm run docs, route validation for 66 guarded pages, and git diff --check passed. Fern reported 0 errors and two existing suppressed warnings. OpenClaw, Hermes, and Deep Agents generated variants are synchronized.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit:
  • Station profile/scenario:
  • Result: Not applicable; scripts/prepare-dgx-station-host.sh is unchanged, and no DGX Station review is claimed.
  • Supporting evidence:

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub — all sixteen displayed commits are GitHub Verified at revision 6737a54e5081449e4af06d3af3311cc9120307b4 on base a5562015029fd8cdbebdce5664e8b8bfda9d6ba8.
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run validate:pr passed after refreshing origin/main when hooks were skipped or unavailable — canonical-base diff-aware pre-commit, commitlint, and pre-push stages passed; the non-force push also passed normal pre-push hooks.
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — vitest passed 92/92 focused gateway-service, authority, journal, and rebuild tests after refresh; npm run build:cli, npm --prefix nemoclaw run build, npm run typecheck:cli, npm --prefix nemoclaw run typecheck, and npm run checks:repository passed.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result: Not applicable; this focused onboarding authority and recovery change is covered at its resolver, transaction-journal, rebuild, service, compatibility, and pre-start mutation boundaries. GitHub required CI is authoritative.
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only) — passed with 0 errors and Fern's two existing suppressed warnings.
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

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

NemoClaw prefers the upstream package-managed `openshell-gateway.service`
whenever its unit file exists. That unit hard-codes an absolute ExecStart
under `/usr/bin`, so when preflight finds a packaged OpenShell outside the
blueprint version window and reinstalls a supported build into the
user-local bin directory, the service still starts the packaged binary.
Onboarding then drives a gateway it has already classified as unsupported:
on a host carrying OpenShell 0.0.91 the gateway never reaches health and
onboarding aborts, while the same host succeeds once the package is removed.

Adopt the packaged unit only when the packaged `openshell-gateway` binary
falls inside the blueprint range, and otherwise report it once and fall
through to NemoClaw's own managed service. The check sits in the single
resolver every consumer already routes through, so startup, status and
teardown authority all agree on which service is eligible. A packaged
binary whose version cannot be read is still adopted, keeping hosts that
work today unchanged.

Fixes #8094

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

coderabbitai Bot commented Aug 3, 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

Linux onboarding validates the packaged OpenShell gateway’s effective executable path and version before adoption. Known incompatible versions and untrusted binaries are rejected. Supported or indeterminate versions remain adoptable, with fallback to the NemoClaw-managed service when required.

Changes

Gateway version gating

Layer / File(s) Summary
Version validation and test seams
src/lib/onboard/docker-driver-gateway-service.ts, src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts
Adds blueprint version bounds, semantic version checks, injectable readers, diagnostics, warning-latch reset support, and tests for supported, unsupported, unresolved, and unreadable versions.
Linux service selection and fallback
src/lib/onboard/docker-driver-gateway-service.ts, src/lib/onboard/docker-driver-gateway-service.test.ts, src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts
Linux resolution validates the effective ExecStart path and trust identity. It rejects unsupported or untrusted package services, emits warnings once, and selects the NemoClaw-managed fallback.
Architecture documentation
docs/reference/architecture.mdx
Documents trusted executable checks, version outcomes, development-channel exceptions, and fallback versus hard-failure behavior.

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

Sequence Diagram(s)

sequenceDiagram
  participant LinuxServiceResolver
  participant checkUpstreamGatewayVersion
  participant PackagedGateway
  participant NemoClawManagedService
  LinuxServiceResolver->>LinuxServiceResolver: validate systemd ExecStart identity
  LinuxServiceResolver->>checkUpstreamGatewayVersion: check packaged gateway version
  checkUpstreamGatewayVersion->>PackagedGateway: read and parse executable version
  PackagedGateway-->>checkUpstreamGatewayVersion: supported, unsupported, or unknown
  checkUpstreamGatewayVersion-->>LinuxServiceResolver: return verdict
  LinuxServiceResolver->>NemoClawManagedService: select fallback when package service is rejected
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#8053: Adds OpenShell gateway version and path validation for existing Linux systemd services.
  • NVIDIA/NemoClaw#8106: Modifies managed gateway resolution and fallback behavior in the same service module.

Suggested labels: area: onboarding, bug-fix

Suggested reviewers: cv

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses version-mismatch fallback for #8094, but it does not implement the recovery fix required by directly linked #8103. Implement or merge the #8103 recovery fix before merging this PR, because version gating can change recorded gateway authority.
✅ Passed checks (4 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed The code, tests, and documentation changes remain focused on gateway version gating, trust validation, fallback behavior, and related diagnostics.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes gating the packaged gateway service by its supported version window.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/gateway-service-version-gate-8094

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

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

@github-code-quality

github-code-quality Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 6737a54 in the fix/gateway-service-... branch remains at 96%, unchanged from commit a556201 in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit 6737a54 in the fix/gateway-service-... branch remains at 81%, unchanged from commit a556201 in the main branch.

Show a code coverage summary of the most impacted files.
File main a556201 fix/gateway-service-... 6737a54 +/-
src/lib/domain/.../connect-env.ts 97% 89% -8%
src/lib/onboard...hell-version.ts 100% 97% -3%
src/lib/shields/index.ts 70% 70% 0%
src/lib/onboard...eway-service.ts 86% 86% 0%
src/lib/onboard...y-management.ts 96% 96% 0%
src/lib/sandbox...rce-identity.ts 88% 88% 0%
src/lib/onboard...wn-authority.ts 93% 97% +4%

Updated August 04, 2026 05:26 UTC

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

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

Model lanes

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

Advisory only. These are normalized differences from the primary terminology receipt.

  • managed-service at docs/deployment/gateway-lifecycle-authority.mdx:156: selected only by the second-opinion lane as define.
  • authority drift at docs/deployment/gateway-lifecycle-authority.mdx:158: selected only by the second-opinion lane as justified.
  • version window at src/lib/onboard/docker-driver-gateway-service.ts:38: selected only by the second-opinion lane as define.
  • trusted package paths at docs/reference/architecture.mdx:86: selected only by the second-opinion lane as define.
  • effective ExecStart at src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts:159: selected only by the second-opinion lane as define.
  • rebuild journal at src/lib/onboard/gateway-teardown-authority.ts:159: selected only by the second-opinion lane as define.
1 additional E2E selection from the second opinion

Advisory only. The primary lane did not select these E2E jobs or targets.

  • concurrent-gateway-ports: The completed second-opinion lane identified E2E coverage that the primary lane omitted.

Second-opinion terminology and E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate.

4 semantic terminology decisions

Terminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.

  • replace — managed lifecycle change at docs/deployment/gateway-lifecycle-authority.mdx:156: Replace with "managed-service migration" and name the permitted packaged-service-to-standalone direction.
  • justified — package-managed service at docs/deployment/gateway-lifecycle-authority.mdx:156: Retain the term because the modifier identifies the lifecycle-authority distinction.
  • define — effective binary at docs/reference/architecture.mdx:86: At first use, state that the effective binary is the binary named by systemd ExecStart.
  • established — standalone gateway fallback at docs/reference/architecture.mdx:95: Retain the established term.

E2E guidance

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

Recommended E2E: onboard-repair, onboard-resume, rebuild-openclaw, state-backup-restore, cloud-onboard

2 optional E2E recommendations
  • gateway-guard-recovery
  • openshell-gateway-upgrade

Workflow run details

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/lib/onboard/docker-driver-gateway-service.ts (1)

189-194: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Fold spawnSyncImpl into the Pick list instead of intersecting it separately.

spawnSyncImpl already exists on OpenShellGatewayUserServiceOptions (line 48). Add it to the Pick union instead of re-declaring its type in a separate intersection member; this avoids two places to keep in sync if the field's type ever changes.

♻️ Proposed refactor
 export function checkUpstreamGatewayVersion(
   opts: Pick<
     OpenShellGatewayUserServiceOptions,
-    "env" | "existsSync" | "getUpstreamGatewayVersion" | "getUpstreamGatewayVersionBounds"
-  > & { spawnSyncImpl?: SpawnSyncLike } = {},
+    | "env"
+    | "existsSync"
+    | "getUpstreamGatewayVersion"
+    | "getUpstreamGatewayVersionBounds"
+    | "spawnSyncImpl"
+  > = {},
 ): UpstreamGatewayVersionVerdict {
🤖 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/onboard/docker-driver-gateway-service.ts` around lines 189 - 194,
Update the parameter type of checkUpstreamGatewayVersion to include
"spawnSyncImpl" in the existing Pick list, and remove the separate intersection
member that redeclares SpawnSyncLike.
🤖 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/onboard/docker-driver-gateway-service-version-gate.test.ts`:
- Around line 38-47: Remove the three `if (verdict.supported) return` guards in
the affected test cases and replace their type-narrowing role with a TypeScript
assertion on `verdict` after the existing
`expect(verdict.supported).toBe(false)` checks. Keep the assertions and message
expectations unchanged so all test bodies remain linear.

---

Nitpick comments:
In `@src/lib/onboard/docker-driver-gateway-service.ts`:
- Around line 189-194: Update the parameter type of checkUpstreamGatewayVersion
to include "spawnSyncImpl" in the existing Pick list, and remove the separate
intersection member that redeclares SpawnSyncLike.
🪄 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: 58773904-034f-461e-8f16-d640bb0aba35

📥 Commits

Reviewing files that changed from the base of the PR and between a931be4 and e117aa2.

📒 Files selected for processing (3)
  • docs/reference/architecture.mdx
  • src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts
  • src/lib/onboard/docker-driver-gateway-service.ts

Comment thread src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts
The repository growth guardrail rejects newly added `if` statements in
test files. Assert the rejected verdicts with `toMatchObject` instead of
narrowing the result union with an early return.

Signed-off-by: yanyunl1991 <yanyunl@nvidia.com>
Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
cv
cv previously requested changes Aug 3, 2026

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

Security review for commit ab31092bb4bb713c709df15097e15df7d8666ec6 — FAIL

This commit is not approval-ready. Required GitHub checks pass for its recorded base, but the branch is behind current main and the implementation has two correctness and security-boundary defects.

  1. Secrets and credentials — PASS. No credential material is added.
  2. Input validation and data sanitization — PASS. Version commands use argument arrays, and version bounds are validated by existing helpers.
  3. Authentication and authorization — PASS. No authentication or authorization surface changes.
  4. Dependencies and third-party libraries — PASS. No dependency changes.
  5. Error handling and logging — WARNING. Version-probe failures return null and permit adoption without preserving an actionable explanation that version evidence was unavailable.
  6. Cryptography and data protection — PASS. No cryptographic behavior changes.
  7. Configuration and security headers — WARNING. The implementation deliberately adopts a managed gateway when its version cannot be determined. Because that gateway holds credentials and enforces policy, retaining this behavior needs explicit acceptance if it remains.
  8. Security testing — FAIL. Tests do not bind the checked version to the effective systemd ExecStart, do not cover both candidate binary paths existing, and do not cover the existing development-channel exception.
  9. System security — FAIL. getOpenShellGatewayUserServiceBinaryPaths orders /usr/local/bin before /usr/bin, and checkUpstreamGatewayVersion checks the first existing path. The resolver then adopts the unit from that verdict, while the effective ExecStart is parsed only later at lines 509–539. With both binaries installed, NemoClaw can approve one binary while systemd starts a below-minimum binary.

The comparison at lines 202–205 also always rejects a version above the blueprint maximum. Existing preflight preserves recognized development builds through shouldAllowOpenshellAboveBlueprintMax; the service resolver needs the same policy and a regression test.

The stated #8103 recovery prerequisite is unresolved: PR #8118 explicitly leaves the managed-MCP destroy deadlock outside its scope. The PR description also has no Documentation Writer Review receipt even though documentation changes.

Smallest safe next step: complete the #8103 recovery path, bind version validation to the effective systemd ExecStart, preserve the development-channel policy, add the missing tests, refresh from current main, and complete the independent documentation writer review. Then rely on required GitHub checks for the updated commit.

@copy-pr-bot

copy-pr-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

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

Security review for f1dc0936206b221c3770bd481011e8a84742ed92 on base 8c542b214f15561f71b262523d80a61ed4a5e9c7 — FAIL

The effective-ExecStart correction closes the previously reported binary-selection and development-channel defects. The change is not safe to merge yet because it can expose the unresolved #8103 recovery deadlock for existing sandboxes whose recorded gateway owner changes from packaged-service to standalone.

# Category Severity File:Line Description Recommendation
1 System security High src/lib/onboard/docker-driver-gateway-service.ts:483 Declining an out-of-window package gateway can change the live owner to standalone. Issue #8103 documents that existing sandboxes with recorded packaged-service authority can then lose every sanctioned recovery path when managed MCP state is present. Its linked PR #8118 explicitly leaves that case incomplete. Complete the accepted #8103 recovery prerequisite first. Then merge current upstream/main into this branch, rerun exact-head validation and reviews, and obtain new exact-head human approval.
  1. Secrets and credentials — PASS. No secret material, credential values, or new credential transport is added. The diff-aware gitleaks hook passed.
  2. Input validation and data sanitization — PASS. The gateway version command uses an argument array, the version parser accepts only a numeric semantic-version core, and the probed path comes from a trusted effective systemd identity.
  3. Authentication and authorization — PASS. No authentication or authorization contract changes. Existing service identity and trusted-path checks remain in force before lifecycle effects.
  4. Dependencies and third-party libraries — PASS. No package, image, download, or dependency changes.
  5. Error handling and logging — WARNING, accepted. An unreadable or unparsable version remains eligible without a new warning. This is an explicit, documented compatibility decision that preserves existing behavior and mirrors CLI preflight; service identity validation still fails closed. No follow-up is required for this issue-scoped fix.
  6. Cryptography and data protection — PASS. No cryptographic or persisted-data protection behavior changes.
  7. Configuration and security headers — WARNING, accepted. NEMOCLAW_OPENSHELL_CHANNEL=dev continues to allow a recognized above-maximum development build. This is the existing supported channel policy, now covered by a regression test. Browser security headers are outside this change.
  8. Security testing — PASS. Focused coverage binds validation to effective ExecStart, covers both candidate binaries existing, below-minimum, stable above-maximum, development above-maximum, in-window, unknown version, marked-service fallback, and warn-once behavior. The focused suite passed 52/52.
  9. System security — FAIL. The version and trust boundary is now correct, but the unresolved #8103 authority-transition recovery failure blocks safe merge sequencing.

Files reviewed: docs/reference/architecture.mdx, src/lib/onboard/docker-driver-gateway-service.ts, and src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts.

Product scope is separately approved for this exact head/base because the PR restores an existing supported Linux onboarding path under QA issue #8094 and creates no new supported product surface. That approval does not waive the #8103 correctness blocker.

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

Caution

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

⚠️ Outside diff range comments (1)
src/lib/onboard/docker-driver-gateway-service.ts (1)

486-511: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Reject an untrusted upstream systemd identity before version gating

When validateSystemdServiceIdentity returns trustFailure: true, do not convert the failure to null. checkUpstreamGatewayVersion(null, ...) returns supported: true, so the resolver adopts a foreign unit without warning. Decline the upstream unit and continue to the NemoClaw-managed fallback. Add a regression test for an untrusted FragmentPath or ExecStart.

🤖 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/onboard/docker-driver-gateway-service.ts` around lines 486 - 511,
Update the upstream service resolution around validateSystemdServiceIdentity and
checkUpstreamGatewayVersion so trustFailure immediately rejects the upstream
unit instead of passing null and treating it as supported. Preserve version
gating for trusted identities, continue to the NemoClaw-managed fallback, and
add a regression test covering an untrusted FragmentPath or ExecStart.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/lib/onboard/docker-driver-gateway-service.ts`:
- Around line 486-511: Update the upstream service resolution around
validateSystemdServiceIdentity and checkUpstreamGatewayVersion so trustFailure
immediately rejects the upstream unit instead of passing null and treating it as
supported. Preserve version gating for trusted identities, continue to the
NemoClaw-managed fallback, and add a regression test covering an untrusted
FragmentPath or ExecStart.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a0ae86c3-db6b-462a-9ed9-2f1aefd1a8a3

📥 Commits

Reviewing files that changed from the base of the PR and between 91dcadd and f1dc093.

📒 Files selected for processing (3)
  • docs/reference/architecture.mdx
  • src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts
  • src/lib/onboard/docker-driver-gateway-service.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts
  • docs/reference/architecture.mdx

@github-actions github-actions Bot added v0.0.102 Release target and removed v0.0.101 labels Aug 3, 2026

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

Security review for revision a71433ed93a2d1b298ace547fe05c7cee5945467 on base d756d15d867cdf91a90cad81971a8a29febe3002 — FAIL

The effective-ExecStart correction closes the previously reported binary-selection and development-channel defects. The change is not safe to merge yet because it can expose the unresolved #8103 recovery deadlock for existing sandboxes whose recorded gateway owner changes from packaged-service to standalone.

# Category Severity File:Line Description Recommendation
1 System security High src/lib/onboard/docker-driver-gateway-service.ts:485 Declining an out-of-window package gateway can change the live owner to standalone. Issue #8103 documents that existing sandboxes with recorded packaged-service authority can then lose every sanctioned recovery path when managed MCP state is present. Its linked PR #8118 remains open with changes requested and explicitly leaves that case incomplete. Complete the accepted #8103 recovery prerequisite first. Then merge current upstream/main into this branch, rerun revision-specific validation and reviews, and obtain new SHA-specific human approval.
  1. Secrets and credentials — PASS. No secret material, credential values, or new credential transport is added. The diff-aware gitleaks hook passed.
  2. Input validation and data sanitization — PASS. The gateway version command uses an argument array, the version parser accepts only a numeric semantic-version core, and the probed path comes from a trusted effective systemd identity. Positive evidence of a foreign unit or executable now rejects the upstream service before version gating.
  3. Authentication and authorization — PASS. No authentication or authorization contract changes. Existing service identity and trusted-path checks remain in force before lifecycle effects.
  4. Dependencies and third-party libraries — PASS. No package, image, download, or dependency changes.
  5. Error handling and logging — WARNING, accepted. An unreadable or unparsable version remains eligible without a new warning. This is an explicit, documented compatibility decision that preserves existing behavior and mirrors CLI preflight; service identity validation still fails closed. No follow-up is required for this issue-scoped fix.
  6. Cryptography and data protection — PASS. No cryptographic or persisted-data protection behavior changes.
  7. Configuration and security headers — WARNING, accepted. NEMOCLAW_OPENSHELL_CHANNEL=dev continues to allow a recognized above-maximum development build. This is the existing supported channel policy, now covered by a regression test. Browser security headers are outside this change.
  8. Security testing — PASS. Focused coverage binds validation to effective ExecStart, covers both candidate binaries existing, below-minimum, stable above-maximum, development above-maximum, in-window, unknown version, untrusted identity rejection, marked-service fallback, and warn-once behavior. The focused suite passed 53/53.
  9. System security — FAIL. The version and trust boundary is now correct, but the unresolved #8103 authority-transition recovery failure blocks safe merge sequencing.

Files reviewed: docs/reference/architecture.mdx, src/lib/onboard/docker-driver-gateway-service.ts, src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts, and src/lib/onboard/docker-driver-gateway-service.test.ts.

Product scope is separately approved for revision a71433ed93a2d1b298ace547fe05c7cee5945467 on base d756d15d867cdf91a90cad81971a8a29febe3002 because the PR restores an existing supported Linux onboarding path under QA issue #8094 and creates no new supported product surface. That approval does not waive the #8103 correctness blocker.

@senthilr-nv

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Security review for revision 5a981c3ed3e5a16425e04933472178d821fa2c6f on base 03fbf5ebf1dfc09506c5fefb1debe4b8766fde57 — FAIL

The effective-ExecStart correction closes the previously reported binary-selection and development-channel defects. The change is not safe to merge yet because it can expose the unresolved #8103 recovery deadlock for existing sandboxes whose recorded gateway owner changes from packaged-service to standalone.

# Category Severity File:Line Description Recommendation
1 System security High src/lib/onboard/docker-driver-gateway-service.ts:485 Declining an out-of-window package gateway can change the live owner to standalone. Issue #8103 documents that existing sandboxes with recorded packaged-service authority can then lose every sanctioned recovery path when managed MCP state is present. Its linked PR #8118 remains open with changes requested and explicitly leaves that case incomplete. Complete the accepted #8103 recovery prerequisite first. Then merge current upstream/main into this branch, rerun revision-specific validation and reviews, and obtain new SHA-specific human approval.
  1. Secrets and credentials — PASS. No secret material, credential values, or new credential transport is added. The diff-aware gitleaks hook passed.
  2. Input validation and data sanitization — PASS. The gateway version command uses an argument array, the version parser accepts only a numeric semantic-version core, and the probed path comes from a trusted effective systemd identity. Positive evidence of a foreign unit or executable now rejects the upstream service before version gating.
  3. Authentication and authorization — PASS. No authentication or authorization contract changes. Existing service identity and trusted-path checks remain in force before lifecycle effects.
  4. Dependencies and third-party libraries — PASS. No package, image, download, or dependency changes.
  5. Error handling and logging — WARNING, accepted. An unreadable or unparsable version remains eligible without a new warning. This is an explicit, documented compatibility decision that preserves existing behavior and mirrors CLI preflight; service identity validation still fails closed. No follow-up is required for this issue-scoped fix.
  6. Cryptography and data protection — PASS. No cryptographic or persisted-data protection behavior changes.
  7. Configuration and security headers — WARNING, accepted. NEMOCLAW_OPENSHELL_CHANNEL=dev continues to allow a recognized above-maximum development build. This is the existing supported channel policy, now covered by a regression test. Browser security headers are outside this change.
  8. Security testing — PASS. Focused coverage binds validation to effective ExecStart, covers both candidate binaries existing, below-minimum, stable above-maximum, development above-maximum, in-window, unknown version, untrusted identity rejection, marked-service fallback, and warn-once behavior. The focused suite passed 53/53.
  9. System security — FAIL. The version and trust boundary is now correct, but the unresolved #8103 authority-transition recovery failure blocks safe merge sequencing.

Files reviewed: docs/reference/architecture.mdx, src/lib/onboard/docker-driver-gateway-service.ts, src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts, and src/lib/onboard/docker-driver-gateway-service.test.ts.

Product scope is separately approved for revision 5a981c3ed3e5a16425e04933472178d821fa2c6f on base 03fbf5ebf1dfc09506c5fefb1debe4b8766fde57 because the PR restores an existing supported Linux onboarding path under QA issue #8094 and creates no new supported product surface. That approval does not waive the #8103 correctness blocker.

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

Security review for revision 62e231b48cebc381e38b49978b7dce9db6fd6cb1 on base 3fb4ac1d37bec961f494ca39faf996c990b9d06b — FAIL

The version and service-identity checks remain correct after the refresh. Approval is blocked because declining a package service can expose the open #8103 recovery deadlock for an existing sandbox with recorded packaged-service authority and managed MCP state.

# Category Severity File:Line Description Recommendation
1 System security High src/lib/onboard/docker-driver-gateway-service.ts:485 A rejected package gateway can change the resolved lifecycle authority to standalone. Issue #8103 documents that managed MCP state can then block rebuild, recreate, and destroy recovery paths. PR #8118 explicitly excludes that managed MCP recovery case. Complete the #8103 managed MCP recovery path before approval. Refresh this PR afterward and rerun revision-specific evidence.
  1. Secrets and credentials — PASS. The four-file diff adds no secret material or new credential transport.
  2. Input validation and data sanitization — PASS. The implementation validates the effective systemd unit and executable, uses argument arrays, and accepts only a numeric semantic-version core.
  3. Authentication and authorization — PASS. No authentication or authorization contract changes. Positive evidence of a foreign unit or executable rejects the package service before lifecycle effects.
  4. Dependencies and third-party libraries — PASS. The PR diff adds no dependency, image, package, or download.
  5. Error handling and logging — WARNING, accepted. A failed identity query or unreadable version preserves eligibility. This compatibility behavior is documented and keeps positive trust failures fail closed.
  6. Cryptography and data protection — PASS. No cryptographic or persisted-data protection behavior changes.
  7. Configuration and security headers — WARNING, accepted. NEMOCLAW_OPENSHELL_CHANNEL=dev preserves the existing above-maximum development-build policy. Browser headers are outside this change.
  8. Security testing — PASS. Focused tests cover both package binaries, trusted and untrusted identity, version boundaries, development builds, unknown versions, fallbacks, and warn-once behavior. The refreshed suite passed 53/53.
  9. System security — FAIL. The trust boundary is correct, but the resulting authority transition can expose the unresolved #8103 managed MCP recovery failure.

Files reviewed: docs/reference/architecture.mdx, src/lib/onboard/docker-driver-gateway-service.ts, src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts, and src/lib/onboard/docker-driver-gateway-service.test.ts.

Product scope is separately approved for this revision and base because the PR restores the existing supported Linux onboarding path described by #8094 and creates no new supported surface. That decision does not waive the #8103 security blocker.

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>

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

Verdict

PASS for revision 790b035ff against base 3fb4ac1d3. The recovery change permits only the one-way NemoClaw-managed packaged-service to standalone transition at the transactional rebuild boundary. The replacement journal persists the selected standalone authority before managed MCP, provider, or sandbox mutation. Credential mutation, ordinary teardown, declaration changes, reverse migration, target changes, and all other authority drift remain fail-closed. No actionable security finding remains in the reviewed diff.

Findings Table

No findings.

Detailed Analysis

  1. Secrets and Credentials — PASS. No secret, credential, token, key, or credential-bearing fixture was added. Commit hooks passed gitleaks.
  2. Input Validation and Data Sanitization — PASS. The migration accepts no new user input. It requires the canonical gateway target and complete owner equality after substituting only the source discriminator.
  3. Authentication and Authorization — PASS. Provider and credential authority checks are unchanged. Credential mutation continues to reject the migration.
  4. Dependencies and Third-Party Libraries — PASS. No dependency or artifact pin changed.
  5. Error Handling and Logging — PASS. The reported recovery path no longer raises the authority-drift error. Other drift continues to abort before gateway effects without exposing secrets.
  6. Cryptography and Data Protection — PASS. No cryptographic or persisted sensitive-data contract changed. The journaled authority remains secret-free.
  7. Configuration and Security Headers — PASS. No network, container, permission, endpoint, header, or policy configuration changed.
  8. Security Testing — PASS. Regression tests cover the permitted one-way migration and rejection of ordinary teardown, credential mutation, reverse migration, and declaration changes. The journal test confirms the standalone owner is persisted. Focused validation passed 94/94 tests.
  9. System Security — PASS. Both owners must remain nemoclaw-managed; gateway name, port, endpoint, state directory, supervisor, and required capabilities must match. Only packaged-service to standalone is accepted, and only for rebuild. The journal is written before MCP teardown, provider mutation, or sandbox deletion.

Files Reviewed

  • docs/deployment/gateway-lifecycle-authority.mdx
  • docs/reference/architecture.mdx
  • src/lib/actions/sandbox/rebuild-recreate-journal.test.ts
  • src/lib/actions/sandbox/rebuild-recreate-journal.ts
  • src/lib/onboard/docker-driver-gateway-service-version-gate.test.ts
  • src/lib/onboard/docker-driver-gateway-service.test.ts
  • src/lib/onboard/docker-driver-gateway-service.ts
  • src/lib/onboard/gateway-teardown-authority.test.ts
  • src/lib/onboard/gateway-teardown-authority.ts

Validation: focused tests 94/94; CLI and plugin builds; CLI type-check; repository checks; docs build and routes; pre-commit, commit-message, and pre-push hooks; diff check. Product scope is approved independently for the accepted #8094 compatibility fix and #8103 recovery path; no new supported integration or product surface is created.

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

Security review: PASS for current revision 6737a54e5 on base a55620150.

  • Secrets and credentials: PASS — no secret material or credential-handling expansion.
  • Injection and command execution: PASS — version probing is limited to the effective executable path already validated against trusted package paths; arguments are fixed.
  • Authentication and authorization: PASS — no authentication or permission boundary changes.
  • Network exposure and SSRF: PASS — no new listener, route, egress, or URL-input surface.
  • Filesystem and path safety: PASS — systemd unit and executable identities must match trusted normalized paths; foreign identities are declined.
  • Sandbox and privilege boundaries: PASS — no privilege, capability, mount, or sandbox-policy expansion.
  • Supply chain and dependencies: PASS — no dependency or artifact-source changes.
  • Denial of service and resource use: PASS — the additional pre-start version probe is bounded by the existing 10-second timeout.
  • Lifecycle and state integrity: PASS — the rebuild exception is one-way, requires full owner equality apart from packaged-service to standalone, and is checkpointed before managed MCP, provider, or sandbox mutation. Startup rechecks the package gateway version after daemon reload and identity validation, before stop, enable, or restart.

No actionable security finding remains. Product scope is independently approved by accepted issues #8094 and #8103; this repairs existing onboarding and rebuild behavior and creates no new supported surface.

@senthilr-nv

Copy link
Copy Markdown
Collaborator

Disposition: the stale CodeRabbit linked-issue warning for #8103 is resolved. Revision 790b035 added the one-way packaged-service-to-standalone rebuild authority migration and regression coverage; revision 6737a54 retains it on the refreshed base. The current advisor reports 0 blockers, 0 warnings, and 0 suggestions.

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

Reviewed Files changed for revision 6737a54. All findings are addressed and required validation passes. Approved.

@senthilr-nv
senthilr-nv dismissed cv’s stale review August 4, 2026 05:41

All requested changes addressed in revision 6737a54; validation refreshed.

@senthilr-nv senthilr-nv added bug-fix PR fixes a bug or regression area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: docs Documentation, examples, guides, or docs build area: security Security controls, permissions, secrets, or hardening security platform: linux Affects non-Ubuntu Linux environments labels Aug 4, 2026
@senthilr-nv
senthilr-nv merged commit 453b5df into main Aug 4, 2026
68 of 69 checks passed
@senthilr-nv
senthilr-nv deleted the fix/gateway-service-version-gate-8094 branch August 4, 2026 05:57
cv added a commit that referenced this pull request Aug 4, 2026
…8118)

<!-- markdownlint-disable MD041 -->
## Summary

`resolveGatewayEffectAuthority` refuses gateway effects when a sandbox's
recorded gateway owner no longer matches the live one. Three callers let
that refusal escape as an uncaught exception, so the CLI crashed with a
raw Node stack trace instead of naming the migration. This PR raises the
refusal as a typed error and reports it at those boundaries.

Related report: issue 8103. This PR implements only the accepted
reporting subset and does not close the remaining managed MCP recovery
scope.

## Reproduction

Executed on our DGX Spark aarch64 test host (GB10 GPU), Ubuntu 24.04,
against `main` at `4cd4d64fe`.

```bash
nemoclaw onboard --name repro-8103 --non-interactive --yes   # records the live authority
# reconstruct the pre-migration recording: source packaged-service, live standalone
nemoclaw repro-8103 rebuild --yes
nemoclaw repro-8103 destroy --yes --cleanup-gateway
```

**How the drift was produced.** The reporter's sandbox was onboarded
while the packaged `openshell-gateway.service` was authoritative, then
the managed gateway migrated to standalone. On our test host the
packaged gateway service cannot start at all for an unrelated reason
(its `EnvironmentFile` supplies a quoted `DOCKER_HOST`, so the value
reaches the process with the quotes and the socket URL is invalid), so
onboarding against it is not possible here. The recorded authority was
therefore set to `packaged-service` directly in the onboarding
checkpoint after a normal onboard, which reproduces the recorded-vs-live
drift this issue is about while leaving the sandbox, gateway, and
registry real.

**Observed on `main` (before fix)**

`rebuild --yes`:

```text
Error: Gateway lifecycle authority changed since onboarding (nemoclaw@8080:nemoclaw-managed:packaged-service -> nemoclaw@8080:nemoclaw-managed:standalone). Changing authority requires a fresh onboarding run; gateway teardown will not perform gateway effects.
    at resolveGatewayEffectAuthority (.../dist/lib/onboard/gateway-teardown-authority.js:80:15)
    at resolveGatewayTeardownAuthority (.../dist/lib/onboard/gateway-teardown-authority.js:87:12)
    at openRebuildRecreateJournal (.../dist/lib/actions/sandbox/rebuild-recreate-journal.js:73:88)
    ...
Node.js v22.22.2
```

`destroy --yes --cleanup-gateway` crashed the same way from
`cleanupGatewayAfterLastSandbox`. Both exited `1`.

**Observed on `fix/...` (after fix)** — same host, same commit, same
drifted state

`rebuild --yes` (exit `1`, zero stack-trace lines):

```text
  ✓ State backed up (12 directories, 1 files)
    Refusing sandbox rebuild because the gateway lifecycle authority could not be revalidated.
  Gateway lifecycle authority changed since onboarding (nemoclaw@8080:nemoclaw-managed:packaged-service -> nemoclaw@8080:nemoclaw-managed:standalone). Changing authority requires a fresh onboarding run; gateway teardown will not perform gateway effects.
  Re-run onboarding to bind the current gateway authority before retrying.
```

`destroy --yes --cleanup-gateway` (exit `0`, zero stack-trace lines,
registry empty afterwards):

```text
  Refusing shared gateway cleanup because the gateway lifecycle authority could not be revalidated.
  Gateway lifecycle authority changed since onboarding (...packaged-service -> ...standalone). ...
  Re-run onboarding to bind the current gateway authority before retrying.
  The shared NemoClaw gateway was left running.
  ✓ Sandbox 'repro-8103' destroyed
```

The verification script asserts the built `dist/` actually contains the
change before running, because an earlier attempt silently tested an
unpatched build.

## Analysis

`resolveGatewayEffectAuthority`
(`src/lib/onboard/gateway-teardown-authority.ts`) threw plain `Error`s.
`credentials/command-support.ts` was the only caller that caught them,
so `credentials add`/`reset` already reported the refusal cleanly. The
remaining callers did not:

- `rebuild-recreate-journal.ts` — reached from `rebuild --yes`
- `onboard-recreate-journal.ts` — reached from `onboard
--recreate-sandbox`
- `destroy-gateway.ts` — reached from the final-sandbox gateway cleanup

There is no process-level error boundary in the CLI entry, so each of
those escaped as an uncaught exception and printed a Node stack trace.

## Fix

- `GatewayAuthorityError` is a distinct type, so boundaries recognise
the refusal without matching message text. All four refusal sites in the
resolver raise it; an invalid management declaration deliberately keeps
its own type because it is a different failure class.
- `gatewayAuthorityFailureLines` is the single source of the wording
`credentialsGatewayAuthorityFailureLines` already used. The remedy line
is binary-agnostic so this module takes no branding dependency, which
the source-architecture budget counts against every consumer.
- The catches live in the two modules that already import the resolver,
so no new import edges are added. `rebuild-recreate-journal` hands the
lines back through a new `onAuthorityRefusal` callback and the pipeline
routes it to its existing `bail`.
- Shared gateway cleanup reports and returns instead of throwing. The
sandbox and its registry entry are already gone at that point, so
refusing the optional last step must not undo the removal.

**The #6576 contract is preserved.** The catch sits at the resolver
call, before any gateway effect, so nothing touches the gateway before
authority is proven — the existing test asserting no side effects still
passes unchanged, and a new case pins the same guarantee for the typed
refusal. Any failure that is not an authority refusal still aborts
outright.

## Scope

This does not close issue 8103. The report also describes `destroy
--yes` failing in MCP-bridge teardown with managed MCP servers present;
that path raises `McpBridgeError`, a different root cause this PR does
not touch. Our repro had no managed MCP servers and `destroy --yes`
without `--cleanup-gateway` already succeeded on `main`, so that half is
unverified here and left for a separate change.

## Interaction with #8098

#8098 makes NemoClaw decline a packaged gateway service whose binary is
outside the blueprint version window, moving the resolved owner from
`packaged-service` to `standalone`. That is exactly the drift this PR
reports on, so landing this first (or together) keeps existing sandboxes
on a working path.

## Changes

- `src/lib/onboard/gateway-teardown-authority.ts`: add
`GatewayAuthorityError` and `gatewayAuthorityFailureLines`; raise the
typed error from every refusal site.
- `src/lib/actions/sandbox/destroy-gateway.ts`: report an authority
refusal and skip cleanup instead of throwing.
- `src/lib/actions/sandbox/rebuild-recreate-journal.ts`: surface the
refusal through an `onAuthorityRefusal` callback.
- `src/lib/actions/sandbox/rebuild-pipeline.ts`: route that callback to
the existing `bail`.
- tests: regression coverage for the typed refusal, the shared wording,
and the preserved no-side-effect guarantee.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: Existing gateway lifecycle
authority and sandbox destroy documentation already describes the
unchanged fail-closed authority and optional cleanup boundaries; this PR
replaces raw stack traces with existing-pattern operator guidance.
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: Exact-head
nine-category security review at
`27a3a1f13c7be9b6a7ab87a73585b99ec6de11e4` against base
`e9fb170a2e3e4c4dcfa19e398232f71b8f2bace6`: PASS with no findings. Typed
refusals remain fail closed, unrelated and malformed-declaration errors
still propagate, diagnostics contain no credential material, and no
gateway effect runs before authority is proven. Base commit #8145
changes separate Docker-context inference validation and does not
interact with these typed errors.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `no-docs-needed`
- Evidence: Reviewed the complete eight-file diff at `27a3a1f13` against
base `e9fb170a2e3e4c4dcfa19e398232f71b8f2bace6`, stable patch ID
`2a1a9ce90bda5c03abf2788d381656fb42c301da`, and the NemoClaw writing
guide, controlled word list, documentation contributor guide, and shared
documentation-writing review contract. The change replaces raw Node.js
stack traces with existing-pattern operator guidance when gateway
lifecycle authority cannot be revalidated during rebuild, `onboard
--recreate-sandbox`, or final shared-gateway cleanup. It adds no
command, flag, default, configuration, schema, workflow, or supported
product surface. Existing documentation already states that authority
drift requires fresh onboarding and prevents gateway effects, while
command documentation describes final shared-gateway cleanup after
sandbox and registry deletion. Base commit #8145 adds credential-free
Windows Ollama validation from Docker's network context in separate
adapter and inference-selection files. It does not throw or consume
`GatewayAuthorityError` and does not interact with the changed
command-boundary handling. Exact-head validation passed: CLI and plugin
builds; 6 focused files and 104 tests; `npm run validate:pr`; and `git
diff --check`. No blocking findings.
- Agent: Codex Desktop documentation writer subagent
<!-- docs-review-head-sha: 27a3a1f -->
<!-- docs-review-agents-blob-sha: 3dd7c24 -->

## Verification

- [x] Exact-head maintainer validation at `27a3a1f13`: 6 focused files /
104 tests passed; CLI and plugin builds passed; `npm run validate:pr`
passed; `git diff --check` passed.
- [x] PR description includes a `Signed-off-by:` line and every current
commit appears as `Verified` in GitHub.

- [x] `npx prek run` passes on the changed files
- [x] `npm test` passes (640 files / 7228 tests under `src/lib/onboard`,
`src/lib/actions`, `src/lib/credentials`)
- [x] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [ ] Docs updated for user-facing behavior changes
- [ ] `make docs` builds without warnings (doc changes only)
- [ ] 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)

Platform scope: reproduced and verified on aarch64 (DGX Spark), matching
the reporter's environment. The changed code is platform-independent;
x86_64 was not exercised.

## 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

* **Bug Fixes**
* Improved gateway teardown handling when ownership or authority cannot
be confirmed.
* Shared gateways remain running when authority checks fail, preventing
unintended cleanup.
* Sandbox rebuilds now report authority refusals clearly and stop
safely.
  * CLI errors provide actionable details without exposing stack traces.
  * Unrelated errors continue to surface normally.
* Gateway authority failure messages are standardized for invalid or
changed authorization details.
* **Tests**
* Added coverage for authority changes, credential updates, invalid
targets, declined checkpoints, malformed errors, and safe cleanup
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: yanyunl1991 <yanyunl@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Prekshi Vyas <34834085+prekshivyas@users.noreply.github.com>
Co-authored-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: docs Documentation, examples, guides, or docs build area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: security Security controls, permissions, secrets, or hardening bug-fix PR fixes a bug or regression platform: linux Affects non-Ubuntu Linux environments security v0.0.102 Release target

Projects

None yet

3 participants