From 2b540705264291b45e108e65b0c1e7752f4e377e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 7 Mar 2026 23:47:32 +0000 Subject: [PATCH] refactor: share allowlist provider warning resolution --- extensions/feishu/src/channel.ts | 14 ++----- extensions/imessage/src/channel.ts | 14 ++----- extensions/line/src/channel.ts | 14 ++----- extensions/mattermost/src/channel.ts | 14 ++----- extensions/msteams/src/channel.ts | 14 ++----- extensions/signal/src/channel.ts | 14 ++----- .../plugins/group-policy-warnings.test.ts | 42 +++++++++++++++++++ src/channels/plugins/group-policy-warnings.ts | 30 +++++++++++++ src/plugin-sdk/index.ts | 1 + 9 files changed, 97 insertions(+), 60 deletions(-) diff --git a/extensions/feishu/src/channel.ts b/extensions/feishu/src/channel.ts index d4c3bb1c33b..38ab07a8b85 100644 --- a/extensions/feishu/src/channel.ts +++ b/extensions/feishu/src/channel.ts @@ -1,5 +1,5 @@ import { - collectOpenGroupPolicyRestrictSendersWarnings, + collectAllowlistProviderRestrictSendersWarnings, formatAllowFromLowercase, mapAllowFromEntries, } from "openclaw/plugin-sdk"; @@ -10,8 +10,6 @@ import { createDefaultChannelRuntimeState, DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, - resolveAllowlistProviderRuntimeGroupPolicy, - resolveDefaultGroupPolicy, } from "openclaw/plugin-sdk/feishu"; import { resolveFeishuAccount, @@ -261,14 +259,10 @@ export const feishuPlugin: ChannelPlugin = { collectWarnings: ({ cfg, accountId }) => { const account = resolveFeishuAccount({ cfg, accountId }); const feishuCfg = account.config; - const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg); - const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({ + return collectAllowlistProviderRestrictSendersWarnings({ + cfg, providerConfigPresent: cfg.channels?.feishu !== undefined, - groupPolicy: feishuCfg?.groupPolicy, - defaultGroupPolicy, - }); - return collectOpenGroupPolicyRestrictSendersWarnings({ - groupPolicy, + configuredGroupPolicy: feishuCfg?.groupPolicy, surface: `Feishu[${account.accountId}] groups`, openScope: "any member", groupPolicyPath: "channels.feishu.groupPolicy", diff --git a/extensions/imessage/src/channel.ts b/extensions/imessage/src/channel.ts index 6823197077c..33f24c532ba 100644 --- a/extensions/imessage/src/channel.ts +++ b/extensions/imessage/src/channel.ts @@ -1,6 +1,6 @@ import { buildAccountScopedDmSecurityPolicy, - collectOpenGroupPolicyRestrictSendersWarnings, + collectAllowlistProviderRestrictSendersWarnings, } from "openclaw/plugin-sdk"; import { applyAccountNameToChannelSection, @@ -25,8 +25,6 @@ import { resolveIMessageConfigDefaultTo, resolveIMessageGroupRequireMention, resolveIMessageGroupToolPolicy, - resolveAllowlistProviderRuntimeGroupPolicy, - resolveDefaultGroupPolicy, setAccountEnabledInConfigSection, type ChannelPlugin, type ResolvedIMessageAccount, @@ -145,14 +143,10 @@ export const imessagePlugin: ChannelPlugin = { }); }, collectWarnings: ({ account, cfg }) => { - const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg); - const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({ + return collectAllowlistProviderRestrictSendersWarnings({ + cfg, providerConfigPresent: cfg.channels?.imessage !== undefined, - groupPolicy: account.config.groupPolicy, - defaultGroupPolicy, - }); - return collectOpenGroupPolicyRestrictSendersWarnings({ - groupPolicy, + configuredGroupPolicy: account.config.groupPolicy, surface: "iMessage groups", openScope: "any member", groupPolicyPath: "channels.imessage.groupPolicy", diff --git a/extensions/line/src/channel.ts b/extensions/line/src/channel.ts index 57cd8eacc1c..7d7be509c33 100644 --- a/extensions/line/src/channel.ts +++ b/extensions/line/src/channel.ts @@ -1,7 +1,7 @@ import { buildAccountScopedDmSecurityPolicy, - collectOpenGroupPolicyRestrictSendersWarnings, createScopedAccountConfigAccessors, + collectAllowlistProviderRestrictSendersWarnings, } from "openclaw/plugin-sdk"; import { buildChannelConfigSchema, @@ -11,8 +11,6 @@ import { DEFAULT_ACCOUNT_ID, LineConfigSchema, processLineMessage, - resolveAllowlistProviderRuntimeGroupPolicy, - resolveDefaultGroupPolicy, type ChannelPlugin, type ChannelStatusIssue, type OpenClawConfig, @@ -175,14 +173,10 @@ export const linePlugin: ChannelPlugin = { }); }, collectWarnings: ({ account, cfg }) => { - const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg); - const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({ + return collectAllowlistProviderRestrictSendersWarnings({ + cfg, providerConfigPresent: cfg.channels?.line !== undefined, - groupPolicy: account.config.groupPolicy, - defaultGroupPolicy, - }); - return collectOpenGroupPolicyRestrictSendersWarnings({ - groupPolicy, + configuredGroupPolicy: account.config.groupPolicy, surface: "LINE groups", openScope: "any member in groups", groupPolicyPath: "channels.line.groupPolicy", diff --git a/extensions/mattermost/src/channel.ts b/extensions/mattermost/src/channel.ts index b70cee76e46..6fca0e3af3a 100644 --- a/extensions/mattermost/src/channel.ts +++ b/extensions/mattermost/src/channel.ts @@ -1,6 +1,6 @@ import { buildAccountScopedDmSecurityPolicy, - collectOpenGroupPolicyRestrictSendersWarnings, + collectAllowlistProviderRestrictSendersWarnings, createScopedAccountConfigAccessors, formatNormalizedAllowFromEntries, } from "openclaw/plugin-sdk"; @@ -13,8 +13,6 @@ import { deleteAccountFromConfigSection, migrateBaseNameToDefaultAccount, normalizeAccountId, - resolveAllowlistProviderRuntimeGroupPolicy, - resolveDefaultGroupPolicy, setAccountEnabledInConfigSection, type ChannelMessageActionAdapter, type ChannelMessageActionName, @@ -302,14 +300,10 @@ export const mattermostPlugin: ChannelPlugin = { }); }, collectWarnings: ({ account, cfg }) => { - const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg); - const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({ + return collectAllowlistProviderRestrictSendersWarnings({ + cfg, providerConfigPresent: cfg.channels?.mattermost !== undefined, - groupPolicy: account.config.groupPolicy, - defaultGroupPolicy, - }); - return collectOpenGroupPolicyRestrictSendersWarnings({ - groupPolicy, + configuredGroupPolicy: account.config.groupPolicy, surface: "Mattermost channels", openScope: "any member", groupPolicyPath: "channels.mattermost.groupPolicy", diff --git a/extensions/msteams/src/channel.ts b/extensions/msteams/src/channel.ts index 75bcfbfe463..1aeebf0c7b2 100644 --- a/extensions/msteams/src/channel.ts +++ b/extensions/msteams/src/channel.ts @@ -1,5 +1,5 @@ import { - collectOpenGroupPolicyRestrictSendersWarnings, + collectAllowlistProviderRestrictSendersWarnings, formatAllowFromLowercase, } from "openclaw/plugin-sdk"; import type { @@ -15,8 +15,6 @@ import { DEFAULT_ACCOUNT_ID, MSTeamsConfigSchema, PAIRING_APPROVED_MESSAGE, - resolveAllowlistProviderRuntimeGroupPolicy, - resolveDefaultGroupPolicy, } from "openclaw/plugin-sdk/msteams"; import { listMSTeamsDirectoryGroupsLive, listMSTeamsDirectoryPeersLive } from "./directory-live.js"; import { msteamsOnboardingAdapter } from "./onboarding.js"; @@ -134,14 +132,10 @@ export const msteamsPlugin: ChannelPlugin = { }, security: { collectWarnings: ({ cfg }) => { - const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg); - const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({ + return collectAllowlistProviderRestrictSendersWarnings({ + cfg, providerConfigPresent: cfg.channels?.msteams !== undefined, - groupPolicy: cfg.channels?.msteams?.groupPolicy, - defaultGroupPolicy, - }); - return collectOpenGroupPolicyRestrictSendersWarnings({ - groupPolicy, + configuredGroupPolicy: cfg.channels?.msteams?.groupPolicy, surface: "MS Teams groups", openScope: "any member", groupPolicyPath: "channels.msteams.groupPolicy", diff --git a/extensions/signal/src/channel.ts b/extensions/signal/src/channel.ts index 9dc2268a3b0..20c957f9552 100644 --- a/extensions/signal/src/channel.ts +++ b/extensions/signal/src/channel.ts @@ -1,7 +1,7 @@ import { buildAccountScopedDmSecurityPolicy, - collectOpenGroupPolicyRestrictSendersWarnings, createScopedAccountConfigAccessors, + collectAllowlistProviderRestrictSendersWarnings, } from "openclaw/plugin-sdk"; import { applyAccountNameToChannelSection, @@ -22,8 +22,6 @@ import { PAIRING_APPROVED_MESSAGE, resolveChannelMediaMaxBytes, resolveDefaultSignalAccountId, - resolveAllowlistProviderRuntimeGroupPolicy, - resolveDefaultGroupPolicy, resolveSignalAccount, setAccountEnabledInConfigSection, signalOnboardingAdapter, @@ -171,14 +169,10 @@ export const signalPlugin: ChannelPlugin = { }); }, collectWarnings: ({ account, cfg }) => { - const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg); - const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({ + return collectAllowlistProviderRestrictSendersWarnings({ + cfg, providerConfigPresent: cfg.channels?.signal !== undefined, - groupPolicy: account.config.groupPolicy, - defaultGroupPolicy, - }); - return collectOpenGroupPolicyRestrictSendersWarnings({ - groupPolicy, + configuredGroupPolicy: account.config.groupPolicy, surface: "Signal groups", openScope: "any member", groupPolicyPath: "channels.signal.groupPolicy", diff --git a/src/channels/plugins/group-policy-warnings.test.ts b/src/channels/plugins/group-policy-warnings.test.ts index e09bcfdaf2c..e25493a74a7 100644 --- a/src/channels/plugins/group-policy-warnings.test.ts +++ b/src/channels/plugins/group-policy-warnings.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from "vitest"; import { collectOpenGroupPolicyConfiguredRouteWarnings, + collectAllowlistProviderRestrictSendersWarnings, collectOpenGroupPolicyRestrictSendersWarnings, collectOpenGroupPolicyRouteAllowlistWarnings, buildOpenGroupPolicyConfigureRouteAllowlistWarning, @@ -84,6 +85,47 @@ describe("group policy warning builders", () => { ).toHaveLength(1); }); + it("resolves allowlist-provider runtime policy before collecting restrict-senders warnings", () => { + expect( + collectAllowlistProviderRestrictSendersWarnings({ + cfg: { + channels: { + defaults: { groupPolicy: "open" }, + }, + }, + providerConfigPresent: false, + configuredGroupPolicy: undefined, + surface: "Example groups", + openScope: "any member", + groupPolicyPath: "channels.example.groupPolicy", + groupAllowFromPath: "channels.example.groupAllowFrom", + }), + ).toEqual([]); + + expect( + collectAllowlistProviderRestrictSendersWarnings({ + cfg: { + channels: { + defaults: { groupPolicy: "open" }, + }, + }, + providerConfigPresent: true, + configuredGroupPolicy: "open", + surface: "Example groups", + openScope: "any member", + groupPolicyPath: "channels.example.groupPolicy", + groupAllowFromPath: "channels.example.groupAllowFrom", + }), + ).toEqual([ + buildOpenGroupPolicyRestrictSendersWarning({ + surface: "Example groups", + openScope: "any member", + groupPolicyPath: "channels.example.groupPolicy", + groupAllowFromPath: "channels.example.groupAllowFrom", + }), + ]); + }); + it("collects route allowlist warning variants", () => { const params = { groupPolicy: "open" as const, diff --git a/src/channels/plugins/group-policy-warnings.ts b/src/channels/plugins/group-policy-warnings.ts index 7f6501662c7..e232c40abf1 100644 --- a/src/channels/plugins/group-policy-warnings.ts +++ b/src/channels/plugins/group-policy-warnings.ts @@ -1,3 +1,10 @@ +import type { OpenClawConfig } from "../../config/config.js"; +import { + resolveAllowlistProviderRuntimeGroupPolicy, + resolveDefaultGroupPolicy, +} from "../../config/runtime-group-policy.js"; +import type { GroupPolicy } from "../../config/types.base.js"; + export function buildOpenGroupPolicyWarning(params: { surface: string; openBehavior: string; @@ -63,6 +70,29 @@ export function collectOpenGroupPolicyRestrictSendersWarnings( return [buildOpenGroupPolicyRestrictSendersWarning(params)]; } +export function collectAllowlistProviderRestrictSendersWarnings( + params: { + cfg: OpenClawConfig; + providerConfigPresent: boolean; + configuredGroupPolicy?: GroupPolicy | null; + } & Omit[0], "groupPolicy">, +): string[] { + const defaultGroupPolicy = resolveDefaultGroupPolicy(params.cfg); + const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({ + providerConfigPresent: params.providerConfigPresent, + groupPolicy: params.configuredGroupPolicy ?? undefined, + defaultGroupPolicy, + }); + return collectOpenGroupPolicyRestrictSendersWarnings({ + groupPolicy, + surface: params.surface, + openScope: params.openScope, + groupPolicyPath: params.groupPolicyPath, + groupAllowFromPath: params.groupAllowFromPath, + mentionGated: params.mentionGated, + }); +} + export function collectOpenGroupPolicyRouteAllowlistWarnings(params: { groupPolicy: "open" | "allowlist" | "disabled"; routeAllowlistConfigured: boolean; diff --git a/src/plugin-sdk/index.ts b/src/plugin-sdk/index.ts index 68da9afb8e1..1381d6eda5c 100644 --- a/src/plugin-sdk/index.ts +++ b/src/plugin-sdk/index.ts @@ -547,6 +547,7 @@ export { buildOpenGroupPolicyNoRouteAllowlistWarning, buildOpenGroupPolicyRestrictSendersWarning, buildOpenGroupPolicyWarning, + collectAllowlistProviderRestrictSendersWarnings, collectOpenGroupPolicyConfiguredRouteWarnings, collectOpenGroupPolicyRestrictSendersWarnings, collectOpenGroupPolicyRouteAllowlistWarnings,