fix(botsfw)!: scope bot settings lookup by platform#81
Merged
Conversation
GetBotContext accepted a platformID parameter and never read it. It resolved purely by bot ID or code, so the platform a webhook arrived on had no bearing on which bot's settings came back. With Telegram as the only framework-side platform this was invisible. bots-fw-whatsapp now exists, which is exactly what makes it reachable: a WhatsApp webhook could resolve a Telegram bot's settings - including its Token and WebhookSecretToken - whenever the two shared an ID or code. Note bots-fw-telegram's handler passes PlatformID and then verifies its secret against whatever settings came back. Two bugs, one root cause: bot codes were treated as globally unique when they are only unique per platform. 1. GetBotContext is now platform-scoped, via BotSettingsBy.findByPlatform. A bot on another platform returns ErrUnknownBot rather than being silently substituted. A blank platformID is rejected. 2. NewBotSettingsBy panicked on duplicate codes regardless of platform, so the same product could not be registered on two platforms - "debtus" on Telegram and "debtus" on WhatsApp are different bots with different tokens. It now panics only on a duplicate WITHIN a platform. This is what made a second platform registrable at all. Added BotSettingsBy.ByPlatformAndCode / ByPlatformAndID. ByCode and ByID are kept populated (first-wins) for compatibility but are now deprecated: they are ambiguous across platforms by construction. The legacy fallback in findByPlatform still checks Platform, so it cannot reintroduce the leak it exists to be compatible with. The test suite had ENCODED the bug: three separate fixtures hand-built a BotSettings with no Platform and passed only because platformID was ignored. All three are fixed rather than worked around. NewBotSettings has always panicked on an empty platform, so those fixtures were malformed - they bypassed the constructor. BREAKING: - A BotSettings with an empty Platform now panics in NewBotSettingsBy. Previously accepted, but such a bot can never be resolved by the platform-scoped GetBotContext, so it was silently unreachable. Failing at registration beats failing at 3am. - GetBotContext returns ErrUnknownBot for a bot that exists on a different platform. That is the fix, not a regression. Verified: bots-fw-telegram builds and its tests pass against this branch (temporary local replace, reverted; that repo is untouched). Full suite green, gofmt + vet + golangci-lint clean. Background: spec/research/bots-fw-platform-neutrality-gap-analysis.md "Seam bug" in bots-go-framework/backstage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
GetBotContextaccepted aplatformIDparameter and never read it. It resolved purely by bot ID or code, so the platform a webhook arrived on had no bearing on which bot's settings came back.With Telegram as the only framework-side platform, this was invisible.
bots-fw-whatsappnow exists, which is precisely what makes it reachable: a WhatsApp webhook could resolve a Telegram bot's settings — including itsTokenandWebhookSecretToken— whenever the two shared an ID or code.Worth noting
bots-fw-telegram's handler passesPlatformIDand then verifies its secret against whatever settings came back.Two bugs, one root cause
Bot codes were treated as globally unique when they are only unique per platform.
1. The leak.
GetBotContextis now platform-scoped viaBotSettingsBy.findByPlatform. A bot on another platform returnsErrUnknownBotrather than being silently substituted. A blankplatformIDis rejected.2. The blocker.
NewBotSettingsBypanicked on duplicate codes regardless of platform — so the same product could not be registered on two platforms at all.debtuson Telegram anddebtuson WhatsApp are different bots with different tokens. It now panics only on a duplicate within a platform.The second one isn't cosmetic: without it, Debtus-on-WhatsApp cannot be registered alongside Debtus-on-Telegram.
Compatibility
Added
ByPlatformAndCode/ByPlatformAndID.ByCodeandByIDstay populated (first-wins) but are deprecated — they're ambiguous across platforms by construction. The legacy fallback infindByPlatformstill checksPlatform, so it cannot reintroduce the leak it exists to be compatible with.Verified:
bots-fw-telegrambuilds and its tests pass against this branch (temporary localreplace, reverted — that repo is untouched).The test suite had encoded the bug
Three separate fixtures hand-built a
BotSettingswith noPlatformand passed only becauseplatformIDwas ignored:botsfw/bot_context_test.go—&BotSettings{Code: "mybot"}, then asked for it as"telegram"botswebhook/settings_test.go—{Profile, Code, ID}, no platformAll three are fixed rather than worked around.
NewBotSettingshas always panicked on an empty platform, so those fixtures were malformed — they bypassed the constructor.BotSettingswith an emptyPlatformnow panics inNewBotSettingsBy. Previously accepted — but such a bot can never be resolved by the platform-scopedGetBotContext, so it was silently unreachable. Failing at registration beats failing at 3am.GetBotContextreturnsErrUnknownBotfor a bot that exists on a different platform. That's the fix, not a regression.Tests
New:
TestGetBotContext_isPlatformScoped(the security regression test — pins that a WhatsApp lookup gets WhatsApp's token, never Telegram's),TestGetBotContext_legacyFlatMapsStillCheckPlatform,TestNewBotSettingsBy_duplicateCodeAcrossPlatforms.Full suite green;
gofmt,go vet,golangci-lintclean.Background: platform-neutrality gap analysis, "Seam bug" section.
🤖 Generated with Claude Code
https://claude.ai/code/session_01SE2shvgkXuR8fAzzMui4zN