diff --git a/src/channels/plugins/normalize/signal.test.ts b/src/channels/plugins/normalize/signal.test.ts index 6f4aee049..fa90c2d6b 100644 --- a/src/channels/plugins/normalize/signal.test.ts +++ b/src/channels/plugins/normalize/signal.test.ts @@ -3,6 +3,28 @@ import { describe, expect, it } from "vitest"; import { looksLikeSignalTargetId, normalizeSignalMessagingTarget } from "./signal.js"; describe("signal target normalization", () => { + describe("group targets", () => { + it("preserves case for base64-encoded group IDs", () => { + // Signal group IDs are base64-encoded and case-sensitive + expect( + normalizeSignalMessagingTarget("group:igVOP2EJR1sBXYYwsLhif/AEMTJWtiDiTyu88GWP5ZQ="), + ).toBe("group:igVOP2EJR1sBXYYwsLhif/AEMTJWtiDiTyu88GWP5ZQ="); + }); + + it("handles signal: prefix with group targets", () => { + expect( + normalizeSignalMessagingTarget("signal:group:igVOP2EJR1sBXYYwsLhif/AEMTJWtiDiTyu88GWP5ZQ="), + ).toBe("group:igVOP2EJR1sBXYYwsLhif/AEMTJWtiDiTyu88GWP5ZQ="); + }); + + it("accepts group: prefix for target detection", () => { + expect(looksLikeSignalTargetId("group:igVOP2EJR1sBXYYwsLhif/AEMTJWtiDiTyu88GWP5ZQ=")).toBe( + true, + ); + expect(looksLikeSignalTargetId("signal:group:someGroupId")).toBe(true); + }); + }); + it("normalizes uuid targets by stripping uuid:", () => { expect(normalizeSignalMessagingTarget("uuid:123E4567-E89B-12D3-A456-426614174000")).toBe( "123e4567-e89b-12d3-a456-426614174000", @@ -29,4 +51,17 @@ describe("signal target normalization", () => { expect(looksLikeSignalTargetId("uuid:")).toBe(false); expect(looksLikeSignalTargetId("uuid:not-a-uuid")).toBe(false); }); + + it("preserves group ID case (base64 is case-sensitive)", () => { + // Base64 group IDs contain mixed case that must be preserved + expect( + normalizeSignalMessagingTarget("group:igVOP2EJR1sBXYYwsLhif/AEMTJWtiDiTyu88GWP5ZQ="), + ).toBe("group:igVOP2EJR1sBXYYwsLhif/AEMTJWtiDiTyu88GWP5ZQ="); + expect(normalizeSignalMessagingTarget("signal:group:ABC123xyz+/=")).toBe("group:ABC123xyz+/="); + }); + + it("normalizes group prefix case but preserves ID", () => { + expect(normalizeSignalMessagingTarget("GROUP:TestGroupId123=")).toBe("group:TestGroupId123="); + expect(normalizeSignalMessagingTarget("Group:MixedCase/+ABC=")).toBe("group:MixedCase/+ABC="); + }); }); diff --git a/src/channels/plugins/normalize/signal.ts b/src/channels/plugins/normalize/signal.ts index c8ff17da6..b32264f5f 100644 --- a/src/channels/plugins/normalize/signal.ts +++ b/src/channels/plugins/normalize/signal.ts @@ -9,7 +9,8 @@ export function normalizeSignalMessagingTarget(raw: string): string | undefined const lower = normalized.toLowerCase(); if (lower.startsWith("group:")) { const id = normalized.slice("group:".length).trim(); - return id ? `group:${id}`.toLowerCase() : undefined; + // Keep group ID case-sensitive (base64 is case-sensitive) + return id ? `group:${id}` : undefined; } if (lower.startsWith("username:")) { const id = normalized.slice("username:".length).trim();