From 23db233bb5ac910f7a02c4dcb2c015feeeb45ade Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 29 Jul 2026 01:51:48 -0400 Subject: [PATCH] fix(msteams): recognize provider-prefixed target ids (#115609) * fix(msteams): recognize provider-prefixed target ids * style(msteams): format explicit target regression matrix --- extensions/msteams/src/channel.test.ts | 20 +++++++++++++ .../msteams/src/resolve-allowlist.test.ts | 29 +++++++++++++++---- extensions/msteams/src/resolve-allowlist.ts | 2 +- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/extensions/msteams/src/channel.test.ts b/extensions/msteams/src/channel.test.ts index 284171e15475..12528fc0e6ae 100644 --- a/extensions/msteams/src/channel.test.ts +++ b/extensions/msteams/src/channel.test.ts @@ -108,6 +108,26 @@ describe("msteamsPlugin", () => { expect(looksLikeId?.("a:1bfPersonalChat")).toBe(true); expect(looksLikeId?.("user:Jane Doe")).toBe(false); }); + + it("recognizes provider-prefixed explicit targets without claiming display names", () => { + const messaging = msteamsPlugin.messaging; + const aadUserId = "40a1a0ed-4ff2-4164-a219-55518990c197"; + + expect( + ["teams", "msteams"].map((provider) => { + const target = `${provider}:user:${aadUserId}`; + return { + explicit: messaging?.targetResolver?.looksLikeId?.(target), + normalized: messaging?.normalizeTarget?.(target), + }; + }), + ).toEqual([ + { explicit: true, normalized: `user:${aadUserId}` }, + { explicit: true, normalized: `user:${aadUserId}` }, + ]); + expect(messaging?.targetResolver?.looksLikeId?.("teams:user:Jane Doe")).toBe(false); + expect(messaging?.targetResolver?.looksLikeId?.("msteams:user:Jane Doe")).toBe(false); + }); }); describe("msteams config schema", () => { diff --git a/extensions/msteams/src/resolve-allowlist.test.ts b/extensions/msteams/src/resolve-allowlist.test.ts index df540b469521..5b3a3cee74a4 100644 --- a/extensions/msteams/src/resolve-allowlist.test.ts +++ b/extensions/msteams/src/resolve-allowlist.test.ts @@ -500,12 +500,29 @@ describe("looksLikeMSTeamsTargetId", () => { expect(looksLikeMSTeamsTargetId("user:40a1a0ed-4ff2-4164-a219-55518990c197")).toBe(true); }); - it.each(["", " ", "user:John Smith", "Product Team/Roadmap", "Engineering", "hello"])( - "rejects non-id inputs (%s)", - (raw) => { - expect(looksLikeMSTeamsTargetId(raw)).toBe(false); - }, - ); + it.each([ + "teams:user:40a1a0ed-4ff2-4164-a219-55518990c197", + "msteams:user:40a1a0ed-4ff2-4164-a219-55518990c197", + "TEAMS:conversation:19:abc@thread.tacv2", + "msteams:19:abc@thread.tacv2", + "teams:29:1a2b3c4d5e6f", + " teams:user:40a1a0ed-4ff2-4164-a219-55518990c197 ", + ])("accepts provider-prefixed explicit ids (%s)", (raw) => { + expect(looksLikeMSTeamsTargetId(raw)).toBe(true); + }); + + it.each([ + "", + " ", + "user:John Smith", + "teams:user:John Smith", + "msteams:user:John Smith", + "Product Team/Roadmap", + "Engineering", + "hello", + ])("rejects non-id inputs (%s)", (raw) => { + expect(looksLikeMSTeamsTargetId(raw)).toBe(false); + }); it("normalizes leading/trailing whitespace before classifying", () => { expect(looksLikeMSTeamsTargetId(" 19:abc@thread.tacv2 ")).toBe(true); diff --git a/extensions/msteams/src/resolve-allowlist.ts b/extensions/msteams/src/resolve-allowlist.ts index 309100b1ac80..9e269e14ed63 100644 --- a/extensions/msteams/src/resolve-allowlist.ts +++ b/extensions/msteams/src/resolve-allowlist.ts @@ -183,7 +183,7 @@ export function looksLikeMSTeamsConversationId(raw: string): boolean { * can forward verbatim to the channel adapter. */ export function looksLikeMSTeamsTargetId(raw: string): boolean { - const trimmed = raw.trim(); + const trimmed = stripProviderPrefix(raw.trim()).trim(); if (looksLikeMSTeamsConversationId(trimmed)) { return true; }