mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-16 23:52:40 -06:00
c39abcecda
* fix(security): audit effective DM session ownership Resolve admitted DM principals through canonical route, account, identity-link, and channel-owned session policy before reporting shared-session risk. Doctor now renders the structured channel security owner instead of duplicating the global-only default-account heuristic.\n\nCloses #121711 * chore(plugin-sdk): refresh API contract baseline * fix(telegram): preserve direct peer SDK export * fix(telegram): preserve direct peer resolver signature * fix(ci): use supported DM audit grouping * fix(protocol): refresh approval reviewer Swift models
78 lines
2.4 KiB
TypeScript
78 lines
2.4 KiB
TypeScript
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
|
|
import {
|
|
buildAgentSessionKey,
|
|
normalizeAccountId,
|
|
type ResolvedAgentRoute,
|
|
} from "openclaw/plugin-sdk/routing";
|
|
|
|
export function resolveTelegramDirectPeerId(params: {
|
|
chatId: number | string;
|
|
senderId?: number | string | null;
|
|
}) {
|
|
const normalized = params.senderId == null ? "" : String(params.senderId).trim();
|
|
return normalized || String(params.chatId);
|
|
}
|
|
|
|
export function resolveTelegramNamedAccountBaseSessionKey(
|
|
defaultAccountId: string,
|
|
params: {
|
|
cfg: OpenClawConfig;
|
|
route: Pick<ResolvedAgentRoute, "agentId" | "accountId" | "matchedBy" | "sessionKey">;
|
|
chatId: number | string;
|
|
isGroup: boolean;
|
|
senderId?: string | number | null;
|
|
},
|
|
): string {
|
|
const routeAccountId = normalizeAccountId(params.route.accountId);
|
|
const normalizedDefaultAccountId = normalizeAccountId(defaultAccountId);
|
|
const isNamedAccountFallback =
|
|
routeAccountId !== normalizedDefaultAccountId && params.route.matchedBy === "default";
|
|
if (!isNamedAccountFallback || params.isGroup) {
|
|
return params.route.sessionKey;
|
|
}
|
|
return buildAgentSessionKey({
|
|
agentId: params.route.agentId,
|
|
channel: "telegram",
|
|
accountId: params.route.accountId,
|
|
peer: {
|
|
kind: "direct",
|
|
id: resolveTelegramDirectPeerId({
|
|
chatId: params.chatId,
|
|
senderId: params.senderId,
|
|
}),
|
|
},
|
|
dmScope: "per-account-channel-peer",
|
|
identityLinks: params.cfg.session?.identityLinks,
|
|
});
|
|
}
|
|
|
|
export function resolveTelegramSecurityDmRoute(
|
|
defaultAccountId: string,
|
|
params: {
|
|
cfg: OpenClawConfig;
|
|
accountId: string;
|
|
route: ResolvedAgentRoute;
|
|
principalId?: string;
|
|
},
|
|
): { kind: "core" | "isolated" } | { sessionKey: string } {
|
|
if (params.principalId !== undefined) {
|
|
return {
|
|
sessionKey: resolveTelegramNamedAccountBaseSessionKey(defaultAccountId, {
|
|
...params,
|
|
chatId: params.principalId,
|
|
isGroup: false,
|
|
senderId: params.principalId,
|
|
}),
|
|
};
|
|
}
|
|
const isNamedAccountFallback =
|
|
normalizeAccountId(params.accountId) !== normalizeAccountId(defaultAccountId) &&
|
|
params.route.matchedBy === "default";
|
|
if (isNamedAccountFallback || params.route.dmScope === "per-account-channel-peer") {
|
|
return { kind: "isolated" };
|
|
}
|
|
return params.route.dmScope === "main"
|
|
? { sessionKey: params.route.sessionKey }
|
|
: { kind: "core" };
|
|
}
|