Skip to content

Commit 2cedcef

Browse files
prekshivyasgithub-actions[bot]senthilr-nv
authored
fix(messaging): bind OpenClaw WeChat credentials (#10601)
## Outcome This PR repairs the remaining OpenClaw WeChat credential lifecycle for the two iLink hosts currently authorized by repository policy. The Tencent plugin account file now receives the exact revision-scoped OpenShell placeholder, both authorized REST endpoints retain endpointless provider binding, and channel removal clears durable account state before policy or registry teardown. Raw bot tokens remain outside sandbox files, arguments, and diagnostics. ## Reason The WeChat seed hook writes its token outside `openclaw.json`, while the generic startup refresh updated placeholders only inside `openclaw.json`. OpenShell therefore could not match the canonical account-file placeholder to the provider revision required by L7 credential binding. ### Related issues Fixes #10079 ## Changes - Bind both currently authorized OpenClaw WeChat REST endpoints to `{sandboxName}-wechat-bridge` and require the WeChat preset at sandbox creation. - Refresh enabled WeChat account files from the exact runtime `WECHAT_BOT_TOKEN` placeholder through descriptor-relative, no-follow operations. - Fail closed on raw or malformed values, unsafe IDs, symlinks, hard links, permissive modes, and concurrent file replacement. - Clear `/sandbox/.openclaw/openclaw-weixin` account state before removal mutates provider, policy, plan, or registry state; preserve retryable state if cleanup fails. - Execute the checked-in production refresh helper directly in deterministic tests and register its Python path in the changed-test trigger map. - Extend the existing `messaging-providers` and `channels-stop-start` contracts with redacted installed-runtime and cleanup evidence. ## Product scope boundary Valid QR responses may return an `idc-N.weixin.qq.com` host, while current OpenClaw and Hermes policies authorize only literal static iLink hosts. That pre-existing network-policy inconsistency is tracked in #10606 and is not introduced by this PR. #10606 is still `needs: triage` and has no recorded `Accept` product decision, so the repository product-scope gate prohibits widening or changing that supported network surface here. This PR does not claim IDC-host support. ## Verification Candidate head: `aeeae739a22e868853060f3ee2965c51cdd74531` Trusted base: `ab118eb2d14727d411726e34a385f65ccfd1d180` - Credential-registration boundary: 25/25 tests passed. - Fake WeChat API and runtime proof support: 24/24 tests passed. - CLI type-check, repository checks, Oxfmt, Oxlint, gitleaks, source-shape budget, and commit/pre-push hooks passed. - Codebase growth guardrails: 32/32 passed locally on the refreshed base; exact-head GitHub run [33302574932](https://github.com/NVIDIA/NemoClaw/actions/runs/33302574932) passed without a budget change. - The exact CLI/integration/E2E-support shard 11 selection passed the credential-registration test and 3,336 tests overall locally. Three unrelated local tests failed: one macOS shell lacks `BASHPID`, one agent-command test timed out, and one warmup test did not create its expected log. - Exact-head CI [33302575905](https://github.com/NVIDIA/NemoClaw/actions/runs/33302575905), Review Advisor [33302574922](https://github.com/NVIDIA/NemoClaw/actions/runs/33302574922), security [33302575862](https://github.com/NVIDIA/NemoClaw/actions/runs/33302575862), managed images [33302575896](https://github.com/NVIDIA/NemoClaw/actions/runs/33302575896), rootless Podman [33302575893](https://github.com/NVIDIA/NemoClaw/actions/runs/33302575893), and self-hosted qualification [33302576858](https://github.com/NVIDIA/NemoClaw/actions/runs/33302576858) passed. The exact head has 70 passing checks, 6 expected skips, and no failures. - All nine exact-head Review Advisor summaries report no finding after the documented best-effort synchronization result was clarified. No review thread is unresolved. ### Live qualification boundary Trusted manual run [33298977079](https://github.com/NVIDIA/NemoClaw/actions/runs/33298977079) used candidate `6db670ed0b954cc217b607bc830fec54a2b1c72d`, base/workflow `d1f401eeac15cd4354c42578fecf34b9c7463c75`, and correlation `2acb6c65-41bf-4f23-a088-fd9ab074f220`. The current head differs from that candidate only by non-production changes: deleting a source-shape-only routing assertion, moving the full onboarding import outside the timed drift-guard assertion, merging the unrelated voice-test-only upstream commit `ab118eb2d14727d411726e34a385f65ccfd1d180`, and clarifying the documented failure result of best-effort session policy synchronization. - OpenClaw Telegram add/remove passed with 85 product-evidence files. - OpenClaw and Hermes all-channel stop/start both stopped during initial onboarding after the gateway registered Google Chat refresh and reported mint status `error`; downstream lifecycle phases were skipped. This is a validation-fixture gate, not passing evidence for the channel matrix. - Both failed jobs completed cleanup with no failures: each destroyed its sandbox, deleted every registered messaging provider, removed the gateway, and stopped the heartbeat. - The run did not send bot messages. Current bot-reply validation remains unrun because no configured `_REAL` route target was proven automation-only. Historical #10273 evidence records actual replies for Slack, Discord, and Google Chat on both agents; it is not represented as current-head proof. ## Review notes This changes a credential-binding, startup file-mutation, and durable-state cleanup boundary. Diagnostics name only the affected key or state class, never credential values. The installed WeChat proof uses a repository fake API and must not be described as a real bot reply. --- Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added WeChat messaging support, including account configuration, credential handling, runtime validation, and message delivery. * Added secure WeChat token placeholder refresh during startup. * Added cleanup of WeChat account state when removing the channel. * **Bug Fixes** * Improved channel-state cleanup with validation, safer recovery, and clearer remediation guidance. * Prevented unsafe or invalid state paths from being processed. * **Tests** * Added comprehensive WeChat lifecycle, runtime, credential-redaction, and cleanup coverage. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Senthil Ravichandran <senthilr@nvidia.com>
1 parent 5708798 commit 2cedcef

41 files changed

Lines changed: 3179 additions & 400 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ COPY scripts/lib/sandbox-rlimits.sh /usr/local/lib/nemoclaw/sandbox-rlimits.sh
580580
COPY scripts/lib/openclaw_device_approval_policy.py /usr/local/lib/nemoclaw/openclaw_device_approval_policy.py
581581
COPY scripts/lib/clean_runtime_shell_env_shim.py /usr/local/lib/nemoclaw/clean_runtime_shell_env_shim.py
582582
COPY scripts/lib/normalize_mutable_config_perms.py /usr/local/lib/nemoclaw/normalize_mutable_config_perms.py
583+
COPY scripts/lib/refresh-openclaw-wechat-placeholder.py /usr/local/lib/nemoclaw/refresh-openclaw-wechat-placeholder.py
583584
COPY scripts/state-dir-guard.py /usr/local/lib/nemoclaw/state-dir-guard.py
584585
COPY agents/openclaw/state-lock-plan.json /usr/local/share/nemoclaw/state-lock-plan.json
585586
COPY scripts/openclaw-config-guard.py /usr/local/lib/nemoclaw/openclaw-config-guard.py

docs/manage-sandboxes/manage-messaging-channels.mdx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,17 @@ The cleanup targets `/sandbox/.openclaw/<channel>/`.
6969
The cleanup targets `/sandbox/.hermes/platforms/<channel>/`.
7070
</AgentOnly>
7171

72-
It tries `openshell sandbox exec` and falls back to SSH if the first transport does not produce the success sentinel. If neither transport can reach a running sandbox, the command exits nonzero and asks you to start the sandbox and rerun it.
72+
It tries `openshell sandbox exec` and falls back to SSH if the first transport does not produce the success sentinel.
7373

74-
NemoClaw leaves the registry and current OpenShell policy unchanged on that failure path so a later retry can complete cleanly.
74+
<AgentOnly variant="openclaw">
75+
For OpenClaw WeChat only, if neither transport succeeds, NemoClaw tries the stopped Docker fallback.
76+
It confirms that the container belongs to the registered sandbox and has one writable Docker volume at `/sandbox`.
77+
The helper removes only the WeChat state paths declared by the channel manifest.
78+
Only when WeChat appears in neither the messaging plan nor the current OpenShell policy does NemoClaw treat state cleanup as complete without inspecting a volume if the registry entry is missing, the driver is not Docker, or no eligible stopped container exists.
79+
</AgentOnly>
80+
81+
If the messaging plan or current OpenShell policy still records the channel and NemoClaw cannot confirm cleanup, the command exits nonzero with recovery guidance.
82+
It leaves the bridge provider, credentials, registry, and current OpenShell policy unchanged so you can fix the reported condition and retry removal.
7583

7684
`channels remove whatsapp` clears the client-side Baileys session but cannot deregister the linked device with WhatsApp's servers after the local connection is gone. The phone continues to list the sandbox as a Linked Device until you remove it manually or WhatsApp's 14-day inactivity timeout expires.
7785

0 commit comments

Comments
 (0)