From 88ea0751a9bb418bfeeb4ce9281b0a412c9f31fb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 5 Apr 2026 12:55:50 +0100 Subject: [PATCH] fix(test): add lightweight whatsapp group-policy seam --- extensions/whatsapp/contract-api.ts | 2 ++ .../whatsapp/src/inbound/access-control.ts | 17 +--------- .../whatsapp/src/runtime-group-policy.ts | 16 +++++++++ extensions/whatsapp/test-api.ts | 9 +---- .../group-policy.fallback.contract.test.ts | 33 +++++-------------- test/helpers/channels/policy-contract.ts | 7 ++-- 6 files changed, 31 insertions(+), 53 deletions(-) create mode 100644 extensions/whatsapp/src/runtime-group-policy.ts diff --git a/extensions/whatsapp/contract-api.ts b/extensions/whatsapp/contract-api.ts index c93d0815763..01c9a4ffc9f 100644 --- a/extensions/whatsapp/contract-api.ts +++ b/extensions/whatsapp/contract-api.ts @@ -23,6 +23,7 @@ import { createWhatsAppPollFixture as createWhatsAppPollFixtureImpl, expectWhatsAppPollSent as expectWhatsAppPollSentImpl, } from "./src/outbound-test-support.js"; +import { resolveWhatsAppRuntimeGroupPolicy as resolveWhatsAppRuntimeGroupPolicyImpl } from "./src/runtime-group-policy.js"; import { canonicalizeLegacySessionKey as canonicalizeLegacySessionKeyImpl, isLegacyGroupSessionKey as isLegacyGroupSessionKeyImpl, @@ -35,6 +36,7 @@ export const isLegacyGroupSessionKey = isLegacyGroupSessionKeyImpl; export const isWhatsAppGroupJid = isWhatsAppGroupJidImpl; export const normalizeWhatsAppTarget = normalizeWhatsAppTargetImpl; export const resolveLegacyGroupSessionKey = resolveLegacyGroupSessionKeyImpl; +export const resolveWhatsAppRuntimeGroupPolicy = resolveWhatsAppRuntimeGroupPolicyImpl; export const whatsappAccessControlTesting = whatsappAccessControlTestingImpl; export const whatsappCommandPolicy = whatsappCommandPolicyImpl; diff --git a/extensions/whatsapp/src/inbound/access-control.ts b/extensions/whatsapp/src/inbound/access-control.ts index 6dfcf890467..a08bbc5353b 100644 --- a/extensions/whatsapp/src/inbound/access-control.ts +++ b/extensions/whatsapp/src/inbound/access-control.ts @@ -1,7 +1,6 @@ import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing"; import { loadConfig } from "openclaw/plugin-sdk/config-runtime"; import { - resolveOpenProviderRuntimeGroupPolicy, resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce, } from "openclaw/plugin-sdk/config-runtime"; @@ -12,6 +11,7 @@ import { resolveDmGroupAccessWithLists, } from "openclaw/plugin-sdk/security-runtime"; import { resolveWhatsAppAccount } from "../accounts.js"; +import { resolveWhatsAppRuntimeGroupPolicy } from "../runtime-group-policy.js"; import { isSelfChatMode, normalizeE164 } from "../text-runtime.js"; export type InboundAccessControlResult = { @@ -23,21 +23,6 @@ export type InboundAccessControlResult = { const PAIRING_REPLY_HISTORY_GRACE_MS = 30_000; -function resolveWhatsAppRuntimeGroupPolicy(params: { - providerConfigPresent: boolean; - groupPolicy?: "open" | "allowlist" | "disabled"; - defaultGroupPolicy?: "open" | "allowlist" | "disabled"; -}): { - groupPolicy: "open" | "allowlist" | "disabled"; - providerMissingFallbackApplied: boolean; -} { - return resolveOpenProviderRuntimeGroupPolicy({ - providerConfigPresent: params.providerConfigPresent, - groupPolicy: params.groupPolicy, - defaultGroupPolicy: params.defaultGroupPolicy, - }); -} - export async function checkInboundAccessControl(params: { accountId: string; from: string; diff --git a/extensions/whatsapp/src/runtime-group-policy.ts b/extensions/whatsapp/src/runtime-group-policy.ts new file mode 100644 index 00000000000..033bd891a47 --- /dev/null +++ b/extensions/whatsapp/src/runtime-group-policy.ts @@ -0,0 +1,16 @@ +import { resolveOpenProviderRuntimeGroupPolicy } from "openclaw/plugin-sdk/config-runtime"; + +export function resolveWhatsAppRuntimeGroupPolicy(params: { + providerConfigPresent: boolean; + groupPolicy?: "open" | "allowlist" | "disabled"; + defaultGroupPolicy?: "open" | "allowlist" | "disabled"; +}): { + groupPolicy: "open" | "allowlist" | "disabled"; + providerMissingFallbackApplied: boolean; +} { + return resolveOpenProviderRuntimeGroupPolicy({ + providerConfigPresent: params.providerConfigPresent, + groupPolicy: params.groupPolicy, + defaultGroupPolicy: params.defaultGroupPolicy, + }); +} diff --git a/extensions/whatsapp/test-api.ts b/extensions/whatsapp/test-api.ts index 5ac296cbf56..82444aab71d 100644 --- a/extensions/whatsapp/test-api.ts +++ b/extensions/whatsapp/test-api.ts @@ -1,8 +1 @@ -export { whatsappPlugin } from "./src/channel.js"; -export { setWhatsAppRuntime } from "./src/runtime.js"; -export { whatsappOutbound } from "./src/outbound-adapter.js"; -export { deliverWebReply } from "./src/auto-reply/deliver-reply.js"; -export { - trackBackgroundTask, - updateLastRouteInBackground, -} from "./src/auto-reply/monitor/last-route.js"; +export { resolveWhatsAppRuntimeGroupPolicy } from "./src/runtime-group-policy.js"; diff --git a/src/channels/plugins/contracts/group-policy.fallback.contract.test.ts b/src/channels/plugins/contracts/group-policy.fallback.contract.test.ts index 4d54bdf64d0..62f3faeddc0 100644 --- a/src/channels/plugins/contracts/group-policy.fallback.contract.test.ts +++ b/src/channels/plugins/contracts/group-policy.fallback.contract.test.ts @@ -1,24 +1,11 @@ -import { describe, it } from "vitest"; -import { whatsappAccessControlTesting } from "../../../../extensions/whatsapp/api.js"; -import { resolveZaloRuntimeGroupPolicy } from "../../../../extensions/zalo/api.js"; +import { describe, expect, it } from "vitest"; +import { installChannelRuntimeGroupPolicyFallbackSuite } from "../../../../test/helpers/channels/group-policy-contract-suites.js"; import { - expectResolvedGroupPolicyCase, - installChannelRuntimeGroupPolicyFallbackSuite, -} from "../../../../test/helpers/channels/group-policy-contract-suites.js"; + resolveZaloRuntimeGroupPolicy, + resolveWhatsAppRuntimeGroupPolicy, +} from "../../../../test/helpers/channels/policy-contract.js"; import { resolveOpenProviderRuntimeGroupPolicy } from "../../../config/runtime-group-policy.js"; -type ResolvedGroupPolicy = ReturnType; - -function expectResolvedDiscordGroupPolicyCase(params: { - providerConfigPresent: Parameters< - typeof resolveOpenProviderRuntimeGroupPolicy - >[0]["providerConfigPresent"]; - groupPolicy: Parameters[0]["groupPolicy"]; - expected: Pick; -}) { - expectResolvedGroupPolicyCase(resolveOpenProviderRuntimeGroupPolicy(params), params.expected); -} - describe("channel runtime group policy fallback contract", () => { describe("slack", () => { installChannelRuntimeGroupPolicyFallbackSuite({ @@ -42,7 +29,7 @@ describe("channel runtime group policy fallback contract", () => { describe("whatsapp", () => { installChannelRuntimeGroupPolicyFallbackSuite({ - resolve: whatsappAccessControlTesting.resolveWhatsAppRuntimeGroupPolicy, + resolve: resolveWhatsAppRuntimeGroupPolicy, configuredLabel: "keeps open fallback when channels.whatsapp is configured", defaultGroupPolicyUnderTest: "disabled", missingConfigLabel: "fails closed when channels.whatsapp is missing and no defaults are set", @@ -73,13 +60,11 @@ describe("channel runtime group policy fallback contract", () => { { providerConfigPresent: false, groupPolicy: "disabled", - expected: { - groupPolicy: "disabled", - providerMissingFallbackApplied: false, - }, }, ] as const)("respects explicit provider policy %#", (testCase) => { - expectResolvedDiscordGroupPolicyCase(testCase); + const resolved = resolveOpenProviderRuntimeGroupPolicy(testCase); + expect(resolved.groupPolicy).toBe("disabled"); + expect(resolved.providerMissingFallbackApplied).toBe(false); }); }); diff --git a/test/helpers/channels/policy-contract.ts b/test/helpers/channels/policy-contract.ts index 92ef712896f..2823dd0035e 100644 --- a/test/helpers/channels/policy-contract.ts +++ b/test/helpers/channels/policy-contract.ts @@ -1,8 +1,5 @@ -export { whatsappAccessControlTesting } from "../../../extensions/whatsapp/contract-api.js"; -export { - evaluateZaloGroupAccess, - resolveZaloRuntimeGroupPolicy, -} from "../../../extensions/zalo/contract-api.js"; +export { resolveWhatsAppRuntimeGroupPolicy } from "../../../extensions/whatsapp/test-api.js"; +export { resolveZaloRuntimeGroupPolicy } from "../../../extensions/zalo/test-api.js"; export { isSignalSenderAllowed, type SignalSender,