refactor: enforce plugin-owned channel boundaries

This commit is contained in:
Peter Steinberger
2026-04-18 22:45:03 +01:00
parent e89e214516
commit 8bfa06e992
26 changed files with 546 additions and 388 deletions

View File

@@ -39,6 +39,31 @@ describe("delivery context helpers", () => {
},
},
},
{
pluginId: "thread-child-chat",
source: "test",
plugin: {
...createChannelTestPluginBase({
id: "thread-child-chat",
label: "Thread child chat",
}),
messaging: {
resolveDeliveryTarget: ({
conversationId,
parentConversationId,
}: {
conversationId: string;
parentConversationId?: string;
}) => {
const parent = parentConversationId?.trim();
const child = conversationId.trim();
return parent && parent !== child
? { to: `channel:${parent}`, threadId: child }
: { to: `channel:${child}` };
},
},
},
},
]),
);
});
@@ -149,37 +174,15 @@ describe("delivery context helpers", () => {
});
});
it.each([
{
channel: "slack",
conversationId: "1710000000.000100",
parentConversationId: "C123",
expected: { to: "channel:C123", threadId: "1710000000.000100" },
},
{
channel: "telegram",
conversationId: "42",
parentConversationId: "-10099",
expected: { to: "channel:-10099", threadId: "42" },
},
{
channel: "mattermost",
conversationId: "msg-child-id",
parentConversationId: "channel-parent-id",
expected: { to: "channel:channel-parent-id", threadId: "msg-child-id" },
},
])(
"resolves parent-scoped thread delivery targets for $channel",
({ channel, conversationId, parentConversationId, expected }) => {
expect(
resolveConversationDeliveryTarget({
channel,
conversationId,
parentConversationId,
}),
).toEqual(expected);
},
);
it("resolves parent-scoped thread delivery targets through channel messaging hooks", () => {
expect(
resolveConversationDeliveryTarget({
channel: "thread-child-chat",
conversationId: "msg-child-id",
parentConversationId: "channel-parent-id",
}),
).toEqual({ to: "channel:channel-parent-id", threadId: "msg-child-id" });
});
it("derives delivery context from a session entry", () => {
expect(

View File

@@ -67,22 +67,6 @@ export function resolveConversationDeliveryTarget(params: {
: typeof params.parentConversationId === "string"
? normalizeOptionalString(params.parentConversationId)
: undefined;
const isThreadChild =
conversationId && parentConversationId && parentConversationId !== conversationId;
if (channel && isThreadChild) {
if (channel === "matrix") {
return {
to: `room:${parentConversationId}`,
threadId: conversationId,
};
}
if (channel === "slack" || channel === "mattermost" || channel === "telegram") {
return {
to: `channel:${parentConversationId}`,
threadId: conversationId,
};
}
}
const pluginTarget =
channel && conversationId
? getChannelPlugin(