Skip to content

Feishu: parse group/dm target prefixes as intended receive IDs#31594

Merged
steipete merged 7 commits intoopenclaw:mainfrom
liuxiaopai-ai:codex/fix-feishu-group-target-receive-id
Mar 2, 2026
Merged

Feishu: parse group/dm target prefixes as intended receive IDs#31594
steipete merged 7 commits intoopenclaw:mainfrom
liuxiaopai-ai:codex/fix-feishu-group-target-receive-id

Conversation

@liuxiaopai-ai
Copy link

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: Feishu send-target parsing did not normalize group: / dm: prefixes, so targets like group:oc_... could be treated as user_id and fail send APIs.
  • Why it matters: sessions_send / announce flows for Feishu group sessions can fail with invalid {user_id} errors when the target is actually a chat id.
  • What changed: extended Feishu target normalization and ID-shape detection to support group: and dm: prefixes, and aligned looksLikeFeishuId with the same forms.
  • What did NOT change (scope boundary): no message payload format changes, no Feishu client/API contract changes, no routing policy changes.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • Feishu targets with group: / dm: prefixes now resolve to the intended receive id type instead of defaulting to user_id.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local dev checkout
  • Model/provider: N/A
  • Integration/channel (if any): Feishu extension send target parsing
  • Relevant config (redacted): default

Steps

  1. Call Feishu target normalization with feishu:group:oc_123 and lark:dm:ou_123.
  2. Resolve receive id types for prefixed targets.
  3. Validate target-shape detection for prefixed forms.

Expected

  • Group targets resolve to chat_id and DM targets normalize to user/open id forms correctly.

Actual

  • Parsing now strips group:/dm: prefixes and resolves the correct receive id type.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: new normalization and receive-id-type tests for group/dm prefixes.
  • Edge cases checked: provider-prefixed (feishu: / lark:) + prefixed target combinations.
  • What you did not verify: live Feishu API send from a real group chat.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert commit 8b2d8a1c4.
  • Files/config to restore: extensions/feishu/src/targets.ts, extensions/feishu/src/targets.test.ts.
  • Known bad symptoms reviewers should watch for: unexpected Feishu target id-type inference for legacy unprefixed IDs.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: broader prefix matching could alter interpretation of malformed custom targets.
    • Mitigation: normalization only strips explicit known prefixes and keeps existing prefix-based id rules for unprefixed IDs.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 2, 2026

Greptile Summary

Extended Feishu target parsing to recognize group: and dm: prefixes, preventing targets like group:oc_123 from being misinterpreted as user_id and causing send API failures. The changes make resolveReceiveIdType more robust by handling both normalized and non-normalized IDs, while maintaining backward compatibility with unprefixed ID detection.

  • Added group: and dm: prefix stripping in normalizeFeishuTarget
  • Enhanced resolveReceiveIdType to detect prefixed targets before falling back to ID-shape detection
  • Updated looksLikeFeishuId regex to recognize the new prefixes
  • Minimal test coverage added (missing dm: prefix tests for resolveReceiveIdType)

Confidence Score: 4/5

  • Safe to merge with minor test coverage gap
  • The implementation is correct and follows existing patterns consistently. The logic handles both prefixed and unprefixed IDs defensively. Only concern is incomplete test coverage for dm: prefix in resolveReceiveIdType, though the implementation itself is sound.
  • No files require special attention

Last reviewed commit: 8b2d8a1

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +17 to +19
it("treats explicit group targets as chat_id", () => {
expect(resolveReceiveIdType("group:oc_123")).toBe("chat_id");
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add test case for dm: prefix handling (e.g., dm:ou_123open_id, dm:u_123user_id)

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/feishu/src/targets.test.ts
Line: 17-19

Comment:
add test case for `dm:` prefix handling (e.g., `dm:ou_123``open_id`, `dm:u_123``user_id`)

How can I resolve this? If you propose a fix, please make it concise.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3bc36cef7d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +72 to +74
if (lowered.startsWith("user:") || lowered.startsWith("dm:")) {
const normalized = trimmed.replace(/^(user|dm):/i, "").trim();
return normalized.startsWith(OPEN_ID_PREFIX) ? "open_id" : "user_id";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route dm-prefixed oc_ targets as chat_id

The new dm: branch forces non-ou_ IDs to user_id, so dm:oc_... now resolves to receive_id_type=user_id even though oc_ is a chat ID format (the outbound routing code explicitly documents dm:oc_xxx as a valid direct-chat target). In flows that now accept dm: prefixes, this causes Feishu sends to fail (or target the wrong principal) because the request uses a chat ID with the user-id receive type instead of chat_id.

Useful? React with 👍 / 👎.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3739ba3428

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +72 to +74
if (lowered.startsWith("user:") || lowered.startsWith("dm:")) {
const normalized = trimmed.replace(/^(user|dm):/i, "").trim();
return normalized.startsWith(OPEN_ID_PREFIX) ? "open_id" : "user_id";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route dm:oc_ targets with chat_id receive type

The dm: branch currently maps every non-ou_ value to user_id, so dm:oc_... is sent as receive_id_type=user_id even though oc_ is a Feishu chat identifier. This breaks explicit direct-chat targets that use chat IDs (the send call will use an incompatible receive type and can fail). Fresh evidence: src/infra/outbound/outbound-session.ts documents dm:oc_xxx as a valid explicit DM form for Feishu chat IDs, so this path is expected to work.

Useful? React with 👍 / 👎.

@steipete steipete force-pushed the codex/fix-feishu-group-target-receive-id branch from 3739ba3 to 0a05c16 Compare March 2, 2026 14:28
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a05c16d10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +72 to +74
if (lowered.startsWith("user:") || lowered.startsWith("dm:")) {
const normalized = trimmed.replace(/^(user|dm):/i, "").trim();
return normalized.startsWith(OPEN_ID_PREFIX) ? "open_id" : "user_id";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route dm:oc_ targets with chat_id receive type

resolveReceiveIdType now sends every dm: target that is not ou_... as user_id, so dm:oc_... gets receive_id_type=user_id even though oc_ is a Feishu chat ID; this makes explicit DM chat targets fail or hit the wrong principal when resolveFeishuSendTarget forwards the type to send APIs. Fresh evidence: src/infra/outbound/outbound-session.ts and src/infra/outbound/outbound.test.ts explicitly treat dm:oc_xxx as a valid direct-chat form, so this path is expected to work with chat IDs.

Useful? React with 👍 / 👎.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5cfd3f2da2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
if (lowered.startsWith("user:") || lowered.startsWith("dm:")) {
const normalized = trimmed.replace(/^(user|dm):/i, "").trim();
return normalized.startsWith(OPEN_ID_PREFIX) ? "open_id" : "user_id";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route dm:oc_ targets with chat_id receive type

resolveReceiveIdType currently treats every dm: target that is not ou_... as user_id, so dm:oc_... is sent with receive_id_type=user_id even though oc_ is a Feishu chat ID. This breaks explicit DM chat targets in outbound flows that intentionally use dm:oc_xxx (see the explicit support in src/infra/outbound/outbound-session.ts and tests in src/infra/outbound/outbound.test.ts), because the send API receives a chat identifier under the wrong receive-id type.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle bot added the app: android App: android label Mar 2, 2026
Linux2010 pushed a commit to Linux2010/openclaw that referenced this pull request Mar 2, 2026
Linux2010 pushed a commit to Linux2010/openclaw that referenced this pull request Mar 2, 2026
Linux2010 pushed a commit to Linux2010/openclaw that referenced this pull request Mar 2, 2026
Linux2010 pushed a commit to Linux2010/openclaw that referenced this pull request Mar 2, 2026
execute008 pushed a commit to execute008/openclaw that referenced this pull request Mar 2, 2026
execute008 pushed a commit to execute008/openclaw that referenced this pull request Mar 2, 2026
execute008 pushed a commit to execute008/openclaw that referenced this pull request Mar 2, 2026
execute008 pushed a commit to execute008/openclaw that referenced this pull request Mar 2, 2026
dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
OWALabuy pushed a commit to kcinzgg/openclaw that referenced this pull request Mar 4, 2026
OWALabuy pushed a commit to kcinzgg/openclaw that referenced this pull request Mar 4, 2026
OWALabuy pushed a commit to kcinzgg/openclaw that referenced this pull request Mar 4, 2026
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: android App: android channel: feishu Channel integration: feishu channel: slack Channel integration: slack size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: sessions_send announce fails in Feishu group: passes group ID as user_id

2 participants