Matrix: scope verification fallback by DM room

This commit is contained in:
Gustavo Madeira Santana
2026-03-13 02:23:40 +00:00
parent 8d25168f89
commit 4e05790695
2 changed files with 77 additions and 1 deletions

View File

@@ -26,6 +26,7 @@ function createHarness(params?: {
verifications?: Array<{
id: string;
transactionId?: string;
roomId?: string;
otherUserId: string;
updatedAt?: string;
completed?: boolean;
@@ -457,6 +458,73 @@ describe("registerMatrixMonitorEvents verification routing", () => {
expect(bodies.some((body) => body.includes("SAS decimal: 1111 2222 3333"))).toBe(false);
});
it("prefers the active verification for the current DM when multiple active summaries exist", async () => {
const { sendMessage, roomEventListener } = createHarness({
joinedMembersByRoom: {
"!dm-current:example.org": ["@alice:example.org", "@bot:example.org"],
},
verifications: [
{
id: "verification-other-room",
roomId: "!dm-other:example.org",
transactionId: "$different-flow-other",
otherUserId: "@alice:example.org",
updatedAt: new Date("2026-02-25T21:44:54.000Z").toISOString(),
phaseName: "started",
phase: 3,
pending: true,
sas: {
decimal: [1111, 2222, 3333],
emoji: [
["🚀", "Rocket"],
["🦋", "Butterfly"],
["📕", "Book"],
],
},
},
{
id: "verification-current-room",
roomId: "!dm-current:example.org",
transactionId: "$different-flow-current",
otherUserId: "@alice:example.org",
updatedAt: new Date("2026-02-25T21:43:54.000Z").toISOString(),
phaseName: "started",
phase: 3,
pending: true,
sas: {
decimal: [6158, 1986, 3513],
emoji: [
["🎁", "Gift"],
["🌍", "Globe"],
["🐴", "Horse"],
],
},
},
],
});
roomEventListener("!dm-current:example.org", {
event_id: "$start-room-scoped",
sender: "@alice:example.org",
type: "m.key.verification.start",
origin_server_ts: Date.now(),
content: {
"m.relates_to": { event_id: "$req-room-scoped" },
},
});
await vi.waitFor(() => {
const bodies = (sendMessage.mock.calls as unknown[][]).map((call) =>
String((call[1] as { body?: string } | undefined)?.body ?? ""),
);
expect(bodies.some((body) => body.includes("SAS decimal: 6158 1986 3513"))).toBe(true);
});
const bodies = (sendMessage.mock.calls as unknown[][]).map((call) =>
String((call[1] as { body?: string } | undefined)?.body ?? ""),
);
expect(bodies.some((body) => body.includes("SAS decimal: 1111 2222 3333"))).toBe(false);
});
it("does not emit SAS notices for cancelled verification events", async () => {
const { sendMessage, roomEventListener } = createHarness({
joinedMembersByRoom: {

View File

@@ -16,6 +16,7 @@ type MatrixVerificationStage = "request" | "ready" | "start" | "cancel" | "done"
type MatrixVerificationSummaryLike = {
id: string;
transactionId?: string;
roomId?: string;
otherUserId: string;
updatedAt?: string;
completed?: boolean;
@@ -223,7 +224,14 @@ async function resolveVerificationSummaryForSignal(
const activeByUser = list
.filter((entry) => entry.otherUserId === params.senderId && isActiveVerificationSummary(entry))
.sort((a, b) => resolveSummaryRecency(b) - resolveSummaryRecency(a));
return activeByUser.length === 1 ? (activeByUser[0] ?? null) : null;
const activeInRoom = activeByUser.filter((entry) => {
const roomId = trimMaybeString(entry.roomId);
return roomId === params.roomId;
});
if (activeInRoom.length > 0) {
return activeInRoom[0] ?? null;
}
return activeByUser[0] ?? null;
}
async function resolveVerificationSasNoticeForSignal(