fix(runtime): keep proxy env POSIX-compatible#6560
Conversation
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
📝 WalkthroughWalkthroughThe runtime env and WhatsApp login flow now enforce trusted-gateway token handling with POSIX shell primitives. Tests were updated to run the env and login probes under both bash and sh, and guard-extraction helpers now inject the trusted gateway URL into generated guard snippets. ChangesPOSIX Shell Gateway Handling
Estimated code review effort: 4 (Complex) | ~45 minutes Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Code Coverage OverviewLanguages: TypeScript TypeScript / code-coverage/pluginThe overall coverage remains at 96%, unchanged from the branch. TypeScript / code-coverage/cliThe overall coverage in the branch remains at 76%, unchanged from the branch. Show a code coverage summary of the most impacted files.
Updated |
PR Review Advisor (Nemotron Ultra) — InformationalMerge posture: Informational / low confidence Action checklist
Findings index
Review findings by urgency: 0 required fixes, 1 item to resolve/justify, 0 in-scope improvements
|
PR Review Advisor — No blocking findingsMerge posture: No blocking advisor findings Action checklist
Test follow-ups to resolve or justifyIf these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.
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. |
E2E Advisor RecommendationRequired E2E: Dispatch hint: Full advisor summaryE2E Recommendation AdvisorBase: Required E2E
Optional E2E
New E2E recommendations
Dispatch hint
|
E2E Target RecommendationRequired E2E targets: Dispatch required E2E targets:
Full E2E target advisor summaryE2E Target AdvisorBase: Required E2E targets
Optional E2E targets
Relevant changed files
|
E2E Target Results — ✅ All requested jobs passedRun: 29008085596
|
E2E Target Results — ✅ All selected jobs passedRun: 29008260147
|
E2E Target Results — ✅ All requested jobs passedRun: 29008260120
|
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
E2E Target Results — ✅ All selected jobs passedRun: 29009134059
|
E2E Target Results — ✅ All requested jobs passedRun: 29009134045
|
E2E Target Results — ✅ All requested jobs passedRun: 29009134091
|
E2E Target Results — ✅ All selected jobs passedRun: 29009460466
|
E2E Target Results — ✅ All requested jobs passedRun: 29009460549
|
E2E Target Results — ✅ All requested jobs passedRun: 29009460556
|
E2E Target Results — ✅ All selected jobs passedRun: 29010342567
|
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
There was a problem hiding this comment.
🧹 Nitpick comments (2)
test/repro-6413-whatsapp-postpair-start.test.ts (2)
39-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract the duplicated
extractGuardFunctioninto a shared test helper.This helper is copy-pasted in
test/whatsapp-qr-compact.test.ts(lines 277-293) and the two copies have already diverged (assert(...)here vsthrow new Error(...)there). Consolidating into one shared module keeps the marker/injection contract in a single place so both suites stay in sync as the guard structure evolves.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/repro-6413-whatsapp-postpair-start.test.ts` around lines 39 - 59, The extractGuardFunction logic is duplicated across multiple test suites and has already diverged in error handling, so centralize it into a shared test helper and have both suites import the same implementation. Move the marker parsing and injection replacement logic from extractGuardFunction into a common module, then update the callers in the WhatsApp-related tests to use that helper so the trusted-gateway marker contract stays in sync.
48-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffReconstruction may drift from the actually generated guard.
The marker-based surgery re-derives the guard by hand instead of running the real writer, so it re-implements the script's literal-injection. Note the escaping is not identical: the script emits
printf "..._nemoclaw_whatsapp_trusted_url='%s'"(sed single-quote escaping), whereas this reconstruction usesJSON.stringify(double-quote/JS escaping). For plain URLs they coincide, but a URL containing a quote would be assembled differently, so the test would validate a body the script never emits. Consider deriving the guard from realwrite_runtime_shell_envoutput (astest/nemoclaw-start-gateway-ws-host.test.tsdoes) for higher fidelity.As per path instructions: "Prefer observable outcomes through the public boundary over source-text, private-shape, or mock-call assertions" and "Flag copied production algorithms."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/repro-6413-whatsapp-postpair-start.test.ts` around lines 48 - 59, The reconstruction in this test is re-implementing the trusted-gateway guard logic instead of using the real generator, so it can diverge from the actual emitted shell body. Update the test to derive the guard from the real write_runtime_shell_env output, following the approach used in test/nemoclaw-start-gateway-ws-host.test.ts, rather than slicing and rebuilding the marker block by hand. Make sure the assertion still targets the same observable trusted-gateway injection behavior, but avoid using JSON.stringify-based reconstruction that can differ from the script’s sed/printf escaping in the actual writer.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@test/repro-6413-whatsapp-postpair-start.test.ts`:
- Around line 39-59: The extractGuardFunction logic is duplicated across
multiple test suites and has already diverged in error handling, so centralize
it into a shared test helper and have both suites import the same
implementation. Move the marker parsing and injection replacement logic from
extractGuardFunction into a common module, then update the callers in the
WhatsApp-related tests to use that helper so the trusted-gateway marker contract
stays in sync.
- Around line 48-59: The reconstruction in this test is re-implementing the
trusted-gateway guard logic instead of using the real generator, so it can
diverge from the actual emitted shell body. Update the test to derive the guard
from the real write_runtime_shell_env output, following the approach used in
test/nemoclaw-start-gateway-ws-host.test.ts, rather than slicing and rebuilding
the marker block by hand. Make sure the assertion still targets the same
observable trusted-gateway injection behavior, but avoid using
JSON.stringify-based reconstruction that can differ from the script’s sed/printf
escaping in the actual writer.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: c0f18006-2169-4f6e-a650-586e381557ee
📒 Files selected for processing (4)
scripts/nemoclaw-start.shtest/nemoclaw-start-gateway-ws-host.test.tstest/repro-6413-whatsapp-postpair-start.test.tstest/whatsapp-qr-compact.test.ts
E2E Target Results —
|
| Job | Result |
|---|---|
| gateway-guard-recovery | ✅ success |
| messaging-providers | |
| openshell-gateway-auth-contract | ✅ success |
E2E Target Results — ✅ All selected jobs passedRun: 29010902764
|
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
E2E Target Results —
|
| Job | Result |
|---|---|
| gateway-guard-recovery | ✅ success |
| messaging-providers | |
| openshell-gateway-auth-contract | ✅ success |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
test/whatsapp-qr-compact.test.ts (2)
278-296: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffMarker-based source-text splicing is brittle and tightly coupled to
scripts/nemoclaw-start.shlayout.
extractGuardFunctionnow depends on exact substrings (GUARDENVEOF\n # nemoclaw-trusted-gateway-literal-injection begin, etc.) from the generated shell script. Any whitespace/indentation change in the production script (even a harmless one) silently breaks this test via theassertfailure rather than exercising real behavioral drift. As per path instructions, tests should prefer observable outcomes through the public boundary over source-text/private-shape assertions; this pattern is inherently source-text coupled. If there's no alternative to extracting the raw guard body, consider deriving markers from named anchors that are less likely to shift with formatting-only edits.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/whatsapp-qr-compact.test.ts` around lines 278 - 296, The `extractGuardFunction` helper is too tightly coupled to the exact text layout of `scripts/nemoclaw-start.sh`, making the test brittle on formatting-only changes. Refactor the test to avoid splicing with hardcoded substrings like the trusted gateway injection markers, and instead assert behavior through a more stable boundary or use named anchors that are less sensitive to whitespace/indentation shifts. Keep the change localized to `extractGuardFunction` in `test/whatsapp-qr-compact.test.ts`.Source: Path instructions
291-295: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value
JSON.stringifyisn't shell-safe quoting for the injected URL.
JSON.stringify(trustedGatewayUrl)escapes"and\but not$or backticks, which remain special inside double-quoted shell strings (variable expansion / command substitution). If any test's gateway URL fixture ever contains$or a backtick, the generated guard script would be corrupted or trigger unintended substitution when sourced.🔧 Safer approach
- return `${guardSource.slice(0, injectionStart)} _nemoclaw_whatsapp_trusted_url=${JSON.stringify(trustedGatewayUrl)}\n${guardSource.slice(injectionEnd + injectionEndMarker.length)}`; + const shellSingleQuoted = `'${trustedGatewayUrl.replace(/'/g, "'\\''")}'`; + return `${guardSource.slice(0, injectionStart)} _nemoclaw_whatsapp_trusted_url=${shellSingleQuoted}\n${guardSource.slice(injectionEnd + injectionEndMarker.length)}`;Since test URLs are currently simple/controlled, real-world impact is limited today, but this is fragile if fixtures ever change.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/whatsapp-qr-compact.test.ts` around lines 291 - 295, The trusted gateway URL injection in the whatsapp QR compact test uses JSON.stringify, which is not safe for shell assignment content in the generated guard script. Update the injection logic around the marker replacement in the test to use shell-safe quoting/escaping for the `_nemoclaw_whatsapp_trusted_url` value so `$` and backticks cannot be expanded when sourced, and keep the change localized to the trusted gateway literal generation in this test helper.
🤖 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/repro-4538-raw-doctor-perms.test.ts`:
- Line 75: The injected URL in the guard script is being serialized with
JSON.stringify, which can alter shell semantics for special characters; update
the URL injection in the helper around the return template to use POSIX shell
single-quote escaping instead. Keep the shell literal form consistent with the
guard source so the emitted script remains safe for URLs containing $,
backticks, quotes, or backslashes.
---
Nitpick comments:
In `@test/whatsapp-qr-compact.test.ts`:
- Around line 278-296: The `extractGuardFunction` helper is too tightly coupled
to the exact text layout of `scripts/nemoclaw-start.sh`, making the test brittle
on formatting-only changes. Refactor the test to avoid splicing with hardcoded
substrings like the trusted gateway injection markers, and instead assert
behavior through a more stable boundary or use named anchors that are less
sensitive to whitespace/indentation shifts. Keep the change localized to
`extractGuardFunction` in `test/whatsapp-qr-compact.test.ts`.
- Around line 291-295: The trusted gateway URL injection in the whatsapp QR
compact test uses JSON.stringify, which is not safe for shell assignment content
in the generated guard script. Update the injection logic around the marker
replacement in the test to use shell-safe quoting/escaping for the
`_nemoclaw_whatsapp_trusted_url` value so `$` and backticks cannot be expanded
when sourced, and keep the change localized to the trusted gateway literal
generation in this test helper.
🪄 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: 16691850-9340-418e-9453-28c6c4911966
📒 Files selected for processing (2)
test/repro-4538-raw-doctor-perms.test.tstest/whatsapp-qr-compact.test.ts
E2E Target Results — ✅ All selected jobs passedRun: 29011947901
|
E2E Target Results — ✅ All requested jobs passedRun: 29011618741
|
E2E Target Results — ✅ All requested jobs passedRun: 29011948002
|
|
Exact-head gate complete at
The PR is content-mergeable with no pending or failed current checks. The remaining gate is independent review; I am not self-approving or merging a |
<!-- markdownlint-disable MD041 --> ## Summary Adds the pre-tag v0.0.79 release notes entry to `docs/about/release-notes.mdx` so the release plan can be generated after docs merge. The entry summarizes the merged v0.0.79 release train across inference, diagnostics, runtime hardening, policies, onboarding recovery, and release validation. ## Changes - Added the v0.0.79 release notes section with linked follow-up documentation for OpenRouter onboarding, managed vLLM changes, completion and logging, Deep Agents runtime limits, policy updates, onboarding recovery, and release validation. - Source summary: - #6461 -> `docs/about/release-notes.mdx`: Documents OpenRouter onboarding support and links to inference/provider references. - #6271 and #6272 -> `docs/about/release-notes.mdx`: Documents shell completion and structured logging highlights. - #6465, #6539, #6570, and #6528 -> `docs/about/release-notes.mdx`: Documents status route-drift, orphaned sandbox, gateway cleanup, and DGX Spark express-install diagnostics. - #6523, #6551, #6484, #6488, #6324, and #6542 -> `docs/about/release-notes.mdx`: Documents managed vLLM, Qwen3.6 tool parser, compaction, and timeout/readiness improvements. - #6559, #6538, #6560, #6568, #6552, #6567, and #6587 -> `docs/about/release-notes.mdx`: Documents runtime, credential, proxy, PID namespace, TOML, and provider-state hardening. - #6541, #5415, #6246, #6496, and #6573 -> `docs/about/release-notes.mdx`: Documents GitHub policy, Gmail policy, MCP allowlist, WhatsApp, and messaging-variant updates. - #6253, #6572, #6444, #6536, and #5860 -> `docs/about/release-notes.mdx`: Documents onboarding resume and create-step recovery improvements. - #6508, #6527, #5506, #6588, #6446, #6447, #6582, #6296, #6367, #6397, and #6505 -> `docs/about/release-notes.mdx`: Documents docs, release-risk, and E2E validation updates. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates <!-- Check exactly one tests line and one docs line. Check other lines when applicable. Add every requested justification or approval reference. --> - [ ] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [x] Tests not applicable — justification: Release-note prose only. - [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 <!-- 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. --> - [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 — command/result or justification: Tests not applicable, release-note prose only. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [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) Docs validation note: `npm run docs:check-agent-variants && npm run docs:check-routes && git diff --check` passed. Full `npm run docs` is currently blocked before Fern validation because the pinned `fern-api@5.65.2` package is unavailable from npm (`ETARGET No matching version found`). --- <!-- 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: Julie Yaunches <jyaunches@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes for v0.0.79 with a new summary of recent improvements, including onboarding and inference options, operator/CLI diagnostics, sandbox recovery hardening, runtime limits, network policy behavior, and release validation updates. * Added updated references and links for the latest release. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…plugin provenance (#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 (#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 (#4462) — and the restart succeeds natively. Replaces the #6496 reconcile, which no-ops on exactly this token-authed connect-shell path (`0:1:1` dispatch arm); fresh-install validation with #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 #6496's reconcile:** its config token reader, `--account` forwarding, and the readonly gateway trust anchor (source of the DGX Spark/Station regression, #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 #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 #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-#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>
<!-- markdownlint-disable MD041 --> ## Summary Fixes a regression from NVIDIA#6496 where the generated `/tmp/nemoclaw-proxy-env.sh` used Bash-only `builtin` commands, causing POSIX login shells to reject the gateway trust anchor and fail lifecycle operations. The generated file now preserves fail-closed trust behavior in Bash and POSIX `sh`, including when ordinary Bash functions are imported from the caller environment. ## Changes - Invoke the `readonly` and `unset` shell builtins through portable `command` dispatch in the generated runtime environment. - Validate source-time anchor values with unshadowable shell `case` syntax and structurally withhold token re-export unless the exact baked anchor is readonly. - Bake the trusted gateway URL directly into the root-owned WhatsApp helper, independently of caller-preseedable variables. - Route WhatsApp login and trust decisions with shell syntax that imported functions cannot intercept. - Launch caller-selected gateway logins through `/usr/bin/env -u OPENCLAW_GATEWAY_TOKEN`, so readonly parent variables and imported `command`, `unset`, or `exit` functions cannot preserve the token in the child. - Cover repeated Bash/POSIX-sh sourcing, conflicting and mutable anchors, readonly tokens, and before/after-source function-shadowing regressions. ## Type of Change - [x] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates <!-- 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: - [ ] Docs updated for user-facing behavior changes - [x] Docs not applicable — justification: this restores the documented shell-hook behavior without changing commands, configuration, security boundaries, or operator workflows. - [x] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [x] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: independent audit exercised source-time and invocation-time function-shadowing, readonly-token, poisoned-anchor, mutable-anchor, and caller-selected gateway paths; the final audit found no remaining bypass in the imported ordinary-function boundary. - [ ] 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. --> - [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 — command/result or justification: `npx vitest run --project integration test/nemoclaw-start-gateway-ws-host.test.ts test/whatsapp-qr-compact.test.ts test/repro-6413-whatsapp-postpair-start.test.ts` (56/56 passed) - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [ ] 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: Carlos Villela <cvillela@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved trusted-gateway and read-only enforcement in POSIX shells, adding confirmation checks and fail-closed behavior when enforcement can’t be verified. * Strengthened WhatsApp gateway login flow to ensure the gateway token is stripped in non-trusted paths, with clearer detection of token-clearing failures. * **Tests** * Expanded WhatsApp pairing/login and gateway websocket-host probes to run under both `bash` and POSIX `sh`, with per-shell assertions. * Updated guard and token-stripping tests to inject per-scenario trusted gateway URLs and validate outcomes via the `openclaw` call log. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Carlos Villela <cvillela@nvidia.com> Co-authored-by: J. Yaunches <jyaunches@nvidia.com>
<!-- markdownlint-disable MD041 --> ## Summary Adds the pre-tag v0.0.79 release notes entry to `docs/about/release-notes.mdx` so the release plan can be generated after docs merge. The entry summarizes the merged v0.0.79 release train across inference, diagnostics, runtime hardening, policies, onboarding recovery, and release validation. ## Changes - Added the v0.0.79 release notes section with linked follow-up documentation for OpenRouter onboarding, managed vLLM changes, completion and logging, Deep Agents runtime limits, policy updates, onboarding recovery, and release validation. - Source summary: - NVIDIA#6461 -> `docs/about/release-notes.mdx`: Documents OpenRouter onboarding support and links to inference/provider references. - NVIDIA#6271 and NVIDIA#6272 -> `docs/about/release-notes.mdx`: Documents shell completion and structured logging highlights. - NVIDIA#6465, NVIDIA#6539, NVIDIA#6570, and NVIDIA#6528 -> `docs/about/release-notes.mdx`: Documents status route-drift, orphaned sandbox, gateway cleanup, and DGX Spark express-install diagnostics. - NVIDIA#6523, NVIDIA#6551, NVIDIA#6484, NVIDIA#6488, NVIDIA#6324, and NVIDIA#6542 -> `docs/about/release-notes.mdx`: Documents managed vLLM, Qwen3.6 tool parser, compaction, and timeout/readiness improvements. - NVIDIA#6559, NVIDIA#6538, NVIDIA#6560, NVIDIA#6568, NVIDIA#6552, NVIDIA#6567, and NVIDIA#6587 -> `docs/about/release-notes.mdx`: Documents runtime, credential, proxy, PID namespace, TOML, and provider-state hardening. - NVIDIA#6541, NVIDIA#5415, NVIDIA#6246, NVIDIA#6496, and NVIDIA#6573 -> `docs/about/release-notes.mdx`: Documents GitHub policy, Gmail policy, MCP allowlist, WhatsApp, and messaging-variant updates. - NVIDIA#6253, NVIDIA#6572, NVIDIA#6444, NVIDIA#6536, and NVIDIA#5860 -> `docs/about/release-notes.mdx`: Documents onboarding resume and create-step recovery improvements. - NVIDIA#6508, NVIDIA#6527, NVIDIA#5506, NVIDIA#6588, NVIDIA#6446, NVIDIA#6447, NVIDIA#6582, NVIDIA#6296, NVIDIA#6367, NVIDIA#6397, and NVIDIA#6505 -> `docs/about/release-notes.mdx`: Documents docs, release-risk, and E2E validation updates. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates <!-- Check exactly one tests line and one docs line. Check other lines when applicable. Add every requested justification or approval reference. --> - [ ] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [x] Tests not applicable — justification: Release-note prose only. - [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 <!-- 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. --> - [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 — command/result or justification: Tests not applicable, release-note prose only. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [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) Docs validation note: `npm run docs:check-agent-variants && npm run docs:check-routes && git diff --check` passed. Full `npm run docs` is currently blocked before Fern validation because the pinned `fern-api@5.65.2` package is unavailable from npm (`ETARGET No matching version found`). --- <!-- 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: Julie Yaunches <jyaunches@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes for v0.0.79 with a new summary of recent improvements, including onboarding and inference options, operator/CLI diagnostics, sandbox recovery hardening, runtime limits, network policy behavior, and release validation updates. * Added updated references and links for the latest release. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…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>
Summary
Fixes a regression from #6496 where the generated
/tmp/nemoclaw-proxy-env.shused Bash-onlybuiltincommands, causing POSIX login shells to reject the gateway trust anchor and fail lifecycle operations. The generated file now preserves fail-closed trust behavior in Bash and POSIXsh, including when ordinary Bash functions are imported from the caller environment.Changes
readonlyandunsetshell builtins through portablecommanddispatch in the generated runtime environment.casesyntax and structurally withhold token re-export unless the exact baked anchor is readonly./usr/bin/env -u OPENCLAW_GATEWAY_TOKEN, so readonly parent variables and importedcommand,unset, orexitfunctions cannot preserve the token in the child.Type of Change
Quality Gates
Verification
Verifiedin GitHubpre-commit,commit-msg, andpre-pushhooks passed, ornpm run check:diffpassed when hooks were skipped or unavailablenpx vitest run --project integration test/nemoclaw-start-gateway-ws-host.test.ts test/whatsapp-qr-compact.test.ts test/repro-6413-whatsapp-postpair-start.test.ts(56/56 passed)npm testfor broad runtime/test-harness changes;npm run checkfor repo-wide validation/coverage changes — command/result:npm run docsbuilds without warnings (doc changes only)Signed-off-by: Carlos Villela cvillela@nvidia.com
Summary by CodeRabbit
bashand POSIXsh, with per-shell assertions.openclawcall log.