fix(slack): match channel-prefixed allowlist keys · openclaw/openclaw@b867ed4
steipete
·
2026-05-02
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -77,6 +77,7 @@ Docs: https://docs.openclaw.ai
|
77 | 77 | - Slack/capabilities: read granted scopes from `auth.test` response metadata before trying legacy scope APIs, so modern bot tokens no longer report `unknown_method` for channel capabilities. Fixes #44625. Thanks @Qquanwei and @martingarramon. |
78 | 78 | - Slack/DMs: send text/block-only proactive DMs directly with `chat.postMessage(channel=<user id>)` while keeping conversation resolution for uploads and threaded sends. Fixes #62042. Thanks @MarkMolina. |
79 | 79 | - Slack/routing: match route bindings written with Slack target syntax such as `channel:C...`, `user:U...`, or `<@U...>`, so bound Slack peers route to the configured agent instead of `main`. Fixes #41608. Thanks @Winnsolutionsadmin. |
| 80 | +- Slack/routing: match public-channel allowlist entries written as `channel:C...` against bare Slack runtime channel IDs, so allowed channel mentions do not fail as `channel-not-allowed`. Fixes #41264 and supersedes #56530. Thanks @babutree and @Realworld404. |
80 | 81 | - Slack/message actions: prefer the account bound to the outbound target peer before falling back to the agent's first channel account, so multi-workspace sends use the intended Slack account. Supersedes #66807. Thanks @rijhsinghani. |
81 | 82 | - Slack/delivery: retry Slack Web API writes only when the SDK wraps a DNS request failure such as `EAI_AGAIN`, so transient resolver hiccups can recover without retrying platform errors that may duplicate messages. Fixes #68789. Thanks @sonnyb9. |
82 | 83 | - Slack/message actions: forward agent-scoped media roots through the bundled upload-file action path, so workspace files can be attached without failing the local-media guard. Fixes #64625. Thanks @benpchandler. |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -74,10 +74,16 @@ export function resolveSlackChannelConfig(params: {
|
74 | 74 | // entry-scan. buildChannelKeyCandidates deduplicates identical keys. |
75 | 75 | const channelIdLower = normalizeLowercaseStringOrEmpty(channelId); |
76 | 76 | const channelIdUpper = channelId.toUpperCase(); |
| 77 | +const channelTarget = `channel:${channelId}`; |
| 78 | +const channelTargetLower = `channel:${channelIdLower}`; |
| 79 | +const channelTargetUpper = `channel:${channelIdUpper}`; |
77 | 80 | const candidates = buildChannelKeyCandidates( |
78 | 81 | channelId, |
79 | 82 | channelIdLower !== channelId ? channelIdLower : undefined, |
80 | 83 | channelIdUpper !== channelId ? channelIdUpper : undefined, |
| 84 | +channelTarget, |
| 85 | +channelTargetLower !== channelTarget ? channelTargetLower : undefined, |
| 86 | +channelTargetUpper !== channelTarget ? channelTargetUpper : undefined, |
81 | 87 | allowNameMatching ? (channelName ? `#${directName}` : undefined) : undefined, |
82 | 88 | allowNameMatching ? directName : undefined, |
83 | 89 | allowNameMatching ? normalizedName : undefined, |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -79,6 +79,34 @@ describe("resolveSlackChannelConfig", () => {
|
79 | 79 | expect(res).toMatchObject({ allowed: true, requireMention: false }); |
80 | 80 | }); |
81 | 81 | |
| 82 | +it("matches channel-prefixed config keys when Slack delivers a bare channel ID", () => { |
| 83 | +const res = resolveSlackChannelConfig({ |
| 84 | +channelId: "C0AJYR3BVTJ", |
| 85 | +channels: { "channel:C0AJYR3BVTJ": { enabled: true, requireMention: false } }, |
| 86 | +defaultRequireMention: true, |
| 87 | +}); |
| 88 | +expect(res).toMatchObject({ |
| 89 | +allowed: true, |
| 90 | +requireMention: false, |
| 91 | +matchKey: "channel:C0AJYR3BVTJ", |
| 92 | +matchSource: "direct", |
| 93 | +}); |
| 94 | +}); |
| 95 | + |
| 96 | +it("matches lowercase channel-prefixed config keys when Slack delivers uppercase channel IDs", () => { |
| 97 | +const res = resolveSlackChannelConfig({ |
| 98 | +channelId: "C0AJYR3BVTJ", |
| 99 | +channels: { "channel:c0ajyr3bvtj": { enabled: true, requireMention: false } }, |
| 100 | +defaultRequireMention: true, |
| 101 | +}); |
| 102 | +expect(res).toMatchObject({ |
| 103 | +allowed: true, |
| 104 | +requireMention: false, |
| 105 | +matchKey: "channel:c0ajyr3bvtj", |
| 106 | +matchSource: "direct", |
| 107 | +}); |
| 108 | +}); |
| 109 | + |
82 | 110 | it("blocks channel-name route matches by default", () => { |
83 | 111 | const res = resolveSlackChannelConfig({ |
84 | 112 | channelId: "C1", |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。