fix(runtime): route DingTalk 1:1 replies by stamped conversation type - #5116
Open
ggbdpq wants to merge 1 commit into
Open
fix(runtime): route DingTalk 1:1 replies by stamped conversation type#5116ggbdpq wants to merge 1 commit into
ggbdpq wants to merge 1 commit into
Conversation
Real DingTalk 1:1 and group conversationIds share the same `cid`
prefix, so `pickDingTalkSendRoute`'s `startsWith('cid')` guess routed
every direct reply to the group endpoint, which rejects it with a
misleading `resource.not.found`. The 1:1 endpoint also addresses by
`senderStaffId`, which the payload parser dropped — so even with the
route fixed no direct reply could be delivered (apache#5111).
Follow the QQ bridge convention: `dingTalkPayloadToEvent` stamps the
chatId from the authoritative `conversationType` (`group:` for groups,
`oto:` + `senderStaffId` for 1:1, captured from the payload), and
`pickDingTalkSendRoute` decodes the stamp instead of guessing the id
shape, failing closed on unstamped ids. A 1:1 message without
`senderStaffId` still arrives (its bare conversationId stays unstamped)
but cannot be replied to rather than sending a request destined to
fail; previously stored conversations share that fate either way, and
new messages pick up the stamp.
Tests now use realistic identifier shapes — both conversation kinds
carry `cid…=` ids — so a prefix-guessing regression fails the suite,
where the old fixtures (`user-99`) encoded the same wrong assumption
as the implementation.
End-to-end delivery against a live DingTalk Stream connection was not
run locally; routing and payload mapping are pinned by unit tests at
the bridge's public helpers. Group replies were not exercised in the
report either; the stamped group path sends the same body to the same
endpoint as before.
Fixes apache#5111
Generated-by: GLM-5.3-Flash (ZCode)
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.
Summary
Fixes #5111. Real DingTalk 1:1 and group conversationIds share the same
cidprefix, so the send router'sstartsWith('cid')guess sent every direct reply to the group endpoint — which rejects it with a misleadingresource.not.found. The 1:1 endpoint additionally addresses bysenderStaffId, which the payload parser dropped, so no direct reply could ever be delivered even with the route fixed.The fix follows the existing QQ bridge convention (
pickQQSendRouteroutes on receive-side-stamped prefixes):DingTalkBotMessagePayloadnow capturessenderStaffId.dingTalkPayloadToEventstamps the chatId from the authoritativeconversationType—group:<conversationId>for groups,oto:<senderStaffId>for 1:1 — instead of storing the bare conversation id.pickDingTalkSendRoutedecodes the stamp and fails closed (null) on unstamped ids rather than guessing. A 1:1 message received withoutsenderStaffIdstill arrives (bare conversationId kept as the session key) but the send side declines instead of firing a request destined to fail. Previously stored conversations could not be replied to either way (old path 400s), and new inbound messages pick up the stamp.Verification
cid…=shapes; they fail against the old prefix guess (the old fixturesuser-99/cidp-abcencoded the same wrong assumption as the implementation)node --test dist/bots/__tests__/*.test.js→ 102/102 (dingtalk-bridge 9/9, including: bare real-shapedcid…=ids route tonull, stamped ids route to their own endpoints,senderStaffIdis captured)npm --workspace @maka/runtime run buildexit 0biome formatclean on touched files; ASF headers intactNot verified locally: end-to-end delivery against a live DingTalk Stream connection (the issue reporter's live experiment pins the API behavior: conversationId → 400 on the group endpoint, senderId → 400
staffId.notExisted, senderStaffId → delivered). Group replies were not exercised in the report either; the stamped group path sends the same body to the same endpoint as before.AI use
Implemented with ZCode (GLM-5.3-Flash): followed the issue's three-way experiment and suggested fix shape, mirrored the QQ bridge stamping convention, rewrote the test fixtures to realistic identifier shapes per the acceptance criteria, and carried the
Generated-bytrailer in the commit.Checklist
senderStaffIdcaptured from the callback payloadsenderStaffIdis absent (fail-closed send, event still delivered)