diff --git a/src/media/channel-inbound-roots.contract.test.ts b/extensions/imessage/src/channel-inbound-roots.contract.test.ts similarity index 93% rename from src/media/channel-inbound-roots.contract.test.ts rename to extensions/imessage/src/channel-inbound-roots.contract.test.ts index 0dac351389d..cf23c473277 100644 --- a/src/media/channel-inbound-roots.contract.test.ts +++ b/extensions/imessage/src/channel-inbound-roots.contract.test.ts @@ -1,12 +1,12 @@ +import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; import { describe, expect, it } from "vitest"; import { DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, resolveIMessageAttachmentRoots, resolveIMessageRemoteAttachmentRoots, -} from "../../test/helpers/channels/channel-media-roots-contract.js"; -import type { OpenClawConfig } from "../config/types.js"; +} from "../contract-api.js"; -describe("channel-inbound-roots contract", () => { +describe("iMessage channel-inbound-roots contract", () => { function expectResolvedRootsCase(resolve: () => string[], expected: readonly string[]) { expect(resolve()).toEqual(expected); } diff --git a/src/channels/plugins/contracts/dm-policy.contract.test.ts b/extensions/signal/src/dm-policy.contract.test.ts similarity index 77% rename from src/channels/plugins/contracts/dm-policy.contract.test.ts rename to extensions/signal/src/dm-policy.contract.test.ts index bc633c9650b..02f75a6eb6a 100644 --- a/src/channels/plugins/contracts/dm-policy.contract.test.ts +++ b/extensions/signal/src/dm-policy.contract.test.ts @@ -1,12 +1,9 @@ -import { describe, expect, it } from "vitest"; -import { - getSignalContractSurface, - type SignalSender, -} from "../../../../test/helpers/channels/dm-policy-contract.js"; import { DM_GROUP_ACCESS_REASON, resolveDmGroupAccessWithLists, -} from "../../../security/dm-policy-shared.js"; +} from "openclaw/plugin-sdk/channel-policy"; +import { describe, expect, it } from "vitest"; +import { isSignalSenderAllowed, type SignalSender } from "../contract-api.js"; type ChannelSmokeCase = { name: string; @@ -21,9 +18,7 @@ const signalSender: SignalSender = { }; const signalSenderE164 = "+15550001111"; -function createChannelSmokeCases( - isSignalSenderAllowed: (sender: SignalSender, allowFrom: string[]) => boolean, -): ChannelSmokeCase[] { +function createChannelSmokeCases(): ChannelSmokeCase[] { return [ { name: "bluebubbles", @@ -52,7 +47,7 @@ function expandChannelIngressCases(cases: readonly ChannelSmokeCase[]) { ); } -describe("security/dm-policy-shared channel smoke", () => { +describe("Signal dm-policy shared contract", () => { function expectBlockedGroupAccess(params: { storeAllowFrom: string[]; isSenderAllowed: (allowFrom: string[]) => boolean; @@ -71,11 +66,8 @@ describe("security/dm-policy-shared channel smoke", () => { expect(access.reason).toBe("groupPolicy=allowlist (not allowlisted)"); } - it("blocks group ingress when sender is only in pairing store", async () => { - const { isSignalSenderAllowed } = await getSignalContractSurface(); - for (const { testCase } of expandChannelIngressCases( - createChannelSmokeCases(isSignalSenderAllowed), - )) { + it("blocks group ingress when sender is only in pairing store", () => { + for (const { testCase } of expandChannelIngressCases(createChannelSmokeCases())) { expectBlockedGroupAccess({ storeAllowFrom: testCase.storeAllowFrom, isSenderAllowed: testCase.isSenderAllowed, diff --git a/test/helpers/channels/channel-media-roots-contract.ts b/test/helpers/channels/channel-media-roots-contract.ts deleted file mode 100644 index 33378e6cd4f..00000000000 --- a/test/helpers/channels/channel-media-roots-contract.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { resolveRelativeBundledPluginPublicModuleId } from "../../../src/test-utils/bundled-plugin-public-surface.js"; - -type IMessageContractSurface = { - DEFAULT_IMESSAGE_ATTACHMENT_ROOTS: string[]; - resolveIMessageAttachmentRoots: (params: unknown) => string[]; - resolveIMessageRemoteAttachmentRoots: (params: unknown) => string[]; -}; - -const { - DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, - resolveIMessageAttachmentRoots, - resolveIMessageRemoteAttachmentRoots, -} = (await import( - resolveRelativeBundledPluginPublicModuleId({ - fromModuleUrl: import.meta.url, - pluginId: "imessage", - artifactBasename: "contract-api.js", - }) -)) as IMessageContractSurface; - -export { - DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, - resolveIMessageAttachmentRoots, - resolveIMessageRemoteAttachmentRoots, -}; diff --git a/test/helpers/channels/dm-policy-contract.ts b/test/helpers/channels/dm-policy-contract.ts deleted file mode 100644 index 81a6da6d594..00000000000 --- a/test/helpers/channels/dm-policy-contract.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { resolveRelativeBundledPluginPublicModuleId } from "../../../src/test-utils/bundled-plugin-public-surface.js"; - -export type SignalSender = { - kind: string; - raw: string; - e164?: string; - uuid?: string; - username?: string; -}; - -type SignalContractApiSurface = { - isSignalSenderAllowed: (...args: unknown[]) => boolean; -}; - -let signalContractSurface: Promise | undefined; - -export function getSignalContractSurface(): Promise { - signalContractSurface ??= import( - resolveRelativeBundledPluginPublicModuleId({ - fromModuleUrl: import.meta.url, - pluginId: "signal", - artifactBasename: "contract-api.js", - }) - ) as Promise; - return signalContractSurface; -} diff --git a/test/helpers/channels/security-audit-contract.ts b/test/helpers/channels/security-audit-contract.ts deleted file mode 100644 index 6d04bf47f30..00000000000 --- a/test/helpers/channels/security-audit-contract.ts +++ /dev/null @@ -1,146 +0,0 @@ -import type { OpenClawConfig } from "../../../src/config/config.js"; -import type { SecurityAuditFinding } from "../../../src/security/audit.types.js"; -import { - loadBundledPluginPublicSurfaceSync, - resolveRelativeBundledPluginPublicModuleId, -} from "../../../src/test-utils/bundled-plugin-public-surface.js"; - -type SecurityAuditAccount = { - accountId: string; - enabled?: boolean; - token?: unknown; - tokenSource?: string; - config?: Record; - [key: string]: unknown; -}; -type FlexibleSecurityAuditParams = { - cfg?: OpenClawConfig; - sourceConfig?: OpenClawConfig; - account: SecurityAuditAccount; - accountId?: string | null; - orderedAccountIds?: string[]; - hasExplicitAccountPath?: boolean; -}; -type ConfigSecurityAuditParams = { - cfg: OpenClawConfig; -}; -type AsyncChannelSecurityAuditCollector = ( - params: FlexibleSecurityAuditParams, -) => Promise; -type SyncChannelSecurityAuditCollector = ( - params: FlexibleSecurityAuditParams, -) => SecurityAuditFinding[]; -type ConfigSecurityAuditCollector = (params: ConfigSecurityAuditParams) => SecurityAuditFinding[]; -type DiscordSecurityAuditSurface = { - collectDiscordSecurityAuditFindings: AsyncChannelSecurityAuditCollector; -}; -type FeishuSecuritySurface = { - collectFeishuSecurityAuditFindings: ConfigSecurityAuditCollector; -}; -type SlackSecuritySurface = { - collectSlackSecurityAuditFindings: AsyncChannelSecurityAuditCollector; -}; -type SynologyChatSecuritySurface = { - collectSynologyChatSecurityAuditFindings: SyncChannelSecurityAuditCollector; -}; -type TelegramSecuritySurface = { - collectTelegramSecurityAuditFindings: AsyncChannelSecurityAuditCollector; -}; -type ZalouserSecuritySurface = { - collectZalouserSecurityAuditFindings: SyncChannelSecurityAuditCollector; -}; - -const discordSecurityAuditModuleId = resolveRelativeBundledPluginPublicModuleId({ - fromModuleUrl: import.meta.url, - pluginId: "discord", - artifactBasename: "security-audit-contract-api.js", -}); -const slackSecurityModuleId = resolveRelativeBundledPluginPublicModuleId({ - fromModuleUrl: import.meta.url, - pluginId: "slack", - artifactBasename: "security-contract-api.js", -}); -const telegramSecurityModuleId = resolveRelativeBundledPluginPublicModuleId({ - fromModuleUrl: import.meta.url, - pluginId: "telegram", - artifactBasename: "security-audit-contract-api.js", -}); -let discordSecurityAuditSurfacePromise: Promise | undefined; -let slackSecuritySurfacePromise: Promise | undefined; -let telegramSecuritySurfacePromise: Promise | undefined; - -function loadDiscordSecurityAuditSurface(): Promise { - discordSecurityAuditSurfacePromise ??= import( - discordSecurityAuditModuleId - ) as Promise; - return discordSecurityAuditSurfacePromise; -} - -function loadFeishuSecuritySurface(): FeishuSecuritySurface { - return loadBundledPluginPublicSurfaceSync({ - pluginId: "feishu", - artifactBasename: "security-contract-api.js", - }); -} - -function loadSlackSecuritySurface(): Promise { - slackSecuritySurfacePromise ??= import(slackSecurityModuleId) as Promise; - return slackSecuritySurfacePromise; -} - -function loadSynologyChatSecuritySurface(): SynologyChatSecuritySurface { - return loadBundledPluginPublicSurfaceSync({ - pluginId: "synology-chat", - artifactBasename: "contract-api.js", - }); -} - -function loadTelegramSecuritySurface(): Promise { - telegramSecuritySurfacePromise ??= import( - telegramSecurityModuleId - ) as Promise; - return telegramSecuritySurfacePromise; -} - -function loadZalouserSecuritySurface(): ZalouserSecuritySurface { - return loadBundledPluginPublicSurfaceSync({ - pluginId: "zalouser", - artifactBasename: "contract-api.js", - }); -} - -export const collectDiscordSecurityAuditFindings: DiscordSecurityAuditSurface["collectDiscordSecurityAuditFindings"] = - (async (...args) => - (await loadDiscordSecurityAuditSurface()).collectDiscordSecurityAuditFindings( - ...args, - )) as DiscordSecurityAuditSurface["collectDiscordSecurityAuditFindings"]; - -export const collectFeishuSecurityAuditFindings: FeishuSecuritySurface["collectFeishuSecurityAuditFindings"] = - ((...args) => - loadFeishuSecuritySurface().collectFeishuSecurityAuditFindings( - ...args, - )) as FeishuSecuritySurface["collectFeishuSecurityAuditFindings"]; - -export const collectSlackSecurityAuditFindings: SlackSecuritySurface["collectSlackSecurityAuditFindings"] = - (async (...args) => - (await loadSlackSecuritySurface()).collectSlackSecurityAuditFindings( - ...args, - )) as SlackSecuritySurface["collectSlackSecurityAuditFindings"]; - -export const collectSynologyChatSecurityAuditFindings: SynologyChatSecuritySurface["collectSynologyChatSecurityAuditFindings"] = - ((...args) => - loadSynologyChatSecuritySurface().collectSynologyChatSecurityAuditFindings( - ...args, - )) as SynologyChatSecuritySurface["collectSynologyChatSecurityAuditFindings"]; - -export const collectTelegramSecurityAuditFindings: TelegramSecuritySurface["collectTelegramSecurityAuditFindings"] = - (async (...args) => - (await loadTelegramSecuritySurface()).collectTelegramSecurityAuditFindings( - ...args, - )) as TelegramSecuritySurface["collectTelegramSecurityAuditFindings"]; - -export const collectZalouserSecurityAuditFindings: ZalouserSecuritySurface["collectZalouserSecurityAuditFindings"] = - ((...args) => - loadZalouserSecuritySurface().collectZalouserSecurityAuditFindings( - ...args, - )) as ZalouserSecuritySurface["collectZalouserSecurityAuditFindings"];