Skip to content

fix(integrations): allow listing Slack DM/user remote dirs within event scope#186

Merged
kjgbot merged 1 commit into
mainfrom
fix/slack-dm-remote-dir-scope
Jun 9, 2026
Merged

fix(integrations): allow listing Slack DM/user remote dirs within event scope#186
kjgbot merged 1 commit into
mainfrom
fix/slack-dm-remote-dir-scope

Conversation

@kjgbot

@kjgbot kjgbot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Symptom

Inbox error:

Error invoking remote method 'integrations:list-remote-dir': Error: Integration remote directory is outside this project integration scope

It fired whenever a Slack DM / per-user message event arrived (e.g. .integrations/slack/users/U0ADJH4P83T/messages/<ts>/meta.json) and the renderer tried to list or read that remote directory.

Root cause

  • integrations:list-remote-dirIntegrationsManager.listRemoteDirectory (and readRemoteFile) gate the requested path against listableRemoteMountPaths(), which is the discovery path + canonical channel mount paths for each visible integration.
  • Slack DM/user paths are event-subscribed via a separate glob set when DM listening is enabled — SLACK_DM_EVENT_GLOBS = /slack/channels/D*/**, /slack/users/*/messages/** (see integration-event-bridge.ts).
  • Those DM/user roots are not in the canonical channel mount set, so the scope guard rejected every delivered DM/user event the UI tried to open.

Fix

Recognize the exact event-subscribed Slack DM roots and permit list/read of them only when DM listening is on for a visible Slack integration — without widening scope to non-DM channels.

  • isSlackDmListablePath() — pure predicate matching /slack/users/** and /slack/channels/D*/** (Slack's D-prefixed DM channel-id convention, which a plain root path can't express).
  • slackListenDms() is now exported; slackDmListingEnabledForProject() gates the predicate so the relaxation applies only when DM listening is actually enabled.
  • Applied the gate in readRemoteFile, listRemoteDirectory, and the directory-entry filter. The existing mount-path guards are otherwise unchanged.

Tests

  • vitest (integrations.test.ts): reading /slack/users/<id>/messages/<ts>/meta.json succeeds with DM listening on, and is still rejected with DM listening off (proving the gate is scoped to the flag, not a blanket loosening).
  • node --test (integration-remote-paths.test.ts): unit coverage for isSlackDmListablePath, including D* DM channels and rejection of non-DM Slack / other-provider / discovery paths.
  • Full integration-event-bridge suite (75) and integrations suite (30) pass.

🤖 Generated with Claude Code

…nt scope

Slack DM and per-user message paths (/slack/users/*/messages/** and
/slack/channels/D*/**) are delivered as events when DM listening is enabled,
but they are not part of the canonical channel mount paths. The
list-remote-dir / read-remote-file scope guards only consulted the channel
mount set, so when the renderer opened a delivered DM/user event it threw
"Integration remote directory is outside this project integration scope".

Recognize those exact event-subscribed DM roots and permit list/read of them
only when DM listening is on for a visible Slack integration — without
widening scope to non-DM channels.

- Add isSlackDmListablePath() pure predicate for /slack/users/** and
  /slack/channels/D*/** (Slack's DM channel-id convention).
- Export slackListenDms() and gate the predicate behind
  slackDmListingEnabledForProject() so the relaxation applies only when DM
  listening is enabled.
- Apply the gate in readRemoteFile, listRemoteDirectory, and the directory
  entry filter.
- Regression tests: vitest covers readRemoteFile on a /slack/users path
  (allowed with DM on, rejected with DM off); node tests cover the pure
  predicate including D* DM channels and non-DM rejection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codeant-ai

codeant-ai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR extends the integrations manager to permit access to Slack direct-message and user-message paths when a project's Slack integration has DM listening enabled, using a new path predicate and project-level DM configuration check applied to file reads and directory listings.

Changes

Slack DM Access Control

Layer / File(s) Summary
DM Path Detection Contract and Tests
src/main/integration-remote-paths.ts, src/main/__tests__/integration-remote-paths.test.ts
New isSlackDmListablePath() recognizes Slack user-message routes (/slack/users/*/...) and DM-channel routes (/slack/channels/D*/...); tests verify DM patterns are matched and non-DM patterns are rejected.
DM Listening Check Export and Mock
src/main/integration-event-bridge.ts, src/main/integrations.test.ts
slackListenDms() is exported from integration-event-bridge.ts to enable integration-level DM listening queries; test mocking integrates the check with scope flags.
DM Access Control in Remote Operations
src/main/integrations.ts
Imports DM helpers, adds slackDmListingEnabledForProject() to check project-level DM status, and extends readRemoteFile() and listRemoteDirectory() to allow DM paths when project DM listening is enabled, even outside regular mount-path scopes.
DM Access Control Tests
src/main/integrations.test.ts
Tests readRemoteFile() for Slack DM paths: reads succeed when scope.listenDms is enabled, and fail with scope error when disabled.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • AgentWorkforce/pear#154: Both PRs change Slack DM opt-in/scoping behavior by centering on slackListenDms (including integration-event-bridge.ts changes) and restricting which Slack DM/user message paths/contexts are considered listable or readable, so the changes are directly related at the Slack DM handling code level.
  • AgentWorkforce/pear#156: Both PRs expand Slack DM support by coordinating on the canonical DM path patterns and listenDms behavior—main PR adds isSlackDmListablePath/scope gating for DM list/read in integrations.ts, while the retrieved PR updates the Slack DM event glob logic and public exports in integration-event-bridge.ts.

Poem

🐰 A rabbit hops through Slack with glee,
DM paths now flow so free,
When listening's on, the messages sing,
Cross projects and scopes, every DM ring!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% 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 accurately summarizes the main change: allowing Slack DM/user remote directory listing within event scope, directly reflecting the fix described in the PR.
Description check ✅ Passed The description is well-structured and comprehensively related to the changeset, detailing the symptom, root cause, fix approach, and test coverage for the Slack DM/user path scope issue.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/slack-dm-remote-dir-scope

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request enables listing and reading Slack direct-message (DM) and per-user message paths when DM listening is enabled, even if they fall outside the canonical channel mount paths. This is implemented via a new isSlackDmListablePath helper and checking the project's DM listening status. The review feedback suggests simplifying the path segment parsing in isSlackDmListablePath by removing a redundant trailing slash replacement.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

// non-DM channels. The "D" prefix on a channel segment is Slack's DM channel
// convention, which a plain root path cannot express.
export function isSlackDmListablePath(remotePath: string): boolean {
const segments = (remotePath || '').trim().replace(/\/+$/, '').split('/').filter(Boolean)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The .replace(/\/+$/, '') call is redundant because .split('/') followed by .filter(Boolean) already discards any empty segments, including those resulting from trailing slashes. Removing it simplifies the code and slightly improves performance.

Suggested change
const segments = (remotePath || '').trim().replace(/\/+$/, '').split('/').filter(Boolean)
const segments = (remotePath || '').trim().split('/').filter(Boolean)

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@kjgbot kjgbot merged commit 4e41f8a into main Jun 9, 2026
3 of 4 checks passed
@kjgbot kjgbot deleted the fix/slack-dm-remote-dir-scope branch June 9, 2026 16:19
@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #186 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant