Problem
A user reports that a Cyrillic command containing ё is matched for some Telegram users and not for others. The report is not reproducible yet.
The current dispatcher compares command tokens with StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase; it does not apply Unicode normalization first. That can distinguish a composed ё (U+0451) from a canonically equivalent decomposed sequence (е + U+0308). It must not be assumed that affected users actually send this sequence: they may instead be entering the distinct letter е.
Why This Needs Investigation Before Design
ё versus decomposed е + diaeresis is a Unicode representation issue. е versus ё is a product-level aliasing decision. A global replacement or normalization of incoming message text would be unsafe: it could alter raw handler input, template route values, and regex captures.
Investigation Plan
- Capture the exact
Message.Text code points from one matching and one non-matching update. Record the Telegram update type and the route declaration, but do not publish user text or personal data.
- Add a deterministic regression test for the observed representation through the generated registration path and direct handler registration path.
- Confirm whether the mismatch is:
- composed versus decomposed canonical Unicode;
- plain
е versus ё spelling;
- a routing-boundary issue unrelated to Unicode normalization.
- Verify the behavior for
Command, CommandTemplate, and CommandRegex separately. Regex capture values must be treated as a distinct contract.
- Only after the observed case is classified, write and review the implementation design.
Design Constraints After Reproduction
- Preserve the raw
ctx.Message.Text exposed to handlers.
- Do not globally replace
е with ё or the reverse.
- If canonical normalization is justified, scope it to the smallest safe command-matching boundary and use
NormalizationForm.FormC consistently for both route literals and compared command input.
- Do not silently normalize regex captures or arbitrary text routes without an explicit, tested contract.
- Keep user-facing spelling aliases explicit, for example separate
[Command("работенка")] and [Command("работёнка")] routes when a bot chooses to support both.
Code Pointers
src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerSelector.cs:321-339 chooses the command route matching path.
src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerSelector.cs:404-474 extracts the prefixed or prefix-less command body.
src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerSelector.cs:500-524 compares exact command tokens with ordinal comparers.
src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerSelector.cs:543-575 passes command templates and regex routes to the pattern matcher.
tests/TeleFlow.ArchitectureTests/TelegramHandlerDispatcherTests.cs:823-870 covers command-template dispatch and prefix-less regressions; extend it with the verified Unicode case.
Acceptance Criteria
- A deterministic test demonstrates the actual reported representation mismatch, or the report is classified as a bot-level aliasing/configuration issue.
- The issue records the verified Unicode sequences and the affected route kinds without retaining user message content.
- A reviewed design is added only after reproduction and explicitly states the behavior for exact commands, templates, regex, raw handler text, and aliases.
- No implementation is merged under this issue before those conditions are met.
Problem
A user reports that a Cyrillic command containing
ёis matched for some Telegram users and not for others. The report is not reproducible yet.The current dispatcher compares command tokens with
StringComparison.OrdinalorStringComparison.OrdinalIgnoreCase; it does not apply Unicode normalization first. That can distinguish a composedё(U+0451) from a canonically equivalent decomposed sequence (е+U+0308). It must not be assumed that affected users actually send this sequence: they may instead be entering the distinct letterе.Why This Needs Investigation Before Design
ёversus decomposedе+ diaeresis is a Unicode representation issue.еversusёis a product-level aliasing decision. A global replacement or normalization of incoming message text would be unsafe: it could alter raw handler input, template route values, and regex captures.Investigation Plan
Message.Textcode points from one matching and one non-matching update. Record the Telegram update type and the route declaration, but do not publish user text or personal data.еversusёspelling;Command,CommandTemplate, andCommandRegexseparately. Regex capture values must be treated as a distinct contract.Design Constraints After Reproduction
ctx.Message.Textexposed to handlers.еwithёor the reverse.NormalizationForm.FormCconsistently for both route literals and compared command input.[Command("работенка")]and[Command("работёнка")]routes when a bot chooses to support both.Code Pointers
src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerSelector.cs:321-339chooses the command route matching path.src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerSelector.cs:404-474extracts the prefixed or prefix-less command body.src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerSelector.cs:500-524compares exact command tokens with ordinal comparers.src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerSelector.cs:543-575passes command templates and regex routes to the pattern matcher.tests/TeleFlow.ArchitectureTests/TelegramHandlerDispatcherTests.cs:823-870covers command-template dispatch and prefix-less regressions; extend it with the verified Unicode case.Acceptance Criteria