Skip to content

Commit 3adee18

Browse files
committed
fix(sessions): derive channel from account-scoped DM session keys in send-policy
1 parent 15e4fbf commit 3adee18

2 files changed

Lines changed: 19 additions & 6 deletions

File tree

src/sessions/send-policy.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { describe, expect, it } from "vitest";
33
import type { OpenClawConfig } from "../config/config.js";
44
import type { SessionEntry } from "../config/sessions.js";
5+
import { buildAgentPeerSessionKey } from "../routing/session-key.js";
56
import { resolveSendPolicy } from "./send-policy.js";
67

78
describe("resolveSendPolicy", () => {
@@ -73,6 +74,19 @@ describe("resolveSendPolicy", () => {
7374
sessionKey: "demo-channel:direct:user-1",
7475
expected: "deny",
7576
},
77+
{
78+
name: "channel-scoped deny fires for per-account-channel-peer DM key without explicit channel field",
79+
cfg: cfgWithRules([{ action: "deny", match: { channel: "demo-channel" } }]),
80+
sessionKey: buildAgentPeerSessionKey({
81+
agentId: "main",
82+
channel: "demo-channel",
83+
accountId: "acct-1",
84+
peerKind: "direct",
85+
peerId: "user-1",
86+
dmScope: "per-account-channel-peer",
87+
}),
88+
expected: "deny",
89+
},
7690
])("$name", ({ cfg, entry, sessionKey, expected }) => {
7791
expect(resolveSendPolicy({ cfg, entry, sessionKey })).toBe(expected);
7892
});

src/sessions/send-policy.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,11 @@ function deriveChannelFromKey(key?: string) {
4646
return undefined;
4747
}
4848
const parts = normalizedKey.split(":").filter(Boolean);
49-
// Canonical key layout is <channel>:<peerKind>:<peerId>; parts[0] is the channel
50-
// for direct/dm peers too, so channel-scoped rules also fire for direct chats.
51-
if (
52-
parts.length >= 3 &&
53-
(parts[1] === "group" || parts[1] === "channel" || parts[1] === "direct" || parts[1] === "dm")
54-
) {
49+
// Key layout is <channel>:[<accountId>:]<peerKind>:<peerId>; parts[0] is the
50+
// channel for account-scoped DM keys too, so channel-scoped rules also fire
51+
// for per-account-channel-peer sessions, not just 3-part direct/group keys.
52+
const peerKinds = new Set(["group", "channel", "direct", "dm"]);
53+
if (parts.length >= 3 && parts.slice(1).some((part) => peerKinds.has(part))) {
5554
return normalizeMatchValue(parts[0]);
5655
}
5756
return undefined;

0 commit comments

Comments
 (0)