// Discord plugin module implements security behavior. import { createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers"; import { createConditionalWarningCollector, createOpenProviderConfiguredRouteWarningCollector, } from "openclaw/plugin-sdk/channel-policy"; import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; import { resolveDiscordAccountAllowFrom, resolveDiscordAccountDmPolicy, type ResolvedDiscordAccount, } from "./accounts.js"; import type { ChannelPlugin } from "./channel-api.js"; const resolveDiscordDmPolicy = createScopedDmSecurityResolver({ channelKey: "discord", resolvePolicy: (account) => account.config.dmPolicy, resolveAllowFrom: (account) => account.config.allowFrom, resolveAccess: ({ cfg, account }) => ({ dmPolicy: resolveDiscordAccountDmPolicy({ cfg, accountId: account.accountId }), allowFrom: resolveDiscordAccountAllowFrom({ cfg, accountId: account.accountId }), }), policyPathSuffix: "dmPolicy", normalizeEntry: (raw) => raw .trim() .replace(/^(discord|user):/i, "") .replace(/^<@!?(\d+)>$/, "$1"), }); const collectDiscordSecurityWarnings = createOpenProviderConfiguredRouteWarningCollector({ providerConfigPresent: (cfg) => cfg.channels?.discord !== undefined, resolveGroupPolicy: (account) => account.config.groupPolicy, resolveRouteAllowlistConfigured: (account) => Object.keys(account.config.guilds ?? {}).length > 0, configureRouteAllowlist: { surface: "Discord guilds", openScope: "any channel not explicitly denied", groupPolicyPath: "channels.discord.groupPolicy", routeAllowlistPath: "channels.discord.guilds..channels", }, missingRouteAllowlist: { surface: "Discord guilds", openBehavior: "with no guild/channel allowlist; any channel can trigger (mention-gated)", remediation: 'Set channels.discord.groupPolicy="allowlist" and configure channels.discord.guilds..channels', }, }); const collectDiscordSecurityFindings = createConditionalWarningCollector.findings({ collectWarnings: collectDiscordSecurityWarnings, checkId: "channels.discord.groups.open", severity: "critical", title: "Discord security warning", }); const loadDiscordSecurityAuditModule = createLazyRuntimeModule( () => import("./security-audit.runtime.js"), ); export const discordSecurityAdapter = { resolveDmPolicy: resolveDiscordDmPolicy, collectWarnings: collectDiscordSecurityFindings, collectAuditFindings: async (params) => (await loadDiscordSecurityAuditModule()).collectDiscordSecurityAuditFindings(params), } satisfies NonNullable["security"]>;