← Back to PRs

#19190: Signal: preserve group ID casing in session keys

by clzoc open 2026-02-17 14:13 View on GitHub →
gateway size: M
## Summary - preserve case for `signal:group:<groupId>` session keys instead of lowercasing the base64 group ID - route explicit `SessionKey` and gateway `sessionKey` inputs through a signal-aware normalizer - keep non-Signal providers on the existing lowercase normalization path ## Testing - pnpm test src/routing/session-key.test.ts src/config/sessions.test.ts src/infra/outbound/outbound.test.ts src/gateway/server-methods/send.test.ts src/gateway/session-utils.test.ts - pnpm lint -- src/routing/session-key.ts src/routing/session-key.test.ts src/config/sessions/session-key.ts src/config/sessions.test.ts src/gateway/server-methods/send.ts src/gateway/server-methods/send.test.ts src/gateway/session-utils.ts src/gateway/session-utils.test.ts src/infra/outbound/outbound-policy.ts src/infra/outbound/outbound.test.ts Fixes #19139 <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a bug where Signal group IDs (which are base64-encoded and case-sensitive) were being lowercased during session key normalization, causing session key mismatches. - Introduces `normalizeSessionKeyForStorage()` in `src/routing/session-key.ts` that selectively preserves case for Signal group IDs (the `signal:group:<base64Id>` segment) while lowercasing all other components (agent IDs, channel names, other provider IDs) - Adds `normalizePeerIdForSessionKey()` to handle case preservation at the peer ID level in `buildAgentPeerSessionKey` and `buildGroupHistoryKey` - Updates `normalizeTarget()` in outbound policy to preserve Signal target casing for cross-context comparison - Replaces all direct `.toLowerCase()` calls on session keys with `normalizeSessionKeyForStorage()` across 5 call sites: explicit `SessionKey` resolution, gateway send handler, session store key resolution, session key canonicalization, and spawned-by canonicalization - Comprehensive test coverage added across all affected modules - One potential follow-up: `src/auto-reply/reply/dispatch-from-config.ts:70` still uses `sessionKey.toLowerCase()` for store lookups, which could miss Signal group sessions stored with preserved casing (mitigated by fallback to original key) <h3>Confidence Score: 4/5</h3> - This PR is safe to merge with minimal risk; the normalization logic is well-structured and comprehensively tested. - Score of 4 reflects that the core changes are correct, well-tested, and narrowly scoped. One minor concern is that a pre-existing session store lookup in dispatch-from-config.ts still uses .toLowerCase() which could theoretically miss Signal group sessions, though this is mitigated by its fallback to the original key. All changed paths are covered by tests. - No files in the PR require special attention. Outside the PR, `src/auto-reply/reply/dispatch-from-config.ts` has a pre-existing `sessionKey.toLowerCase()` store lookup that may warrant a follow-up. <sub>Last reviewed commit: ade6f06</sub> <!-- greptile_other_comments_section --> <sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs