feat(onboard): add SLACK_ALLOWED_CHANNELS support for channel allowlisting#1757
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Slack Socket Mode support: docs and onboarding flows, new Slack sandbox env vars and a Docker build-time allowlist arg, onboarding logic to bake channel allowlists into staged Dockerfiles, and a unit test verifying allowlist injection. Changes
Sequence DiagramsequenceDiagram
actor User
participant Onboard as Onboarding
participant Provider as OpenShellProvider
participant Docker as DockerBuild
participant Sandbox as SandboxImage
User->>Onboard: run `nemoclaw onboard` (provide SLACK_BOT_TOKEN, optional SLACK_APP_TOKEN, SLACK_ALLOWED_CHANNELS)
Onboard->>Provider: persist tokens as providers (not injected into sandbox)
Onboard->>Onboard: parse SLACK_ALLOWED_CHANNELS → JSON → Base64
Onboard->>Docker: patch staged Dockerfile with ARG NEMOCLAW_SLACK_ALLOWED_CHANNELS_B64
Docker->>Docker: decode ARG, merge channels into slack.accounts.default.channels
Docker->>Sandbox: build image with allowlist baked in
Onboard->>User: advise `nemoclaw onboard --recreate-sandbox` and `nemoclaw <sandbox> policy-add slack`
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (5)
docs/reference/architecture.md (1)
191-193: Split into one sentence per line.Line 193 contains two sentences on the same line. Per the documentation style guide, each sentence should be on its own line to make diffs more readable.
📝 Suggested fix
| `SLACK_BOT_TOKEN` | Slack bot token (`xoxb-...`) you provide before `nemoclaw onboard`. Stored as an OpenShell provider; never passed directly to the sandbox. | | `SLACK_APP_TOKEN` | Slack app-level token (`xapp-...`) required for Socket Mode. Stored alongside `SLACK_BOT_TOKEN` during onboarding. | -| `SLACK_ALLOWED_CHANNELS` | Comma-separated Slack channel IDs to allowlist (e.g. `C012AB3CD,C987ZY6XW`). Baked into the sandbox image at build time. When unset, no channels are allowed by default. | +| `SLACK_ALLOWED_CHANNELS` | Comma-separated Slack channel IDs to allowlist (e.g. `C012AB3CD,C987ZY6XW`). Baked into the sandbox image at build time. |Note: For markdown tables, the "one sentence per line" rule is often relaxed since table cells are inherently single-line. If this is intentional for table formatting, this can be ignored.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/reference/architecture.md` around lines 191 - 193, The table row for `SLACK_ALLOWED_CHANNELS` contains two sentences on the same line; split that cell into two sentences on separate lines so each sentence is its own line in the markdown source (update the `SLACK_ALLOWED_CHANNELS` table cell text to break after "Baked into the sandbox image at build time." and move "When unset, no channels are allowed by default." to the next line) to satisfy the one-sentence-per-line rule for diffs.src/lib/onboard.ts (1)
2508-2517: Type annotation in@ts-nocheckfile.Line 2511 uses a TypeScript type annotation (
const slackAllowedChannels: string[] = []), but the file has//@ts-nocheck`` at the top. While syntactically valid, this is inconsistent with the rest of the file which uses plain JavaScript variable declarations. Consider removing the type annotation for consistency:- const slackAllowedChannels: string[] = []; + const slackAllowedChannels = [];🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/onboard.ts` around lines 2508 - 2517, Remove the TypeScript-specific type annotation from the slackAllowedChannels declaration to match the file's // `@ts-nocheck` JavaScript style: change the declaration for slackAllowedChannels (used alongside enabledTokenEnvKeys and process.env.SLACK_ALLOWED_CHANNELS) to a plain JS declaration (e.g., const slackAllowedChannels = []) and leave the rest of the logic (splitting, trimming, filtering, and pushing ids) unchanged.docs/deployment/set-up-slack-bridge.md (3)
107-113: Missing "Next Steps" section.Per the documentation style guide, pages should include a "Next Steps" section at the bottom linking to related pages. Consider adding links to related content such as other messaging bridges (Telegram, Discord) or policy preset documentation.
- Gateway logs inside the sandbox: `openshell sandbox connect <sandbox-name>` then `tail -f /tmp/gateway.log`. + +## Next Steps + +- [Set Up Telegram Bridge](set-up-telegram-bridge.md) — configure Telegram messaging. +- [Set Up Discord Bridge](set-up-discord-bridge.md) — configure Discord messaging.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/deployment/set-up-slack-bridge.md` around lines 107 - 113, Add a "Next Steps" section after the "Confirm Delivery" paragraph that links to related messaging bridge docs (e.g., Telegram and Discord bridge setup) and to the policy preset documentation; reference the existing terms in this page (SLACK_ALLOWED_CHANNELS, the 'slack' policy preset, and the openshell sandbox troubleshooting command like openshell sandbox connect <sandbox-name> /tmp/gateway.log) so readers can navigate from confirmation to other bridge guides and to the policy preset reference.
25-25: One sentence per line.This line contains two sentences. Per the style guide, each sentence should be on its own line to make diffs more readable.
-NemoClaw supports Slack via Socket Mode — a persistent WebSocket connection that does not require a public URL or inbound firewall rules. The bot and app tokens are stored by OpenShell as secure providers; the sandbox receives placeholder values, not the raw secrets. +NemoClaw supports Slack via Socket Mode — a persistent WebSocket connection that does not require a public URL or inbound firewall rules. +The bot and app tokens are stored by OpenShell as secure providers; the sandbox receives placeholder values, not the raw secrets.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/deployment/set-up-slack-bridge.md` at line 25, The sentence "NemoClaw supports Slack via Socket Mode — a persistent WebSocket connection that does not require a public URL or inbound firewall rules. The bot and app tokens are stored by OpenShell as secure providers; the sandbox receives placeholder values, not the raw secrets." contains two sentences on one line; split them into two lines so each sentence is its own line in the docs file (update the line containing the text shown above and ensure the first sentence ends after "inbound firewall rules." and the second sentence "The bot and app tokens..." starts on the next line).
89-89: One sentence per line.Split this into separate lines for better diff readability:
-Channel entries in `/sandbox/.openclaw/openclaw.json` are fixed at image build time. Landlock keeps that path read-only at runtime, so you cannot patch messaging config inside a running sandbox. +Channel entries in `/sandbox/.openclaw/openclaw.json` are fixed at image build time. +Landlock keeps that path read-only at runtime, so you cannot patch messaging config inside a running sandbox.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/deployment/set-up-slack-bridge.md` at line 89, The paragraph "Channel entries in `/sandbox/.openclaw/openclaw.json` are fixed at image build time. Landlock keeps that path read-only at runtime, so you cannot patch messaging config inside a running sandbox." should be split into separate lines so each sentence is on its own line; edit the markdown so the first line is "Channel entries in `/sandbox/.openclaw/openclaw.json` are fixed at image build time." and the next line is "Landlock keeps that path read-only at runtime, so you cannot patch messaging config inside a running sandbox."
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.agents/skills/nemoclaw-user-deploy-remote/SKILL.md:
- Around line 173-175: The onboarding flow in src/lib/onboard.ts never prompts
for or stores SLACK_APP_TOKEN (xapp-...) even though SKILL.md requires it for
Socket Mode; update the Slack branch of the onboarding logic (the function that
collects Slack credentials—e.g., the Slack provider prompt handler /
saveProviderCredentials block) to prompt for SLACK_APP_TOKEN when the provider
is Slack, validate the token format (starts with "xapp-"), and persist it in the
same storage/credentials structure used for SLACK_BOT_TOKEN so the token is
available wherever SLACK_BOT_TOKEN is stored/loaded during runtime.
- Around line 140-226: The README-like skill doc under
.agents/skills/nemoclaw-user-deploy-remote/SKILL.md was edited directly and now
diverges from source (renumbered steps); regenerate this file from the canonical
docs using the documentation script. Run the docs-to-skills generator (python3
scripts/docs-to-skills.py docs/ .agents/skills/ --prefix nemoclaw-user) to
rebuild all .agents/skills/nemoclaw-user-*.md files so the SKILL.md content
(including Step X headings and Slack section) matches the source; commit the
regenerated output and remove manual edits to prevent future drift.
---
Nitpick comments:
In `@docs/deployment/set-up-slack-bridge.md`:
- Around line 107-113: Add a "Next Steps" section after the "Confirm Delivery"
paragraph that links to related messaging bridge docs (e.g., Telegram and
Discord bridge setup) and to the policy preset documentation; reference the
existing terms in this page (SLACK_ALLOWED_CHANNELS, the 'slack' policy preset,
and the openshell sandbox troubleshooting command like openshell sandbox connect
<sandbox-name> /tmp/gateway.log) so readers can navigate from confirmation to
other bridge guides and to the policy preset reference.
- Line 25: The sentence "NemoClaw supports Slack via Socket Mode — a persistent
WebSocket connection that does not require a public URL or inbound firewall
rules. The bot and app tokens are stored by OpenShell as secure providers; the
sandbox receives placeholder values, not the raw secrets." contains two
sentences on one line; split them into two lines so each sentence is its own
line in the docs file (update the line containing the text shown above and
ensure the first sentence ends after "inbound firewall rules." and the second
sentence "The bot and app tokens..." starts on the next line).
- Line 89: The paragraph "Channel entries in `/sandbox/.openclaw/openclaw.json`
are fixed at image build time. Landlock keeps that path read-only at runtime, so
you cannot patch messaging config inside a running sandbox." should be split
into separate lines so each sentence is on its own line; edit the markdown so
the first line is "Channel entries in `/sandbox/.openclaw/openclaw.json` are
fixed at image build time." and the next line is "Landlock keeps that path
read-only at runtime, so you cannot patch messaging config inside a running
sandbox."
In `@docs/reference/architecture.md`:
- Around line 191-193: The table row for `SLACK_ALLOWED_CHANNELS` contains two
sentences on the same line; split that cell into two sentences on separate lines
so each sentence is its own line in the markdown source (update the
`SLACK_ALLOWED_CHANNELS` table cell text to break after "Baked into the sandbox
image at build time." and move "When unset, no channels are allowed by default."
to the next line) to satisfy the one-sentence-per-line rule for diffs.
In `@src/lib/onboard.ts`:
- Around line 2508-2517: Remove the TypeScript-specific type annotation from the
slackAllowedChannels declaration to match the file's // `@ts-nocheck` JavaScript
style: change the declaration for slackAllowedChannels (used alongside
enabledTokenEnvKeys and process.env.SLACK_ALLOWED_CHANNELS) to a plain JS
declaration (e.g., const slackAllowedChannels = []) and leave the rest of the
logic (splitting, trimming, filtering, and pushing ids) unchanged.
🪄 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: Pro
Run ID: 9b7a0dad-a9f0-4f37-a188-cb6752e9dacf
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (7)
.agents/skills/nemoclaw-user-deploy-remote/SKILL.md.agents/skills/nemoclaw-user-reference/references/architecture.mdDockerfiledocs/deployment/set-up-slack-bridge.mddocs/reference/architecture.mdsrc/lib/onboard.tstest/onboard.test.ts
4b119d5 to
2a76ce8
Compare
2a76ce8 to
a3ed780
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/lib/onboard.ts (2)
2513-2522: Minor style inconsistency: explicit type annotation.Line 2516 uses TypeScript type annotation
const slackAllowedChannels: string[] = [];while the rest of the file (under//@ts-nocheck``) avoids explicit type annotations. This works but is stylistically inconsistent.♻️ Optional: remove explicit type annotation for consistency
- const slackAllowedChannels: string[] = []; + const slackAllowedChannels = [];Otherwise, the logic is correct — it properly parses the comma-separated channel IDs, filters empty strings, and only populates when both Slack is enabled and channels are specified.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/onboard.ts` around lines 2513 - 2522, Remove the explicit TypeScript type annotation on the slackAllowedChannels declaration to match the file's style (the code under // `@ts-nocheck` avoids explicit types); locate the const slackAllowedChannels declaration and change it from a typed declaration to an untyped one (leaving the rest of the logic that checks enabledTokenEnvKeys.has("SLACK_BOT_TOKEN") and parses process.env.SLACK_ALLOWED_CHANNELS intact).
762-764: Consider importingencodeDockerJsonArgfromweb-search.tsinstead of duplicating it.This function is already exported from
src/lib/web-search.ts(line 10-12). The local copy creates a maintenance burden — if the encoding logic ever needs to change, both copies must be updated.♻️ Suggested refactor
const webSearch = require("./web-search"); +const { encodeDockerJsonArg } = webSearch; -function encodeDockerJsonArg(value) { - return Buffer.from(JSON.stringify(value || {}), "utf8").toString("base64"); -}Alternatively, if you prefer to keep imports at the top unchanged, you can reference it via the existing import:
// Replace calls to encodeDockerJsonArg(...) with: webSearch.encodeDockerJsonArg(...)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/onboard.ts` around lines 762 - 764, Duplicate encodeDockerJsonArg implementation in onboard.ts should be removed and the existing exported function from src/lib/web-search.ts reused; replace local function usage with the imported encodeDockerJsonArg (or call it via the existing webSearch import if present) so there’s a single source of truth for encodeDockerJsonArg and avoid duplicated encoding logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/lib/onboard.ts`:
- Around line 2513-2522: Remove the explicit TypeScript type annotation on the
slackAllowedChannels declaration to match the file's style (the code under //
`@ts-nocheck` avoids explicit types); locate the const slackAllowedChannels
declaration and change it from a typed declaration to an untyped one (leaving
the rest of the logic that checks enabledTokenEnvKeys.has("SLACK_BOT_TOKEN") and
parses process.env.SLACK_ALLOWED_CHANNELS intact).
- Around line 762-764: Duplicate encodeDockerJsonArg implementation in
onboard.ts should be removed and the existing exported function from
src/lib/web-search.ts reused; replace local function usage with the imported
encodeDockerJsonArg (or call it via the existing webSearch import if present) so
there’s a single source of truth for encodeDockerJsonArg and avoid duplicated
encoding logic.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6daaf20b-b1a8-442f-968a-9f83369ef7be
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (7)
.agents/skills/nemoclaw-user-deploy-remote/SKILL.md.agents/skills/nemoclaw-user-reference/references/architecture.mdDockerfiledocs/deployment/set-up-slack-bridge.mddocs/reference/architecture.mdsrc/lib/onboard.tstest/onboard.test.ts
✅ Files skipped from review due to trivial changes (4)
- docs/reference/architecture.md
- .agents/skills/nemoclaw-user-reference/references/architecture.md
- docs/deployment/set-up-slack-bridge.md
- test/onboard.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- .agents/skills/nemoclaw-user-deploy-remote/SKILL.md
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
.agents/skills/nemoclaw-user-deploy-remote/SKILL.md (1)
1-293:⚠️ Potential issue | 🟠 MajorRegenerate this skill file from
docs/instead of editing it directly.This file path is under
.agents/skills/nemoclaw-user-*/*.md, so direct edits should be replaced by generated output from the docs source to avoid drift.As per coding guidelines, ".agents/skills/nemoclaw-user-/.md: Never edit
.agents/skills/nemoclaw-user-*/*.mddirectly; regenerate skills fromdocs/source".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.agents/skills/nemoclaw-user-deploy-remote/SKILL.md around lines 1 - 293, This skill markdown was edited directly under .agents/skills/nemoclaw-user-deploy-remote/SKILL.md but must be regenerated from the canonical docs source; revert this file and regenerate the skill from docs/ (update the source docs entry that defines the "nemoclaw-user-deploy-remote" skill or the "NemoClaw User Deploy Remote" document, then run the docs→skills generation step) so the generated SKILL.md matches the docs source and avoids direct edits in .agents/skills/nemoclaw-user-*/*.md.
🧹 Nitpick comments (1)
src/lib/onboard.ts (1)
3659-3676: Consider extracting channel-specific follow-up prompts.This adds another nested special case inside an already stateful prompt loop. Pulling Slack/Discord extras into per-channel handlers would make future channel additions safer and keep this flow closer to the repo's complexity target. As per coding guidelines, "Limit cyclomatic complexity to 20 in JavaScript/TypeScript files, with target of 15".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/onboard.ts` around lines 3659 - 3676, The channel-specific app-token prompt block increases cyclomatic complexity and nests special cases inside the main onboarding loop; extract this logic into a dedicated per-channel handler (e.g., a function like handleChannelAppToken(channel) or a channelHandlers map keyed by channel name) that encapsulates the behavior around getMessagingToken, prompt/normalizeCredentialValue, saveCredential, and setting process.env, and move any Slack/Discord-specific extras into their own handlers; then replace the inline block in the loop with a single call to that handler (pass ch, ch.appTokenEnvKey, ch.appTokenHelp, ch.appTokenLabel, ch.name) so the loop stays simple and future channels can add custom flows without increasing the main function's complexity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.agents/skills/nemoclaw-user-deploy-remote/SKILL.md:
- Around line 197-198: The doc line about creating a provider for the bot token
is inaccurate: update the sentence to state that onboarding creates providers
for both SLACK_BOT_TOKEN and SLACK_APP_TOKEN (in addition to baking
NEMOCLAW_SLACK_ALLOWED_CHANNELS_B64 into the image and starting the sandbox), so
replace the phrase "creates an OpenShell provider for the bot token" with
wording that explicitly references both SLACK_BOT_TOKEN and SLACK_APP_TOKEN
providers.
In `@Dockerfile`:
- Line 138: The current line unconditionally injects the placeholder
openshell:resolve:env:SLACK_APP_TOKEN into
_ch_cfg['slack']['accounts']['default'] which breaks the "no Socket Mode" path
when no app token provider/env exists; change the logic in the Dockerfile
snippet so you only call
_ch_cfg['slack']['accounts']['default'].update({'appToken':
'openshell:resolve:env:SLACK_APP_TOKEN'}) if 'slack' in _ch_cfg AND the
SLACK_APP_TOKEN provider/env is actually present and non-empty (e.g., check for
existence/non-empty value before updating), so the appToken key is only added
when a real app token will be resolvable.
In `@src/lib/onboard.ts`:
- Around line 3519-3523: The follow-up logging in setupMessagingChannels() still
uses "user ID"/"manual pairing" copy when allowIdsMode is set to "channel";
update setupMessagingChannels() to special-case allowIdsMode === "channel" (like
it already does for "guild") and change the log strings and user-facing messages
to refer to "Slack channel ID(s)", "channel allowlist", and "channels remain
blocked until configured" instead of user/pairing wording; ensure any references
to manual pairing or user IDs (e.g., in prompts, help text, and processLogger
messages) are replaced with channel-specific phrasing so the behavior matches
userIdHelp/userIdLabel and the "channel" mode semantics.
- Around line 2328-2332: The SLACK_APP_TOKEN entry is being dropped by the
enabledEnvKeys filter because the Slack provider only contributes its primary
envKey (SLACK_BOT_TOKEN); update the provider selection so secondary tokens are
preserved: change the enabledEnvKeys computation or the logic inside
upsertMessagingProviders to include all envKey values from messaging provider
definitions (not just the primary one), so entries created with
getMessagingToken("SLACK_APP_TOKEN") are retained and passed through to Socket
Mode; alternatively, explicitly add "SLACK_APP_TOKEN" to the set contributed by
the Slack provider alongside "SLACK_BOT_TOKEN" to ensure it survives the
filtering that currently prevents the fallback path.
---
Duplicate comments:
In @.agents/skills/nemoclaw-user-deploy-remote/SKILL.md:
- Around line 1-293: This skill markdown was edited directly under
.agents/skills/nemoclaw-user-deploy-remote/SKILL.md but must be regenerated from
the canonical docs source; revert this file and regenerate the skill from docs/
(update the source docs entry that defines the "nemoclaw-user-deploy-remote"
skill or the "NemoClaw User Deploy Remote" document, then run the docs→skills
generation step) so the generated SKILL.md matches the docs source and avoids
direct edits in .agents/skills/nemoclaw-user-*/*.md.
---
Nitpick comments:
In `@src/lib/onboard.ts`:
- Around line 3659-3676: The channel-specific app-token prompt block increases
cyclomatic complexity and nests special cases inside the main onboarding loop;
extract this logic into a dedicated per-channel handler (e.g., a function like
handleChannelAppToken(channel) or a channelHandlers map keyed by channel name)
that encapsulates the behavior around getMessagingToken,
prompt/normalizeCredentialValue, saveCredential, and setting process.env, and
move any Slack/Discord-specific extras into their own handlers; then replace the
inline block in the loop with a single call to that handler (pass ch,
ch.appTokenEnvKey, ch.appTokenHelp, ch.appTokenLabel, ch.name) so the loop stays
simple and future channels can add custom flows without increasing the main
function's complexity.
🪄 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: Pro
Run ID: 78f373b4-3ded-40c3-a341-39b8030b4f70
📒 Files selected for processing (7)
.agents/skills/nemoclaw-user-deploy-remote/SKILL.md.agents/skills/nemoclaw-user-reference/references/architecture.mdDockerfiledocs/deployment/set-up-slack-bridge.mddocs/reference/architecture.mdsrc/lib/onboard.tstest/onboard.test.ts
✅ Files skipped from review due to trivial changes (2)
- docs/reference/architecture.md
- docs/deployment/set-up-slack-bridge.md
🚧 Files skipped from review as they are similar to previous changes (1)
- .agents/skills/nemoclaw-user-reference/references/architecture.md
|
✨ Thanks for submitting this PR, which proposes a new feature to add support for SLACK_ALLOWED_CHANNELS. |
a3ed780 to
7953ad3
Compare
…sting Slack's default groupPolicy is "allowlist" but NemoClaw provided no way to bake channel IDs into openclaw.json at image build time, leaving all channels blocked after onboarding with no CLI workaround. This change adds SLACK_ALLOWED_CHANNELS (comma-separated Slack channel IDs) parallel to the existing TELEGRAM_ALLOWED_IDS mechanism. The IDs are base64-encoded into a new NEMOCLAW_SLACK_ALLOWED_CHANNELS_B64 Dockerfile ARG and written into channels.slack.accounts.default.channels at image build time. - Dockerfile: add NEMOCLAW_SLACK_ALLOWED_CHANNELS_B64 ARG/ENV and write the channels map in the Python config generation script - src/lib/onboard.ts: add userIdEnvKey/allowIdsMode to the Slack MESSAGING_CHANNELS entry; collect and inject slackAllowedChannels into patchStagedDockerfile - test/onboard.test.ts: add test for Slack channel allowlist build arg - docs/deployment/set-up-slack-bridge.md: new how-to guide for Slack setup including Socket Mode, token collection, and channel allowlisting - docs/reference/architecture.md: document SLACK_BOT_TOKEN, SLACK_APP_TOKEN, and SLACK_ALLOWED_CHANNELS env vars
7953ad3 to
81d426a
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
Dockerfile (1)
138-138:⚠️ Potential issue | 🟠 MajorOnly write
appTokenwhen the app-token provider is actually wired in.Line 138 still bakes
openshell:resolve:env:SLACK_APP_TOKENinto every Slack config, butsrc/lib/onboard.tsonly creates theSLACK_APP_TOKENprovider when that token already exists. Fresh Slack sandboxes can still end up with an unresolvable secret reference.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Dockerfile` at line 138, The Dockerfile currently unconditionally injects the unresolved secret reference via _ch_cfg['slack']['accounts']['default'].update({'appToken': 'openshell:resolve:env:SLACK_APP_TOKEN'}), which can produce an unresolvable secret for fresh sandboxes; change this to only add the appToken entry when the SLACK_APP_TOKEN provider will actually be created (the logic in src/lib/onboard.ts). Concretely, guard or conditionalize the update so it only runs if the SLACK_APP_TOKEN provider/flag (or an env check like presence of SLACK_APP_TOKEN) is present, leaving the slack.accounts.default config untouched otherwise. Ensure you reference and use the same signal that onboard.ts uses to decide wiring the provider so configs remain consistent.
🧹 Nitpick comments (1)
src/lib/onboard.ts (1)
2569-2590: Consider extracting messaging-config assembly out ofcreateSandbox().This adds another provider-specific branch to an already very large function. Pulling the
messagingAllowedIds/discordGuilds/slackAllowedChannelsharvesting into a helper would make the flow easier to reason about and keep it closer to the repo's complexity target.As per coding guidelines, "Limit cyclomatic complexity to 20 in JavaScript/TypeScript files, with target of 15".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/onboard.ts` around lines 2569 - 2590, The createSandbox() function is getting large and includes provider-specific harvesting of messagingAllowedIds, discordGuilds, and slackAllowedChannels; extract that logic into a new helper (e.g., assembleMessagingConfig or buildMessagingChannels) that accepts the inputs used inside createSandbox (env, enabledTokenEnvKeys, etc.) and returns an object { messagingAllowedIds, discordGuilds, slackAllowedChannels, activeMessagingChannels } (or individual values); replace the inlined code in createSandbox() with a single call to that helper and pass the returned values into patchStagedDockerfile and other call sites, ensuring all referenced symbols (messagingAllowedIds, discordGuilds, slackAllowedChannels, createSandbox, patchStagedDockerfile) still compile and tests cover the refactor.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lib/onboard.ts`:
- Around line 3571-3574: The onboarding metadata added
appTokenEnvKey/appTokenLabel/appTokenHelp are never used by the interactive
wizard, so update setupMessagingChannels to include and prompt for the new
appTokenEnvKey (in addition to ch.envKey) when the selected channel/provider is
Slack: modify the logic in setupMessagingChannels that builds the prompt list
for a channel (look for references to ch.envKey and Slack-specific branches) to
add a second prompt entry for ch.appTokenEnvKey (or use the metadata field name
appTokenEnvKey) with label appTokenLabel and help appTokenHelp, validate and
save the provided value into the same store where ch.envKey is persisted so
first-time Slack onboarding can populate SLACK_APP_TOKEN.
---
Duplicate comments:
In `@Dockerfile`:
- Line 138: The Dockerfile currently unconditionally injects the unresolved
secret reference via _ch_cfg['slack']['accounts']['default'].update({'appToken':
'openshell:resolve:env:SLACK_APP_TOKEN'}), which can produce an unresolvable
secret for fresh sandboxes; change this to only add the appToken entry when the
SLACK_APP_TOKEN provider will actually be created (the logic in
src/lib/onboard.ts). Concretely, guard or conditionalize the update so it only
runs if the SLACK_APP_TOKEN provider/flag (or an env check like presence of
SLACK_APP_TOKEN) is present, leaving the slack.accounts.default config untouched
otherwise. Ensure you reference and use the same signal that onboard.ts uses to
decide wiring the provider so configs remain consistent.
---
Nitpick comments:
In `@src/lib/onboard.ts`:
- Around line 2569-2590: The createSandbox() function is getting large and
includes provider-specific harvesting of messagingAllowedIds, discordGuilds, and
slackAllowedChannels; extract that logic into a new helper (e.g.,
assembleMessagingConfig or buildMessagingChannels) that accepts the inputs used
inside createSandbox (env, enabledTokenEnvKeys, etc.) and returns an object {
messagingAllowedIds, discordGuilds, slackAllowedChannels,
activeMessagingChannels } (or individual values); replace the inlined code in
createSandbox() with a single call to that helper and pass the returned values
into patchStagedDockerfile and other call sites, ensuring all referenced symbols
(messagingAllowedIds, discordGuilds, slackAllowedChannels, createSandbox,
patchStagedDockerfile) still compile and tests cover the refactor.
🪄 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: Pro Plus
Run ID: fab57749-ae5c-4363-9f76-b591a777f120
📒 Files selected for processing (7)
.agents/skills/nemoclaw-user-deploy-remote/SKILL.md.agents/skills/nemoclaw-user-reference/references/architecture.mdDockerfiledocs/deployment/set-up-slack-bridge.mddocs/reference/architecture.mdsrc/lib/onboard.tstest/onboard.test.ts
✅ Files skipped from review due to trivial changes (3)
- test/onboard.test.ts
- docs/deployment/set-up-slack-bridge.md
- .agents/skills/nemoclaw-user-reference/references/architecture.md
🚧 Files skipped from review as they are similar to previous changes (2)
- docs/reference/architecture.md
- .agents/skills/nemoclaw-user-deploy-remote/SKILL.md
There was a problem hiding this comment.
♻️ Duplicate comments (2)
src/lib/onboard.ts (2)
3709-3713:⚠️ Potential issue | 🟡 MinorThe new
"channel"allowlist mode still reuses DM/pairing copy.
setupMessagingChannels()only special-cases"guild", so Slack still prints"allowed IDs already set","user ID saved", and"manual pairing"messaging for this path. That makes the new channel allowlist flow read like DM pairing instead of channel gating.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/onboard.ts` around lines 3709 - 3713, setupMessagingChannels currently only treats allowIdsMode "guild" as a special case, so when allowIdsMode is "channel" the code reuses DM/pairing messages like "allowed IDs already set", "user ID saved", and "manual pairing"; update setupMessagingChannels to detect allowIdsMode === "channel" and provide channel-specific messaging and flow (e.g., replace user/DM/pairing text with channel-focused text such as "channel IDs already set", "channel ID saved", and instructions for manual channel gating) ensuring any branches that reference allowIdsMode or the labels "Slack Channel IDs (optional allowlist)" use the new channel-specific strings and logic.
3705-3708:⚠️ Potential issue | 🟠 MajorSlack can still be enabled without
SLACK_APP_TOKEN.These new fields are only metadata right now:
setupMessagingChannels()never prompts forch.appTokenEnvKey, andcreateSandbox()still enables Slack fromSLACK_BOT_TOKENalone. First-time onboarding can therefore finish with a Slack bridge that cannot connect in Socket Mode.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/onboard.ts` around lines 3705 - 3708, The new Slack app token metadata (ch.appTokenEnvKey / "SLACK_APP_TOKEN") is only descriptive right now, so onboarding can finish with Slack enabled but missing the App-Level token required for Socket Mode: update setupMessagingChannels() to prompt for and save ch.appTokenEnvKey when the user selects Slack and chooses Socket Mode (or when Socket Mode is required), and update createSandbox() to validate presence of both SLACK_BOT_TOKEN and SLACK_APP_TOKEN before enabling Socket Mode (or fall back to disabling Socket Mode and log/warn clearly); ensure references to ch.appTokenEnvKey, SLACK_APP_TOKEN and SLACK_BOT_TOKEN are used for the presence check so the sandbox isn't created in a broken state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/lib/onboard.ts`:
- Around line 3709-3713: setupMessagingChannels currently only treats
allowIdsMode "guild" as a special case, so when allowIdsMode is "channel" the
code reuses DM/pairing messages like "allowed IDs already set", "user ID saved",
and "manual pairing"; update setupMessagingChannels to detect allowIdsMode ===
"channel" and provide channel-specific messaging and flow (e.g., replace
user/DM/pairing text with channel-focused text such as "channel IDs already
set", "channel ID saved", and instructions for manual channel gating) ensuring
any branches that reference allowIdsMode or the labels "Slack Channel IDs
(optional allowlist)" use the new channel-specific strings and logic.
- Around line 3705-3708: The new Slack app token metadata (ch.appTokenEnvKey /
"SLACK_APP_TOKEN") is only descriptive right now, so onboarding can finish with
Slack enabled but missing the App-Level token required for Socket Mode: update
setupMessagingChannels() to prompt for and save ch.appTokenEnvKey when the user
selects Slack and chooses Socket Mode (or when Socket Mode is required), and
update createSandbox() to validate presence of both SLACK_BOT_TOKEN and
SLACK_APP_TOKEN before enabling Socket Mode (or fall back to disabling Socket
Mode and log/warn clearly); ensure references to ch.appTokenEnvKey,
SLACK_APP_TOKEN and SLACK_BOT_TOKEN are used for the presence check so the
sandbox isn't created in a broken state.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: a1288a32-ce47-4d02-9086-4d26b5fd16fd
📒 Files selected for processing (7)
.agents/skills/nemoclaw-user-deploy-remote/SKILL.md.agents/skills/nemoclaw-user-reference/references/architecture.mdDockerfiledocs/deployment/set-up-slack-bridge.mddocs/reference/architecture.mdsrc/lib/onboard.tstest/onboard.test.ts
✅ Files skipped from review due to trivial changes (4)
- docs/reference/architecture.md
- .agents/skills/nemoclaw-user-reference/references/architecture.md
- test/onboard.test.ts
- docs/deployment/set-up-slack-bridge.md
🚧 Files skipped from review as they are similar to previous changes (1)
- Dockerfile
|
Thanks for contributing — |
Signed-off-by: Aaron Erickson <aerickson@nvidia.com> # Conflicts: # .agents/skills/nemoclaw-user-deploy-remote/SKILL.md # Dockerfile # src/lib/onboard.ts # test/onboard.test.ts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Selective E2E Results — ❌ Some jobs failedRun: 26407205250
|
Selective E2E Results — ❌ Some jobs failedRun: 26433368796
|
Selective E2E Results — ✅ All requested jobs passedRun: 26449305113
|
ericksoa
left a comment
There was a problem hiding this comment.
Looks good. Validated with the full nightly sweep plus a focused rerun of hermes-onboard-security-posture-e2e on the current head.
## Summary Refresh NemoClaw documentation and generated user skills for the v0.0.50 and v0.0.51 release-prep window. Remove obsolete legacy docs version metadata now that Fern docs no longer use `docs/project.json`, `docs/versions1.json`, or the legacy Sphinx config. ## Source summary - #1757 -> `docs/manage-sandboxes/messaging-channels.mdx`, `docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Document Slack channel allowlisting with `SLACK_ALLOWED_CHANNELS`. - #4134 -> `docs/manage-sandboxes/messaging-channels.mdx`, `docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Document Cloudflare named tunnel support through `CLOUDFLARE_TUNNEL_TOKEN`. - #4186 and #4135 -> `docs/inference/use-local-inference.mdx`, `docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Document Ollama upgrade and user-local install behavior. - #4185 -> `docs/network-policy/integration-policy-examples.mdx`, `docs/about/release-notes.mdx`: Clarify Jira policy validation probes. - Release cleanup -> `.claude/skills/nemoclaw-contributor-update-docs/SKILL.md`, `docs/CONTRIBUTING.md`, `.github/PULL_REQUEST_TEMPLATE.md`, `scripts/bump-version.ts`: Stop using legacy docs version JSON files and align docs verification on `npm run docs`. ## Changes - Add v0.0.50 and v0.0.51 release notes. - Regenerate NemoClaw user skills from the current Fern docs. - Remove obsolete `docs/conf.py`, `docs/project.json`, and `docs/versions1.json`. - Update docs workflow guidance and PR templates to use `npm run docs` instead of `make docs`. - Remove release-version JSON handling from `scripts/bump-version.ts`. ## 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) ## Verification - [ ] `npx prek run --all-files` passes - [ ] `npm test` passes - [ ] Tests added or updated for new or changed behavior - [x] No secrets, API keys, or credentials committed - [x] Docs updated for user-facing behavior changes - [ ] `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) Additional verification: - `python3 scripts/docs-to-skills.py docs/ .agents/skills/ --prefix nemoclaw-user --doc-platform fern-mdx` - `npm run build:cli` - `npx tsc --noEmit --allowSyntheticDefaultImports --module NodeNext --moduleResolution NodeNext --target ES2022 --types node scripts/bump-version.ts` - `ReadLints` on touched docs, skills, template, and script files - Searched for stale `versions1.json`, `project.json`, and `make docs` references Known gaps: - `npm run docs` was not rerun after cleanup because the earlier Fern CLI fetch failed with npm registry `403 Forbidden` in this environment. - A broad `npm run typecheck -- --noEmit` hit an unrelated existing `scripts/dev-tier-selector.js` type error. --- Signed-off-by: Miyoung Cho <miyoungc@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added resource profiling with CPU/RAM configuration controls for sandboxes * Enhanced local Ollama inference with automatic GPU memory-aware model fallback * Added `nemoclaw resources` command to display host hardware inventory * Enabled Cloudflare named tunnel support via environment configuration * **Documentation** * Improved setup guides for local inference, sandbox hardening, and policy validation * Enhanced troubleshooting for messaging delivery and host service routing * Added release notes for v0.0.50 and v0.0.51 * **Chores** * Updated build documentation commands from `make docs` to `npm run docs` <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/NVIDIA/NemoClaw/pull/4262?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
Slack's
groupPolicydefaults toallowlistbut NemoClaw had no way to bake channel IDs intoopenclaw.jsonat image build time, leaving all channels blocked after onboarding with no CLI workaround. This addsSLACK_ALLOWED_CHANNELSsupport parallel to the existingTELEGRAM_ALLOWED_IDSmechanism.Related Issue
Changes
Dockerfile: addNEMOCLAW_SLACK_ALLOWED_CHANNELS_B64ARG/ENVand writechannels.slack.accounts.default.channelsin the Python config generation script when the list is non-emptysrc/lib/onboard.ts: adduserIdEnvKey/allowIdsMode/userIdLabelto the Slack entry inMESSAGING_CHANNELS; collectSLACK_ALLOWED_CHANNELSintoslackAllowedChannels; add param and replacement block topatchStagedDockerfiletest/onboard.test.ts: add test verifying the build arg is correctly base64-encoded with the expected channel IDsdocs/deployment/set-up-slack-bridge.md: new how-to guide for Slack setup including Socket Mode, token collection, and channel allowlistingdocs/reference/architecture.md: addSLACK_BOT_TOKEN,SLACK_APP_TOKEN, andSLACK_ALLOWED_CHANNELSto the env var tableType of Change
Testing
npx prek run --all-filespasses (or equivalentlymake check).npm testpasses.Manual verification:
Checklist
General
Code Changes
npx prek run --all-filesauto-fixes formatting (ormake formatfor targeted runs).Doc Changes
set-up-slack-bridge.md) includes SPDX header and frontmatter.Signed-off-by: Filipe Felisbino filipenf@gmail.com
Summary by CodeRabbit
New Features
Documentation
Tests