Skip to content

fix(sandbox): report gateway authority migration instead of crashing - #8118

Merged
cv merged 8 commits into
mainfrom
fix/gateway-authority-migration-8103
Aug 4, 2026
Merged

fix(sandbox): report gateway authority migration instead of crashing#8118
cv merged 8 commits into
mainfrom
fix/gateway-authority-migration-8103

Conversation

@yanyunl1991

@yanyunl1991 yanyunl1991 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

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.

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:

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):

  ✓ 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):

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

  • 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: 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.
  • 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: 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 fix(onboard): validate Windows Ollama from Docker #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

  • 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 fix(onboard): validate Windows Ollama from Docker #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

Verification

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

  • PR description includes a Signed-off-by: line and every current commit appears as Verified in GitHub.

  • npx prek run passes on the changed files

  • npm test passes (640 files / 7228 tests under src/lib/onboard, src/lib/actions, src/lib/credentials)

  • Tests added or updated for new or changed behavior

  • 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 (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

  • AI-assisted — tool: Claude Code

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

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.

Authority revalidation refuses gateway effects when the recorded owner no
longer matches the live one. Three callers let that refusal escape as an
uncaught exception: rebuild, `onboard --recreate-sandbox`, and the
final-sandbox gateway cleanup. Operators saw a raw Node stack trace, and
because rebuild and destroy both hit it, a sandbox recorded against the
packaged gateway service could not be rebuilt or removed after the managed
gateway migrated to the standalone service.

Raise the refusal as a typed `GatewayAuthorityError` so command boundaries
recognise it without matching message text, and reuse the wording
`credentialsGatewayAuthorityFailureLines` already used for the same
refusal. Rebuild now bails with that message through its existing `bail`
channel. Shared gateway cleanup reports it and leaves the gateway running:
the sandbox and its registry entry are already gone by then, so refusing
the optional last step must not undo the removal.

The #6576 guarantee is unchanged. Nothing touches the gateway before
authority is proven, and any failure that is not an authority refusal still
aborts outright.

Refs #8103

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

The change adds typed gateway authority refusals and standardized failure formatting. Sandbox teardown now skips cleanup when authority changes. Rebuild and onboarding flows report authority refusals before aborting. Tests cover migration, validation, formatting, teardown, and CLI behavior.

Changes

Gateway authority lifecycle handling

Layer / File(s) Summary
Typed authority refusals and validation
src/lib/onboard/gateway-teardown-authority.ts, src/lib/onboard/gateway-authority-migration.test.ts
Gateway authority validation now throws GatewayAuthorityError and formats refusal lines. Tests cover authority drift, invalid targets, unchanged authority, malformed declarations, and non-Error failures.
Gateway teardown refusal handling
src/lib/actions/sandbox/destroy-gateway.ts, src/lib/actions/sandbox/destroy-gateway.test.ts
Teardown logs authority refusals, keeps the shared gateway running, skips cleanup, and continues to propagate unrelated errors.
Rebuild refusal propagation
src/lib/actions/sandbox/rebuild-recreate-journal.ts, src/lib/actions/sandbox/rebuild-pipeline.ts
The rebuild journal reports formatted authority refusals to the abort handler before rethrowing the typed error.
Onboarding refusal reporting
src/lib/onboard/command.ts, src/lib/onboard/command.test.ts
Onboarding handles sandbox recreation authority refusals as clean nonzero CLI failures and suppresses stack traces. Tests verify refusal details and remediation guidance.

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

Sequence Diagram(s)

sequenceDiagram
  participant OnboardCommand
  participant RebuildJournal
  participant AuthorityResolver
  participant RebuildPipeline
  OnboardCommand->>RebuildJournal: open rebuild journal
  RebuildJournal->>AuthorityResolver: resolve gateway authority
  AuthorityResolver-->>RebuildJournal: GatewayAuthorityError
  RebuildJournal->>RebuildPipeline: pass formatted refusal lines
  RebuildPipeline->>RebuildPipeline: call bail
  RebuildJournal-->>OnboardCommand: rethrow authority refusal
  OnboardCommand->>OnboardCommand: emit clean nonzero CLI failure
Loading

Possibly related PRs

Suggested labels: area: sandbox, area: onboarding, bug-fix

Suggested reviewers: cv, sandl99

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: reporting gateway authority migration failures instead of allowing crashes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 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-authority-migration-8103

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

@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 db07335 in the fix/gateway-authorit... branch remains at 96%, unchanged from commit 643a4ab in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit db07335 in the fix/gateway-authorit... 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-authorit... db07335 +/-
src/lib/domain/.../connect-env.ts 97% 89% -8%
src/lib/policy/...ne-exclusion.ts 96% 92% -4%
src/lib/private-networks.ts 93% 90% -3%
src/lib/onboard...eway-service.ts 86% 86% 0%
src/lib/actions...all/run-plan.ts 83% 84% +1%
src/lib/inferen...ving/catalog.ts 91% 93% +2%
src/lib/onboard...eway-process.ts 95% 97% +2%
src/lib/state/g...way-registry.ts 94% 97% +3%
src/lib/onboard...eway-cleanup.ts 59% 66% +7%
src/lib/actions...ateway-ports.ts 0% 93% +93%

Updated August 04, 2026 06:15 UTC

@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: 2

🤖 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/gateway-authority-migration.test.ts`:
- Around line 138-148: Strengthen the assertion in the malformed-declaration
test for resolveGatewayTeardownAuthority to verify that the call actually
throws, while still confirming it is not a GatewayAuthorityError. Assert the
specific error type or message produced by
invalidGatewayManagementDeclarationError when available, rather than relying
only on not.toThrow(GatewayAuthorityError).

In `@src/lib/onboard/gateway-teardown-authority.ts`:
- Around line 71-76: Update runOnboardCommand to catch GatewayAuthorityError
thrown by openOnboardRecreateJournal before journaling, and report
gatewayAuthorityFailureLines(error, "sandbox recreate") at the onboard command
boundary. Add public-command coverage verifying the recreate-sandbox failure is
reported cleanly without escaping as an unhandled error.
🪄 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: 8774f243-5626-40f8-a59c-49e91bce7872

📥 Commits

Reviewing files that changed from the base of the PR and between 4cd4d64 and 0584acf.

📒 Files selected for processing (6)
  • src/lib/actions/sandbox/destroy-gateway.test.ts
  • src/lib/actions/sandbox/destroy-gateway.ts
  • src/lib/actions/sandbox/rebuild-pipeline.ts
  • src/lib/actions/sandbox/rebuild-recreate-journal.ts
  • src/lib/onboard/gateway-authority-migration.test.ts
  • src/lib/onboard/gateway-teardown-authority.ts

Comment thread src/lib/onboard/gateway-authority-migration.test.ts
Comment thread src/lib/onboard/gateway-teardown-authority.ts
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / low confidence
Next action: Review the warnings below.
Findings: 0 blockers · 1 warning · 0 suggestions
Status: Partial review preserved 1 canonical finding(s) and 3 terminology decision(s) before the advisor stopped.

Model lanes

  • GPT-5.6 Terra (primary): Failed after a partial review · low confidence · 0 blockers · 1 warning · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Failed after a partial review · low confidence · 0 blockers · 0 warnings · 0 suggestions

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

3 semantic terminology decisions

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

  • established — gateway lifecycle authority at src/lib/onboard/gateway-teardown-authority.ts:110: Keep the established term.
  • justified — authority refusal at src/lib/actions/sandbox/destroy-gateway.ts:100: Keep the term for the distinct revalidation outcome.
  • justified — typed refusal at src/lib/onboard/gateway-authority-migration.test.ts:60: Keep the modifier where the exception-class distinction affects error handling.

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

1 warning · 0 suggestions

Warnings

Warnings do not block.

PRA-1 Warning — Cover the rebuild authority-refusal boundary

  • Location: src/lib/actions/sandbox/rebuild-pipeline.ts:257
  • Category: correctness
  • Problem: The pipeline now converts a journal authority refusal into `bail`, but checked-in tests do not exercise this production boundary or prove that no destroy-phase action follows.
  • Impact: A regression in callback propagation could reintroduce a raw rebuild failure or allow later destructive work without checked-in coverage of the changed boundary.
  • Recommendation: Add a rebuild-pipeline regression test that makes authority resolution throw `GatewayAuthorityError`, asserts the formatted refusal reaches `bail`, and asserts `runRebuildDestroyPhase` is not called.
  • Verification: Inspect the pipeline test seam for `runRebuildDestroyPhase` and run the focused rebuild pipeline test after adding the authority-refusal case.
  • Test coverage: A production-pipeline test for a `GatewayAuthorityError` during journal creation that asserts `bail` receives the refusal lines and no sandbox deletion phase runs.
  • Evidence: src/lib/actions/sandbox/rebuild-pipeline.ts:248-272 opens the journal before `runRebuildDestroyPhase` and passes the callback to `bail`. src/lib/actions/sandbox/rebuild-recreate-journal.ts:115-122 invokes the callback only for `GatewayAuthorityError`, then rethrows. src/lib/actions/sandbox/rebuild-recreate-journal.test.ts:200-379 exercises journal state transitions but does not configure an authority refusal or assert the callback and no-destroy outcome.

Workflow run details

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

@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 0584acf566eac972d25fc776d3e8e6112a0c2a86 — FAIL

The accepted design in #6576 authorizes fail-closed gateway-authority revalidation and supports this limited reporting remediation. Issue #8103 is not accepted as authority to rebind ownership automatically, and this PR explicitly does not complete its remaining managed MCP destroy scope.

  1. Secrets and credentials — PASS. No secret values or credential material are added or exposed.
  2. Input validation and data sanitization — PASS. Gateway identity and recorded authority remain validated before gateway effects.
  3. Authentication and authorization — PASS. Authority drift remains fail closed; the patch changes reporting, not authorization.
  4. Dependencies and third-party libraries — PASS. No dependency, package, image, or download changes.
  5. Error handling and logging — FAIL. onboard --recreate-sandbox still reaches runOnboardCommand without a command-boundary handler for GatewayAuthorityError, so that path can still emit the raw stack trace this PR claims to replace. This matches current unresolved thread r3703127950. Add the command-boundary handling and a public-command regression.
  6. Cryptography and data protection — PASS. No cryptographic or persisted-secret behavior changes.
  7. Configuration and security headers — PASS. Gateway authority records retain their existing schema and fail-closed semantics; browser headers are outside this change.
  8. Security testing — FAIL. The malformed-declaration test uses not.toThrow(GatewayAuthorityError), which also passes if the call stops throwing entirely. Assert the expected non-authority error or message so the failure boundary is protected. This matches current unresolved thread r3703127942.
  9. System security — PASS. Rebuild and optional final gateway cleanup preserve the #6576 invariant that no gateway effect runs before authority is proven.

Required before approval: cover onboard --recreate-sandbox at the public command boundary; make the malformed-declaration assertion prove that a non-authority error still propagates; resolve both review threads; add current documentation writer and sensitive-path security review receipts. GitHub also lists this PR as closing #8103 even though the PR says it does not complete that issue. Remove that closing relationship unless the remaining accepted issue scope is implemented.

@github-actions github-actions Bot added v0.0.102 and removed v0.0.101 labels Aug 3, 2026
@prekshivyas prekshivyas self-assigned this Aug 3, 2026

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

Blocking at current head deda597: the supported onboard --recreate-sandbox path still crashes instead of reporting gateway authority migration, so the PR does not fulfill its stated purpose at all three public boundaries. openOnboardRecreateJournal calls resolveGatewayTeardownAuthority before journaling; packaged-service to standalone drift throws GatewayAuthorityError there. runOnboardCommand catches only GatewayManagementDeclarationError and prompt cancellation, then rethrows every other error, and src/lib/actions/onboard.ts only awaits it. Reproduction: invoke onboard --recreate-sandbox with persisted packaged-service authority while current discovery resolves standalone; the command emits an uncaught stack before destructive work. Catch GatewayAuthorityError at the onboard command boundary, render gatewayAuthorityFailureLines(error, "sandbox recreate") through the clean failure path, and add a public-command regression proving bounded guidance, no stack, and no destructive action. The mainline merge did not change this feature code; focused tests pass because they omit this public-command case.

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

Blocking at current head 27a3a1f: the explicit --recreate-sandbox case is fixed, but the documented environment-driven recreation path still crashes, so the PR does not yet fulfill its stated purpose. Reproduction: call runOnboardCommand with no recreate flag, env containing NEMOCLAW_RECREATE_SANDBOX=1, and a runOnboard dependency that throws GatewayAuthorityError. resolveOnboardOptions records recreateSandbox from the flag only in src/lib/onboard/command.ts, while runOnboard independently honors the environment request in src/lib/onboard.ts and can reach openOnboardRecreateJournal. The new catch guard is therefore false and rethrows the typed refusal into the raw stack path. Automatic drift-triggered recreation reaches the same journal without the flag as well. Please handle GatewayAuthorityError at the onboard command boundary regardless of how recreation was selected, or propagate the effective recreation intent to that boundary, and add a no-flag environment-path regression that asserts exit 1, recovery guidance, and no stack. The focused command and migration suites pass 52/52; the new test currently covers only the explicit flag case.

`handleOnboardCommandError` reported a `GatewayAuthorityError` only when
`options.recreateSandbox` was set, but that flag records the explicit
`--recreate-sandbox` selection alone. `runOnboard` independently honours
NEMOCLAW_RECREATE_SANDBOX and also enters the recreate journal when it detects
sandbox drift mid-run. Both of those selections left the guard false, so the
typed refusal was rethrown and surfaced as a raw Node stack trace — the exact
failure this PR set out to remove.

Drop the flag guard. Within onboarding the recreate journal's authority
revalidation is the only source of this typed error, so reporting it
unconditionally keeps the "sandbox recreate" label accurate however recreation
was selected, and reclassifies no other onboarding failure.

Cover all three selections with a table-driven regression asserting exit 1, the
bounded recovery guidance, and no stack frames. Mutation check: restoring the
flag guard fails the environment-request and drift cases while the
explicit-flag case still passes.

Refs #8103

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

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

Approve — re-reviewed exact head a5c60e4. The prior blocking environment-driven and drift-driven recreation crash is resolved: GatewayAuthorityError is now rendered at the onboard command boundary regardless of how recreation was selected, while unrelated errors still propagate. The table-driven regression covers the explicit flag, environment request, and drift paths with exit 1, bounded recovery guidance, and no stack. Exact-head build/typecheck, static checks, installer integration, security scans, and the completed test shards pass. The advisor’s request for an additional rebuild-journal callback test is a non-blocking coverage fast follow because the typed refusal is already caught before journal mutation and the existing resolver/command tests preserve that boundary. No blocking correctness, security, compatibility, or regression defect remains.

@copy-pr-bot

copy-pr-bot Bot commented Aug 4, 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.

@cv
cv merged commit e31a23a into main Aug 4, 2026
17 of 23 checks passed
@cv
cv deleted the fix/gateway-authority-migration-8103 branch August 4, 2026 07:27
@wscurran wscurran added area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression platform: arm64 Affects ARM64 or aarch64 architecture platform: dgx-spark Affects DGX Spark hardware or workflows labels Aug 4, 2026
apurvvkumaria added a commit that referenced this pull request Aug 4, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Prepares the canonical v0.0.102 release documentation from the current
release-labeled scope.
The change adds a dated changelog for all 38 user-facing shipping PRs
and corrects the OpenClaw agent command reference for the behavior
delivered by #8191.

## Changes

- Add `docs/changelog/2026-08-04.mdx` with the v0.0.102 release summary,
detailed behavior changes, support boundaries, security evidence links,
and links to durable documentation.
- Update `docs/reference/commands.mdx` to describe non-JSON OpenClaw
output capture, its combined limit, marker handling, stream suppression,
recovery guidance, and exit behavior.
- [#8167](#8167) ->
`docs/changelog/2026-08-04.mdx`: Records authenticated attachment of
operator-managed llama.cpp servers.
- [#8129](#8129) ->
`docs/changelog/2026-08-04.mdx`: Records the Experimental managed vLLM
profile for two DGX Spark systems.
- [#7983](#7983) ->
`docs/changelog/2026-08-04.mdx`: Records qualification of the May 2026
GB300WS factory image.
- [#8207](#8207) ->
`docs/changelog/2026-08-04.mdx`: Records the qualified DGX Station
driver transaction.
- [#8208](#8208) ->
`docs/changelog/2026-08-04.mdx`: Records mode-bound Express resume
state.
- [#8158](#8158) ->
`docs/changelog/2026-08-04.mdx`: Records recovery of host-global
dual-Station runtime ownership.
- [#8145](#8145) ->
`docs/changelog/2026-08-04.mdx`: Records Windows-host Ollama validation
from Docker Desktop's network context.
- [#8190](#8190) ->
`docs/changelog/2026-08-04.mdx`: Records HTTP model pulls when WSL has
no local Ollama executable.
- [#8195](#8195) ->
`docs/changelog/2026-08-04.mdx`: Records reuse of a healthy
installer-managed CLI.
- [#8053](#8053) ->
`docs/changelog/2026-08-04.mdx`: Records early rejection of incompatible
OpenShell gateway versions.
- [#8098](#8098) ->
`docs/changelog/2026-08-04.mdx`: Records the bounded
package-service-to-standalone gateway recovery transition.
- [#8216](#8216) ->
`docs/changelog/2026-08-04.mdx`: Records the final dashboard port
selected during multi-sandbox onboarding.
- [#8146](#8146) ->
`docs/changelog/2026-08-04.mdx`: Records managed startup-state
restoration for stopped sandboxes.
- [#8092](#8092) ->
`docs/changelog/2026-08-04.mdx`: Records gateway watchdog recovery for
classified not-serving states.
- [#8182](#8182) ->
`docs/changelog/2026-08-04.mdx`: Records consistent managed-recovery
wait configuration.
- [#8040](#8040) ->
`docs/changelog/2026-08-04.mdx`: Records Docker sandbox rollback
authority through late validation.
- [#8130](#8130) ->
`docs/changelog/2026-08-04.mdx`: Records bounded Shields deadline
recovery and durable containment.
- [#8086](#8086) ->
`docs/changelog/2026-08-04.mdx`: Records repair of narrowly validated
permission-only configuration drift.
- [#8122](#8122) ->
`docs/changelog/2026-08-04.mdx`: Records prompt failure and guidance for
corrupt transition locks.
- [#8124](#8124) ->
`docs/changelog/2026-08-04.mdx`: Records policy restoration flags,
previews, and target revalidation.
- [#7886](#7886) ->
`docs/changelog/2026-08-04.mdx`: Records explicit destruction after
pre-delete Shields hardening failures while preserving recovery
authority.
- [#7901](#7901) ->
`docs/changelog/2026-08-04.mdx`: Records multi-port uninstall behavior
and shared-resource preservation.
- [#7984](#7984) ->
`docs/changelog/2026-08-04.mdx`: Records one classified transient remote
MCP startup retry.
- [#7954](#7954) ->
`docs/changelog/2026-08-04.mdx`: Records bounded hosted-inference probe
replies.
- [#7574](#7574) ->
`docs/changelog/2026-08-04.mdx`: Records preservation of validated
reasoning capabilities through onboarding.
- [#8089](#8089) ->
`docs/changelog/2026-08-04.mdx`: Records proxy routing for Hermes
WhatsApp pairing and media traffic.
- [#7682](#7682) ->
`docs/changelog/2026-08-04.mdx`: Records native Hermes session deletion
and identifier validation.
- [#8150](#8150) ->
`docs/changelog/2026-08-04.mdx`: Records corporate CA trust for
LangChain Deep Agents Code image builds.
- [#8156](#8156) ->
`docs/changelog/2026-08-04.mdx`: Records reviewed managed runtime
dependency remediation.
- [#8180](#8180) ->
`docs/changelog/2026-08-04.mdx`: Records reviewed MCP discovery runtime
dependency updates.
- [#8196](#8196) ->
`docs/changelog/2026-08-04.mdx`: Records private npm dependency
remediation across managed images.
- [#8203](#8203) ->
`docs/changelog/2026-08-04.mdx`: Records reviewed Hermes and LangChain
Deep Agents Code Python dependency updates.
- [#8125](#8125) ->
`docs/changelog/2026-08-04.mdx`: Records bounded diagnostics for invalid
enumerated CLI values.
- [#8193](#8193) ->
`docs/changelog/2026-08-04.mdx`: Records bounded diagnostics for
unresolved sandbox base images.
- [#8118](#8118) ->
`docs/changelog/2026-08-04.mdx`: Records bounded diagnostics for changed
gateway authority.
- [#8191](#8191) ->
`docs/changelog/2026-08-04.mdx`, `docs/reference/commands.mdx`: Records
output capture, marker handling, recovery guidance, and exit behavior
for non-JSON OpenClaw agent commands.
- [#8187](#8187) ->
`docs/changelog/2026-08-04.mdx`: Records the aligned
interactive-installation start across supported agents.
- [#8153](#8153) ->
`docs/changelog/2026-08-04.mdx`: Records current product capabilities
and support boundaries.

## Type of Change

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

## Quality Gates

- [ ] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: This documentation-only
release preparation does not change executable behavior. Existing
changelog and published-route tests pass.
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `docs-updated`
- Evidence: Independently reviewed `docs/changelog/2026-08-04.mdx` and
`docs/reference/commands.mdx` at commit `b89913780`. All 38 user-facing
v0.0.102 PRs are represented, #8191 behavior matches the implementation,
and the writing rules, documentation style, controlled terminology,
route structure, and skip policy pass review. Targeted tests pass 36/36
and the documentation build completes with 0 errors.
- Agent: Codex Desktop independent documentation writer
<!-- docs-review-head-sha: b899137 -->
<!-- docs-review-agents-blob-sha: 3dd7c24 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit: Not applicable
- Station profile/scenario: Not applicable
- Result: Not applicable
- Supporting evidence: Not applicable

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run validate:pr` passed after refreshing `origin/main` 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/changelog-docs.test.ts test/check-docs-published-routes.test.ts`
passed 36/36.
- [x] Applicable broad gate passed — not applicable to
documentation-only changes; `npm run docs` completed successfully with 0
errors.
- [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 existing Fern warnings.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [x] New doc pages include SPDX header and frontmatter (new pages only)
— the native dated changelog uses the required parser-safe MDX SPDX
comment and intentionally has no frontmatter.

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


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

## Summary by CodeRabbit

- **Documentation**
- Added release notes for v0.0.102, covering authentication, hardware
setup, WSL, installer recovery, sandbox resilience, policy management,
inference reliability, CLI improvements, and unified quickstarts.
- Updated command documentation to explain how non-JSON agent output is
collected, replayed, and reported.

- **Bug Fixes**
- Improved command-output recovery guidance when output exceeds limits
or contains unsupported fallback markers.
- Preserved accurate command exit-status reporting after output
processing.

<!-- 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: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression platform: arm64 Affects ARM64 or aarch64 architecture platform: dgx-spark Affects DGX Spark hardware or workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants