fix: preserve DM access precedence in Slack runtime

This commit is contained in:
Peter Steinberger
2026-04-29 15:21:37 +01:00
parent e6d72548b7
commit 1d9959b77e
5 changed files with 74 additions and 7 deletions

View File

@@ -5,6 +5,7 @@ import {
} from "openclaw/plugin-sdk/account-helpers";
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
import {
mapAllowFromEntries,
normalizeChannelDmPolicy,
resolveChannelDmAllowFrom,
resolveChannelDmPolicy,
@@ -58,10 +59,11 @@ export function resolveDiscordAccountAllowFrom(params: {
const accountConfig = resolveDiscordAccountConfig(params.cfg, accountId);
const rootConfig = params.cfg.channels?.discord as DiscordAccountConfig | undefined;
return resolveChannelDmAllowFrom({
const allowFrom = resolveChannelDmAllowFrom({
account: accountConfig as Record<string, unknown> | undefined,
parent: rootConfig as Record<string, unknown> | undefined,
}) as string[] | undefined;
});
return allowFrom ? mapAllowFromEntries(allowFrom) : undefined;
}
export function resolveDiscordAccountDmPolicy(params: {

View File

@@ -110,4 +110,22 @@ describe("discordConfigAdapter", () => {
"account-legacy",
]);
});
it("coerces numeric allowFrom entries at the config boundary", () => {
const cfg = {
channels: {
discord: {
accounts: {
default: {
allowFrom: [123456789],
},
},
},
},
} as unknown as OpenClawConfig;
expect(discordConfigAdapter.resolveAllowFrom?.({ cfg, accountId: "default" })).toEqual([
"123456789",
]);
});
});

View File

@@ -1,6 +1,10 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import { describe, expect, it } from "vitest";
import { resolveSlackAccount, resolveSlackAccountAllowFrom } from "./accounts.js";
import {
resolveSlackAccount,
resolveSlackAccountAllowFrom,
resolveSlackAccountDmPolicy,
} from "./accounts.js";
describe("resolveSlackAccount allowFrom precedence", () => {
it("uses configured defaultAccount when accountId is omitted", () => {
@@ -126,6 +130,43 @@ describe("resolveSlackAccount allowFrom precedence", () => {
expect(resolveSlackAccountAllowFrom({ cfg, accountId: "work" })).toEqual(["account-legacy"]);
});
it("coerces numeric allowFrom entries at the config boundary", () => {
const cfg = {
channels: {
slack: {
accounts: {
work: {
botToken: "xoxb-work",
appToken: "xapp-work",
allowFrom: [12345],
},
},
},
},
} as unknown as OpenClawConfig;
expect(resolveSlackAccountAllowFrom({ cfg, accountId: "work" })).toEqual(["12345"]);
});
it("resolves account legacy dm policy before inherited root policy", () => {
const cfg = {
channels: {
slack: {
dmPolicy: "open",
accounts: {
work: {
botToken: "xoxb-work",
appToken: "xapp-work",
dm: { policy: "allowlist" },
},
},
},
},
} satisfies OpenClawConfig;
expect(resolveSlackAccountDmPolicy({ cfg, accountId: "work" })).toBe("allowlist");
});
});
describe("resolveSlackAccount active secret surfaces", () => {

View File

@@ -6,6 +6,7 @@ import {
type OpenClawConfig,
} from "openclaw/plugin-sdk/account-resolution";
import {
mapAllowFromEntries,
normalizeChannelDmPolicy,
resolveChannelDmAllowFrom,
resolveChannelDmPolicy,
@@ -57,10 +58,11 @@ export function resolveSlackAccountAllowFrom(params: {
);
const accountConfig = params.cfg.channels?.slack?.accounts?.[accountId];
const rootConfig = params.cfg.channels?.slack as SlackAccountConfig | undefined;
return resolveChannelDmAllowFrom({
const allowFrom = resolveChannelDmAllowFrom({
account: accountConfig as Record<string, unknown> | undefined,
parent: rootConfig as Record<string, unknown> | undefined,
}) as string[] | undefined;
});
return allowFrom ? mapAllowFromEntries(allowFrom) : undefined;
}
export function resolveSlackAccountDmPolicy(params: {

View File

@@ -22,7 +22,11 @@ import {
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
import { normalizeStringEntries } from "openclaw/plugin-sdk/text-runtime";
import { installRequestBodyLimitGuard } from "openclaw/plugin-sdk/webhook-request-guards";
import { resolveSlackAccount, resolveSlackAccountAllowFrom } from "../accounts.js";
import {
resolveSlackAccount,
resolveSlackAccountAllowFrom,
resolveSlackAccountDmPolicy,
} from "../accounts.js";
import { resolveSlackWebClientOptions } from "../client-options.js";
import { isSlackExecApprovalClientEnabled } from "../exec-approvals.js";
import { normalizeSlackWebhookPath, registerSlackHttpHandler } from "../http/index.js";
@@ -148,7 +152,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
const dmConfig = slackCfg.dm;
const dmEnabled = dmConfig?.enabled ?? true;
const dmPolicy = slackCfg.dmPolicy ?? dmConfig?.policy ?? "pairing";
const dmPolicy = resolveSlackAccountDmPolicy({ cfg, accountId: account.accountId }) ?? "pairing";
let allowFrom = resolveSlackAccountAllowFrom({ cfg, accountId: account.accountId });
const groupDmEnabled = dmConfig?.groupEnabled ?? false;
const groupDmChannels = dmConfig?.groupChannels;