refactor: unify channel config matching and gating
Co-authored-by: thewilloftheshadow <thewilloftheshadow@users.noreply.github.com>
This commit is contained in:
@@ -42,4 +42,16 @@ describe("resolveSlackChannelConfig", () => {
|
||||
matchSource: "wildcard",
|
||||
});
|
||||
});
|
||||
|
||||
it("uses direct match metadata when channel config exists", () => {
|
||||
const res = resolveSlackChannelConfig({
|
||||
channelId: "C1",
|
||||
channels: { C1: { allow: true, requireMention: false } },
|
||||
defaultRequireMention: true,
|
||||
});
|
||||
expect(res).toMatchObject({
|
||||
matchKey: "C1",
|
||||
matchSource: "direct",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { SlackReactionNotificationMode } from "../../config/config.js";
|
||||
import type { SlackMessageEvent } from "../types.js";
|
||||
import {
|
||||
buildChannelKeyCandidates,
|
||||
resolveChannelEntryMatch,
|
||||
resolveChannelEntryMatchWithFallback,
|
||||
} from "../../channels/channel-config.js";
|
||||
import { allowListMatches, normalizeAllowListLower, normalizeSlackSlug } from "./allow-list.js";
|
||||
|
||||
@@ -91,10 +91,10 @@ export function resolveSlackChannelConfig(params: {
|
||||
);
|
||||
const {
|
||||
entry: matched,
|
||||
key: matchedKey,
|
||||
wildcardEntry: fallback,
|
||||
wildcardKey,
|
||||
} = resolveChannelEntryMatch({
|
||||
matchKey,
|
||||
matchSource,
|
||||
} = resolveChannelEntryMatchWithFallback({
|
||||
entries,
|
||||
keys: candidates,
|
||||
wildcardKey: "*",
|
||||
@@ -127,12 +127,9 @@ export function resolveSlackChannelConfig(params: {
|
||||
skills,
|
||||
systemPrompt,
|
||||
};
|
||||
if (matchedKey) {
|
||||
result.matchKey = matchedKey;
|
||||
result.matchSource = "direct";
|
||||
} else if (wildcardKey && fallback) {
|
||||
result.matchKey = wildcardKey;
|
||||
result.matchSource = "wildcard";
|
||||
if (matchKey) result.matchKey = matchKey;
|
||||
if (matchSource === "direct" || matchSource === "wildcard") {
|
||||
result.matchSource = matchSource;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ import { buildPairingReply } from "../../../pairing/pairing-messages.js";
|
||||
import { upsertChannelPairingRequest } from "../../../pairing/pairing-store.js";
|
||||
import { resolveAgentRoute } from "../../../routing/resolve-route.js";
|
||||
import { resolveThreadSessionKeys } from "../../../routing/session-key.js";
|
||||
import { resolveMentionGating } from "../../../channels/mention-gating.js";
|
||||
import { resolveMentionGatingWithBypass } from "../../../channels/mention-gating.js";
|
||||
import { resolveConversationLabel } from "../../../channels/conversation-label.js";
|
||||
import { resolveCommandAuthorizedFromAuthorizers } from "../../../channels/command-gating.js";
|
||||
import { resolveControlCommandGate } from "../../../channels/command-gating.js";
|
||||
|
||||
import type { ResolvedSlackAccount } from "../../accounts.js";
|
||||
import { reactSlackMessage } from "../../actions.js";
|
||||
@@ -229,6 +229,7 @@ export async function prepareSlackMessage(params: {
|
||||
cfg,
|
||||
surface: "slack",
|
||||
});
|
||||
const hasControlCommandInMessage = hasControlCommand(message.text ?? "", cfg);
|
||||
|
||||
const ownerAuthorized = resolveSlackAllowListMatch({
|
||||
allowList: allowFromLower,
|
||||
@@ -245,20 +246,18 @@ export async function prepareSlackMessage(params: {
|
||||
userName: senderName,
|
||||
})
|
||||
: false;
|
||||
const commandAuthorized = resolveCommandAuthorizedFromAuthorizers({
|
||||
const commandGate = resolveControlCommandGate({
|
||||
useAccessGroups: ctx.useAccessGroups,
|
||||
authorizers: [
|
||||
{ configured: allowFromLower.length > 0, allowed: ownerAuthorized },
|
||||
{ configured: channelUsersAllowlistConfigured, allowed: channelCommandAuthorized },
|
||||
],
|
||||
allowTextCommands,
|
||||
hasControlCommand: hasControlCommandInMessage,
|
||||
});
|
||||
const commandAuthorized = commandGate.commandAuthorized;
|
||||
|
||||
if (
|
||||
allowTextCommands &&
|
||||
isRoomish &&
|
||||
hasControlCommand(message.text ?? "", cfg) &&
|
||||
!commandAuthorized
|
||||
) {
|
||||
if (isRoomish && commandGate.shouldBlock) {
|
||||
logVerbose(`Blocked slack control command from unauthorized sender ${senderId}`);
|
||||
return null;
|
||||
}
|
||||
@@ -268,22 +267,17 @@ export async function prepareSlackMessage(params: {
|
||||
: false;
|
||||
|
||||
// Allow "control commands" to bypass mention gating if sender is authorized.
|
||||
const shouldBypassMention =
|
||||
allowTextCommands &&
|
||||
isRoom &&
|
||||
shouldRequireMention &&
|
||||
!wasMentioned &&
|
||||
!hasAnyMention &&
|
||||
commandAuthorized &&
|
||||
hasControlCommand(message.text ?? "", cfg);
|
||||
|
||||
const canDetectMention = Boolean(ctx.botUserId) || mentionRegexes.length > 0;
|
||||
const mentionGate = resolveMentionGating({
|
||||
const mentionGate = resolveMentionGatingWithBypass({
|
||||
isGroup: isRoom,
|
||||
requireMention: Boolean(shouldRequireMention),
|
||||
canDetectMention,
|
||||
wasMentioned,
|
||||
implicitMention,
|
||||
shouldBypassMention,
|
||||
hasAnyMention,
|
||||
allowTextCommands,
|
||||
hasControlCommand: hasControlCommandInMessage,
|
||||
commandAuthorized,
|
||||
});
|
||||
const effectiveWasMentioned = mentionGate.effectiveWasMentioned;
|
||||
if (isRoom && shouldRequireMention && mentionGate.shouldSkip) {
|
||||
|
||||
Reference in New Issue
Block a user