Skip to content

fix(feishu): group message auth, reply routing, and i18n key regex - #3

Merged
LinekForge merged 1 commit into
LinekForge:mainfrom
wangviola7:fix/feishu-group-message-auth
Apr 20, 2026
Merged

fix(feishu): group message auth, reply routing, and i18n key regex#3
LinekForge merged 1 commit into
LinekForge:mainfrom
wangviola7:fix/feishu-group-message-auth

Conversation

@wangviola7

Copy link
Copy Markdown
Contributor

Summary

  • Group authorization: oc_ chat_id in allowlist now authorizes all group members — previously, any group member not individually added to the allowlist was blocked with a 403 error even if the group itself was allowed
  • Group reply routing: Bot replies now go to the group thread (oc_ chat_id) instead of the sender's private chat
  • Image/file key regex: Added support for Chinese compact-mode prefixes [图片: img_v3_xxx] and [文件: file_xxx] alongside existing English patterns

Root cause

isAllowed(senderId) only checked the sender's personal ou_ id. Group messages have an oc_ chat_id that was already in the allowlist, but the check never looked at it. Group members were blocked unless each one was individually added.

Test plan

  • Add a group oc_ id to state/feishu/allowlist.json
  • Send a message from a group member whose personal ou_ id is NOT in the allowlist
  • Verify message is received and bot reply appears in the group thread
  • Send an image in the group — verify img_v3_xxx key is parsed correctly

🤖 Generated with Claude Code

Three related fixes for Feishu group chat support:

1. **Group authorization**: Allow `oc_` chat_id in allowlist to authorize
   all group members, so group members don't need individual allowlist entries.
   Before: only `senderId` was checked → group members blocked
   After: if `chatId.startsWith("oc_")` and chatId is allowed, pass through

2. **Group reply routing**: Route replies to group chat_id (`oc_`) instead
   of private `senderId`, so bot replies appear in the group thread.
   Also include `chat_id` in the raw message for downstream use.

3. **Image/file key regex**: Support Chinese compact-mode prefixes
   `[图片: img_v3_xxx]` and `[文件: file_xxx]` in addition to English.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LinekForge

Copy link
Copy Markdown
Owner

Approving workflow — will merge after CI passes. Thanks for the clean PR!

@LinekForge
LinekForge merged commit 793944d into LinekForge:main Apr 20, 2026
2 checks passed
@LinekForge

Copy link
Copy Markdown
Owner

Merged in 793944d. Thanks for the clean, tightly-scoped fix! 🙏

The three changes hang together naturally — auth / routing / i18n for the same code path. Separating by oc_ prefix is the right abstraction, and group-level allowlist becoming first-class is a real unlock for team deployments.

CI passed on both hub-server and hub-client typecheck.

Maintainer follow-up: we'll add a docs note clarifying that adding a group oc_ id authorizes all current and future group members — good default for trusted teams, but worth being explicit in the allowlist docs.

Also — really appreciated the detailed PR description with root cause analysis. Makes review fast.

Looking forward to more from you 👋

— Forge (maintainer)

LinekForge added a commit that referenced this pull request Apr 20, 2026
Credit external contributors from PR #1 / #2 / #3.

Co-authored-by: Forge <270260515+ForgeLinek@users.noreply.github.com>
LinekForge added a commit that referenced this pull request Apr 20, 2026
Following up on PR #3 merge: adding a group oc_ id to the allowlist
authorizes ALL current and future group members — not just the people
you currently know. This should be explicit in the docs so users can
make an informed trade-off between convenience and blast radius.

Old copy said "allowlist stores ou_ user open_id" — stale after #3
made oc_ group chat_id a first-class allowlist entry.

Co-authored-by: Forge <270260515+ForgeLinek@users.noreply.github.com>
@LinekForge

Copy link
Copy Markdown
Owner

Follow-up: the docs note on group allowlist broadcast semantics landed in 3eb0087. 配置.md 里的飞书 allowlist 段现在明确说了 oc_ 群授权 = 广播所有现在和未来的群成员 + 适用场景建议。

— Forge (maintainer)

LinekForge added a commit that referenced this pull request May 14, 2026
… engine path guard

Kai 安全全仓审核修复(P1 #1-#2 + P2 #3-#4):

- Native App: curl shell-out 全部改 URLSession,token 不再进 argv
- WeChat: allowlist 检查移到 extractContent 之前,未授权媒体不下载
- formatUnauthorizedNotice: displayName/senderId 走 sanitize 净化
- fh engine remove: 拒绝路径穿越(/、\、..),只匹配 engine.d 内 basename
- channel-plugin-guide 文档更新、echo.ts 示例更新
- 新增测试:未授权媒体不下载、notice 注入净化、路径穿越拒绝

Co-authored-by: Kai <kai@codex.local>
Co-authored-by: Forge <270260515+ForgeLinek@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LinekForge added a commit that referenced this pull request May 14, 2026
…idence dedup, docs sync

Kai 全仓风险复审修复(P2 #1-#3 + P3 #4-#7):

- 安全事件告警前同步 flush,CLI 立即可查
- hub-client 区分 /health liveness 和 /status auth,401 不再误判为 Hub 未运行
- Native/Dashboard 通道选择:显式"全部通道"选项,零选择禁用
- 删除 Dashboard 未接通的 sendFile bridge(v1 = 发路径文本)
- stripMarkdown 移到可导出 helper,测试真实函数
- evidence 空 updateId 生成唯一 fallback,不再去重合并
- /status 暴露通道 stoppedReason,WeChat auth 判定改用稳定枚举
- SECURITY.md + 架构.md 同步更新

Co-authored-by: Kai <kai@codex.local>
Co-authored-by: Forge <270260515+ForgeLinek@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants