openclaw-matrix-multiaccounts/src/slack
Jay Winder 72d62a54c6 fix: groupPolicy: "open" ignored when channel-specific config exists
## Summary

Fix Slack `groupPolicy: "open"` to allow unlisted channels even when `channels.slack.channels` contains custom entries.

## Problem

When `groupPolicy` is set to `"open"`, the bot should respond in **any channel** it's invited to. However, if `channels.slack.channels` contains *any* entries—even just one channel with a custom system prompt—the open policy is ignored. Only explicitly listed channels receive responses; all others get an ephemeral "This channel is not allowed" error.

### Example config

```json
{
  "channels": {
    "slack": {
      "groupPolicy": "open",
      "channels": {
        "C0123456789": { "systemPrompt": "Custom prompt for this channel" }
      }
    }
  }
}
```

With this config, the bot only responds in `C0123456789`. Messages in any other channel are blocked—even though the policy is `"open"`.

## Root Cause

In `src/slack/monitor/context.ts`, `isChannelAllowed()` has two sequential checks:

1. `isSlackChannelAllowedByPolicy()` — correctly returns `true` for open policy
2. A secondary `!channelAllowed` check — was blocking channels when `resolveSlackChannelConfig()` returned `{ allowed: false }` for unlisted channels

The second check conflated "channel not in config" with "channel explicitly denied."

## Fix

Use `matchSource` to distinguish explicit denial from absence of config:

```ts
const hasExplicitConfig = Boolean(channelConfig?.matchSource);
if (!channelAllowed && (params.groupPolicy !== "open" || hasExplicitConfig)) {
  return false;
}
```

When `matchSource` is undefined, the channel has no explicit config entry and should be allowed under open policy.

## Behavior After Fix

| Scenario | Result |
|----------|--------|
| `groupPolicy: "open"`, channel unlisted |  Allowed |
| `groupPolicy: "open"`, channel explicitly denied (`allow: false`) |  Blocked |
| `groupPolicy: "open"`, channel with custom config |  Allowed |
| `groupPolicy: "allowlist"`, channel unlisted |  Blocked |

## Test Plan

- [x] Open policy + unlisted channel → allowed
- [x] Open policy + explicitly denied channel → blocked
- [x] Allowlist policy + unlisted channel → blocked
- [x] Allowlist policy + listed channel → allowed
2026-01-24 07:05:55 +00:00
..
http feat(slack): add HTTP receiver webhook mode (#1143) - thanks @jdrhyne 2026-01-18 15:04:07 +00:00
monitor fix: groupPolicy: "open" ignored when channel-specific config exists 2026-01-24 07:05:55 +00:00
accounts.ts feat: add slack replyToModeByChatType overrides 2026-01-23 05:38:28 +00:00
actions.read.test.ts fix: read Slack thread replies for message reads (#1450) (#1450) 2026-01-23 04:17:45 +00:00
actions.ts fix: reduce Slack WebClient retries 2026-01-23 06:31:53 +00:00
channel-migration.test.ts feat(config): gate channel config writes 2026-01-15 01:41:15 +00:00
channel-migration.ts feat(config): gate channel config writes 2026-01-15 01:41:15 +00:00
client.test.ts fix: reduce Slack WebClient retries 2026-01-23 06:31:53 +00:00
client.ts fix: reduce Slack WebClient retries 2026-01-23 06:31:53 +00:00
directory-live.ts fix: reduce Slack WebClient retries 2026-01-23 06:31:53 +00:00
format.test.ts refactor: unify markdown formatting pipeline 2026-01-15 00:31:07 +00:00
format.ts fix: add per-channel markdown table conversion (#1495) (thanks @odysseus0) 2026-01-23 18:39:25 +00:00
index.ts feat: add slack multi-account routing 2026-01-08 08:49:16 +01:00
monitor.test-helpers.ts refactor: unify threading contexts 2026-01-21 20:35:12 +00:00
monitor.test.ts refactor: prune room legacy 2026-01-17 07:41:24 +00:00
monitor.threading.missing-thread-ts.test.ts fix: resolve heartbeat sender and Slack thread_ts 2026-01-23 02:05:34 +00:00
monitor.tool-result.forces-thread-replies-replytoid-is-set.test.ts refactor: unify threading contexts 2026-01-21 20:35:12 +00:00
monitor.tool-result.sends-tool-summaries-responseprefix.test.ts refactor: unify threading contexts 2026-01-21 20:35:12 +00:00
monitor.tool-result.threads-top-level-replies-replytomode-is-all.test.ts refactor: unify threading contexts 2026-01-21 20:35:12 +00:00
monitor.ts refactor: prune room legacy 2026-01-17 07:41:24 +00:00
probe.ts fix: reduce Slack WebClient retries 2026-01-23 06:31:53 +00:00
resolve-channels.test.ts feat(channels): add resolve command + defaults 2026-01-18 01:00:24 +00:00
resolve-channels.ts fix: reduce Slack WebClient retries 2026-01-23 06:31:53 +00:00
resolve-users.ts fix: reduce Slack WebClient retries 2026-01-23 06:31:53 +00:00
scopes.ts fix: reduce Slack WebClient retries 2026-01-23 06:31:53 +00:00
send.ts fix: add per-channel markdown table conversion (#1495) (thanks @odysseus0) 2026-01-23 18:39:25 +00:00
targets.test.ts refactor(channels): unify target parsing 2026-01-18 00:31:42 +00:00
targets.ts refactor(channels): unify target parsing 2026-01-18 00:31:42 +00:00
threading-tool-context.test.ts feat: add slack replyToModeByChatType overrides 2026-01-23 05:38:28 +00:00
threading-tool-context.ts feat(slack): add dm-specific replyToMode configuration (#1442) 2026-01-23 05:13:23 +00:00
threading.test.ts refactor: unify threading contexts 2026-01-21 20:35:12 +00:00
threading.ts refactor: unify threading contexts 2026-01-21 20:35:12 +00:00
token.ts Slack: add some fixes and connect it all up 2026-01-04 01:53:26 -06:00
types.ts refactor: centralize slack threading helpers 2026-01-09 16:01:53 +00:00