Skip to content

fix(whatsapp): pair login over the loopback gateway and preserve npm plugin provenance#6645

Merged
cv merged 20 commits into
mainfrom
fix/whatsapp-login-loopback
Jul 11, 2026
Merged

fix(whatsapp): pair login over the loopback gateway and preserve npm plugin provenance#6645
cv merged 20 commits into
mainfrom
fix/whatsapp-login-loopback

Conversation

@hunglp6d

@hunglp6d hunglp6d commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes two stacked failures that made WhatsApp unusable on a stock install — pairing succeeded but the channel never ran:

Blast radius: the npm-pack change flows through the shared installer, so all externally-installed channels (whatsapp, discord, slack, msteams, weixin) plus diagnostics-otel/brave gain npm provenance; telegram is bundled and unaffected. Audited: trust flip is benefit-only (unblocks keyed stores that today crash or silently degrade), and the new install layout breaks no path assumption (details below).

Validated: WhatsApp end-to-end live on a fresh install — QR pair, no missing-scope, trusted record, channel running, real message round-trip. Control run on unfixed main on the same host still fails.

Blast-radius audit: why the npm-pack change is safe for the other channels

What actually changes for a channel plugin? Only two things: (1) the install ledger now says the plugin came from npm (name, exact version, integrity) instead of from an anonymous archive file, and (2) the plugin's files land under .openclaw/npm/projects/<hash>/node_modules/<pkg> instead of extensions/<id>. The tarball itself, and the integrity verification before installing it, are byte-for-byte the same as before.

Could the new ledger entry break anything? No — it only unlocks. The trusted-official-install check is the single consumer of this provenance, and today it fails for all five external channels. That is why WhatsApp crash-loops at startup (it opens openKeyedStore immediately), why Slack silently loses its duplicate-message protection across restarts, and why Discord's interactive buttons/modals lose their persistent state. With npm provenance the check passes and those features work as designed. Nothing consumes "archive" provenance as a positive signal, so nothing regresses.

Could the new file location break anything? We audited every place that could care about the old path:

  • Runtime patches/preloads: none match on extensions/<id>. The WhatsApp compact-QR preload recognizes the qrcode module by its shape, not its path.
  • Sandbox rebuild (backup/restore): the backup never includes npm/, so after a rebuild the plugin files and ledger always come from the freshly built image. The old extensions-restore logic simply sees "no extensions dir to preserve" and moves on — a state it already handles.
  • WeChat seed files: they are written to the state dir (~/.openclaw/openclaw-weixin/), not into the plugin's install dir, so the move doesn't touch them. WeChat's hand-written plugins.installs config entry keeps the old path, but the trust check never reads config — only the ledger — so the stale entry is inert.

Who is not affected at all? Telegram — it ships bundled inside the openclaw package, never goes through this installer, and was already trusted.

What was tested? WhatsApp end-to-end on a fresh install (the only channel that hard-fails today). The openclaw-lifecycle-policy contract test verifies every reviewed package spec installs through the new npm-pack: form.

Related Issue

Fixes #6413

Changes

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 — targeted replacement of the fix(whatsapp): reconcile post-pair gateway restart without operator.admin #6496 login machinery: removes gateway-token movement entirely (the reconcile helper and its config token reader are deleted), removes the readonly trust anchor that regressed DGX Spark/Station, and restores the pre-fix(whatsapp): reconcile post-pair gateway restart without operator.admin #6496 runtime-env emission; the ws:// scheme check on an explicitly exported OPENCLAW_GATEWAY_URL is retained.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification:
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result:
  • 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)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Hung Le hple@nvidia.com

Summary by CodeRabbit

  • Improvements
    • Updated OpenClaw plugin installation to use npm-pack: based installs, aligning provenance/version traces (replacing direct archive installs and --pin).
    • Adjusted Docker-based plugin installation to use the verified tarball install path that preserves npm provenance.
    • Refreshed WhatsApp pairing/login: defaults to in-sandbox loopback, accepts gateway URL overrides only for loopback ws:///wss://, and exports gateway tokens whenever available.
  • Documentation
    • Shortened WhatsApp sandbox guidance and added troubleshooting for gateway close code 1008.
  • Tests
    • Updated messaging/OpenClaw trace expectations for npm-pack: formats and revised WhatsApp guard coverage/fixtures to match the new pairing/token/exit-code behavior.

@copy-pr-bot

copy-pr-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 10, 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 switches OpenClaw plugin installs to npm-pack: archives and updates related tests. It also revises NemoClaw’s WhatsApp login wrapper, gateway environment handling, pairing validation, test coverage, and troubleshooting documentation.

Changes

OpenClaw plugin installation

Layer / File(s) Summary
npm-pack installation path
Dockerfile, src/lib/messaging/applier/build/messaging-build-applier.mts
Verified and messaging plugin installs now use npm-pack: archive specifications without conditional --pin arguments.
Installation contract validation
test/messaging-build-applier*.test.ts, test/openclaw-*.test.ts, test/sandbox-provisioning.test.ts
Trace, integrity, provisioning, lifecycle, and dependency assertions now match npm-pack installation arguments.

WhatsApp pairing flow

Layer / File(s) Summary
Gateway environment and login flow
scripts/nemoclaw-start.sh
Runtime token export, login option parsing, loopback URL validation, gateway selection, and conditional login environment setup are updated.
Pairing behavior coverage
test/nemoclaw-start-gateway-ws-host.test.ts, test/whatsapp-qr-compact.test.ts, test/repro-4538-raw-doctor-perms.test.ts
Tests cover loopback resolution, rejected non-loopback overrides, token handling, private URL behavior, shell handling, and exit-status preservation.
Pairing guidance
docs/manage-sandboxes/messaging-channels.mdx
WhatsApp documentation now describes URL validation, compact QR output, and close-code 1008 retry guidance.

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

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant NemoClawWrapper
  participant OpenClaw
  Operator->>NemoClawWrapper: channels login --channel whatsapp
  NemoClawWrapper->>NemoClawWrapper: validate loopback gateway override
  NemoClawWrapper->>OpenClaw: run WhatsApp login with conditional gateway environment
  OpenClaw-->>Operator: render pairing result
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR adds unrelated npm-pack provenance and messaging plugin changes that are not required by #6413. Move the plugin provenance and messaging installer updates to a separate PR or link the corresponding issue.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and matches the main WhatsApp loopback pairing and npm provenance changes.
Linked Issues check ✅ Passed The WhatsApp loopback pairing changes address the restart failure without operator.admin described in [#6413].
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/whatsapp-login-loopback

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

@github-code-quality

github-code-quality Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage remains at 96%, unchanged from the branch.

TypeScript / code-coverage/cli

The overall coverage in the branch remains at 78%, unchanged from the branch.

Show a code coverage summary of the most impacted files.
File e4d2e91 1b22b22 +/-
src/lib/inferen...er-lifecycle.ts 68% 62% -6%
src/lib/shields/seal.ts 88% 100% +12%

Updated July 11, 2026 08:00 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: cloud-onboard, channels-add-remove, channels-stop-start, issue-4462-scope-upgrade-approval
Optional E2E: brave-search, whatsapp-qr-compact-e2e

Dispatch hint: cloud-onboard,channels-add-remove,channels-stop-start,issue-4462-scope-upgrade-approval

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • cloud-onboard: Required by the deterministic risk plan for Dockerfile/platform-install changes; validates clean hosted onboarding against the changed image build and pinned runtime dependency path.
  • channels-add-remove: Required by the deterministic risk plan for messaging build-applier changes; validates real add, rebuild, policy-list, credential reuse, and remove lifecycle after plugin install provenance changes.
  • channels-stop-start: Required by the deterministic risk plan for messaging lifecycle changes; validates configured channels survive stop/start toggles, rebuilds, policy state, and runtime config across OpenClaw/Hermes channel paths.
  • issue-4462-scope-upgrade-approval: The start script changes connect-session gateway URL/token export and OpenClaw wrapper dispatch. This live test exercises the real sandbox gateway-token boundary, absence of public URL leakage, and device/scope approval behavior.

Optional E2E

  • brave-search: Useful adjacent coverage because the Dockerfile also changes reviewed non-messaging OpenClaw plugin installation through npm-pack provenance for the Brave plugin path.
  • whatsapp-qr-compact-e2e: Optional regression confirmation for the WhatsApp pairing user flow documentation area; this existing regression job covers QR rendering only, not the changed gateway-token/pairing restart boundary.

New E2E recommendations

  • whatsapp-pairing-gateway-token-boundary (high): No existing live E2E appears to exercise openclaw channels login --channel whatsapp inside a NemoClaw sandbox through the new loopback-default gateway path, including rejection of non-loopback explicit OPENCLAW_GATEWAY_URL and successful post-pair channel restart without leaking the gateway token.
    • Suggested test: Add a focused WhatsApp pairing gateway-boundary E2E using a deterministic/mockable OpenClaw WhatsApp login or gateway RPC harness so it can validate token withholding and restart behavior without requiring a real phone QR scan.

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: cloud-onboard,channels-add-remove,channels-stop-start,issue-4462-scope-upgrade-approval

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: cloud-onboard, channels-add-remove, channels-stop-start
Optional E2E targets: openclaw-slack-pairing, openclaw-discord-pairing

Dispatch required E2E targets:

  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=cloud-onboard
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=channels-add-remove
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=channels-stop-start

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • cloud-onboard: Installer and platform changes must work on a clean supported host with the pinned runtime dependencies.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=cloud-onboard
  • channels-add-remove: Messaging changes must preserve the manifest-to-policy-to-runtime lifecycle through restart and removal.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=channels-add-remove
  • channels-stop-start: Messaging changes must preserve the manifest-to-policy-to-runtime lifecycle through restart and removal.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=channels-stop-start

Optional E2E targets

  • openclaw-slack-pairing: Optional adjacent coverage for OpenClaw messaging plugin install provenance changes, especially plugin-backed channel pairing/runtime startup behavior beyond the required lifecycle jobs.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=openclaw-slack-pairing
  • openclaw-discord-pairing: Optional adjacent coverage for OpenClaw messaging plugin install provenance changes across another plugin-backed channel pairing path.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=openclaw-discord-pairing

Relevant changed files

  • Dockerfile
  • scripts/nemoclaw-start.sh
  • src/lib/messaging/applier/build/messaging-build-applier.mts

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Changes requested

Merge posture: Do not merge yet
Primary next action: Fix PRA-1: Unmet acceptance clause: #6413 required automatic reload or recovery command; then add or justify PRA-T1.
Open items: 16 required · 9 warnings · 0 suggestions · 8 test follow-ups
Top item: Unmet acceptance clause: #6413 required automatic reload or recovery command

Action checklist

  • PRA-1 Fix: Unmet acceptance clause: fix(whatsapp): post-pair gateway restart fails without operator.admin #6413 required automatic reload or recovery command in scripts/nemoclaw-start.sh:3580
  • PRA-2 Fix: Caller/callee contract drift: --account flag silently ignored in scripts/nemoclaw-start.sh:3540
  • PRA-5 Fix: Risk plan required jobs not implemented as checked-in tests in test/sandbox-provisioning.test.ts:1
  • PRA-6 Fix: Source-of-truth workaround: Loopback-only pairing assumes unverified OpenClaw gateway locality behavior in scripts/nemoclaw-start.sh:3400
  • PRA-8 Fix: Unmet acceptance clause: fix(whatsapp): post-pair gateway restart fails without operator.admin #6413 required automatic reload or recovery command in scripts/nemoclaw-start.sh:3580
  • PRA-9 Fix: Error handling collapse: 5 distinct error branches reduced to 1 generic branch in scripts/nemoclaw-start.sh:3580
  • PRA-10 Fix: Caller/callee contract drift: --account flag silently ignored in scripts/nemoclaw-start.sh:3540
  • PRA-11 Fix: Source-of-truth workaround: Loopback-only pairing assumes unverified OpenClaw gateway locality behavior in scripts/nemoclaw-start.sh:3400
  • PRA-14 Fix: State transition gap: No post-login channel-active verification in scripts/nemoclaw-start.sh:3580
  • PRA-15 Fix: Security test coverage regression: 7 gateway trust anchor SSRF defense tests deleted with zero replacements in test/nemoclaw-start-gateway-ws-host.test.ts:1
  • PRA-3 Resolve or justify: Breaking change: Explicit OPENCLAW_GATEWAY_URL override restricted to loopback hosts only in scripts/nemoclaw-start.sh:3540
  • PRA-4 Resolve or justify: Simplification: Gateway trust anchor replaced by native case-statement token gating in scripts/nemoclaw-start.sh:3632
  • PRA-7 Resolve or justify: Source-of-truth workaround: NODE_OPTIONS preload injection for non-connect shells lacks regression test and removal tracker in scripts/nemoclaw-start.sh:3632
  • PRA-12 Resolve or justify: Source-of-truth workaround: NODE_OPTIONS preload injection for non-connect shells lacks regression test and removal tracker in scripts/nemoclaw-start.sh:3632
  • PRA-13 Resolve or justify: Breaking change undocumented: Explicit OPENCLAW_GATEWAY_URL override restricted to loopback hosts only in scripts/nemoclaw-start.sh:3540
  • PRA-16 Resolve or justify: Input validation regression: --account flag validation removed, caller input passes unvalidated to OpenClaw in scripts/nemoclaw-start.sh:3540
  • PRA-17 Resolve or justify: Unverified security assumption: Loopback-only pairing relies on unconfirmed OpenClaw gateway locality behavior in scripts/nemoclaw-start.sh:3400
  • PRA-18 Resolve or justify: Workaround without regression test: NODE_OPTIONS preload injection for non-connect shells in scripts/nemoclaw-start.sh:3632
  • PRA-25 Resolve or justify: Workaround regression tests missing: NODE_OPTIONS preload injection and loopback-only assumption in scripts/nemoclaw-start.sh:3632
  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Risk plan required jobs not implemented as checked-in tests
  • PRA-T5 Add or justify test follow-up: Security test coverage regression: 7 gateway trust anchor tests deleted, 0 replacements for new token gating
  • PRA-T6 Add or justify test follow-up: Missing tests for --account flag validation removal
  • PRA-T7 Add or justify test follow-up: Error handling collapse: 5→1 branches with 0 negative tests
  • PRA-T8 Add or justify test follow-up: No post-login channel-active verification test

Findings index

ID Severity Category Location Required action
PRA-1 Required scope scripts/nemoclaw-start.sh:3580 Either verify OpenClaw 2026.6.10's loopback-origin channels.start succeeds without operator.admin (with code comment linking to OpenClaw source), or add nemoclaw channels/gateway restart command as explicit recovery path per #6413.
PRA-2 Required scope scripts/nemoclaw-start.sh:3540 Restore account ID validation (allowlist [A-Za-z0-9._:-], max 128 chars) in the WhatsApp login block before invoking openclaw channels login --account. Either forward the validated account ID or explicitly reject the flag with a clear error if not supported.
PRA-3 Resolve/justify scope scripts/nemoclaw-start.sh:3540 Add migration note to docs/changelog: explicit gateway overrides now restricted to loopback hosts only. Consider if an escape hatch is needed for legitimate remote gateway use cases, or document as intentional security hardening.
PRA-4 Resolve/justify architecture scripts/nemoclaw-start.sh:3632 Acknowledge this simplification as a security improvement. Add focused unit tests for the new case-based token gating: (1) token emitted when URL empty, (2) token emitted for loopback URLs, (3) token withheld for userinfo URLs, (4) token withheld for non-loopback URLs, (5) token withheld for malformed URLs.
PRA-5 Required scope test/sandbox-provisioning.test.ts:1 Implement the three required E2E tests as checked-in Vitest tests that can run in CI without external dependencies. At minimum: channels-add-remove test covering WhatsApp loopback flow, channels-stop-start test, and cloud-onboard smoke test.
PRA-6 Required scope scripts/nemoclaw-start.sh:3400 Add code comment with direct link to OpenClaw 2026.6.10 source file/line where gateway locality check strips operator scopes for private-IP origins, or retain minimal fallback reconciliation with clear error surfacing, or acknowledge assumption in tracked follow-up issue with failing repro test.
PRA-7 Resolve/justify scope scripts/nemoclaw-start.sh:3632 Either make all shell entry points connect-session-sourced (fix at source), or document workaround with removal condition tied to tracked issue and add regression test verifying preloads load in non-connect shells.
PRA-8 Required acceptance scripts/nemoclaw-start.sh:3580 Either verify OpenClaw 2026.6.10's loopback-origin channels.start succeeds without operator.admin (with code comment linking to OpenClaw source), or add nemoclaw channels/gateway restart command as explicit recovery path per #6413.
PRA-9 Required correctness scripts/nemoclaw-start.sh:3580 Restore at minimum: (a) verification that channel is active after login, (b) distinct guidance for login failure vs post-pair restart failure, (c) account ID validation (allowlist [A-Za-z0-9._:-], max 128 chars) with specific error messages, (d) scheme validation for explicit OPENCLAW_GATEWAY_URL override (already present).
PRA-10 Required correctness scripts/nemoclaw-start.sh:3540 Restore account ID validation (allowlist [A-Za-z0-9._:-], max 128 chars) in the WhatsApp login block before invoking openclaw channels login --account. Either forward the validated account ID or explicitly reject the flag with a clear error if not supported.
PRA-11 Required acceptance scripts/nemoclaw-start.sh:3400 Add code comment with direct link to OpenClaw 2026.6.10 source file/line where gateway locality check strips operator scopes for private-IP origins, or retain minimal fallback reconciliation with clear error surfacing, or acknowledge assumption in tracked follow-up issue with failing repro test.
PRA-12 Resolve/justify acceptance scripts/nemoclaw-start.sh:3632 Either make all shell entry points connect-session-sourced (fix at source), or document workaround with removal condition tied to tracked issue and add regression test verifying preloads load in non-connect shells.
PRA-13 Resolve/justify docs scripts/nemoclaw-start.sh:3540 Add migration note to docs/changelog: explicit gateway overrides now restricted to loopback hosts only. Consider if an escape hatch is needed for legitimate remote gateway use cases, or document as intentional security hardening.
PRA-14 Required correctness scripts/nemoclaw-start.sh:3580 Add post-login verification that channel is active on gateway (e.g., query gateway for channel status), or implement automatic reload via loopback-origin channels.start with verified OpenClaw source, or add nemoclaw channels/gateway restart command as explicit recovery path per #6413.
PRA-15 Required security test/nemoclaw-start-gateway-ws-host.test.ts:1 Add focused unit tests for the new case-based token gating covering all 5 gating scenarios. Restore security test coverage as checked-in Vitest tests.
PRA-16 Resolve/justify security scripts/nemoclaw-start.sh:3540 Restore account ID validation (allowlist [A-Za-z0-9._:-], max 128 chars) in WhatsApp login block before invoking openclaw channels login. Either forward validated account ID or explicitly reject flag with clear error.
PRA-17 Resolve/justify security scripts/nemoclaw-start.sh:3400 Add code comment with direct link to OpenClaw 2026.6.10 source file/line where gateway locality check strips operator scopes for private-IP origins, or retain minimal fallback reconciliation with clear error surfacing, or acknowledge assumption in tracked follow-up issue with failing repro test.
PRA-18 Resolve/justify security scripts/nemoclaw-start.sh:3632 Either make all shell entry points connect-session-sourced (fix at source), or add regression test verifying preloads load in non-connect shells and document workaround with removal condition tied to tracked issue.
PRA-19 Required security test/sandbox-provisioning.test.ts:1 Implement the three required E2E tests as checked-in Vitest tests that run in CI without external dependencies: channels-add-remove (WhatsApp loopback flow), channels-stop-start, cloud-onboard smoke test.
PRA-20 Required tests test/sandbox-provisioning.test.ts:1 Implement the three required E2E tests as checked-in Vitest tests that run in CI without external dependencies: channels-add-remove (WhatsApp loopback flow), channels-stop-start, cloud-onboard smoke test.

🚨 Required before merge

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

PRA-1 Required — Unmet acceptance clause: #6413 required automatic reload or recovery command

  • Location: scripts/nemoclaw-start.sh:3580
  • Category: scope
  • Problem: Issue fix(whatsapp): post-pair gateway restart fails without operator.admin #6413 explicitly required automatic reload or recovery command after WhatsApp QR pairing. The PR deletes _nemoclaw_whatsapp_postpair_start() entirely and updates docs to instruct manual re-login + status check. No nemoclaw channels/gateway restart command exists.
  • Impact: Users who complete WhatsApp QR pairing will have saved credentials but the running channel stays on the old session until manual intervention. The acceptance clause is unmet.
  • Required action: Either verify OpenClaw 2026.6.10's loopback-origin channels.start succeeds without operator.admin (with code comment linking to OpenClaw source), or add nemoclaw channels/gateway restart command as explicit recovery path per fix(whatsapp): post-pair gateway restart fails without operator.admin #6413.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search diff for 'restart' or 'reconcile' in WhatsApp login block — only manual guidance remains. Check docs/manage-sandboxes/messaging-channels.mdx for recovery instructions.
  • Missing regression test: Add E2E test: fresh sandbox, enable WhatsApp, rebuild, connect, run login, scan QR, verify channel active without manual restart.
  • Done when: The required change is committed and verification passes: Search diff for 'restart' or 'reconcile' in WhatsApp login block — only manual guidance remains. Check docs/manage-sandboxes/messaging-channels.mdx for recovery instructions.
  • Evidence: _nemoclaw_whatsapp_postpair_start() deleted in scripts/nemoclaw-start.sh docs/manage-sandboxes/messaging-channels.mdx instructs manual re-login + status check No nemoclaw channels restart command exists in codebase

PRA-2 Required — Caller/callee contract drift: --account flag silently ignored

  • Location: scripts/nemoclaw-start.sh:3540
  • Category: scope
  • Problem: The WhatsApp login block previously parsed and validated --account flag against allowlist [A-Za-z0-9._:-] with max 128 chars, and forwarded it in channels.start params. New code removes all --account parsing (variables _prev_arg_was_account_flag, _login_account, validation case statement deleted). Flag is now silently ignored — callers passing --account=<id> get default account behavior with no error.
  • Impact: Callers passing --account=<id> will have the account ID silently dropped. The OpenClaw login command may behave differently (use default account vs specified), causing silent misconfiguration. The validation contract is broken without deprecation or error.
  • Required action: Restore account ID validation (allowlist [A-Za-z0-9._:-], max 128 chars) in the WhatsApp login block before invoking openclaw channels login --account. Either forward the validated account ID or explicitly reject the flag with a clear error if not supported.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search for _prev_arg_was_account_flag, _login_account, and the account validation case statement in scripts/nemoclaw-start.sh — all removed.
  • Missing regression test: Add tests for account ID validation behavior: valid account ID forwarded, invalid characters rejected, >128 chars rejected, missing flag uses default.
  • Done when: The required change is committed and verification passes: Search for _prev_arg_was_account_flag, _login_account, and the account validation case statement in scripts/nemoclaw-start.sh — all removed.
  • Evidence: _prev_arg_was_account_flag variable deleted _login_account variable deleted account validation case statement (case $_login_account in *[!A-Za-z0-9._:-]*) deleted --account flag no longer appears in login command invocation

PRA-5 Required — Risk plan required jobs not implemented as checked-in tests

  • Location: test/sandbox-provisioning.test.ts:1
  • Category: scope
  • Problem: The risk plan (version 2, planHash c22eaee4) requires three E2E jobs as validation floor: cloud-onboard (tier 3), channels-add-remove (tier 2), channels-stop-start (tier 2). None appear as checked-in Vitest tests in the diff. The deleted repro-6413-whatsapp-postpair-start.test.ts was the prior E2E coverage for the post-pair invariant.
  • Impact: Required validation jobs exist only as risk-plan metadata, not as executable checked-in tests. CI cannot run them. The channels-add-remove invariant (messaging lifecycle through restart/removal) has no checked-in test coverage in this PR.
  • Required action: Implement the three required E2E tests as checked-in Vitest tests that can run in CI without external dependencies. At minimum: channels-add-remove test covering WhatsApp loopback flow, channels-stop-start test, and cloud-onboard smoke test.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check test/ directory for tests named channels-add-remove, channels-stop-start, cloud-onboard. Verify risk plan requiredJobs array matches checked-in test files.
  • Missing regression test: Add checked-in Vitest tests for channels-add-remove, channels-stop-start, and cloud-onboard required jobs.
  • Done when: The required change is committed and verification passes: Check test/ directory for tests named channels-add-remove, channels-stop-start, cloud-onboard. Verify risk plan requiredJobs array matches checked-in test files.
  • Evidence: riskPlan.requiredJobs lists cloud-onboard, channels-add-remove, channels-stop-start test/repro-6413-whatsapp-postpair-start.test.ts deleted (was prior E2E coverage) No new test files added matching required job names test/sandbox-provisioning.test.ts changes are minor (4 lines)

PRA-6 Required — Source-of-truth workaround: Loopback-only pairing assumes unverified OpenClaw gateway locality behavior

  • Location: scripts/nemoclaw-start.sh:3400
  • Category: scope
  • Problem: The PR comment states: 'Root cause + removal condition: the scope-strip is OpenClaw gateway locality behavior... Remove once the pinned OpenClaw keeps operator scopes for a token-authed post-pair channels.start over the stashed private URL.' However, no code comment links to OpenClaw 2026.6.10 source file/line where loopback-origin channels.start bypasses operator.admin. The workaround assumes private-veth origin strips operator scopes regardless of token auth, but this is not verified in OpenClaw source.
  • Impact: If the OpenClaw gateway locality assumption is wrong, the loopback-only pairing could fail silently or the private veth path could have worked. The workaround has no verified removal condition tied to OpenClaw source.
  • Required action: Add code comment with direct link to OpenClaw 2026.6.10 source file/line where gateway locality check strips operator scopes for private-IP origins, or retain minimal fallback reconciliation with clear error surfacing, or acknowledge assumption in tracked follow-up issue with failing repro test.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search for OpenClaw source reference (GitHub URL, file:line) in the WhatsApp login block comment. Verify against OpenClaw 2026.6.10 gateway auth code.
  • Missing regression test: Add regression test for the OpenClaw scope-stripping behavior that necessitates the loopback-only workaround, or add failing repro test that would pass when OpenClaw fixes the root cause.
  • Done when: The required change is committed and verification passes: Search for OpenClaw source reference (GitHub URL, file:line) in the WhatsApp login block comment. Verify against OpenClaw 2026.6.10 gateway auth code.
  • Evidence: WhatsApp login block comment claims 'scope-strip is OpenClaw gateway locality behavior' but no source link Removal condition says 're-run the fix(whatsapp): post-pair gateway restart fails without operator.admin #6413 fresh-install repro to confirm before deleting' but no checked-in repro test exists OpenClaw 2026.6.10 source not cited for gateway locality check behavior

PRA-8 Required — Unmet acceptance clause: #6413 required automatic reload or recovery command

  • Location: scripts/nemoclaw-start.sh:3580
  • Category: acceptance
  • Problem: Issue fix(whatsapp): post-pair gateway restart fails without operator.admin #6413 explicitly required 'automatic reload or recovery command' — either a bounded NemoClaw-owned post-pair gateway reload/restart path, or clearer host-side recovery guidance like 'nemoclaw <sandbox> gateway restart'. The PR deletes _nemoclaw_whatsapp_postpair_start() entirely. Docs now instruct manual 'channels status' check. No automatic reload, no new gateway restart command. PR body claims loopback-origin channels.start succeeds natively without operator.admin, but no OpenClaw 2026.6.10 source citation verifies this.
  • Impact: Users who complete WhatsApp QR pairing will have saved credentials but the running channel stays on the old session until manual intervention. The acceptance clause is unmet.
  • Required action: Either verify OpenClaw 2026.6.10's loopback-origin channels.start succeeds without operator.admin (with code comment linking to OpenClaw source), or add nemoclaw channels/gateway restart command as explicit recovery path per fix(whatsapp): post-pair gateway restart fails without operator.admin #6413.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search diff for 'restart' or 'reconcile' in WhatsApp login block — only manual guidance remains. Check docs/manage-sandboxes/messaging-channels.mdx for recovery instructions.
  • Missing regression test: Add E2E test: fresh sandbox, enable WhatsApp, rebuild, connect, run login, scan QR, verify channel active without manual restart.
  • Done when: The required change is committed and verification passes: Search diff for 'restart' or 'reconcile' in WhatsApp login block — only manual guidance remains. Check docs/manage-sandboxes/messaging-channels.mdx for recovery instructions.
  • Evidence: _nemoclaw_whatsapp_postpair_start() deleted in scripts/nemoclaw-start.sh docs/manage-sandboxes/messaging-channels.mdx instructs manual re-login + status check No nemoclaw channels restart command exists in codebase PR body claims loopback-origin channels.start works but cites no OpenClaw source

PRA-9 Required — Error handling collapse: 5 distinct error branches reduced to 1 generic branch

  • Location: scripts/nemoclaw-start.sh:3580
  • Category: correctness
  • Problem: Old WhatsApp login block had 5 distinct error paths with specific guidance: (a) trusted URL + token → auto-restart; (b) trusted URL, no token → reconcile attempt; (c) caller URL → credentials saved, manual status check; (d) login failure (gateway close 1008) → retry guidance; (e) account ID validation failures (invalid chars, >128 chars) → specific error messages. New code collapses to: exit 0 (success, no channel-active verification) or non-zero (generic 'gateway close 1008' guidance). Account ID validation completely removed.
  • Impact: Users lose specific diagnostic guidance for each failure mode. Account ID validation failures now silently ignored. Gateway close 1008 guidance is generic. No distinction between login failure vs post-pair restart failure.
  • Required action: Restore at minimum: (a) verification that channel is active after login, (b) distinct guidance for login failure vs post-pair restart failure, (c) account ID validation (allowlist [A-Za-z0-9._:-], max 128 chars) with specific error messages, (d) scheme validation for explicit OPENCLAW_GATEWAY_URL override (already present).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Compare old _nemoclaw_whatsapp_postpair_start() and login block error branches with new case statement — only success (exit 0) and generic failure (exit non-zero) remain.
  • Missing regression test: Add negative tests for each error branch with specific expected error messages: invalid account ID chars, account ID >128 chars, gateway close 1008, non-loopback URL rejected, malformed URL rejected.
  • Done when: The required change is committed and verification passes: Compare old _nemoclaw_whatsapp_postpair_start() and login block error branches with new case statement — only success (exit 0) and generic failure (exit non-zero) remain.
  • Evidence: _nemoclaw_whatsapp_postpair_start() deleted (contained 3 error branches) Account ID validation case statement deleted New login block has single _whatsapp_login_exit case: 0=success, *=generic gateway close guidance No channel-active verification after login

PRA-10 Required — Caller/callee contract drift: --account flag silently ignored

  • Location: scripts/nemoclaw-start.sh:3540
  • Category: correctness
  • Problem: The WhatsApp login block previously parsed and validated --account flag against allowlist [A-Za-z0-9._:-] with max 128 chars, and forwarded it in channels.start params. New code removes all --account parsing (variables _prev_arg_was_account_flag, _login_account, validation case statement deleted). Flag is now silently ignored — callers passing --account=<id> get default account behavior with no error.
  • Impact: Callers passing --account=<id> will have the account ID silently dropped. The OpenClaw login command may behave differently (use default account vs specified), causing silent misconfiguration. The validation contract is broken without deprecation or error.
  • Required action: Restore account ID validation (allowlist [A-Za-z0-9._:-], max 128 chars) in the WhatsApp login block before invoking openclaw channels login --account. Either forward the validated account ID or explicitly reject the flag with a clear error if not supported.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search for _prev_arg_was_account_flag, _login_account, and the account validation case statement in scripts/nemoclaw-start.sh — all removed.
  • Missing regression test: Add tests for account ID validation behavior: valid account ID forwarded, invalid characters rejected, >128 chars rejected, missing flag uses default.
  • Done when: The required change is committed and verification passes: Search for _prev_arg_was_account_flag, _login_account, and the account validation case statement in scripts/nemoclaw-start.sh — all removed.
  • Evidence: _prev_arg_was_account_flag variable deleted _login_account variable deleted account validation case statement (case $_login_account in *[!A-Za-z0-9._:-]*) deleted --account flag no longer appears in login command invocation

PRA-11 Required — Source-of-truth workaround: Loopback-only pairing assumes unverified OpenClaw gateway locality behavior

  • Location: scripts/nemoclaw-start.sh:3400
  • Category: acceptance
  • Problem: The PR comment states: 'Root cause + removal condition: the scope-strip is OpenClaw gateway locality behavior... Remove once the pinned OpenClaw keeps operator scopes for a token-authed post-pair channels.start over the stashed private URL.' However, no code comment links to OpenClaw 2026.6.10 source file/line where loopback-origin channels.start bypasses operator.admin. The workaround assumes private-veth origin strips operator scopes regardless of token auth, but this is not verified in OpenClaw source.
  • Impact: If the OpenClaw gateway locality assumption is wrong, the loopback-only pairing could fail silently or the private veth path could have worked. The workaround has no verified removal condition tied to OpenClaw source.
  • Required action: Add code comment with direct link to OpenClaw 2026.6.10 source file/line where gateway locality check strips operator scopes for private-IP origins, or retain minimal fallback reconciliation with clear error surfacing, or acknowledge assumption in tracked follow-up issue with failing repro test.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search for OpenClaw source reference (GitHub URL, file:line) in the WhatsApp login block comment. Verify against OpenClaw 2026.6.10 gateway auth code.
  • Missing regression test: Add regression test for the OpenClaw scope-stripping behavior that necessitates the loopback-only workaround, or add failing repro test that would pass when OpenClaw fixes the root cause.
  • Done when: The required change is committed and verification passes: Search for OpenClaw source reference (GitHub URL, file:line) in the WhatsApp login block comment. Verify against OpenClaw 2026.6.10 gateway auth code.
  • Evidence: WhatsApp login block comment claims 'scope-strip is OpenClaw gateway locality behavior' but no source link Removal condition says 're-run the fix(whatsapp): post-pair gateway restart fails without operator.admin #6413 fresh-install repro to confirm before deleting' but no checked-in repro test exists OpenClaw 2026.6.10 source not cited for gateway locality check behavior

PRA-14 Required — State transition gap: No post-login channel-active verification

  • Location: scripts/nemoclaw-start.sh:3580
  • Category: correctness
  • Problem: Old code had _nemoclaw_whatsapp_postpair_start() that read gateway token from config and called channels.start RPC to restart the channel on the running gateway. New code assumes OpenClaw's own post-pair channels.start succeeds on loopback origin. No verification in code that channel is actually active after login. No test asserting channel-active state post-pair.
  • Impact: Credentials may be saved but channel remains on old session. Users have no programmatic confirmation that pairing succeeded and channel is running. Manual 'channels status' check required.
  • Required action: Add post-login verification that channel is active on gateway (e.g., query gateway for channel status), or implement automatic reload via loopback-origin channels.start with verified OpenClaw source, or add nemoclaw channels/gateway restart command as explicit recovery path per fix(whatsapp): post-pair gateway restart fails without operator.admin #6413.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search for channel status check or channels.start RPC call after login in new WhatsApp login block — absent. Check test/nemoclaw-start.test.ts for post-login channel-active assertion.
  • Missing regression test: Add test: fresh sandbox, enable WhatsApp, rebuild, connect, run login, scan QR, verify channel active on gateway without manual restart.
  • Done when: The required change is committed and verification passes: Search for channel status check or channels.start RPC call after login in new WhatsApp login block — absent. Check test/nemoclaw-start.test.ts for post-login channel-active assertion.
  • Evidence: _nemoclaw_whatsapp_postpair_start() deleted (contained channels.start RPC call) New login block has no gateway interaction after login succeeds No test asserting channel-active state post-pair Docs instruct manual 'channels status' check

PRA-15 Required — Security test coverage regression: 7 gateway trust anchor SSRF defense tests deleted with zero replacements

  • Location: test/nemoclaw-start-gateway-ws-host.test.ts:1
  • Category: security
  • Problem: The PR deletes 7 security unit tests that verified the gateway trust anchor readonly enforcement: (1) conflict anchor test, (2) shadowed dispatch test, (3) readonly token test, (4) bracket function test, (5) source poisoning test, (6) selective bracket test, (7) shadowed return test. The new case-statement token gating in write_runtime_shell_env() has zero replacement tests. No tests verify: token emitted when URL empty, token emitted for loopback URLs, token withheld for userinfo URLs, token withheld for non-loopback URLs, token withheld for malformed URLs.
  • Impact: The security boundary that prevents gateway token leakage to non-loopback endpoints has no automated verification. Regression in token gating logic would not be caught. The simplification to case-statement gating is security-positive but untested.
  • Required action: Add focused unit tests for the new case-based token gating covering all 5 gating scenarios. Restore security test coverage as checked-in Vitest tests.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check test/nemoclaw-start-gateway-ws-host.test.ts — 7 tests deleted, no new tests added for case-statement token gating.
  • Missing regression test: Add 5 unit tests for new token gating: (1) empty URL emits token, (2) loopback URL emits token, (3) userinfo URL withholds token, (4) non-loopback URL withholds token, (5) malformed URL withholds token.
  • Done when: The required change is committed and verification passes: Check test/nemoclaw-start-gateway-ws-host.test.ts — 7 tests deleted, no new tests added for case-statement token gating.
  • Evidence: 7 security tests deleted from test/nemoclaw-start-gateway-ws-host.test.ts New case statement in write_runtime_shell_env() gates OPENCLAW_GATEWAY_TOKEN based on OPENCLAW_GATEWAY_URL No tests for new token gating logic in any test file

PRA-19 Required — Required E2E security validation jobs not implemented as checked-in tests

  • Location: test/sandbox-provisioning.test.ts:1
  • Category: security
  • Problem: Risk plan (version 2) requires three E2E jobs as validation floor: cloud-onboard (tier 3), channels-add-remove (tier 2), channels-stop-start (tier 2). None implemented as checked-in Vitest tests. The deleted repro-6413-whatsapp-postpair-start.test.ts was prior E2E coverage for post-pair invariant. Messaging lifecycle invariants (channel credentials/policy applied to intended agent, restart/rebuild restores channel, removal tears down state) have no checked-in test coverage.
  • Impact: Security-critical messaging lifecycle invariants cannot be verified in CI. The channels-add-remove invariant (WhatsApp loopback flow through add/remove/restart) has no automated coverage. SSRF defense (loopback-only override) not tested end-to-end.
  • Required action: Implement the three required E2E tests as checked-in Vitest tests that run in CI without external dependencies: channels-add-remove (WhatsApp loopback flow), channels-stop-start, cloud-onboard smoke test.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check test/ directory for tests named channels-add-remove, channels-stop-start, cloud-onboard. Verify risk plan requiredJobs array matches checked-in test files.
  • Missing regression test: Add checked-in Vitest tests for channels-add-remove, channels-stop-start, and cloud-onboard required jobs.
  • Done when: The required change is committed and verification passes: Check test/ directory for tests named channels-add-remove, channels-stop-start, cloud-onboard. Verify risk plan requiredJobs array matches checked-in test files.
  • Evidence: riskPlan.requiredJobs lists cloud-onboard, channels-add-remove, channels-stop-start test/repro-6413-whatsapp-postpair-start.test.ts deleted (was prior E2E coverage) No new test files added matching required job names test/sandbox-provisioning.test.ts changes are minor (4 lines)

PRA-20 Required — Risk plan required jobs not implemented as checked-in tests

  • Location: test/sandbox-provisioning.test.ts:1
  • Category: tests
  • Problem: Risk plan (version 2) requires three E2E jobs as validation floor: cloud-onboard (tier 3), channels-add-remove (tier 2), channels-stop-start (tier 2). None implemented as checked-in Vitest tests. The deleted repro-6413-whatsapp-postpair-start.test.ts was prior E2E coverage for post-pair invariant. Messaging lifecycle invariants have no checked-in test coverage.
  • Impact: Security-critical messaging lifecycle invariants cannot be verified in CI. The channels-add-remove invariant (WhatsApp loopback flow through add/remove/restart) has no automated coverage. SSRF defense (loopback-only override) not tested end-to-end.
  • Required action: Implement the three required E2E tests as checked-in Vitest tests that run in CI without external dependencies: channels-add-remove (WhatsApp loopback flow), channels-stop-start, cloud-onboard smoke test.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check test/ directory for tests named channels-add-remove, channels-stop-start, cloud-onboard. Verify risk plan requiredJobs array matches checked-in test files.
  • Missing regression test: Add checked-in Vitest tests for channels-add-remove, channels-stop-start, and cloud-onboard required jobs.
  • Done when: The required change is committed and verification passes: Check test/ directory for tests named channels-add-remove, channels-stop-start, cloud-onboard. Verify risk plan requiredJobs array matches checked-in test files.
  • Evidence: riskPlan.requiredJobs lists cloud-onboard, channels-add-remove, channels-stop-start test/repro-6413-whatsapp-postpair-start.test.ts deleted (was prior E2E coverage) No new test files added matching required job names test/sandbox-provisioning.test.ts changes are minor (4 lines)

PRA-21 Required — Security test coverage regression: 7 gateway trust anchor tests deleted, 0 replacements for new token gating

  • Location: test/nemoclaw-start-gateway-ws-host.test.ts:1
  • Category: tests
  • Problem: The PR deletes 7 security unit tests that verified the gateway trust anchor readonly enforcement. The new case-statement token gating in write_runtime_shell_env() has zero replacement tests. No tests verify: token emitted when URL empty, token emitted for loopback URLs, token withheld for userinfo URLs, token withheld for non-loopback URLs, token withheld for malformed URLs.
  • Impact: The security boundary that prevents gateway token leakage to non-loopback endpoints has no automated verification. Regression in token gating logic would not be caught.
  • Required action: Add focused unit tests for the new case-based token gating covering all 5 gating scenarios. Restore security test coverage as checked-in Vitest tests.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check test/nemoclaw-start-gateway-ws-host.test.ts — 7 tests deleted, no new tests added for case-statement token gating.
  • Missing regression test: Add 5 unit tests for new token gating: (1) empty URL emits token, (2) loopback URL emits token, (3) userinfo URL withholds token, (4) non-loopback URL withholds token, (5) malformed URL withholds token.
  • Done when: The required change is committed and verification passes: Check test/nemoclaw-start-gateway-ws-host.test.ts — 7 tests deleted, no new tests added for case-statement token gating.
  • Evidence: 7 security tests deleted from test/nemoclaw-start-gateway-ws-host.test.ts New case statement in write_runtime_shell_env() gates OPENCLAW_GATEWAY_TOKEN based on OPENCLAW_GATEWAY_URL No tests for new token gating logic in any test file

PRA-22 Required — Missing tests for --account flag validation removal

  • Location: scripts/nemoclaw-start.sh:3540
  • Category: tests
  • Problem: The WhatsApp login block previously validated --account flag against allowlist [A-Za-z0-9._:-] with max 128 chars. New code removes all validation — flag silently ignored. No tests exist for: valid ID forwarded, invalid chars rejected, >128 chars rejected, missing flag uses default.
  • Impact: Caller-controlled account ID bypasses allowlist/length validation with no test coverage to catch regression or verify behavior.
  • Required action: Add tests for account ID validation behavior, or restore validation with tests.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search for _prev_arg_was_account_flag, _login_account, and account validation case statement in scripts/nemoclaw-start.sh — all removed.
  • Missing regression test: Add tests for account ID validation: valid ID forwarded, invalid chars rejected, >128 chars rejected, missing flag uses default.
  • Done when: The required change is committed and verification passes: Search for _prev_arg_was_account_flag, _login_account, and account validation case statement in scripts/nemoclaw-start.sh — all removed.
  • Evidence: _prev_arg_was_account_flag variable deleted _login_account variable deleted account validation case statement (case $_login_account in *[!A-Za-z0-9._:-]*) deleted --account flag no longer appears in login command invocation

PRA-23 Required — Error handling collapse: 5→1 branches with 0 negative tests

  • Location: scripts/nemoclaw-start.sh:3580
  • Category: tests
  • Problem: Old WhatsApp login block had 5 distinct error paths with specific messages. New code collapses to single _whatsapp_login_exit case (0=success, *=generic 1008 guidance). No negative tests for: invalid account ID chars, >128 chars, gateway close 1008, non-loopback URL rejected, malformed URL rejected.
  • Impact: Users lose specific diagnostic guidance. No automated verification that each error condition produces correct behavior.
  • Required action: Add negative tests for each error branch with specific expected error messages.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Compare old _nemoclaw_whatsapp_postpair_start() and login block error branches with new case statement — only success (exit 0) and generic failure (exit non-zero) remain.
  • Missing regression test: Add negative tests for each error branch: invalid account ID chars, account ID >128 chars, gateway close 1008, non-loopback URL rejected, malformed URL rejected.
  • Done when: The required change is committed and verification passes: Compare old _nemoclaw_whatsapp_postpair_start() and login block error branches with new case statement — only success (exit 0) and generic failure (exit non-zero) remain.
  • Evidence: _nemoclaw_whatsapp_postpair_start() deleted (contained 3 error branches) Account ID validation case statement deleted New login block has single _whatsapp_login_exit case: 0=success, *=generic gateway close guidance No channel-active verification after login

PRA-24 Required — No post-login channel-active verification test

  • Location: scripts/nemoclaw-start.sh:3580
  • Category: tests
  • Problem: Old _nemoclaw_whatsapp_postpair_start() called channels.start RPC to restart channel on gateway. New code assumes OpenClaw loopback-origin channels.start succeeds. No test asserts channel-active state post-pair. No gateway interaction after login in new code.
  • Impact: Credentials may be saved but channel remains on old session. No programmatic confirmation that pairing succeeded.
  • Required action: Add test: fresh sandbox, enable WhatsApp, rebuild, connect, run login, scan QR, verify channel active on gateway without manual restart.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search for channel status check or channels.start RPC call after login in new WhatsApp login block — absent. Check test/nemoclaw-start.test.ts for post-login channel-active assertion.
  • Missing regression test: Add test: fresh sandbox, enable WhatsApp, rebuild, connect, run login, scan QR, verify channel active on gateway without manual restart.
  • Done when: The required change is committed and verification passes: Search for channel status check or channels.start RPC call after login in new WhatsApp login block — absent. Check test/nemoclaw-start.test.ts for post-login channel-active assertion.
  • Evidence: _nemoclaw_whatsapp_postpair_start() deleted (contained channels.start RPC call) New login block has no gateway interaction after login succeeds No test asserting channel-active state post-pair Docs instruct manual 'channels status' check
Review findings by urgency: 16 required fixes, 9 items to resolve/justify, 0 in-scope improvements

⚠️ Resolve or justify before merge

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

PRA-3 Resolve/justify — Breaking change: Explicit OPENCLAW_GATEWAY_URL override restricted to loopback hosts only

  • Location: scripts/nemoclaw-start.sh:3540
  • Category: scope
  • Problem: Previously, explicit OPENCLAW_GATEWAY_URL override was accepted for any ws:// or wss:// URL (with token withheld for non-trusted URLs). New code restricts explicit overrides to loopback hosts only (ws://127.0.0.1:<port>, ws://localhost:<port>, ws://[::1]:<port>). Non-loopback explicit overrides are rejected with error. This is a breaking change for any legitimate remote gateway use cases.
  • Impact: Operators who previously used explicit gateway overrides for remote gateways (e.g., shared gateway across sandboxes) will now have their override rejected. No migration note in docs/changelog. No escape hatch documented.
  • Recommended action: Add migration note to docs/changelog: explicit gateway overrides now restricted to loopback hosts only. Consider if an escape hatch is needed for legitimate remote gateway use cases, or document as intentional security hardening.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check the WhatsApp login case statement for OPENCLAW_GATEWAY_URL — only loopback patterns accepted. Search docs/changelog for migration note.
  • Missing regression test: Add test verifying non-loopback explicit gateway override is rejected with clear error message.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check the WhatsApp login case statement for OPENCLAW_GATEWAY_URL — only loopback patterns accepted. Search docs/changelog for migration note.
  • Evidence: WhatsApp login case statement only accepts loopback URL patterns (127.0.0.1, localhost, [::1]) Non-loopback ws://* | wss://* case returns error and sets _nemoclaw_whatsapp_gateway_allowed=0 No migration note in docs or changelog in this PR

PRA-4 Resolve/justify — Simplification: Gateway trust anchor replaced by native case-statement token gating

  • Location: scripts/nemoclaw-start.sh:3632
  • Category: architecture
  • Problem: The _NEMOCLAW_TRUSTED_OPENCLAW_GATEWAY_URL readonly anchor and its runtime readonly-enforcement checks (7 security unit tests) have been replaced by a simpler case-statement token gating at env emission time. The new approach uses shell 'case' syntax which cannot be shadowed by imported functions, eliminating the need for readonly verification. However, the 7 deleted security tests are not re-added for the new implementation.
  • Impact: Code simplification reduces attack surface (no shadowable readonly checks), but test coverage for the security boundary is lost. The new token gating logic in write_runtime_shell_env() emits a case statement that gates OPENCLAW_GATEWAY_TOKEN based on OPENCLAW_GATEWAY_URL value.
  • Recommended action: Acknowledge this simplification as a security improvement. Add focused unit tests for the new case-based token gating: (1) token emitted when URL empty, (2) token emitted for loopback URLs, (3) token withheld for userinfo URLs, (4) token withheld for non-loopback URLs, (5) token withheld for malformed URLs.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare deleted trust anchor logic (readonly _NEMOCLAW_TRUSTED_OPENCLAW_GATEWAY_URL, verification subshell) with new case statement in write_runtime_shell_env(). Check test/nemoclaw-start-gateway-ws-host.test.ts for replacement tests.
  • Missing regression test: Restore focused security unit tests as checked-in tests for the new token gating implementation.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare deleted trust anchor logic (readonly _NEMOCLAW_TRUSTED_OPENCLAW_GATEWAY_URL, verification subshell) with new case statement in write_runtime_shell_env(). Check test/nemoclaw-start-gateway-ws-host.test.ts for replacement tests.
  • Evidence: _NEMOCLAW_TRUSTED_OPENCLAW_GATEWAY_URL readonly anchor deleted Runtime readonly verification subshell (if ( _NEMOCLAW_TRUSTED_OPENCLAW_GATEWAY_URL= ) 2>/dev/null) deleted New case statement in write_runtime_shell_env() gates token based on OPENCLAW_GATEWAY_URL 7 security tests in test/nemoclaw-start-gateway-ws-host.test.ts deleted (conflict anchor, shadowed dispatch, readonly token, bracket function, source poisoning, selective bracket, shadowed return)

PRA-7 Resolve/justify — Source-of-truth workaround: NODE_OPTIONS preload injection for non-connect shells lacks regression test and removal tracker

  • Location: scripts/nemoclaw-start.sh:3632
  • Category: scope
  • Problem: The WhatsApp login block injects NODE_OPTIONS preloads again to cover non-connect shells: 'Defense-in-depth: connect-session NODE_OPTIONS already wires manifest-declared connect preloads for every openclaw invocation; injecting them again here covers non-connect shells.' This workaround has no regression test verifying preloads load in non-connect shells, and no removal tracker tied to a fix at source (making all shells connect-session-sourced).
  • Impact: If the workaround is unnecessary (all shells become connect-session-sourced), it remains indefinitely. If it breaks (preloads fail to load), no test catches it. The removal condition 'fix at source by making all shells connect-session-sourced' is not tracked.
  • Recommended action: Either make all shell entry points connect-session-sourced (fix at source), or document workaround with removal condition tied to tracked issue and add regression test verifying preloads load in non-connect shells.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search for NODE_OPTIONS injection in WhatsApp login block. Check for linked issue or removal tracker comment. Check test/nemoclaw-start.test.ts for non-connect shell preload test.
  • Missing regression test: Add regression test for the NODE_OPTIONS injection workaround, or fix at source by making all shells connect-session-sourced.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search for NODE_OPTIONS injection in WhatsApp login block. Check for linked issue or removal tracker comment. Check test/nemoclaw-start.test.ts for non-connect shell preload test.
  • Evidence: NODE_OPTIONS injection in WhatsApp login block with comment 'covers non-connect shells' No linked issue number in comment for removal tracking No test verifying preloads load in non-connect shells Comment says 'Runtime preload modules are idempotent, so a double --require is harmless' but no test proves this

PRA-12 Resolve/justify — Source-of-truth workaround: NODE_OPTIONS preload injection for non-connect shells lacks regression test and removal tracker

  • Location: scripts/nemoclaw-start.sh:3632
  • Category: acceptance
  • Problem: The WhatsApp login block injects NODE_OPTIONS preloads again to cover non-connect shells: 'Defense-in-depth: connect-session NODE_OPTIONS already wires manifest-declared connect preloads for every openclaw invocation; injecting them again here covers non-connect shells.' This workaround has no regression test verifying preloads load in non-connect shells, and no removal tracker tied to a fix at source (making all shells connect-session-sourced). Three injection sites exist (lines ~3632, 3665, 3690).
  • Impact: If the workaround is unnecessary (all shells become connect-session-sourced), it remains indefinitely. If it breaks (preloads fail to load), no test catches it. The removal condition 'fix at source by making all shells connect-session-sourced' is not tracked.
  • Recommended action: Either make all shell entry points connect-session-sourced (fix at source), or document workaround with removal condition tied to tracked issue and add regression test verifying preloads load in non-connect shells.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search for NODE_OPTIONS injection in WhatsApp login block. Check for linked issue or removal tracker comment. Check test/nemoclaw-start.test.ts for non-connect shell preload test.
  • Missing regression test: Add regression test for the NODE_OPTIONS injection workaround, or fix at source by making all shells connect-session-sourced.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search for NODE_OPTIONS injection in WhatsApp login block. Check for linked issue or removal tracker comment. Check test/nemoclaw-start.test.ts for non-connect shell preload test.
  • Evidence: NODE_OPTIONS injection in WhatsApp login block with comment 'covers non-connect shells' No linked issue number in comment for removal tracking No test verifying preloads load in non-connect shells Comment says 'Runtime preload modules are idempotent, so a double --require is harmless' but no test proves this

PRA-13 Resolve/justify — Breaking change undocumented: Explicit OPENCLAW_GATEWAY_URL override restricted to loopback hosts only

  • Location: scripts/nemoclaw-start.sh:3540
  • Category: docs
  • Problem: Previously, explicit OPENCLAW_GATEWAY_URL override was accepted for any ws:// or wss:// URL (with token withheld for non-trusted URLs). New code restricts explicit overrides to loopback hosts only (ws://127.0.0.1:<port>, ws://localhost:<port>, ws://[::1]:<port>). Non-loopback explicit overrides are rejected with error. This is a breaking change for any legitimate remote gateway use cases. No migration note in docs/changelog. No escape hatch documented.
  • Impact: Operators who previously used explicit gateway overrides for remote gateways (e.g., shared gateway across sandboxes) will now have their override rejected. No migration path documented.
  • Recommended action: Add migration note to docs/changelog: explicit gateway overrides now restricted to loopback hosts only. Consider if an escape hatch is needed for legitimate remote gateway use cases, or document as intentional security hardening.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check the WhatsApp login case statement for OPENCLAW_GATEWAY_URL — only loopback patterns accepted. Search docs/changelog for migration note.
  • Missing regression test: Add test verifying non-loopback explicit gateway override is rejected with clear error message.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check the WhatsApp login case statement for OPENCLAW_GATEWAY_URL — only loopback patterns accepted. Search docs/changelog for migration note.
  • Evidence: WhatsApp login case statement only accepts loopback URL patterns (127.0.0.1, localhost, [::1]) Non-loopback ws://* | wss://* case returns error and sets _nemoclaw_whatsapp_gateway_allowed=0 No migration note in docs or changelog in this PR

PRA-16 Resolve/justify — Input validation regression: --account flag validation removed, caller input passes unvalidated to OpenClaw

  • Location: scripts/nemoclaw-start.sh:3540
  • Category: security
  • Problem: The WhatsApp login block previously validated --account flag against allowlist [A-Za-z0-9._:-] with max 128 chars before forwarding in channels.start params. New code removes all validation — flag silently ignored, but if OpenClaw reads it from env/argv, unvalidated caller input reaches the gateway RPC. No sanitization of account ID before embedding in JSON params.
  • Impact: Caller-controlled account ID bypasses allowlist/length validation. If OpenClaw's channels.start processes the account ID, it could contain injection characters or excessive length. Validation contract broken without replacement.
  • Recommended action: Restore account ID validation (allowlist [A-Za-z0-9._:-], max 128 chars) in WhatsApp login block before invoking openclaw channels login. Either forward validated account ID or explicitly reject flag with clear error.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search for _prev_arg_was_account_flag, _login_account, and account validation case statement in scripts/nemoclaw-start.sh — all removed.
  • Missing regression test: Add tests for account ID validation: valid ID forwarded, invalid chars rejected, >128 chars rejected, missing flag uses default.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search for _prev_arg_was_account_flag, _login_account, and account validation case statement in scripts/nemoclaw-start.sh — all removed.
  • Evidence: _prev_arg_was_account_flag variable deleted _login_account variable deleted account validation case statement (case $_login_account in *[!A-Za-z0-9._:-]*) deleted --account flag no longer appears in login command invocation

PRA-17 Resolve/justify — Unverified security assumption: Loopback-only pairing relies on unconfirmed OpenClaw gateway locality behavior

  • Location: scripts/nemoclaw-start.sh:3400
  • Category: security
  • Problem: The entire WhatsApp login redesign assumes OpenClaw 2026.6.10's gateway locality check strips operator.admin for private-veth origins regardless of token auth, making loopback-origin the only working path. No code comment links to OpenClaw source file/line verifying this behavior. If assumption is wrong, loopback-only pairing could fail or private veth path could have worked. No failing repro test exists to detect when OpenClaw fixes the root cause.
  • Impact: Security control (gateway token gating) depends on unverified third-party behavior. If OpenClaw changes gateway auth, the workaround may break silently or expose token to wrong endpoint. No removal condition tied to verifiable source.
  • Recommended action: Add code comment with direct link to OpenClaw 2026.6.10 source file/line where gateway locality check strips operator scopes for private-IP origins, or retain minimal fallback reconciliation with clear error surfacing, or acknowledge assumption in tracked follow-up issue with failing repro test.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search for OpenClaw source reference (GitHub URL, file:line) in WhatsApp login block comment. Verify against OpenClaw 2026.6.10 gateway auth code.
  • Missing regression test: Add failing repro test that would pass when OpenClaw fixes the root cause (keeps operator scopes for token-authed post-pair channels.start over private veth URL).
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search for OpenClaw source reference (GitHub URL, file:line) in WhatsApp login block comment. Verify against OpenClaw 2026.6.10 gateway auth code.
  • Evidence: WhatsApp login block comment claims 'scope-strip is OpenClaw gateway locality behavior' but no source link Removal condition references 'fix(whatsapp): post-pair gateway restart fails without operator.admin #6413 fresh-install repro' but no checked-in repro test exists OpenClaw 2026.6.10 source not cited for gateway locality check behavior

PRA-18 Resolve/justify — Workaround without regression test: NODE_OPTIONS preload injection for non-connect shells

  • Location: scripts/nemoclaw-start.sh:3632
  • Category: security
  • Problem: Three NODE_OPTIONS injection sites in WhatsApp login block (lines ~3632, 3665, 3690) to cover non-connect shells. Comment acknowledges this is defense-in-depth for shells not sourced from connect-session. No regression test verifies preloads load in non-connect shells. No linked issue for removal tracker ('fix at source by making all shells connect-session-sourced').
  • Impact: If workaround becomes unnecessary (all shells connect-session-sourced), it remains indefinitely. If it breaks (preloads fail to load), no test catches it. Security preloads (sandbox safety net, proxy fix, seccomp guard, etc.) may not load in some shell contexts.
  • Recommended action: Either make all shell entry points connect-session-sourced (fix at source), or add regression test verifying preloads load in non-connect shells and document workaround with removal condition tied to tracked issue.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search for NODE_OPTIONS injection in WhatsApp login block. Check for linked issue or removal tracker comment. Check test/nemoclaw-start.test.ts for non-connect shell preload test.
  • Missing regression test: Add regression test for NODE_OPTIONS injection workaround, or fix at source by making all shells connect-session-sourced.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search for NODE_OPTIONS injection in WhatsApp login block. Check for linked issue or removal tracker comment. Check test/nemoclaw-start.test.ts for non-connect shell preload test.
  • Evidence: NODE_OPTIONS injection in WhatsApp login block with comment 'covers non-connect shells' No linked issue number in comment for removal tracking No test verifying preloads load in non-connect shells Comment claims idempotency but no test proves this

PRA-25 Resolve/justify — Workaround regression tests missing: NODE_OPTIONS preload injection and loopback-only assumption

  • Location: scripts/nemoclaw-start.sh:3632
  • Category: tests
  • Problem: Two workarounds lack regression tests: (a) NODE_OPTIONS preload injection at 3 sites (lines ~3632, 3665, 3690) — no test verifying preloads load in non-connect shells. (b) Loopback-only pairing assumption — no failing repro test that would pass when OpenClaw fixes root cause (keeps operator scopes for token-authed post-pair channels.start over private veth URL).
  • Impact: If workarounds become unnecessary, they remain indefinitely. If they break, no test catches it. Security preloads may not load in some shell contexts.
  • Recommended action: Add regression test for NODE_OPTIONS injection workaround, or fix at source by making all shells connect-session-sourced. Add failing repro test for OpenClaw gateway locality behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search for NODE_OPTIONS injection in WhatsApp login block. Check for linked issue or removal tracker comment. Check test/nemoclaw-start.test.ts for non-connect shell preload test. Search for OpenClaw source reference in WhatsApp login block comment.
  • Missing regression test: Add regression test for NODE_OPTIONS injection workaround, or fix at source by making all shells connect-session-sourced. Add failing repro test for OpenClaw gateway locality behavior.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search for NODE_OPTIONS injection in WhatsApp login block. Check for linked issue or removal tracker comment. Check test/nemoclaw-start.test.ts for non-connect shell preload test. Search for OpenClaw source reference in WhatsApp login block comment.
  • Evidence: NODE_OPTIONS injection in WhatsApp login block with comment 'covers non-connect shells' No linked issue number in comment for removal tracking No test verifying preloads load in non-connect shells WhatsApp login block comment claims 'scope-strip is OpenClaw gateway locality behavior' but no source link Removal condition references 'fix(whatsapp): post-pair gateway restart fails without operator.admin #6413 fresh-install repro' but no checked-in repro test exists

💡 In-scope improvements

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

  • None.
Test follow-ups to resolve or justify

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

  • PRA-T1 Runtime validation — Run the `cloud-onboard` E2E job for Installer and platform changes must work on a clean supported host with the pinned runtime dependencies. Matched files: `Dockerfile`.. Deterministic regression risks require live validation: messaging-lifecycle, platform-install.
  • PRA-T2 Runtime validation — Run the `channels-add-remove` E2E job for Messaging changes must preserve the manifest-to-policy-to-runtime lifecycle through restart and removal. Matched files: `src/lib/messaging/applier/build/messaging-build-applier.mts`.. Deterministic regression risks require live validation: messaging-lifecycle, platform-install.
  • PRA-T3 Runtime validation — Run the `channels-stop-start` E2E job for Messaging changes must preserve the manifest-to-policy-to-runtime lifecycle through restart and removal. Matched files: `src/lib/messaging/applier/build/messaging-build-applier.mts`.. Deterministic regression risks require live validation: messaging-lifecycle, platform-install.
  • PRA-T4 Risk plan required jobs not implemented as checked-in tests — Implement the three required E2E tests as checked-in Vitest tests that run in CI without external dependencies: channels-add-remove (WhatsApp loopback flow), channels-stop-start, cloud-onboard smoke test.
  • PRA-T5 Security test coverage regression: 7 gateway trust anchor tests deleted, 0 replacements for new token gating — Add focused unit tests for the new case-based token gating covering all 5 gating scenarios. Restore security test coverage as checked-in Vitest tests.
  • PRA-T6 Missing tests for --account flag validation removal — Add tests for account ID validation behavior, or restore validation with tests.
  • PRA-T7 Error handling collapse: 5→1 branches with 0 negative tests — Add negative tests for each error branch with specific expected error messages.
  • PRA-T8 No post-login channel-active verification test — Add test: fresh sandbox, enable WhatsApp, rebuild, connect, run login, scan QR, verify channel active on gateway without manual restart.

Workflow run details

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

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings

Merge posture: No blocking advisor findings
Primary next action: Add or justify PRA-T1 and any related test follow-ups.
Open items: 0 required · 0 warnings · 0 suggestions · 5 test follow-ups
Since last review: 1 prior item resolved · 0 still apply · 0 new items found

Action checklist

  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Runtime validation
  • PRA-T5 Add or justify test follow-up: Runtime validation
Test follow-ups to resolve or justify

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

  • PRA-T1 Runtime validation — Run the `cloud-onboard` E2E job for Installer and platform changes must work on a clean supported host with the pinned runtime dependencies. Matched files: `Dockerfile`.. Deterministic regression risks require live validation: messaging-lifecycle, platform-install. Checked-in unit and contract tests cover the changed shell token boundary, WhatsApp loopback behavior, negative URL/userinfo paths, plugin provenance, and integrity checks. The deterministic risk plan still requires live validation floors for platform install and messaging lifecycle surfaces.
  • PRA-T2 Runtime validation — Run the `cloud-onboard` E2E job for the Dockerfile/platform install change to validate that a clean supported host installs the pinned runtime dependencies and reaches a usable agent.. Deterministic regression risks require live validation: messaging-lifecycle, platform-install. Checked-in unit and contract tests cover the changed shell token boundary, WhatsApp loopback behavior, negative URL/userinfo paths, plugin provenance, and integrity checks. The deterministic risk plan still requires live validation floors for platform install and messaging lifecycle surfaces.
  • PRA-T3 Runtime validation — Run the `channels-add-remove` E2E job for Messaging changes must preserve the manifest-to-policy-to-runtime lifecycle through restart and removal. Matched files: `src/lib/messaging/applier/build/messaging-build-applier.mts`.. Deterministic regression risks require live validation: messaging-lifecycle, platform-install. Checked-in unit and contract tests cover the changed shell token boundary, WhatsApp loopback behavior, negative URL/userinfo paths, plugin provenance, and integrity checks. The deterministic risk plan still requires live validation floors for platform install and messaging lifecycle surfaces.
  • PRA-T4 Runtime validation — Run the `channels-add-remove` E2E job for the messaging applier change to prove channel add/remove still updates registry, provider, policy, runtime, session, and persisted state with npm-pack plugin provenance.. Deterministic regression risks require live validation: messaging-lifecycle, platform-install. Checked-in unit and contract tests cover the changed shell token boundary, WhatsApp loopback behavior, negative URL/userinfo paths, plugin provenance, and integrity checks. The deterministic risk plan still requires live validation floors for platform install and messaging lifecycle surfaces.
  • PRA-T5 Runtime validation — Run the `channels-stop-start` E2E job for Messaging changes must preserve the manifest-to-policy-to-runtime lifecycle through restart and removal. Matched files: `src/lib/messaging/applier/build/messaging-build-applier.mts`.. Deterministic regression risks require live validation: messaging-lifecycle, platform-install. Checked-in unit and contract tests cover the changed shell token boundary, WhatsApp loopback behavior, negative URL/userinfo paths, plugin provenance, and integrity checks. The deterministic risk plan still requires live validation floors for platform install and messaging lifecycle surfaces.

Workflow run details

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

@hunglp6d
hunglp6d marked this pull request as ready for review July 11, 2026 00:25

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@scripts/nemoclaw-start.sh`:
- Around line 3601-3625: The WhatsApp gateway URL allowlist in the case block
accepts userinfo-based URLs such as ws://127.0.0.1:1@evil.example, exposing the
gateway token to a non-loopback host. Reject any override containing “@” before
the existing loopback pattern matching (or validate the parsed hostname
directly), and add a negative test confirming this URL is rejected.
🪄 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: b2122a2f-ceea-4a4b-94d8-7455a34740e5

📥 Commits

Reviewing files that changed from the base of the PR and between 78d5bc3 and ee121b7.

📒 Files selected for processing (14)
  • Dockerfile
  • docs/manage-sandboxes/messaging-channels.mdx
  • scripts/nemoclaw-start.sh
  • src/lib/messaging/applier/build/messaging-build-applier.mts
  • test/messaging-build-applier-integrity.test.ts
  • test/messaging-build-applier.test.ts
  • test/nemoclaw-start-gateway-ws-host.test.ts
  • test/openclaw-dependency-review.test.ts
  • test/openclaw-integrity-pin.test.ts
  • test/openclaw-lifecycle-policy.test.ts
  • test/repro-4538-raw-doctor-perms.test.ts
  • test/repro-6413-whatsapp-postpair-start.test.ts
  • test/sandbox-provisioning.test.ts
  • test/whatsapp-qr-compact.test.ts
💤 Files with no reviewable changes (1)
  • test/repro-6413-whatsapp-postpair-start.test.ts

Comment thread scripts/nemoclaw-start.sh Outdated
@hunglp6d hunglp6d self-assigned this Jul 11, 2026
@cv cv added the v0.0.81 Release target label Jul 11, 2026
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv

cv commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

CI follow-up at 801a94987:

  • Replaced the setup-only gateway-token if/else in test/whatsapp-qr-compact.test.ts with the equivalent expression, preserving behavior while restoring the changed-test conditional budget.
  • npx vitest run --project integration test/whatsapp-qr-compact.test.ts: 33/33 passed.
  • npm run test-conditionals:scan -- --top 25: passed.
  • Biome, normal pre-commit hooks, CLI TypeScript pre-push check, and package/tag sync passed.

The commit is signed, signed off, and GitHub Verified.

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv

cv commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Security remediation for GPT Advisor PRA-2 at 3d0ec5a06:

  • Replaced the shadowable [-gated URL/token decisions with case routing.
  • Rejected non-loopback, malformed, and userinfo URLs now set a handled failure state and can never continue into child dispatch, even when an imported function shadows return.
  • Validated login execution uses absolute /usr/bin/env, so an imported command function cannot intercept or redirect it. The no-override path explicitly removes URL markers before OpenClaw resolves its loopback config.
  • Final handled dispatch uses builtin return; post-login diagnostics and errexit restoration no longer depend on [.
  • Added separate regressions that poison imported [, return, and command functions. They prove rejection status, absence of child/token exposure, safe executable dispatch, and preservation of nonzero child status.

Verification: 36/36 focused WhatsApp guard tests and 182/182 surrounding start/gateway/provisioning tests passed; ShellCheck, shfmt, Biome, the conditional scanner, normal pre-commit hooks, CLI pre-push typecheck, and package/tag sync passed. The commit is signed, signed off, and GitHub Verified.

This resolves PRA-2. PRA-1, the distinct post-pair restart-state acceptance test, remains separate and is not claimed by this change.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@test/whatsapp-qr-compact.test.ts`:
- Around line 462-487: Update both rejection tests in the “fails closed…” and
“cannot continue…” cases to assert that the sentinel value “guard-secret-token”
is absent from stderr as well as stdout, covering direct token leaks through
either output stream while retaining the existing public-boundary assertions.
🪄 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: 8a904508-ef4e-4b3d-a12a-feeef235487d

📥 Commits

Reviewing files that changed from the base of the PR and between 801a949 and 3d0ec5a.

📒 Files selected for processing (2)
  • scripts/nemoclaw-start.sh
  • test/whatsapp-qr-compact.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/nemoclaw-start.sh

Comment thread test/whatsapp-qr-compact.test.ts
cv added 2 commits July 10, 2026 22:34
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv

cv commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Maintainer remediation pushed at exact head 78110fe295456b38bec391065cec09b59ccf55a4.

This addresses the current GPT Advisor findings and the follow-up security review:

  • couples generated gateway-token publication to an empty or loopback-only URL and strips the token from every generic explicit-URL dispatch;
  • revalidates the mutable WhatsApp URL immediately at the absolute exec boundary, including userinfo rejection, so imported shell functions cannot redirect token-bearing dispatch;
  • preserves explicit-loopback WhatsApp authentication while keeping generic explicit-loopback commands token-free;
  • preserves handled and generic statuses under Bash and /bin/sh without relying on shadowable return, command, or exit functions;
  • adds the fix(whatsapp): post-pair gateway restart fails without operator.admin #6413 modeled channels.start running-state regression and private-veth missing scope: operator.admin control;
  • redacts rejected and accepted credential-like URL values.

Verification on this head:

  • 222 affected integration tests passed;
  • focused security suite passed 49/49;
  • shfmt, ShellCheck, Biome, CLI typecheck, test-project overlap, source-shape/size budgets, secret scan, commitlint, and normal pre-commit/pre-push hooks passed;
  • independent nine-category security review reran the userinfo mutation under strace and confirmed no OpenClaw child receives the attacker URL or token;
  • GitHub reports the signed commit as Verified and the PR-body DCO declaration remains present.

No documentation change is needed because the public pairing workflow is unchanged. Exact-head CI, automated review, and native-runtime E2E evidence are now running.

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv

cv commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

CI follow-up pushed at exact head a47c3882296b636de8cb6b60119950b6cae6c9e3.

The two failures on 78110fe29 were stale test plumbing after the intentional absolute dispatch hardening:

  • test/repro-4538-raw-doctor-perms.test.ts now provides an executable fake openclaw on PATH, so /usr/bin/env openclaw is exercised directly while preserving exit-7, permission restoration, hash refresh, and inherited-errexit assertions.
  • test/service-env.test.ts now checks the split token export/case assignment, expects absolute env dispatch, and sources the generated file to prove the trusted unset-URL path yields the configured token.

Verification: 44 tests passed with the existing opt-in Docker test skipped; Biome, CLI typecheck, project overlap, source-shape/size budgets, secret scan, and normal pre-commit/pre-push hooks passed. The new commit is GitHub Verified and DCO passes.

cv added 2 commits July 11, 2026 00:50
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@github-actions

Copy link
Copy Markdown
Contributor

E2E Target Results — ❌ Some jobs failed

Run: 29144927205
Workflow ref: fix/whatsapp-login-loopback
Requested targets: cloud-onboard,channels-add-remove,channels-stop-start
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 1 passed, 1 failed, 1 cancelled, 0 skipped

Job Result
channels-add-remove ❌ failure
channels-stop-start ⚠️ cancelled
cloud-onboard ✅ success

Failed jobs: channels-add-remove. Check run artifacts for logs.

@cv

cv commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Maintainer follow-up pushed at exact head 1b22b22762c15b38c154fdfa8194dc8a8bc67b80.

  • Fixed the advisor-noted shared-doc placeholder and restored the OpenClaw-only variant boundary so Hermes docs do not inherit OpenClaw gateway/QR troubleshooting.
  • Merged current main without rewriting history. This brings in c12915401 (fix(rebuild): preserve compatible provider recovery), which addresses the stale-base provider-selection failure seen in the earlier channels-add-remove live run before that run reached this PR's messaging behavior.
  • Post-merge verification passed: 345 affected integration tests, with one existing opt-in skip; CLI typecheck; agent-variant generation; route validation; and Fern validation with zero errors.
  • Both new commits are signed and include DCO declarations; normal commit and pre-push hooks passed.

The stale-head manual run was canceled. Fresh exact-head live evidence is running for cloud-onboard, channels-add-remove, and channels-stop-start at run 29145241512.

@github-actions

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All selected jobs passed

Run: 29145241512
Workflow ref: fix/whatsapp-login-loopback
Requested targets: cloud-onboard,channels-add-remove,channels-stop-start
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 3 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
channels-add-remove ✅ success
channels-stop-start ✅ success
cloud-onboard ✅ success

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved at exact head 1b22b22.

Required CI, DCO, commit verification, and CodeRabbit are clean. Exact-head E2E run 29145241512 passed cloud-onboard, channels-add-remove, and channels-stop-start for both OpenClaw and Hermes. The completed GPT-5.5 advisor returned merge_as_is with no findings.

I adjudicated the partial low-confidence Nemotron ledger against the implementation and regression tests: native post-pair reload is restored through the loopback route, the original argument vector (including --account) is forwarded unchanged, replacement security/preload coverage is present, and the claimed missing live targets all passed. The failed partial advisor job and older cancel-superseded status do not identify a valid implementation defect.

@cv
cv merged commit 439b5e7 into main Jul 11, 2026
128 of 130 checks passed
@cv
cv deleted the fix/whatsapp-login-loopback branch July 11, 2026 14:52
@cv cv mentioned this pull request Jul 12, 2026
21 tasks
cv added a commit that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Release-prep documentation for v0.0.81 now summarizes user-facing
changes merged since v0.0.80.
It also closes the Hermes dashboard-profile backup gap and distinguishes
direct blueprint-runner actions from public host CLI commands.

## Changes

- Add the `v0.0.81` section to `docs/about/release-notes.mdx` with links
to the detailed user guides.
- Document that Hermes rebuilds preserve `.hermes/dashboard-home/`,
including Dashboard `MEMORY.md` and `USER.md`.
- Update Hermes manual backup and restore examples to transfer those two
profile files without copying generated configuration or the
secret-bearing dashboard `.env`.
- Explain the new per-item backup failure causes.
- Clarify that migration snapshot retention fragments are direct-runner
arguments and are not exposed by the host `nemoclaw` CLI.

### Source summary

- #6445 -> `docs/about/release-notes.mdx`,
`docs/manage-sandboxes/backup-restore.mdx`, and
`docs/manage-sandboxes/workspace-files.mdx`: Summarize manifest-owned
key-level restore and current-config authority.
- #6617 -> `docs/about/release-notes.mdx` and
`docs/manage-sandboxes/backup-restore.mdx`: Record the fail-closed
`/proc` fallback used to verify an idle Deep Agents runtime before
snapshot creation.
- #6685 -> `docs/about/release-notes.mdx`,
`docs/manage-sandboxes/backup-restore.mdx`, and
`docs/manage-sandboxes/workspace-files.mdx`: Document Hermes Web
Dashboard profile persistence and safe manual transfer.
- #6649 -> `docs/about/release-notes.mdx`: Summarize host-validated
loopback compatible-endpoint routing through the sandbox gateway.
- #6643 -> `docs/about/release-notes.mdx`: Summarize automatic
`max_completion_tokens` handling for GPT-5 and o-series models.
- #6661 -> `docs/about/release-notes.mdx`: Summarize bounded connection
reuse for eligible provider-validation probes.
- #6704 -> `docs/about/release-notes.mdx`: Record that direct blueprint
apply stops instead of persisting incomplete state after provider or
inference setup fails.
- #6677 -> `docs/about/release-notes.mdx`: Summarize transactional
recovery for legacy Docker containers whose managed supervisor
disappeared after restart.
- #6625 -> `docs/about/release-notes.mdx`: Record Hermes managed-startup
persistence across direct Docker restarts.
- #6597 -> `docs/about/release-notes.mdx`: Record final-sandbox gateway
cleanup on macOS.
- #6680 -> `docs/about/release-notes.mdx`: Summarize managed Deep Agents
first-run and process-tree cleanup improvements.
- #6647 -> `docs/about/release-notes.mdx`: Record fail-closed validation
for the managed Deep Agents fetch CA bundle.
- #6645 -> `docs/about/release-notes.mdx`: Summarize WhatsApp loopback
pairing and trusted npm plugin provenance.
- #6673 -> `docs/about/release-notes.mdx` and
`docs/manage-sandboxes/backup-restore.mdx`: Document stopped-sandbox
backup remediation.
- #6631 -> `docs/about/release-notes.mdx` and
`docs/manage-sandboxes/backup-restore.mdx`: Document per-item backup
failure causes.
- #6620 -> `docs/about/release-notes.mdx`: Record the
created-but-not-ready sandbox lifecycle receipt.
- #6664 -> `docs/about/release-notes.mdx`: Record prompt-aware
onboarding progress output.
- #6598 -> `docs/about/release-notes.mdx`: Summarize stale replay-result
invalidation during resumed onboarding.
- #6593 -> `docs/about/release-notes.mdx`: Summarize contextual OpenClaw
audit findings for managed dashboard compatibility settings.
- #6650 -> `docs/about/release-notes.mdx`: Record redaction of
token-shaped URL query values.
- #6638 -> `docs/about/release-notes.mdx`: Record the exact-path MCP
`DELETE` policy recipe for session termination.
- #5453 -> `docs/reference/host-files-and-state.mdx`: Clarify that
snapshot retention actions belong to direct runner integrations and are
not standalone host CLI commands.

### Skipped from docs-skip

- #6633 matched the `openclaw-sandbox-permissive.yaml` path in
`docs/.docs-skip` and produced no documentation in this update.

## Type of Change

- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [x] 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 is a documentation-only
release-prep update; behavior is protected by the merged source PRs, and
the documentation build validates the changed examples and routes.
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — tests are not applicable for this
documentation-only change; `npm run docs` completed successfully.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result: not run for this
documentation-only change.
- [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) — 0
errors; two existing Fern warnings remain.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)
— no new pages.

---
Signed-off-by: Carlos Villela <cvillela@nvidia.com>


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

## Summary by CodeRabbit

- **Documentation**
- Added release notes for v0.0.81 covering state preservation, inference
setup, sandbox recovery, session setup, pairing, diagnostics, and
security policy updates.
- Expanded backup and restore guidance to include dashboard profile
files and clarify files that must not be copied.
- Added dashboard profile persistence details to workspace and rebuild
documentation.
- Clarified snapshot retention guidance and the distinction between host
CLI capabilities and direct runner actions.
  - Added more detailed backup failure reporting information.

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

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
…plugin provenance (NVIDIA#6645)

<!-- markdownlint-disable MD041 -->
## Summary
Fixes two stacked failures that made WhatsApp unusable on a stock
install — pairing succeeded but the channel never ran:

- **Login (NVIDIA#6413):** stop re-injecting the stashed private veth IP URL
into `openclaw channels login`. A private-IP origin makes the gateway's
locality check strip operator scopes (token or not), so the post-pair
`channels.start` was denied with `missing scope: operator.admin`. With
no URL in the env, OpenClaw resolves the loopback gateway from its own
config — same pattern as the `devices approve` wrapper (NVIDIA#4462) — and the
restart succeeds natively. Replaces the NVIDIA#6496 reconcile, which no-ops on
exactly this token-authed connect-shell path (`0:1:1` dispatch arm);
fresh-install validation with NVIDIA#6496 merged still reproduced the error.
- **Plugin trust:** install channel plugins through the `npm-pack:` spec
so OpenClaw records npm provenance for the integrity-verified tarball.
Archive-path installs record archive provenance, which fails the
trusted-official-install check gating `openKeyedStore` on OpenClaw >=
2026.6.10 — the channel crash-looped right after pairing
(`openKeyedStore is only available for trusted plugins in this
release`).
- **Removed with NVIDIA#6496's reconcile:** its config token reader,
`--account` forwarding, and the readonly gateway trust anchor (source of
the DGX Spark/Station regression, NVIDIA#6560). No gateway token moves
anywhere under this design.

**Blast radius:** the npm-pack change flows through the shared
installer, so all externally-installed channels (whatsapp, discord,
slack, msteams, weixin) plus diagnostics-otel/brave gain npm provenance;
telegram is bundled and unaffected. Audited: trust flip is benefit-only
(unblocks keyed stores that today crash or silently degrade), and the
new install layout breaks no path assumption (details below).

**Validated:** WhatsApp end-to-end live on a fresh install — QR pair, no
missing-scope, trusted record, channel running, real message round-trip.
Control run on unfixed main on the same host still fails.

<details>
<summary>Blast-radius audit: why the npm-pack change is safe for the
other channels</summary>

**What actually changes for a channel plugin?** Only two things: (1) the
install ledger now says the plugin came from npm (name, exact version,
integrity) instead of from an anonymous archive file, and (2) the
plugin's files land under
`.openclaw/npm/projects/<hash>/node_modules/<pkg>` instead of
`extensions/<id>`. The tarball itself, and the integrity verification
before installing it, are byte-for-byte the same as before.

**Could the new ledger entry break anything?** No — it only unlocks. The
trusted-official-install check is the single consumer of this
provenance, and today it fails for all five external channels. That is
why WhatsApp crash-loops at startup (it opens `openKeyedStore`
immediately), why Slack silently loses its duplicate-message protection
across restarts, and why Discord's interactive buttons/modals lose their
persistent state. With npm provenance the check passes and those
features work as designed. Nothing consumes "archive" provenance as a
positive signal, so nothing regresses.

**Could the new file location break anything?** We audited every place
that could care about the old path:
- *Runtime patches/preloads:* none match on `extensions/<id>`. The
WhatsApp compact-QR preload recognizes the qrcode module by its shape,
not its path.
- *Sandbox rebuild (backup/restore):* the backup never includes `npm/`,
so after a rebuild the plugin files and ledger always come from the
freshly built image. The old extensions-restore logic simply sees "no
extensions dir to preserve" and moves on — a state it already handles.
- *WeChat seed files:* they are written to the state dir
(`~/.openclaw/openclaw-weixin/`), not into the plugin's install dir, so
the move doesn't touch them. WeChat's hand-written `plugins.installs`
config entry keeps the old path, but the trust check never reads config
— only the ledger — so the stale entry is inert.

**Who is not affected at all?** Telegram — it ships bundled inside the
openclaw package, never goes through this installer, and was already
trusted.

**What was tested?** WhatsApp end-to-end on a fresh install (the only
channel that hard-fails today). The `openclaw-lifecycle-policy` contract
test verifies every reviewed package spec installs through the new
`npm-pack:` form.

</details>

## Related Issue
Fixes NVIDIA#6413

## Changes
<!-- Bullet list of key changes. -->

## Type of Change

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

## Quality Gates
<!-- Check exactly one tests line and one docs line. Check other lines
when applicable. Add every requested justification or approval
reference. -->
- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — targeted replacement of the NVIDIA#6496 login machinery: removes
gateway-token movement entirely (the reconcile helper and its config
token reader are deleted), removes the readonly trust anchor that
regressed DGX Spark/Station, and restores the pre-NVIDIA#6496 runtime-env
emission; the ws:// scheme check on an explicitly exported
`OPENCLAW_GATEWAY_URL` is retained.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification
<!-- Check each applicable item only when supported by the requested
evidence. Run targeted tests once per relevant change set and rerun
after later edits or hook autofixes that can affect the tested behavior.
Do not rerun hook-covered checks. -->
- [ ] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [ ] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [ ] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification:
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [ ] 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)
- [ ] 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)

---
<!-- DCO sign-off is required in this PR description, and every commit
must appear as Verified in GitHub. Run: git config user.name && git
config user.email -->
Signed-off-by: Hung Le <hple@nvidia.com>


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

- **Improvements**
- Updated OpenClaw plugin installation to use `npm-pack:` based
installs, aligning provenance/version traces (replacing direct archive
installs and `--pin`).
- Adjusted Docker-based plugin installation to use the verified tarball
install path that preserves npm provenance.
- Refreshed WhatsApp pairing/login: defaults to in-sandbox loopback,
accepts gateway URL overrides only for loopback `ws://`/`wss://`, and
exports gateway tokens whenever available.
- **Documentation**
- Shortened WhatsApp sandbox guidance and added troubleshooting for
gateway close code **1008**.
- **Tests**
- Updated messaging/OpenClaw trace expectations for `npm-pack:` formats
and revised WhatsApp guard coverage/fixtures to match the new
pairing/token/exit-code behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Hung Le <hple@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Release-prep documentation for v0.0.81 now summarizes user-facing
changes merged since v0.0.80.
It also closes the Hermes dashboard-profile backup gap and distinguishes
direct blueprint-runner actions from public host CLI commands.

## Changes

- Add the `v0.0.81` section to `docs/about/release-notes.mdx` with links
to the detailed user guides.
- Document that Hermes rebuilds preserve `.hermes/dashboard-home/`,
including Dashboard `MEMORY.md` and `USER.md`.
- Update Hermes manual backup and restore examples to transfer those two
profile files without copying generated configuration or the
secret-bearing dashboard `.env`.
- Explain the new per-item backup failure causes.
- Clarify that migration snapshot retention fragments are direct-runner
arguments and are not exposed by the host `nemoclaw` CLI.

### Source summary

- NVIDIA#6445 -> `docs/about/release-notes.mdx`,
`docs/manage-sandboxes/backup-restore.mdx`, and
`docs/manage-sandboxes/workspace-files.mdx`: Summarize manifest-owned
key-level restore and current-config authority.
- NVIDIA#6617 -> `docs/about/release-notes.mdx` and
`docs/manage-sandboxes/backup-restore.mdx`: Record the fail-closed
`/proc` fallback used to verify an idle Deep Agents runtime before
snapshot creation.
- NVIDIA#6685 -> `docs/about/release-notes.mdx`,
`docs/manage-sandboxes/backup-restore.mdx`, and
`docs/manage-sandboxes/workspace-files.mdx`: Document Hermes Web
Dashboard profile persistence and safe manual transfer.
- NVIDIA#6649 -> `docs/about/release-notes.mdx`: Summarize host-validated
loopback compatible-endpoint routing through the sandbox gateway.
- NVIDIA#6643 -> `docs/about/release-notes.mdx`: Summarize automatic
`max_completion_tokens` handling for GPT-5 and o-series models.
- NVIDIA#6661 -> `docs/about/release-notes.mdx`: Summarize bounded connection
reuse for eligible provider-validation probes.
- NVIDIA#6704 -> `docs/about/release-notes.mdx`: Record that direct blueprint
apply stops instead of persisting incomplete state after provider or
inference setup fails.
- NVIDIA#6677 -> `docs/about/release-notes.mdx`: Summarize transactional
recovery for legacy Docker containers whose managed supervisor
disappeared after restart.
- NVIDIA#6625 -> `docs/about/release-notes.mdx`: Record Hermes managed-startup
persistence across direct Docker restarts.
- NVIDIA#6597 -> `docs/about/release-notes.mdx`: Record final-sandbox gateway
cleanup on macOS.
- NVIDIA#6680 -> `docs/about/release-notes.mdx`: Summarize managed Deep Agents
first-run and process-tree cleanup improvements.
- NVIDIA#6647 -> `docs/about/release-notes.mdx`: Record fail-closed validation
for the managed Deep Agents fetch CA bundle.
- NVIDIA#6645 -> `docs/about/release-notes.mdx`: Summarize WhatsApp loopback
pairing and trusted npm plugin provenance.
- NVIDIA#6673 -> `docs/about/release-notes.mdx` and
`docs/manage-sandboxes/backup-restore.mdx`: Document stopped-sandbox
backup remediation.
- NVIDIA#6631 -> `docs/about/release-notes.mdx` and
`docs/manage-sandboxes/backup-restore.mdx`: Document per-item backup
failure causes.
- NVIDIA#6620 -> `docs/about/release-notes.mdx`: Record the
created-but-not-ready sandbox lifecycle receipt.
- NVIDIA#6664 -> `docs/about/release-notes.mdx`: Record prompt-aware
onboarding progress output.
- NVIDIA#6598 -> `docs/about/release-notes.mdx`: Summarize stale replay-result
invalidation during resumed onboarding.
- NVIDIA#6593 -> `docs/about/release-notes.mdx`: Summarize contextual OpenClaw
audit findings for managed dashboard compatibility settings.
- NVIDIA#6650 -> `docs/about/release-notes.mdx`: Record redaction of
token-shaped URL query values.
- NVIDIA#6638 -> `docs/about/release-notes.mdx`: Record the exact-path MCP
`DELETE` policy recipe for session termination.
- NVIDIA#5453 -> `docs/reference/host-files-and-state.mdx`: Clarify that
snapshot retention actions belong to direct runner integrations and are
not standalone host CLI commands.

### Skipped from docs-skip

- NVIDIA#6633 matched the `openclaw-sandbox-permissive.yaml` path in
`docs/.docs-skip` and produced no documentation in this update.

## Type of Change

- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [x] 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 is a documentation-only
release-prep update; behavior is protected by the merged source PRs, and
the documentation build validates the changed examples and routes.
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — tests are not applicable for this
documentation-only change; `npm run docs` completed successfully.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result: not run for this
documentation-only change.
- [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) — 0
errors; two existing Fern warnings remain.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)
— no new pages.

---
Signed-off-by: Carlos Villela <cvillela@nvidia.com>


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

## Summary by CodeRabbit

- **Documentation**
- Added release notes for v0.0.81 covering state preservation, inference
setup, sandbox recovery, session setup, pairing, diagnostics, and
security policy updates.
- Expanded backup and restore guidance to include dashboard profile
files and clarify files that must not be copied.
- Added dashboard profile persistence details to workspace and rebuild
documentation.
- Clarified snapshot retention guidance and the distinction between host
CLI capabilities and direct runner actions.
  - Added more detailed backup failure reporting information.

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

Signed-off-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

v0.0.81 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(whatsapp): post-pair gateway restart fails without operator.admin

2 participants