fix(onboard): filter policy presets by enabled channels, not stored credentials - #1651
fix(onboard): filter policy presets by enabled channels, not stored credentials#1651kagura-agent wants to merge 3 commits into
Conversation
…redentials setupPoliciesWithSelection() was building messaging preset suggestions from credential store tokens instead of the channels selected during the current onboard session. This caused messaging presets to appear even when the user skipped messaging channel selection. Now passes enabledChannels to the preset selection step and filters messaging suggestions accordingly. Fixes NVIDIA#1610
📝 WalkthroughWalkthroughPolicy preset selection now respects the current onboarding session's messaging-channel choices: messaging-related presets (telegram, slack, discord) are only suggested when the corresponding channel is enabled in the session and a bot token is present. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant Onboard as Onboard Flow
participant Session as Onboard Session Store
participant Creds as Credential Store
participant Policy as Policy Preset Selector
User->>Onboard: run onboarding
Onboard->>Onboard: setupMessagingChannels() -> enabledChannels
Onboard->>Session: updateSession(... current.steps.sandbox.enabledChannels ...)
Onboard->>Creds: check tokens (telegram/slack/discord)
Onboard->>Policy: setupPoliciesWithSelection(enabledChannels, detectedTokens)
Policy->>Policy: include messaging presets only if token && (enabledChannels == null || channel in enabledChannels)
Policy->>Onboard: present policy preset suggestions
Onboard->>User: display policy presets
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
bin/lib/onboard.js (1)
4410-4466:⚠️ Potential issue | 🔴 CriticalFix block-scoped
enabledChannelsbefore passing to policy setup
enabledChannelsis declared inside theelseblock (line 4410) but referenced at line 4465 outside that block. This will throwReferenceErrorat runtime.Move the declaration to function scope, initialized to
null, and assign within theelseblock:Suggested fix
+ let enabledChannels = null; const resumeSandbox = resume && ...; if (resumeSandbox) { ... } else { - const enabledChannels = await setupMessagingChannels(); + enabledChannels = await setupMessagingChannels();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/onboard.js` around lines 4410 - 4466, The variable enabledChannels is declared inside the else block (from setupMessagingChannels()) but later referenced by setupPoliciesWithSelection and other logic, causing a ReferenceError; fix by hoisting enabledChannels to the surrounding function scope (declare let enabledChannels = null; before the conditional), then assign enabledChannels = await setupMessagingChannels() inside the existing else block where it currently lives so all later uses (references in setupPoliciesWithSelection, the resume logic, and onboardSession.markStepComplete calls) read the function-scoped variable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@bin/lib/onboard.js`:
- Around line 3832-3833: The Telegram suggestion check currently only uses
getCredential("TELEGRAM_BOT_TOKEN") which misses env-only setups; update the
condition that surrounds suggestions.push("telegram") to mirror the
Slack/Discord branches by checking for an env token as well (e.g., treat either
getCredential("TELEGRAM_BOT_TOKEN") OR process.env.TELEGRAM_BOT_TOKEN as
presence) while keeping the same enabledChannels gating, so Telegram is
suggested in non-interactive env-only setups.
---
Outside diff comments:
In `@bin/lib/onboard.js`:
- Around line 4410-4466: The variable enabledChannels is declared inside the
else block (from setupMessagingChannels()) but later referenced by
setupPoliciesWithSelection and other logic, causing a ReferenceError; fix by
hoisting enabledChannels to the surrounding function scope (declare let
enabledChannels = null; before the conditional), then assign enabledChannels =
await setupMessagingChannels() inside the existing else block where it currently
lives so all later uses (references in setupPoliciesWithSelection, the resume
logic, and onboardSession.markStepComplete calls) read the function-scoped
variable.
🪄 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: be2b206c-8ad6-4524-8eed-05e08edd9ca3
📒 Files selected for processing (1)
bin/lib/onboard.js
cv
left a comment
There was a problem hiding this comment.
Security Review — FAIL (runtime crash)
The filtering logic is correct — it tightens preset suggestions, never loosens them, and degrades gracefully when `enabledChannels` is null.
Blocking issue
ReferenceError: `enabledChannels` is declared with `const` at line ~4401 inside the `else` branch of the `resumeSandbox` conditional. It's then referenced at line ~4462 inside a sibling `else` block (the `resumePolicies` conditional). `const` is block-scoped — this will throw a `ReferenceError` at runtime whenever policy setup runs.
Fix: hoist the declaration to function scope:
```js
let enabledChannels = null;
// ... inside the else branch:
enabledChannels = await setupMessagingChannels();
```
What's good
- Filtering logic is security-correct (AND conjunction, only tightens)
- No credential handling changes
- Graceful null fallback for backward compat
|
Fixed in 5875271 — hoisted |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
bin/lib/onboard.js (1)
4391-4467:⚠️ Potential issue | 🟠 Major
enabledChannelsis dropped on resume when sandbox step is skipped.Line 4391 initializes
enabledChannelstonull, and it is only set at Line 4411 in the non-resume-sandbox branch. WhenresumeSandboxis true, Line 4466 passesnullintosetupPoliciesWithSelection, which reverts to credential-only suggestions and can reintroduce the original UX bug for resumed runs.Suggested fix
- let enabledChannels = null; + let enabledChannels = Array.isArray(session?.enabledChannels) ? session.enabledChannels : null; @@ - enabledChannels = await setupMessagingChannels(); + enabledChannels = await setupMessagingChannels(); + onboardSession.updateSession((current) => { + current.enabledChannels = enabledChannels; + return current; + }); @@ - onboardSession.markStepComplete("sandbox", { sandboxName, provider, model, nimContainer }); + onboardSession.markStepComplete("sandbox", { + sandboxName, + provider, + model, + nimContainer, + enabledChannels, + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/onboard.js` around lines 4391 - 4467, The resume path skips calling setupMessagingChannels so enabledChannels stays null and is passed into setupPoliciesWithSelection; ensure enabledChannels is populated on resume by calling setupMessagingChannels() when resumeSandbox is true (or by retrieving saved channels) before any later use (notably before setupPoliciesWithSelection). Modify the logic around the resumeSandbox branch so enabledChannels is assigned (via setupMessagingChannels) in both the resumed and non-resumed flows, keeping references to the existing variables/resumeSandbox, setupMessagingChannels, createSandbox, and setupPoliciesWithSelection.
♻️ Duplicate comments (1)
bin/lib/onboard.js (1)
3832-3833:⚠️ Potential issue | 🟡 MinorTelegram preset detection still misses env-only token setups.
At Line 3832, Telegram checks only
getCredential("TELEGRAM_BOT_TOKEN"), while Slack/Discord also honorprocess.env. This can skip Telegram suggestions in non-interactive env-only runs.Suggested fix
- if (getCredential("TELEGRAM_BOT_TOKEN") && (!enabledChannels || enabledChannels.includes("telegram"))) + if ( + (getCredential("TELEGRAM_BOT_TOKEN") || process.env.TELEGRAM_BOT_TOKEN) && + (!enabledChannels || enabledChannels.includes("telegram")) + ) suggestions.push("telegram");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/onboard.js` around lines 3832 - 3833, The Telegram preset check in the onboarding flow uses getCredential("TELEGRAM_BOT_TOKEN") only and misses setups where the token is provided via process.env; update the conditional that pushes "telegram" into suggestions to also check process.env.TELEGRAM_BOT_TOKEN (matching how Slack/Discord are handled) and preserve the enabledChannels filter (i.e., if TELEGRAM_BOT_TOKEN exists in either getCredential or process.env and enabledChannels is unset or includes "telegram", push "telegram" onto suggestions). Ensure you reference getCredential, process.env.TELEGRAM_BOT_TOKEN, enabledChannels, and suggestions when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@bin/lib/onboard.js`:
- Around line 4391-4467: The resume path skips calling setupMessagingChannels so
enabledChannels stays null and is passed into setupPoliciesWithSelection; ensure
enabledChannels is populated on resume by calling setupMessagingChannels() when
resumeSandbox is true (or by retrieving saved channels) before any later use
(notably before setupPoliciesWithSelection). Modify the logic around the
resumeSandbox branch so enabledChannels is assigned (via setupMessagingChannels)
in both the resumed and non-resumed flows, keeping references to the existing
variables/resumeSandbox, setupMessagingChannels, createSandbox, and
setupPoliciesWithSelection.
---
Duplicate comments:
In `@bin/lib/onboard.js`:
- Around line 3832-3833: The Telegram preset check in the onboarding flow uses
getCredential("TELEGRAM_BOT_TOKEN") only and misses setups where the token is
provided via process.env; update the conditional that pushes "telegram" into
suggestions to also check process.env.TELEGRAM_BOT_TOKEN (matching how
Slack/Discord are handled) and preserve the enabledChannels filter (i.e., if
TELEGRAM_BOT_TOKEN exists in either getCredential or process.env and
enabledChannels is unset or includes "telegram", push "telegram" onto
suggestions). Ensure you reference getCredential,
process.env.TELEGRAM_BOT_TOKEN, enabledChannels, and suggestions when making the
change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 28f19682-5cf7-4d4a-a47f-bb1db0c6c00e
📒 Files selected for processing (1)
bin/lib/onboard.js
- Add process.env.TELEGRAM_BOT_TOKEN check to match Slack/Discord pattern - Persist enabledChannels to session so resumed runs restore channel selections - Include enabledChannels in sandbox markStepComplete for future resumes
|
Addressed both remaining findings in 1848006:
Thanks for the thorough review @cv! 🙏 |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
bin/lib/onboard.js (1)
4397-4420:⚠️ Potential issue | 🟠 Major
enabledChannelsis persisted in a step field that gets normalized away on save/load.Line 4418 writes to
current.steps.sandbox.enabledChannels, but the session step shape persists only StepState fields; on resume, Line 4397 can readnulland fall back to credential-only suggestion behavior again.Please persist
enabledChannelsin a schema-supported session field (and normalization path) instead of attaching it tosteps.sandboxad hoc.Also applies to: 4433-4433
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/onboard.js` around lines 4397 - 4420, The code writes enabledChannels into current.steps.sandbox.enabledChannels which is not part of the persisted StepState schema and thus gets normalized away on save/load; update the persistence to store enabledChannels in a schema-backed session field instead of ad-hoc steps (e.g. add an enabledChannels property under the session root or a supported session.messaging or sandboxMetadata field), change the onboardSession.updateSession call to set that schema-supported field (rather than current.steps.sandbox.enabledChannels), and ensure setupMessagingChannels() return value is stored/loaded from that canonical field so resume logic (the enabledChannels check near where enabledChannels is read) observes the persisted value.
🧹 Nitpick comments (1)
bin/lib/onboard.js (1)
4391-4475: Add a resume regression test for channel-gated policy suggestions.This flow now depends on restoring
enabledChannelsacross session save/load and reusing it in policy selection. Please add coverage for: “skip messaging channels → resume → no messaging presets suggested.”As per coding guidelines, "Security-sensitive code paths in isolation/sandbox features must have extra test coverage to prevent credential leaks and sandbox escapes."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/onboard.js` around lines 4391 - 4475, Add a regression test that simulates skipping messaging channels and then resuming, by mocking setupMessagingChannels to return null (or no channels), running the onboarding flow twice with onboardSession persisted between runs and resume=true, and asserting that when resumed the call to setupPoliciesWithSelection receives selectedPresets=null (i.e., no messaging presets suggested) and that enabledChannels saved via onboardSession.updateSession remains null; use spies/mocks on setupMessagingChannels, setupPoliciesWithSelection, createSandbox and arePolicyPresetsApplied to reproduce the resume path and verify the policy-selection behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@bin/lib/onboard.js`:
- Around line 4397-4420: The code writes enabledChannels into
current.steps.sandbox.enabledChannels which is not part of the persisted
StepState schema and thus gets normalized away on save/load; update the
persistence to store enabledChannels in a schema-backed session field instead of
ad-hoc steps (e.g. add an enabledChannels property under the session root or a
supported session.messaging or sandboxMetadata field), change the
onboardSession.updateSession call to set that schema-supported field (rather
than current.steps.sandbox.enabledChannels), and ensure setupMessagingChannels()
return value is stored/loaded from that canonical field so resume logic (the
enabledChannels check near where enabledChannels is read) observes the persisted
value.
---
Nitpick comments:
In `@bin/lib/onboard.js`:
- Around line 4391-4475: Add a regression test that simulates skipping messaging
channels and then resuming, by mocking setupMessagingChannels to return null (or
no channels), running the onboarding flow twice with onboardSession persisted
between runs and resume=true, and asserting that when resumed the call to
setupPoliciesWithSelection receives selectedPresets=null (i.e., no messaging
presets suggested) and that enabledChannels saved via
onboardSession.updateSession remains null; use spies/mocks on
setupMessagingChannels, setupPoliciesWithSelection, createSandbox and
arePolicyPresetsApplied to reproduce the resume path and verify the
policy-selection behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 23b77a06-d631-4d8d-b9b6-d1d0b7037e4b
📒 Files selected for processing (1)
bin/lib/onboard.js
|
Hi @cv — just a heads-up that both issues from your review have been addressed:
Would appreciate a re-review when you get a chance! 🙏 (Also noting that @kjw3 mentioned this may be folded into the discord/native remediation branch — totally understand if this PR gets superseded by that effort. Happy either way!) |
kagura-agent
left a comment
There was a problem hiding this comment.
Thanks for the thorough review @cv!
Regarding the scoping concern — enabledChannels is already declared with let at function scope (line 4391, before the resumeSandbox conditional):
let enabledChannels = null; // line 4391 — function scope
const sandboxReuseState = getSandboxReuseState(sandboxName);
const resumeSandbox = resume && ...;
if (resumeSandbox) {
enabledChannels = ...; // reassignment, not declaration
} else {
enabledChannels = await setupMessagingChannels(); // reassignment
}
// ...
enabledChannels, // line 4475 — accessible, same scopeSo there's no ReferenceError risk here — both branches assign to the same let variable in the enclosing scope. The reference at line 4475 is valid.
Could you double-check and re-approve if this addresses your concern?
|
Apologies for the previous commits — I pushed fixes without properly running tests or verifying the changes against the review feedback. That was sloppy and I should have done better. I'm now going through all the review comments carefully, running the full test suite, and will update this PR once everything is properly validated. |
|
After rebasing against upstream/main, I discovered that all the changes from this PR have already been incorporated into the TypeScript migration in #1673. Specifically:
This PR is now redundant. Closing it. Note: Issue #1610 is still open — it could be closed since the fix is in main via #1673. |
Summary
Fixes #1610 — onboard policy preset step was suggesting messaging presets based on stored credentials instead of the channels selected during the current onboard session.
Root Cause
setupPoliciesWithSelection()checkedgetCredential('TELEGRAM_BOT_TOKEN')etc. to build suggestions, but the user may have skipped messaging channel selection entirely. TheenabledChannelsarray fromsetupMessagingChannels()was never passed to the preset step.Fix
enabledChannelsoption tosetupPoliciesWithSelection()enabledChannelsenabledChannelsis not provided (backward compat), falls back to credential-only checkenabledChannelsfromcreateSandboxflow to the policy selection callChanges
bin/lib/onboard.js: 13 insertions, 3 deletions — minimal, surgical fixSummary by CodeRabbit