chore(deadcode): remove unused channel sender validator

This commit is contained in:
Vincent Koc
2026-06-20 23:49:40 +08:00
parent 60159b9f00
commit 021fd5de2b
3 changed files with 29 additions and 83 deletions

View File

@@ -1,6 +1,5 @@
// Channel config tests cover channel config normalization and account lookup behavior.
import { describe, expect, it } from "vitest";
import type { MsgContext } from "../auto-reply/templating.js";
import { typedCases } from "../test-utils/typed-cases.js";
import {
type ChannelMatchSource,
@@ -12,7 +11,6 @@ import {
applyChannelMatchMeta,
resolveChannelMatchConfig,
} from "./channel-config.js";
import { validateSenderIdentity } from "./sender-identity.js";
describe("buildChannelKeyCandidates", () => {
it("dedupes and trims keys", () => {
@@ -136,33 +134,6 @@ describe("resolveChannelMatchConfig", () => {
});
});
describe("validateSenderIdentity", () => {
it("allows direct messages without sender fields", () => {
const ctx: MsgContext = { ChatType: "direct" };
expect(validateSenderIdentity(ctx)).toStrictEqual([]);
});
it("requires some sender identity for non-direct chats", () => {
const ctx: MsgContext = { ChatType: "group" };
expect(validateSenderIdentity(ctx)).toContain(
"missing sender identity (SenderId/SenderName/SenderUsername/SenderE164)",
);
});
it("validates SenderE164 and SenderUsername shape", () => {
const ctx: MsgContext = {
ChatType: "group",
SenderE164: "123",
SenderUsername: "@ada lovelace",
};
expect(validateSenderIdentity(ctx)).toEqual([
"invalid SenderE164: 123",
'SenderUsername should not include "@": @ada lovelace',
"SenderUsername should not include whitespace: @ada lovelace",
]);
});
});
describe("resolveNestedAllowlistDecision", () => {
const cases = [
{

View File

@@ -8,7 +8,6 @@ import type { DispatchFromConfigResult } from "../../../auto-reply/reply/dispatc
import type { MsgContext } from "../../../auto-reply/templating.js";
import { normalizeChatType } from "../../chat-type.js";
import { resolveConversationLabel } from "../../conversation-label.js";
import { validateSenderIdentity } from "../../sender-identity.js";
import {
hasFinalChannelTurnDispatch,
hasVisibleChannelTurnDispatch,
@@ -32,18 +31,45 @@ export function primeChannelOutboundSendMock<TArgs extends unknown[]>(
}
}
export function expectChannelInboundContextContract(ctx: MsgContext) {
expect(validateSenderIdentity(ctx)).toEqual([]);
function normalizeContextString(value: unknown): string {
return typeof value === "string" ? value.trim() : "";
}
export function expectChannelInboundContextContract(ctx: MsgContext) {
expect(ctx.Body).toBeTypeOf("string");
expect(ctx.BodyForAgent).toBeTypeOf("string");
expect(ctx.BodyForCommands).toBeTypeOf("string");
const chatType = normalizeChatType(ctx.ChatType);
if (chatType !== "direct") {
const senderValues = [
normalizeContextString(ctx.SenderId),
normalizeContextString(ctx.SenderName),
normalizeContextString(ctx.SenderUsername),
normalizeContextString(ctx.SenderE164),
].filter(Boolean);
expect(senderValues.length).toBeGreaterThan(0);
}
if (chatType && chatType !== "direct") {
const label = ctx.ConversationLabel?.trim() || resolveConversationLabel(ctx);
expect(label).toBeTruthy();
}
const senderE164 = normalizeContextString(ctx.SenderE164);
if (senderE164) {
expect(senderE164).toMatch(/^\+\d{3,}$/);
}
const senderUsername = normalizeContextString(ctx.SenderUsername);
if (senderUsername) {
expect(senderUsername).not.toContain("@");
expect(senderUsername).not.toMatch(/\s/);
}
if (ctx.SenderId != null) {
expect(normalizeContextString(ctx.SenderId)).toBeTruthy();
}
}
export function expectChannelTurnDispatchResultContract(

View File

@@ -1,51 +0,0 @@
/**
* Core sender identity validation for channel contexts before plugins/tools consume them.
* Keep this generic; channel-specific identity extraction belongs in each plugin.
*/
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import type { MsgContext } from "../auto-reply/templating.js";
import { normalizeChatType } from "./chat-type.js";
/** Validates trusted sender identity fields before channel contexts reach plugins/tools. */
export function validateSenderIdentity(ctx: MsgContext): string[] {
const issues: string[] = [];
const chatType = normalizeChatType(ctx.ChatType);
const isDirect = chatType === "direct";
const senderId = normalizeOptionalString(ctx.SenderId) || "";
const senderName = normalizeOptionalString(ctx.SenderName) || "";
const senderUsername = normalizeOptionalString(ctx.SenderUsername) || "";
const senderE164 = normalizeOptionalString(ctx.SenderE164) || "";
if (!isDirect) {
// Group/channel messages need an actor identity distinct from the conversation target;
// direct chats can derive the actor from the peer route.
if (!senderId && !senderName && !senderUsername && !senderE164) {
issues.push("missing sender identity (SenderId/SenderName/SenderUsername/SenderE164)");
}
}
if (senderE164) {
// Keep E.164 canonical here so access-group matching does not compare mixed phone formats.
if (!/^\+\d{3,}$/.test(senderE164)) {
issues.push(`invalid SenderE164: ${senderE164}`);
}
}
if (senderUsername) {
// Usernames are handle tokens, not display names or @mentions.
if (senderUsername.includes("@")) {
issues.push(`SenderUsername should not include "@": ${senderUsername}`);
}
if (/\s/.test(senderUsername)) {
issues.push(`SenderUsername should not include whitespace: ${senderUsername}`);
}
}
if (ctx.SenderId != null && !senderId) {
issues.push("SenderId is set but empty");
}
return issues;
}