Skip to content

feat(messaging): migrate enrollment to manifest hooks#4248

Open
sandl99 wants to merge 28 commits into
u/sdang/messaging-hooks-channels-3993-3994from
u/sdang/3896-phase-2-messaging-enrollment
Open

feat(messaging): migrate enrollment to manifest hooks#4248
sandl99 wants to merge 28 commits into
u/sdang/messaging-hooks-channels-3993-3994from
u/sdang/3896-phase-2-messaging-enrollment

Conversation

@sandl99
Copy link
Copy Markdown
Contributor

@sandl99 sandl99 commented May 26, 2026

Summary

Migrates messaging enrollment from the legacy ad hoc onboard implementation to the manifest-driven workflow compiler path.

The PR keeps the existing operator-facing enrollment UX, but moves the source of truth for channel setup into channel manifests and registered messaging hooks. Telegram,
Discord, Slack, WeChat, and WhatsApp now declare their enrollment prompts, config inputs, credential bindings, policy needs, render targets, and setup hooks through the
manifest system.

3 key changes

  • Moves onboard messaging orchestration into messaging-channel-setup.ts, with shared manifest-style channels
  • Build messaging plan (a configuration) file including configuration, policy, credential, agent config hooks,
  • Store messaging state into SandboxEntry (sandboxes.json)

Test results

OpenClaw

Discord

image

Telegram

image

WeChat

image

Hermes

N/A

Related Issue

Closes #4247

Changes

  • Moves messaging setup orchestration into messaging-channel-setup.ts and shared helpers into messaging/utils.ts.
  • Adds common manifest hooks for token paste and configuration prompts, then binds Telegram, Discord, Slack, WeChat, and WhatsApp enrollment through channel manifests.
  • Uses static built-in messaging hook initialization so MessagingWorkflowPlanner resolves hooks from the manifest registry.
  • Keeps WeChat QR enrollment and Telegram reachability behavior aligned with the existing onboard UX.
  • Updates compiler, hook runner, channel manifest, and onboard tests for the migrated enrollment flow.

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)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • make docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: San Dang sdang@nvidia.com

Summary by CodeRabbit

Release Notes

  • New Features

    • Added configuration prompts for Discord, Slack, Telegram, and WeChat during channel setup.
    • Enhanced channel enrollment with guidance messages and help text for setup procedures.
    • Improved channel validation and credential handling with format enforcement.
  • Bug Fixes

    • Fixed Telegram setup to handle network issues more gracefully.
    • Corrected token format validation for better error reporting.
  • Improvements

    • Refactored messaging channel onboarding for clearer, more structured workflow.
    • Enhanced enrollment status visibility and conditional prompt logic.

Review Change Stack

@sandl99 sandl99 self-assigned this May 26, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 55a7a32a-bab1-4d52-8794-430c55f3001c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(messaging): migrate enrollment to manifest hooks' directly describes the main change: moving enrollment to manifest hooks, which is the core objective of the PR.
Linked Issues check ✅ Passed The PR fully addresses the coding requirements from #4247: migrates enrollment for Telegram, Discord, WeChat, Slack, and WhatsApp to manifest hooks, preserves onboarding UX via hook-based enrollment, maintains manifest-driven channel availability, and updates tests.
Out of Scope Changes check ✅ Passed All changes align with the linked issue scope: channel manifest extensions, enrollment hook implementations, onboard refactoring, and supporting tests. No unrelated modifications detected.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch u/sdang/3896-phase-2-messaging-enrollment

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/lib/onboard.ts (1)

5940-5945: Please run the onboarding/messaging E2Es for this delegation.

This moves the step-5 messaging flow behind a shared implementation in the core onboarding entrypoint, so I'd still smoke the onboarding-focused E2Es before merge — especially cloud-e2e, sandbox-operations-e2e, channels-stop-start-e2e, and messaging-compatible-endpoint-e2e.

As per coding guidelines, src/lib/onboard.ts: "This file contains core onboarding logic. Changes here affect the full sandbox creation and configuration flow."

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

In `@src/lib/onboard.ts` around lines 5940 - 5945, The change routes step-5
messaging through setupMessagingChannelsImpl in src/lib/onboard.ts; run the
onboarding/messaging E2E suites for this delegation to validate behavior:
execute cloud-e2e, sandbox-operations-e2e, channels-stop-start-e2e, and
messaging-compatible-endpoint-e2e against the updated onboarding flow
(particularly exercising setupMessagingChannelsImpl and the caller
setupMessagingChannels path) and fix any failures uncovered before merging.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/messaging/channels/slack/manifest.ts`:
- Line 22: The formatHint strings in the Slack channel manifest contain
token-like sample literals that trigger secret scanning; update the formatHint
values (both occurrences referenced by the formatHint property in the Slack
manifest object) to use redacted placeholders instead of realistic token
patterns (e.g., replace "xoxb-1234-5678-abcdef" style examples with something
like "xoxb-REDACTED" or "<redacted>") so the manifest still documents expected
format without including token-like samples; ensure you update both formatHint
occurrences (the formatHint property on the exported Slack manifest)
consistently.

In `@src/lib/messaging/channels/wechat/hooks/index.ts`:
- Around line 28-31: The current spread merge into ilinkLoginOptions lets
properties in options.ilinkLogin that are explicitly undefined overwrite
defaults from createDefaultWechatHostQrLoginOptions(), which can remove required
flags like runLogin or saveCredential; before merging, create a cleaned override
object by filtering out keys with undefined values from options.ilinkLogin and
then spread that cleaned object into ilinkLoginOptions (referencing
ilinkLoginOptions, createDefaultWechatHostQrLoginOptions, options.ilinkLogin,
runLogin, saveCredential to locate the code).

In `@src/lib/onboard/messaging-channel-setup.ts`:
- Around line 53-55: The current helper hasManifestCredentials uses
hasMessagingManifestPrimaryCredential(manifest, getMessagingToken), which only
checks the primary secret and allows non-interactive seeding to include
partially configured channels; update hasManifestCredentials so it validates
that all required secrets for a ChannelManifest are present (not just the
primary) and use that stricter predicate inside seedFromState and the
non-interactive branch starting around seedFromState (lines 63-81) so
non-interactive seeding only includes manifests where every required credential
is available; locate and modify the functions hasManifestCredentials and any
call sites in seedFromState to call the new “all required secrets present” check
instead of hasMessagingManifestPrimaryCredential.

---

Nitpick comments:
In `@src/lib/onboard.ts`:
- Around line 5940-5945: The change routes step-5 messaging through
setupMessagingChannelsImpl in src/lib/onboard.ts; run the onboarding/messaging
E2E suites for this delegation to validate behavior: execute cloud-e2e,
sandbox-operations-e2e, channels-stop-start-e2e, and
messaging-compatible-endpoint-e2e against the updated onboarding flow
(particularly exercising setupMessagingChannelsImpl and the caller
setupMessagingChannels path) and fix any failures uncovered before merging.
🪄 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: 09da88a8-cae8-4ea1-b37a-29bf2ebfdd2d

📥 Commits

Reviewing files that changed from the base of the PR and between bb1cb78 and 6cd7dd3.

📒 Files selected for processing (31)
  • src/lib/actions/sandbox/policy-channel.ts
  • src/lib/messaging/applier/setup-applier.test.ts
  • src/lib/messaging/channels/discord/manifest.ts
  • src/lib/messaging/channels/manifests.test.ts
  • src/lib/messaging/channels/slack/manifest.ts
  • src/lib/messaging/channels/telegram/hooks/get-me-reachability.test.ts
  • src/lib/messaging/channels/telegram/manifest.ts
  • src/lib/messaging/channels/wechat/hooks/host-qr-login-runtime.ts
  • src/lib/messaging/channels/wechat/hooks/ilink-login.ts
  • src/lib/messaging/channels/wechat/hooks/implementations.test.ts
  • src/lib/messaging/channels/wechat/hooks/index.ts
  • src/lib/messaging/channels/wechat/manifest.ts
  • src/lib/messaging/channels/whatsapp/manifest.ts
  • src/lib/messaging/compiler/manifest-compiler.test.ts
  • src/lib/messaging/compiler/manifest-compiler.ts
  • src/lib/messaging/compiler/workflow-planner.test.ts
  • src/lib/messaging/compiler/workflow-planner.ts
  • src/lib/messaging/hooks/builtins.ts
  • src/lib/messaging/hooks/common/config-prompt.test.ts
  • src/lib/messaging/hooks/common/config-prompt.ts
  • src/lib/messaging/hooks/common/index.ts
  • src/lib/messaging/hooks/common/token-paste.test.ts
  • src/lib/messaging/hooks/common/token-paste.ts
  • src/lib/messaging/hooks/hook-runner.test.ts
  • src/lib/messaging/index.ts
  • src/lib/messaging/manifest/types.ts
  • src/lib/messaging/utils.ts
  • src/lib/onboard.ts
  • src/lib/onboard/messaging-channel-setup.test.ts
  • src/lib/onboard/messaging-channel-setup.ts
  • test/onboard-messaging.test.ts

required: true,
envKey: "SLACK_BOT_TOKEN",
formatPattern: "^xoxb-[A-Za-z0-9_-]+$",
formatHint: "Slack bot tokens start with 'xoxb-' (e.g. xoxb-1234-5678-abcdef).",
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid token-like sample literals in formatHint text.

Line 22 and Line 35 examples resemble live tokens and are already triggering secret-scan findings. Use redacted placeholder shapes instead.

Proposed wording change
-      formatHint: "Slack bot tokens start with 'xoxb-' (e.g. xoxb-1234-5678-abcdef).",
+      formatHint: "Slack bot tokens start with 'xoxb-' (e.g. xoxb-<workspace>-<bot>-<redacted>).",
...
-      formatHint: "Slack app tokens start with 'xapp-' (e.g. xapp-1-A0000-12345-abcdef).",
+      formatHint: "Slack app tokens start with 'xapp-' (e.g. xapp-<version>-<app-id>-<team-id>-<redacted>).",

Also applies to: 35-35

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

In `@src/lib/messaging/channels/slack/manifest.ts` at line 22, The formatHint
strings in the Slack channel manifest contain token-like sample literals that
trigger secret scanning; update the formatHint values (both occurrences
referenced by the formatHint property in the Slack manifest object) to use
redacted placeholders instead of realistic token patterns (e.g., replace
"xoxb-1234-5678-abcdef" style examples with something like "xoxb-REDACTED" or
"<redacted>") so the manifest still documents expected format without including
token-like samples; ensure you update both formatHint occurrences (the
formatHint property on the exported Slack manifest) consistently.

Comment on lines +28 to +31
const ilinkLoginOptions = {
...createDefaultWechatHostQrLoginOptions(),
...options.ilinkLogin,
};
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Preserve defaults when overrides contain undefined values.

On Line 28-31, spread-merging allows options.ilinkLogin fields set to undefined to clobber defaults (notably runLogin/saveCredential), which can trigger runtime failures later. Filter undefined overrides before merging.

Suggested hardening
-  const ilinkLoginOptions = {
-    ...createDefaultWechatHostQrLoginOptions(),
-    ...options.ilinkLogin,
-  };
+  const defaults = createDefaultWechatHostQrLoginOptions();
+  const overrides = Object.fromEntries(
+    Object.entries(options.ilinkLogin ?? {}).filter(([, value]) => value !== undefined),
+  ) as WechatIlinkLoginHookOptions;
+  const ilinkLoginOptions = { ...defaults, ...overrides };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const ilinkLoginOptions = {
...createDefaultWechatHostQrLoginOptions(),
...options.ilinkLogin,
};
const defaults = createDefaultWechatHostQrLoginOptions();
const overrides = Object.fromEntries(
Object.entries(options.ilinkLogin ?? {}).filter(([, value]) => value !== undefined),
) as WechatIlinkLoginHookOptions;
const ilinkLoginOptions = { ...defaults, ...overrides };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/messaging/channels/wechat/hooks/index.ts` around lines 28 - 31, The
current spread merge into ilinkLoginOptions lets properties in
options.ilinkLogin that are explicitly undefined overwrite defaults from
createDefaultWechatHostQrLoginOptions(), which can remove required flags like
runLogin or saveCredential; before merging, create a cleaned override object by
filtering out keys with undefined values from options.ilinkLogin and then spread
that cleaned object into ilinkLoginOptions (referencing ilinkLoginOptions,
createDefaultWechatHostQrLoginOptions, options.ilinkLogin, runLogin,
saveCredential to locate the code).

Comment on lines +53 to +55
const hasManifestCredentials = (manifest: ChannelManifest) =>
hasMessagingManifestPrimaryCredential(manifest, getMessagingToken);
const seedFromState = (includeAllExisting = false): string[] =>
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Non-interactive seeding should require all required secrets, not just the primary one.

Line 53 currently seeds channels from hasMessagingManifestPrimaryCredential(...). In non-interactive mode (Line 63 onward), this can enable partially configured channels (e.g., primary token exists but another required secret is missing).

Suggested fix
 import {
   createBuiltInChannelManifestRegistry,
+  hasMessagingManifestCredentials,
   getMessagingManifestAvailabilityContext,
   hasMessagingManifestPrimaryCredential,
   MessagingWorkflowPlanner,
   resolveMessagingManifestSeed,
   toMessagingAgentId,
@@
   const hasManifestCredentials = (manifest: ChannelManifest) =>
     hasMessagingManifestPrimaryCredential(manifest, getMessagingToken);
+  const hasAllRequiredManifestCredentials = (manifest: ChannelManifest) =>
+    hasMessagingManifestCredentials(manifest, getMessagingToken);
@@
   if (isNonInteractive() || process.env.NEMOCLAW_NON_INTERACTIVE === "1") {
-    const enabled = new Set(seedFromState(false));
+    const enabled = new Set(
+      resolveMessagingManifestSeed(
+        availableChannels,
+        existingChannels,
+        hasAllRequiredManifestCredentials,
+        { includeAllExisting: false },
+      ),
+    );

Also applies to: 63-81

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

In `@src/lib/onboard/messaging-channel-setup.ts` around lines 53 - 55, The current
helper hasManifestCredentials uses
hasMessagingManifestPrimaryCredential(manifest, getMessagingToken), which only
checks the primary secret and allows non-interactive seeding to include
partially configured channels; update hasManifestCredentials so it validates
that all required secrets for a ChannelManifest are present (not just the
primary) and use that stricter predicate inside seedFromState and the
non-interactive branch starting around seedFromState (lines 63-81) so
non-interactive seeding only includes manifests where every required credential
is available; locate and modify the functions hasManifestCredentials and any
call sites in seedFromState to call the new “all required secrets present” check
instead of hasMessagingManifestPrimaryCredential.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 26, 2026

E2E Advisor Recommendation

Required E2E: cloud-onboard-e2e, messaging-providers-e2e, channels-add-remove-e2e, channels-stop-start-e2e
Optional E2E: hermes-discord-e2e, hermes-slack-e2e, openclaw-discord-pairing-e2e, openclaw-slack-pairing-e2e

Dispatch hint: cloud-onboard-e2e,messaging-providers-e2e,channels-add-remove-e2e,channels-stop-start-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/u/sdang/messaging-hooks-channels-3993-3994
Head: HEAD
Confidence: high

Required E2E

  • cloud-onboard-e2e (high): Installer and onboarding code changed. This is the closest existing required install/onboard E2E to validate install.sh still completes a non-interactive cloud onboarding path after the installer self-path and Docker access changes.
  • messaging-providers-e2e (high): Required for the broad messaging manifest/hook/applier changes: validates provider creation, OpenShell placeholder/token isolation, baked OpenClaw config, L7 proxy rewriting, network policy reachability, Telegram/Discord/Slack token channels, WeChat fake host state, and WhatsApp no-provider QR path.
  • channels-add-remove-e2e (high): Required because policy-channel.ts now drives channels add through the manifest workflow planner and host-state applier. This verifies add/remove registry mutations, provider handling, rebuild behavior, and automatic channel network-policy preset application.
  • channels-stop-start-e2e (very high): Required because registry messaging state, disabledChannels, manifest render state, and setup appliers changed. This E2E exercises stop/start/rebuild for OpenClaw and Hermes across Telegram, Discord, WeChat, Slack, and WhatsApp.

Optional E2E

  • hermes-discord-e2e (high): Useful additional confidence for Discord manifest/config prompt changes on the Hermes renderer and schema. channels-stop-start covers Hermes lifecycle broadly, so this is not the minimum merge-blocking set.
  • hermes-slack-e2e (high): Useful additional confidence for Slack manifest/config prompt changes and Hermes credential rewrite behavior. channels-stop-start covers Hermes Slack lifecycle broadly, so this is optional unless Hermes Slack is the release focus.
  • openclaw-discord-pairing-e2e (high): Optional end-to-end assistant user-flow proof for Discord pairing after manifest/render changes; valuable if the PR is intended to ship Discord enrollment behavior beyond provider/config plumbing.
  • openclaw-slack-pairing-e2e (high): Optional end-to-end assistant user-flow proof for Slack Socket Mode pairing after manifest/render/config changes; valuable but adjacent to the required provider and lifecycle coverage.

New E2E recommendations

  • installer-docker-access (high): The installer change targets a clean non-root Ubuntu host where Docker is installed or added but the active shell lacks docker group membership. Existing E2E install jobs run on CI images where Docker is already reachable, so they do not prove the sg docker self-reexec path with a staged curl|bash installer.
    • Suggested test: Add a clean-VM installer E2E that runs the public/staged installer as a non-root user without active docker group membership and asserts a single non-interactive invocation re-execs through sg docker and completes onboarding without requiring a second shell/login.
  • telegram-compatibility-aliases (medium): The PR moves Telegram allowlist compatibility aliases out of global messaging-channel-config and into Telegram enrollment hooks. Existing broad E2E has some alias coverage, but there is no focused channels add/rebuild E2E proving TELEGRAM_AUTHORIZED_CHAT_IDS or TELEGRAM_CHAT_ID is persisted and baked when enabling Telegram after initial onboarding.
    • Suggested test: Add a channels-add Telegram alias E2E: onboard without Telegram, run channels add telegram with TELEGRAM_CHAT_ID or TELEGRAM_AUTHORIZED_CHAT_IDS, rebuild, and assert registry state plus openclaw.json allowFrom use the canonical Telegram allowed IDs.
  • wechat-host-qr-deferred-rebuild (medium): WeChat host-QR enrollment and metadata persistence were refactored through manifests and host-state appliers, but existing E2E uses fake environment metadata and does not cover an actual host-QR login followed by a deferred rebuild in a fresh CLI process.
    • Suggested test: Add a hermetic WeChat host-QR hook E2E with a fake iLink service that returns token/account metadata, exits before rebuild, then starts a fresh rebuild and asserts WECHAT_ACCOUNT_ID/baseUrl/userId are restored into the baked agent config without leaking secrets.

Dispatch hint

  • Workflow: nightly-e2e.yaml
  • jobs input: cloud-onboard-e2e,messaging-providers-e2e,channels-add-remove-e2e,channels-stop-start-e2e

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 26, 2026

E2E Scenario Advisor Recommendation

Required scenario E2E: ubuntu-repo-cloud-openclaw-telegram, ubuntu-repo-cloud-openclaw-discord, ubuntu-repo-cloud-openclaw-slack
Optional scenario E2E: ubuntu-repo-cloud-hermes-discord, ubuntu-repo-cloud-hermes-slack, ubuntu-repo-cloud-openclaw-token-rotation

Dispatch required scenario E2E:

  • gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-telegram
  • gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-discord
  • gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-slack

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/u/sdang/messaging-hooks-channels-3993-3994
Head: HEAD
Confidence: high

Required scenario E2E

  • ubuntu-repo-cloud-openclaw-telegram: Primary scenario coverage for Telegram messaging enrollment and runtime after changes to Telegram manifest/hooks, common hook execution, manifest planning/appliers, onboarding messaging state/config, and channel add registry/gateway application.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-telegram
  • ubuntu-repo-cloud-openclaw-discord: Primary scenario coverage for Discord messaging provider setup after changes to Discord manifest config prompts, messaging compiler/applier paths, common enrollment hooks, and onboarding messaging state.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-discord
  • ubuntu-repo-cloud-openclaw-slack: Primary scenario coverage for Slack messaging provider setup after changes to Slack manifest inputs/state, token/config prompt hooks, provider binding, messaging planner/appliers, and onboarding messaging state.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-slack

Optional scenario E2E

  • ubuntu-repo-cloud-hermes-discord: Adjacent coverage for the same Discord messaging surface on the Hermes agent render/onboarding path; useful because manifests and appliers include Hermes render targets, but OpenClaw Discord is the primary target.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-hermes-discord
  • ubuntu-repo-cloud-hermes-slack: Adjacent coverage for the same Slack messaging surface on the Hermes agent render/onboarding path; useful because manifests and appliers include Hermes render targets, but OpenClaw Slack is the primary target.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-hermes-slack
  • ubuntu-repo-cloud-openclaw-token-rotation: Adjacent messaging credential lifecycle coverage for changes to messaging host state, credential bindings, registry state, and channel provider application; not the primary enrollment-path target.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw-token-rotation

Relevant changed files

  • scripts/install.sh
  • src/lib/actions/sandbox/policy-channel.ts
  • src/lib/messaging-channel-config.ts
  • src/lib/messaging/applier/host-state-applier.ts
  • src/lib/messaging/applier/index.ts
  • src/lib/messaging/channels/discord/manifest.ts
  • src/lib/messaging/channels/slack/manifest.ts
  • src/lib/messaging/channels/telegram/hooks/allowlist-aliases.ts
  • src/lib/messaging/channels/telegram/hooks/get-me-reachability.ts
  • src/lib/messaging/channels/telegram/hooks/index.ts
  • src/lib/messaging/channels/telegram/manifest.ts
  • src/lib/messaging/channels/wechat/hooks/host-qr-login-runtime.ts
  • src/lib/messaging/channels/wechat/hooks/ilink-login.ts
  • src/lib/messaging/channels/wechat/hooks/index.ts
  • src/lib/messaging/channels/wechat/manifest.ts
  • src/lib/messaging/channels/whatsapp/manifest.ts
  • src/lib/messaging/compiler/manifest-compiler.ts
  • src/lib/messaging/hooks/builtins.ts
  • src/lib/messaging/hooks/common/config-prompt.ts
  • src/lib/messaging/hooks/common/index.ts
  • src/lib/messaging/hooks/common/token-paste.ts
  • src/lib/messaging/hooks/hook-runner.ts
  • src/lib/messaging/hooks/types.ts
  • src/lib/messaging/index.ts
  • src/lib/messaging/manifest/types.ts
  • src/lib/messaging/utils.ts
  • src/lib/onboard.ts
  • src/lib/onboard/host-qr-dispatch.ts
  • src/lib/onboard/machine/handlers/sandbox.ts
  • src/lib/onboard/messaging-channel-setup.ts
  • src/lib/onboard/messaging-config.ts
  • src/lib/onboard/messaging-state.ts
  • src/lib/onboard/telegram-reachability.ts
  • src/lib/sandbox/channels.ts
  • src/lib/state/registry.ts

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 26, 2026

PR Review Advisor

Findings: 2 needs attention, 13 worth checking, 0 nice ideas
Since last review: 2 prior items resolved, 8 still apply, 0 new items found

Review findings

🛠️ Needs attention

  • Apply channel policy before token-backed provider registration (src/lib/actions/sandbox/policy-channel.ts:898): Token-backed channel adds still persist credentials, upsert OpenShell providers, update registry/config state, and then call the channel policy preset helper without checking its return value. A failed preset can leave Telegram, Slack, Discord, or WeChat registered with credentials and durable state but without the expected egress policy.
    • Recommendation: Apply the matching policy preset before credential/provider/registry/plan mutation, or roll back provider, registry, messaging config, and durable plan state when preset application fails. Add negative tests for Telegram, Slack, Discord, and WeChat preset failure proving no provider, registry, messaging config, or durable plan state remains.
    • Evidence: The token-backed branch calls persistChannelTokens(acquired), applyChannelAddToGatewayAndRegistry(...), persistManifestAddState(...), logs the bridge as registered, then calls applyChannelPresetIfAvailable(sandboxName, canonical) at line 906 without checking the boolean result before MessagingHostStateApplier.applyPlanToRegistry(...). The WhatsApp tokenless branch checks preset failure first, but that protection does not cover token-backed channels.
  • Offset growth in security-critical messaging and sandbox hotspots (src/lib/actions/sandbox/policy-channel.ts:1): Several already-large, security-relevant files grew materially while handling sandbox policy/channel setup, manifest compilation, and onboarding tests. This increases review and maintenance risk in areas sensitive to policy bypass, credential handling, blueprint drift, and sandbox lifecycle behavior.
    • Recommendation: Extract the new channel-add planning, manifest config persistence, config prompt assertions, and manifest compiler helpers into narrower modules, or offset hotspot growth with cleanup in the same files before merge.
    • Evidence: Deterministic monolith scan: src/lib/actions/sandbox/policy-channel.ts +71 lines, src/lib/messaging/compiler/manifest-compiler.ts +74, src/lib/messaging/compiler/manifest-compiler.test.ts +128, src/lib/messaging/compiler/workflow-planner.test.ts +73, src/lib/messaging/channels/manifests.test.ts +64, and src/lib/onboard/messaging-channel-setup.test.ts +349.

🔎 Worth checking

  • Source-of-truth review needed: Token-backed channel add preset failure recovery: The advisor marked localized patch analysis as missing.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: persistChannelTokens, applyChannelAddToGatewayAndRegistry, persistManifestAddState, and MessagingHostStateApplier.applyPlanToRegistry run around an ignored applyChannelPresetIfAvailable result.
  • Source-of-truth review needed: Manifest config and WeChat metadata persistence into onboard session: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: Session update failures are caught and ignored; safeLoadOnboardSession returns null on load failure; comments describe registry/session behavior as best-effort.
  • Source-of-truth review needed: Serialized messaging plan env as durable registry state: The advisor marked localized patch analysis as missing.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: assertSandboxMessagingPlan validates schemaVersion, primitive top-level strings, and that major fields are arrays/objects.
  • Source-of-truth review needed: WeChat host-QR runtime adapter around HOST_QR_LOGIN_HANDLERS: The advisor marked localized patch analysis as missing.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: host-qr-login-runtime.ts catches handler exceptions and synthesizes WechatLoginResult errors for no handler, no token, and no account id.
  • Source-of-truth review needed: Telegram compatibility aliases: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: The PR removes global alias canonicalization and adds telegram.allowlistAliases to merge aliases during enrollment.
  • Deep-validate serialized messaging plans before registry persistence (src/lib/messaging/applier/setup-applier.ts:106): The NEMOCLAW_MESSAGING_PLAN_B64 flow decodes a host environment value and can persist it into SandboxEntry.messaging after only shallow top-level shape checks. Downstream appliers validate many path and shell boundaries, but the registry can still store a tampered or oversized plan with unvalidated nested channel IDs, provider names, policy preset names, render metadata, and hook references.
    • Recommendation: Treat the serialized plan as a blueprint/trusted-code boundary. Add size limits and deep validation for channel IDs, agent, workflow, provider/env key formats, policy preset names, render targets, hook phases, and serializable values before accepting it from env or writing it to the registry.
    • Evidence: MessagingSetupApplier.decodePlan parses base64 JSON and assertSandboxMessagingPlan checks schemaVersion, primitive top-level strings, and that major fields are arrays/objects. Onboard reads MessagingHostStateApplier.readPlanStateFromEnv and registers the decoded plan when the sandboxName matches.
  • Keep WeChat host-QR credential runtime out of default planner imports (src/lib/messaging/channels/wechat/hooks/index.ts:6): The default built-in hook registry eagerly imports the WeChat host-side QR runtime. That runtime imports the credential store and HOST_QR_LOGIN_HANDLERS, so credential-capture glue is loaded whenever the default messaging hook registry is constructed rather than only at the interactive WeChat QR enrollment boundary.
    • Recommendation: Lazy-load or inject the WeChat host-QR runner only when WeChat QR enrollment is explicitly selected. Add a transitive import-boundary test from planner/compiler/default hook registry paths that fails if credentials/store or host-qr-handlers enter the default import graph.
    • Evidence: src/lib/messaging/hooks/builtins.ts calls createWechatHookRegistrations; src/lib/messaging/channels/wechat/hooks/index.ts imports ./host-qr-login-runtime; host-qr-login-runtime.ts imports ../../../../credentials/store and ../../../../host-qr-handlers. The manifest import-boundary test checks direct source strings and misses this transitive dependency.
  • Avoid raw identifier logging and validate channel config IDs (src/lib/messaging/hooks/common/config-prompt.ts:207): The config prompt hook logs existing non-secret configuration values such as server IDs, user IDs, and channel IDs verbatim, and most of those identifiers are only trimmed rather than allowlist-validated. These are not credentials, but they can identify workspaces or operators and may be captured in onboarding logs.
    • Recommendation: Confirm this is acceptable under NemoClaw logging policy, or log only that the value is set without printing the raw identifier. Add allowlist validation for expected Telegram, Discord, Slack, and WeChat identifier formats where possible and add regression coverage for the intended redaction/display contract.
    • Evidence: logExistingConfigInput logs `${configInputNoun(field)} already set: ${value}` for non-mention config fields. normalizeConfigValue primarily strips carriage returns and trims values unless validValues is declared. The added config-prompt/onboarding tests assert raw values such as allowed IDs and channel IDs are printed.
  • Clarify registry/session/plan source of truth for manifest config and WeChat metadata (src/lib/actions/sandbox/policy-channel.ts:755): The channel add path writes manifest config to the registry and then best-effort updates onboard session state. WeChat metadata persistence similarly swallows session update failures, while safeLoadOnboardSession returns null on load failure. If the session is stale or unwritable, deferred rebuild behavior can depend on partially persisted state and operator recovery instructions instead of a single authoritative source.
    • Recommendation: Define whether registry, onboard session, or persisted messaging plan is authoritative for manifest channel config and WeChat metadata across immediate and deferred rebuilds. Add regression coverage for session load/write failure that proves deferred rebuild behavior, or make the registry/session write atomic enough that the invalid state cannot occur.
    • Evidence: persistManifestMessagingConfig catches onboardSession.updateSession and continues with the comment that registry state still carries config when available. persistWechatConfigFromEnv catches session write failure and says deferred rebuilds can be recovered by re-running channels add. safeLoadOnboardSession catches load failures and returns null.
  • Define and test the default WeChat host-QR handler contract (src/lib/messaging/channels/wechat/hooks/host-qr-login-runtime.ts:22): The default runtime adapter normalizes missing host handlers, handler exceptions, missing tokens, and missing WECHAT_ACCOUNT_ID into WechatLoginResult errors, but the code does not establish whether those states are valid outcomes of HOST_QR_LOGIN_HANDLERS.wechat or why the handler boundary cannot make them impossible.
    • Recommendation: Define the HOST_QR_LOGIN_HANDLERS.wechat contract at the boundary. Prefer making invalid handler states impossible at the source; if the adapter remains defensive, document the source-fix constraint and removal condition and add direct adapter tests for missing handler, thrown handler, non-ok results, missing token, missing account id, and extraEnv propagation.
    • Evidence: host-qr-login-runtime.ts reads HOST_QR_LOGIN_HANDLERS.wechat, catches handler exceptions, synthesizes errors for no handler/no token/no account id, and maps extraEnv into WechatLoginCredentials. Existing tests exercise onboarding through a mocked handler and injected ilink-login behavior, not the default runtime adapter failure modes directly.
  • Add negative tests for token-backed policy preset failures (test/channels-add-preset.test.ts:351): Unit tests cover the new WhatsApp tokenless preset failure path, but they do not prove the higher-risk token-backed paths are atomic when policy preset application fails.
    • Recommendation: Add tests for Telegram, Slack, Discord, and WeChat where policies.applyPreset returns false or throws, and assert no credential persistence, provider upsert, registry messagingChannels update, manifest config update, durable messaging plan update, or rebuild prompt occurs.
    • Evidence: The existing preset-failure test is named 'aborts tokenless WhatsApp before registry and rebuild when preset apply fails'. The token-backed add branch still calls credential/provider/registry mutation before an ignored applyChannelPresetIfAvailable result.
  • Add targeted runtime validation for provider, policy, sandbox, and installer glue: This PR changes manifest-driven enrollment, sandbox policy/provider binding, Telegram reachability, Slack validation, WeChat host QR setup, WhatsApp activation, and installer re-exec behavior. Unit tests cover many planner and hook paths, but most high-risk OpenShell, gateway, host QR, sandbox policy, session, and network boundaries are mocked.
    • Recommendation: Add or identify targeted runtime/integration validation for channel add/onboard flows for Telegram, Slack, Discord, WeChat, and WhatsApp provider/policy setup, plus the installer sg re-exec path. Keep the unit tests, but do not rely solely on mocked planner tests for OpenShell, gateway, host QR, sandbox policy, and network behavior.
    • Evidence: Trusted test-depth analysis recommends runtime validation for scripts/install.sh, policy-channel.ts, messaging-channel-config.ts, host-state-applier.ts, channel manifests, and Telegram alias handling. Existing tests stub OpenShell, gateway recovery, credentials, fetch, registry, session, and host QR handlers.
  • Document user-facing manifest enrollment behavior (src/lib/messaging/channels/telegram/manifest.ts:12): The PR changes user-facing enrollment prompts, guidance, Slack token validation, WhatsApp instructions, Telegram reachability skip behavior, and WeChat setup behavior, while the PR checklist leaves documentation updates unchecked. That leaves public expectations for the migrated enrollment flow unclear.
    • Recommendation: Update the relevant user-facing docs or release notes for the migrated manifest enrollment flow, including new config prompts, Slack token/channel validation, Telegram privacy/reachability behavior, WeChat host QR requirements, WhatsApp QR pairing, and any skip/recovery env vars.
    • Evidence: Linked issue acceptance asks to preserve onboard UX. The diff moves prompts and setup guidance into manifests/hooks and adds new behavior such as NEMOCLAW_SKIP_TELEGRAM_REACHABILITY and Slack token format enforcement. The PR body marks 'Docs updated for user-facing behavior changes' unchecked.

🌱 Nice ideas

  • None.
Since last review details

Current findings:

  • Source-of-truth review needed: Token-backed channel add preset failure recovery: The advisor marked localized patch analysis as missing.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: persistChannelTokens, applyChannelAddToGatewayAndRegistry, persistManifestAddState, and MessagingHostStateApplier.applyPlanToRegistry run around an ignored applyChannelPresetIfAvailable result.
  • Source-of-truth review needed: Manifest config and WeChat metadata persistence into onboard session: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: Session update failures are caught and ignored; safeLoadOnboardSession returns null on load failure; comments describe registry/session behavior as best-effort.
  • Source-of-truth review needed: Serialized messaging plan env as durable registry state: The advisor marked localized patch analysis as missing.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: assertSandboxMessagingPlan validates schemaVersion, primitive top-level strings, and that major fields are arrays/objects.
  • Source-of-truth review needed: WeChat host-QR runtime adapter around HOST_QR_LOGIN_HANDLERS: The advisor marked localized patch analysis as missing.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: host-qr-login-runtime.ts catches handler exceptions and synthesizes WechatLoginResult errors for no handler, no token, and no account id.
  • Source-of-truth review needed: Telegram compatibility aliases: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: The PR removes global alias canonicalization and adds telegram.allowlistAliases to merge aliases during enrollment.
  • Apply channel policy before token-backed provider registration (src/lib/actions/sandbox/policy-channel.ts:898): Token-backed channel adds still persist credentials, upsert OpenShell providers, update registry/config state, and then call the channel policy preset helper without checking its return value. A failed preset can leave Telegram, Slack, Discord, or WeChat registered with credentials and durable state but without the expected egress policy.
    • Recommendation: Apply the matching policy preset before credential/provider/registry/plan mutation, or roll back provider, registry, messaging config, and durable plan state when preset application fails. Add negative tests for Telegram, Slack, Discord, and WeChat preset failure proving no provider, registry, messaging config, or durable plan state remains.
    • Evidence: The token-backed branch calls persistChannelTokens(acquired), applyChannelAddToGatewayAndRegistry(...), persistManifestAddState(...), logs the bridge as registered, then calls applyChannelPresetIfAvailable(sandboxName, canonical) at line 906 without checking the boolean result before MessagingHostStateApplier.applyPlanToRegistry(...). The WhatsApp tokenless branch checks preset failure first, but that protection does not cover token-backed channels.
  • Offset growth in security-critical messaging and sandbox hotspots (src/lib/actions/sandbox/policy-channel.ts:1): Several already-large, security-relevant files grew materially while handling sandbox policy/channel setup, manifest compilation, and onboarding tests. This increases review and maintenance risk in areas sensitive to policy bypass, credential handling, blueprint drift, and sandbox lifecycle behavior.
    • Recommendation: Extract the new channel-add planning, manifest config persistence, config prompt assertions, and manifest compiler helpers into narrower modules, or offset hotspot growth with cleanup in the same files before merge.
    • Evidence: Deterministic monolith scan: src/lib/actions/sandbox/policy-channel.ts +71 lines, src/lib/messaging/compiler/manifest-compiler.ts +74, src/lib/messaging/compiler/manifest-compiler.test.ts +128, src/lib/messaging/compiler/workflow-planner.test.ts +73, src/lib/messaging/channels/manifests.test.ts +64, and src/lib/onboard/messaging-channel-setup.test.ts +349.
  • Deep-validate serialized messaging plans before registry persistence (src/lib/messaging/applier/setup-applier.ts:106): The NEMOCLAW_MESSAGING_PLAN_B64 flow decodes a host environment value and can persist it into SandboxEntry.messaging after only shallow top-level shape checks. Downstream appliers validate many path and shell boundaries, but the registry can still store a tampered or oversized plan with unvalidated nested channel IDs, provider names, policy preset names, render metadata, and hook references.
    • Recommendation: Treat the serialized plan as a blueprint/trusted-code boundary. Add size limits and deep validation for channel IDs, agent, workflow, provider/env key formats, policy preset names, render targets, hook phases, and serializable values before accepting it from env or writing it to the registry.
    • Evidence: MessagingSetupApplier.decodePlan parses base64 JSON and assertSandboxMessagingPlan checks schemaVersion, primitive top-level strings, and that major fields are arrays/objects. Onboard reads MessagingHostStateApplier.readPlanStateFromEnv and registers the decoded plan when the sandboxName matches.
  • Keep WeChat host-QR credential runtime out of default planner imports (src/lib/messaging/channels/wechat/hooks/index.ts:6): The default built-in hook registry eagerly imports the WeChat host-side QR runtime. That runtime imports the credential store and HOST_QR_LOGIN_HANDLERS, so credential-capture glue is loaded whenever the default messaging hook registry is constructed rather than only at the interactive WeChat QR enrollment boundary.
    • Recommendation: Lazy-load or inject the WeChat host-QR runner only when WeChat QR enrollment is explicitly selected. Add a transitive import-boundary test from planner/compiler/default hook registry paths that fails if credentials/store or host-qr-handlers enter the default import graph.
    • Evidence: src/lib/messaging/hooks/builtins.ts calls createWechatHookRegistrations; src/lib/messaging/channels/wechat/hooks/index.ts imports ./host-qr-login-runtime; host-qr-login-runtime.ts imports ../../../../credentials/store and ../../../../host-qr-handlers. The manifest import-boundary test checks direct source strings and misses this transitive dependency.
  • Avoid raw identifier logging and validate channel config IDs (src/lib/messaging/hooks/common/config-prompt.ts:207): The config prompt hook logs existing non-secret configuration values such as server IDs, user IDs, and channel IDs verbatim, and most of those identifiers are only trimmed rather than allowlist-validated. These are not credentials, but they can identify workspaces or operators and may be captured in onboarding logs.
    • Recommendation: Confirm this is acceptable under NemoClaw logging policy, or log only that the value is set without printing the raw identifier. Add allowlist validation for expected Telegram, Discord, Slack, and WeChat identifier formats where possible and add regression coverage for the intended redaction/display contract.
    • Evidence: logExistingConfigInput logs `${configInputNoun(field)} already set: ${value}` for non-mention config fields. normalizeConfigValue primarily strips carriage returns and trims values unless validValues is declared. The added config-prompt/onboarding tests assert raw values such as allowed IDs and channel IDs are printed.
  • Clarify registry/session/plan source of truth for manifest config and WeChat metadata (src/lib/actions/sandbox/policy-channel.ts:755): The channel add path writes manifest config to the registry and then best-effort updates onboard session state. WeChat metadata persistence similarly swallows session update failures, while safeLoadOnboardSession returns null on load failure. If the session is stale or unwritable, deferred rebuild behavior can depend on partially persisted state and operator recovery instructions instead of a single authoritative source.
    • Recommendation: Define whether registry, onboard session, or persisted messaging plan is authoritative for manifest channel config and WeChat metadata across immediate and deferred rebuilds. Add regression coverage for session load/write failure that proves deferred rebuild behavior, or make the registry/session write atomic enough that the invalid state cannot occur.
    • Evidence: persistManifestMessagingConfig catches onboardSession.updateSession and continues with the comment that registry state still carries config when available. persistWechatConfigFromEnv catches session write failure and says deferred rebuilds can be recovered by re-running channels add. safeLoadOnboardSession catches load failures and returns null.
  • Define and test the default WeChat host-QR handler contract (src/lib/messaging/channels/wechat/hooks/host-qr-login-runtime.ts:22): The default runtime adapter normalizes missing host handlers, handler exceptions, missing tokens, and missing WECHAT_ACCOUNT_ID into WechatLoginResult errors, but the code does not establish whether those states are valid outcomes of HOST_QR_LOGIN_HANDLERS.wechat or why the handler boundary cannot make them impossible.
    • Recommendation: Define the HOST_QR_LOGIN_HANDLERS.wechat contract at the boundary. Prefer making invalid handler states impossible at the source; if the adapter remains defensive, document the source-fix constraint and removal condition and add direct adapter tests for missing handler, thrown handler, non-ok results, missing token, missing account id, and extraEnv propagation.
    • Evidence: host-qr-login-runtime.ts reads HOST_QR_LOGIN_HANDLERS.wechat, catches handler exceptions, synthesizes errors for no handler/no token/no account id, and maps extraEnv into WechatLoginCredentials. Existing tests exercise onboarding through a mocked handler and injected ilink-login behavior, not the default runtime adapter failure modes directly.
  • Add negative tests for token-backed policy preset failures (test/channels-add-preset.test.ts:351): Unit tests cover the new WhatsApp tokenless preset failure path, but they do not prove the higher-risk token-backed paths are atomic when policy preset application fails.
    • Recommendation: Add tests for Telegram, Slack, Discord, and WeChat where policies.applyPreset returns false or throws, and assert no credential persistence, provider upsert, registry messagingChannels update, manifest config update, durable messaging plan update, or rebuild prompt occurs.
    • Evidence: The existing preset-failure test is named 'aborts tokenless WhatsApp before registry and rebuild when preset apply fails'. The token-backed add branch still calls credential/provider/registry mutation before an ignored applyChannelPresetIfAvailable result.
  • Add targeted runtime validation for provider, policy, sandbox, and installer glue: This PR changes manifest-driven enrollment, sandbox policy/provider binding, Telegram reachability, Slack validation, WeChat host QR setup, WhatsApp activation, and installer re-exec behavior. Unit tests cover many planner and hook paths, but most high-risk OpenShell, gateway, host QR, sandbox policy, session, and network boundaries are mocked.
    • Recommendation: Add or identify targeted runtime/integration validation for channel add/onboard flows for Telegram, Slack, Discord, WeChat, and WhatsApp provider/policy setup, plus the installer sg re-exec path. Keep the unit tests, but do not rely solely on mocked planner tests for OpenShell, gateway, host QR, sandbox policy, and network behavior.
    • Evidence: Trusted test-depth analysis recommends runtime validation for scripts/install.sh, policy-channel.ts, messaging-channel-config.ts, host-state-applier.ts, channel manifests, and Telegram alias handling. Existing tests stub OpenShell, gateway recovery, credentials, fetch, registry, session, and host QR handlers.
  • Document user-facing manifest enrollment behavior (src/lib/messaging/channels/telegram/manifest.ts:12): The PR changes user-facing enrollment prompts, guidance, Slack token validation, WhatsApp instructions, Telegram reachability skip behavior, and WeChat setup behavior, while the PR checklist leaves documentation updates unchecked. That leaves public expectations for the migrated enrollment flow unclear.
    • Recommendation: Update the relevant user-facing docs or release notes for the migrated manifest enrollment flow, including new config prompts, Slack token/channel validation, Telegram privacy/reachability behavior, WeChat host QR requirements, WhatsApp QR pairing, and any skip/recovery env vars.
    • Evidence: Linked issue acceptance asks to preserve onboard UX. The diff moves prompts and setup guidance into manifests/hooks and adds new behavior such as NEMOCLAW_SKIP_TELEGRAM_REACHABILITY and Slack token format enforcement. The PR body marks 'Docs updated for user-facing behavior changes' unchecked.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

@wscurran wscurran added enhancement: integration PRs or issues proposing integration of a third-party product or service into NemoClaw. Integration: Discord Use this label to identify Discord bot integration issues with NemoClaw. Integration: Slack Use this label to identify Slack integration issues with NemoClaw. Integration: Telegram Use this label to identify Telegram bot integration issues with NemoClaw. Integration: WhatsApp Use this label to identify WhatsApp communication integration issues with NemoClaw. labels May 26, 2026
@wscurran
Copy link
Copy Markdown
Contributor


Related open issues:

@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26458565211
Target ref: u/sdang/3896-phase-2-messaging-enrollment
Requested jobs: channels-add-remove-e2e,channels-stop-start-e2e,messaging-providers-e2e
Summary: 3 passed, 0 failed, 0 skipped

Job Result
channels-add-remove-e2e ✅ success
channels-stop-start-e2e ✅ success
messaging-providers-e2e ✅ success

@github-actions
Copy link
Copy Markdown
Contributor

Brev E2E (messaging-providers): FAILED on branch u/sdang/3896-phase-2-messaging-enrollmentSee logs

@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26497114878
Target ref: u/sdang/3896-phase-2-messaging-enrollment
Requested jobs: all (no filter)
Summary: 47 passed, 3 failed, 2 skipped

Job Result
bedrock-runtime-compatible-anthropic-e2e ✅ success
brave-search-e2e ✅ success
channels-add-remove-e2e ✅ success
channels-stop-start-e2e ✅ success
cloud-e2e ✅ success
cloud-inference-e2e ✅ success
cloud-onboard-e2e ✅ success
credential-migration-e2e ✅ success
credential-sanitization-e2e ✅ success
device-auth-health-e2e ✅ success
diagnostics-e2e ✅ success
docs-validation-e2e ✅ success
double-onboard-e2e ✅ success
gpu-double-onboard-e2e ⏭️ skipped
gpu-e2e ⏭️ skipped
hermes-discord-e2e ✅ success
hermes-e2e ✅ success
hermes-inference-switch-e2e ✅ success
hermes-onboard-security-posture-e2e ✅ success
hermes-slack-e2e ✅ success
inference-routing-e2e ✅ success
issue-2478-crash-loop-recovery-e2e ✅ success
issue-3600-gpu-proof-optional-e2e ✅ success
kimi-inference-compat-e2e ✅ success
launchable-smoke-e2e ❌ failure
messaging-compatible-endpoint-e2e ✅ success
messaging-providers-e2e ✅ success
network-policy-e2e ✅ success
onboard-negative-paths-e2e ✅ success
onboard-repair-e2e ✅ success
onboard-resume-e2e ✅ success
openclaw-discord-pairing-e2e ✅ success
openclaw-inference-switch-e2e ✅ success
openclaw-onboard-security-posture-e2e ✅ success
openclaw-slack-pairing-e2e ✅ success
openclaw-tui-chat-correlation-e2e ❌ failure
openshell-gateway-upgrade-e2e ✅ success
overlayfs-autofix-e2e ✅ success
rebuild-hermes-e2e ✅ success
rebuild-hermes-stale-base-e2e ✅ success
rebuild-openclaw-e2e ✅ success
runtime-overrides-e2e ❌ failure
sandbox-operations-e2e ✅ success
sandbox-survival-e2e ✅ success
shields-config-e2e ✅ success
skill-agent-e2e ✅ success
snapshot-commands-e2e ✅ success
state-backup-restore-e2e ✅ success
telegram-injection-e2e ✅ success
token-rotation-e2e ✅ success
tunnel-lifecycle-e2e ✅ success
upgrade-stale-sandbox-e2e ✅ success

Failed jobs: launchable-smoke-e2e, openclaw-tui-chat-correlation-e2e, runtime-overrides-e2e. Check run artifacts for logs.

…-3993-3994' into u/sdang/3896-phase-2-messaging-enrollment

# Conflicts:
#	src/lib/onboard.ts
#	src/lib/onboard/machine/handlers/sandbox.ts
#	src/lib/onboard/messaging-channel-setup.test.ts
#	src/lib/onboard/messaging-channel-setup.ts
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26497114878
Target ref: u/sdang/3896-phase-2-messaging-enrollment
Requested jobs: all (no filter)
Summary: 48 passed, 2 failed, 2 skipped

Job Result
bedrock-runtime-compatible-anthropic-e2e ✅ success
brave-search-e2e ✅ success
channels-add-remove-e2e ✅ success
channels-stop-start-e2e ✅ success
cloud-e2e ✅ success
cloud-inference-e2e ✅ success
cloud-onboard-e2e ✅ success
credential-migration-e2e ✅ success
credential-sanitization-e2e ✅ success
device-auth-health-e2e ✅ success
diagnostics-e2e ✅ success
docs-validation-e2e ✅ success
double-onboard-e2e ✅ success
gpu-double-onboard-e2e ⏭️ skipped
gpu-e2e ⏭️ skipped
hermes-discord-e2e ✅ success
hermes-e2e ✅ success
hermes-inference-switch-e2e ✅ success
hermes-onboard-security-posture-e2e ✅ success
hermes-slack-e2e ✅ success
inference-routing-e2e ✅ success
issue-2478-crash-loop-recovery-e2e ✅ success
issue-3600-gpu-proof-optional-e2e ✅ success
kimi-inference-compat-e2e ✅ success
launchable-smoke-e2e ❌ failure
messaging-compatible-endpoint-e2e ✅ success
messaging-providers-e2e ✅ success
network-policy-e2e ✅ success
onboard-negative-paths-e2e ✅ success
onboard-repair-e2e ✅ success
onboard-resume-e2e ✅ success
openclaw-discord-pairing-e2e ✅ success
openclaw-inference-switch-e2e ✅ success
openclaw-onboard-security-posture-e2e ✅ success
openclaw-slack-pairing-e2e ✅ success
openclaw-tui-chat-correlation-e2e ✅ success
openshell-gateway-upgrade-e2e ✅ success
overlayfs-autofix-e2e ✅ success
rebuild-hermes-e2e ✅ success
rebuild-hermes-stale-base-e2e ✅ success
rebuild-openclaw-e2e ✅ success
runtime-overrides-e2e ❌ failure
sandbox-operations-e2e ✅ success
sandbox-survival-e2e ✅ success
shields-config-e2e ✅ success
skill-agent-e2e ✅ success
snapshot-commands-e2e ✅ success
state-backup-restore-e2e ✅ success
telegram-injection-e2e ✅ success
token-rotation-e2e ✅ success
tunnel-lifecycle-e2e ✅ success
upgrade-stale-sandbox-e2e ✅ success

Failed jobs: launchable-smoke-e2e, runtime-overrides-e2e. Check run artifacts for logs.

@sandl99 sandl99 requested a review from cv May 27, 2026 09:29
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26497114878
Target ref: u/sdang/3896-phase-2-messaging-enrollment
Requested jobs: all (no filter)
Summary: 50 passed, 0 failed, 2 skipped

Job Result
bedrock-runtime-compatible-anthropic-e2e ✅ success
brave-search-e2e ✅ success
channels-add-remove-e2e ✅ success
channels-stop-start-e2e ✅ success
cloud-e2e ✅ success
cloud-inference-e2e ✅ success
cloud-onboard-e2e ✅ success
credential-migration-e2e ✅ success
credential-sanitization-e2e ✅ success
device-auth-health-e2e ✅ success
diagnostics-e2e ✅ success
docs-validation-e2e ✅ success
double-onboard-e2e ✅ success
gpu-double-onboard-e2e ⏭️ skipped
gpu-e2e ⏭️ skipped
hermes-discord-e2e ✅ success
hermes-e2e ✅ success
hermes-inference-switch-e2e ✅ success
hermes-onboard-security-posture-e2e ✅ success
hermes-slack-e2e ✅ success
inference-routing-e2e ✅ success
issue-2478-crash-loop-recovery-e2e ✅ success
issue-3600-gpu-proof-optional-e2e ✅ success
kimi-inference-compat-e2e ✅ success
launchable-smoke-e2e ✅ success
messaging-compatible-endpoint-e2e ✅ success
messaging-providers-e2e ✅ success
network-policy-e2e ✅ success
onboard-negative-paths-e2e ✅ success
onboard-repair-e2e ✅ success
onboard-resume-e2e ✅ success
openclaw-discord-pairing-e2e ✅ success
openclaw-inference-switch-e2e ✅ success
openclaw-onboard-security-posture-e2e ✅ success
openclaw-slack-pairing-e2e ✅ success
openclaw-tui-chat-correlation-e2e ✅ success
openshell-gateway-upgrade-e2e ✅ success
overlayfs-autofix-e2e ✅ success
rebuild-hermes-e2e ✅ success
rebuild-hermes-stale-base-e2e ✅ success
rebuild-openclaw-e2e ✅ success
runtime-overrides-e2e ✅ success
sandbox-operations-e2e ✅ success
sandbox-survival-e2e ✅ success
shields-config-e2e ✅ success
skill-agent-e2e ✅ success
snapshot-commands-e2e ✅ success
state-backup-restore-e2e ✅ success
telegram-injection-e2e ✅ success
token-rotation-e2e ✅ success
tunnel-lifecycle-e2e ✅ success
upgrade-stale-sandbox-e2e ✅ success

@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26632897939
Target ref: u/sdang/3896-phase-2-messaging-enrollment
Requested jobs: messaging-providers-e2e,messaging-compatible-endpoint-e2e,channels-add-remove-e2e,channels-stop-start-e2e
Summary: 4 passed, 0 failed, 0 skipped

Job Result
channels-add-remove-e2e ✅ success
channels-stop-start-e2e ✅ success
messaging-compatible-endpoint-e2e ✅ success
messaging-providers-e2e ✅ success

sandl99 added 5 commits June 1, 2026 17:06
…om:NVIDIA/NemoClaw into u/sdang/3896-phase-2-messaging-enrollment

# Conflicts:
#	src/lib/actions/sandbox/policy-channel.ts
#	src/lib/onboard.ts
#	src/lib/onboard/messaging-channel-setup.test.ts
#	src/lib/onboard/messaging-channel-setup.ts
#	test/e2e/test-channels-stop-start.sh
#	test/e2e/test-messaging-providers.sh
@sandl99 sandl99 added the v0.0.56 Release target label Jun 1, 2026
@sandl99 sandl99 requested a review from ericksoa June 1, 2026 11:43
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

Selective E2E Results — ✅ All requested jobs passed

Run: 26752754084
Target ref: u/sdang/3896-phase-2-messaging-enrollment
Requested jobs: all (no filter)
Summary: 55 passed, 0 failed, 2 skipped

Job Result
bedrock-runtime-compatible-anthropic-e2e ✅ success
brave-search-e2e ✅ success
channels-add-remove-e2e ✅ success
channels-stop-start-e2e ✅ success
cloud-e2e ✅ success
cloud-inference-e2e ✅ success
cloud-onboard-e2e ✅ success
credential-migration-e2e ✅ success
credential-sanitization-e2e ✅ success
device-auth-health-e2e ✅ success
diagnostics-e2e ✅ success
docs-validation-e2e ✅ success
double-onboard-e2e ✅ success
gpu-double-onboard-e2e ⏭️ skipped
gpu-e2e ⏭️ skipped
hermes-dashboard-e2e ✅ success
hermes-discord-e2e ✅ success
hermes-e2e ✅ success
hermes-inference-switch-e2e ✅ success
hermes-onboard-security-posture-e2e ✅ success
hermes-root-entrypoint-smoke-e2e ✅ success
hermes-slack-e2e ✅ success
inference-routing-e2e ✅ success
issue-2478-crash-loop-recovery-e2e ✅ success
issue-3600-gpu-proof-optional-e2e ✅ success
issue-4462-gateway-pinned-approval-characterization-e2e ✅ success
issue-4462-scope-upgrade-approval-e2e ✅ success
kimi-inference-compat-e2e ✅ success
launchable-smoke-e2e ✅ success
messaging-compatible-endpoint-e2e ✅ success
messaging-providers-e2e ✅ success
network-policy-e2e ✅ success
onboard-negative-paths-e2e ✅ success
onboard-repair-e2e ✅ success
onboard-resume-e2e ✅ success
openclaw-discord-pairing-e2e ✅ success
openclaw-inference-switch-e2e ✅ success
openclaw-onboard-security-posture-e2e ✅ success
openclaw-slack-pairing-e2e ✅ success
openclaw-tui-chat-correlation-e2e ✅ success
openshell-gateway-upgrade-e2e ✅ success
overlayfs-autofix-e2e ✅ success
rebuild-hermes-e2e ✅ success
rebuild-hermes-stale-base-e2e ✅ success
rebuild-openclaw-e2e ✅ success
runtime-overrides-e2e ✅ success
sandbox-operations-e2e ✅ success
sandbox-survival-e2e ✅ success
shields-config-e2e ✅ success
skill-agent-e2e ✅ success
snapshot-commands-e2e ✅ success
state-backup-restore-e2e ✅ success
telegram-injection-e2e ✅ success
token-rotation-e2e ✅ success
tunnel-lifecycle-e2e ✅ success
upgrade-stale-sandbox-e2e ✅ success
vm-driver-privileged-exec-routing-e2e ✅ success

@NVIDIA NVIDIA deleted a comment from github-actions Bot Jun 1, 2026
@NVIDIA NVIDIA deleted a comment from github-actions Bot Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement: integration PRs or issues proposing integration of a third-party product or service into NemoClaw. Integration: Discord Use this label to identify Discord bot integration issues with NemoClaw. Integration: Slack Use this label to identify Slack integration issues with NemoClaw. Integration: Telegram Use this label to identify Telegram bot integration issues with NemoClaw. Integration: WhatsApp Use this label to identify WhatsApp communication integration issues with NemoClaw. v0.0.56 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants