Files
openclaw/src/test-utils/channel-plugins.ts
Josh Avant fbd330b7aa fix(channels): honor configured read target policies (#99905)
* fix(channels): enforce configured read targets

* test(channels): align policy checks with boundaries

* fix: bind channel reads to trusted turn context

* test: satisfy gateway lint

* fix: narrow message action channel imports

* fix(feishu): authorize message reads before provider access

* fix(slack): await reaction clear authorization

* fix(channels): align provider action contracts

* fix(matrix): read direct-room account data before sync

* fix(channels): reject unsupported attachment actions early

* fix: restore trusted operator conversation reads

* fix(matrix): authorize pin actions before provider reads

* fix: preserve trusted channel read workflows

* fix(discord): resolve current channel ids consistently

* fix(agents): preserve message action turn capability

* fix(plugins): enforce host-owned read provenance

* fix(channels): harden Teams and Discord read policy

* fix(channels): preserve exact-current action compatibility

* fix(imessage): authorize trusted current chat aliases

* fix(channels): preserve normalized current aliases

* fix(channels): preserve external current target aliases

* fix: reconcile channel policy with current main

* fix(discord): isolate DM read policy

* fix(channels): enforce provider read gates

* fix(gateway): await serialized message action identity tokens

* fix(ci): refresh channel protocol contracts
2026-07-10 22:29:37 -05:00

117 lines
3.7 KiB
TypeScript

// Constructs channel plugin registries and plugin fixtures for tests.
import type {
ChannelCapabilities,
ChannelId,
ChannelMessagingAdapter,
ChannelOutboundAdapter,
ChannelPlugin,
} from "../channels/plugins/types.public.js";
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
import type { PluginRegistry } from "../plugins/registry.js";
/** Registry entry shape used by channel tests without loading real plugins. */
export type TestChannelRegistration = {
pluginId: string;
plugin: unknown;
source: string;
origin?: "bundled" | "global" | "workspace" | "config";
};
export const createTestRegistry = (channels: TestChannelRegistration[] = []): PluginRegistry => ({
...createEmptyPluginRegistry(),
channels: channels as unknown as PluginRegistry["channels"],
channelSetups: channels.map((entry) => ({
pluginId: entry.pluginId,
plugin: entry.plugin as PluginRegistry["channelSetups"][number]["plugin"],
...(entry.origin ? { origin: entry.origin } : {}),
source: entry.source,
enabled: true,
})),
});
export const createChannelTestPluginBase = (params: {
id: ChannelId;
label?: string;
docsPath?: string;
markdownCapable?: boolean;
capabilities?: ChannelCapabilities;
config?: Partial<ChannelPlugin["config"]>;
}): Pick<ChannelPlugin, "id" | "meta" | "capabilities" | "config"> => ({
id: params.id,
meta: {
id: params.id,
label: params.label ?? String(params.id),
selectionLabel: params.label ?? String(params.id),
docsPath: params.docsPath ?? `/channels/${params.id}`,
blurb: "test stub.",
...(params.markdownCapable !== undefined ? { markdownCapable: params.markdownCapable } : {}),
},
capabilities: params.capabilities ?? { chatTypes: ["direct"] },
config: {
listAccountIds: () => ["default"],
resolveAccount: () => ({}),
...params.config,
},
});
export const createDirectOutboundTestAdapter = (params: {
channel: ChannelId;
messageId?: string;
resolveTarget?: ChannelOutboundAdapter["resolveTarget"];
}): ChannelOutboundAdapter => ({
deliveryMode: "direct",
...(params.resolveTarget ? { resolveTarget: params.resolveTarget } : {}),
sendText: async () => ({ channel: params.channel, messageId: params.messageId ?? "msg-test" }),
sendMedia: async () => ({ channel: params.channel, messageId: params.messageId ?? "msg-test" }),
});
export const createOutboundTestPlugin = (params: {
id: ChannelId;
outbound: ChannelOutboundAdapter;
messaging?: ChannelMessagingAdapter;
label?: string;
docsPath?: string;
capabilities?: ChannelCapabilities;
}): ChannelPlugin => ({
...createChannelTestPluginBase({
id: params.id,
label: params.label,
docsPath: params.docsPath,
capabilities: params.capabilities,
config: { listAccountIds: () => [] },
}),
outbound: params.outbound,
...(params.messaging ? { messaging: params.messaging } : {}),
});
export type BindingResolverTestPlugin = Pick<
ChannelPlugin,
"id" | "meta" | "capabilities" | "config"
> & {
setup?: Pick<NonNullable<ChannelPlugin["setup"]>, "resolveBindingAccountId">;
};
export const createBindingResolverTestPlugin = (params: {
id: ChannelId;
label?: string;
docsPath?: string;
capabilities?: ChannelCapabilities;
config?: Partial<ChannelPlugin["config"]>;
resolveBindingAccountId?: NonNullable<ChannelPlugin["setup"]>["resolveBindingAccountId"];
}): BindingResolverTestPlugin => ({
...createChannelTestPluginBase({
id: params.id,
label: params.label,
docsPath: params.docsPath,
capabilities: params.capabilities,
config: params.config,
}),
...(params.resolveBindingAccountId
? {
setup: {
resolveBindingAccountId: params.resolveBindingAccountId,
},
}
: {}),
});