makecindy / makecindy/cindy

[Bug] 修复飞书直通接口的分页约束与角色权限适配

Open
#141 4 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
2.7k
Forks
395
Avg merge
21h 48m
Merged PRs (30d)
776

Description

## 问题描述

XD Feishu 插件生成的部分 OpenAPI 直通工具与飞书实际接口契约不一致,导致插件向模型暴露了会被服务端拒绝的参数,且新版多维表格角色接口在当前 OAuth 授权下不可用。

### 1. `calendar.v4.calendar.list` 缩小分页后失败

- 插件将 `page_size` 描述为任意 `num`。
- 飞书官方要求 `page_size` 为整数,取值范围为 `50–1000`。
- `page_size: 20` 会被插件接受并发送到服务端,随后返回 `field validation failed`。

### 2. `calendar.v4.calendarEvent.list` 的合法参数组合无法被可靠使用

- 该接口同样缺失 `page_size` 的 `50–1000` 约束。
- `page_size: 1` 会先被服务端拒绝,掩盖 `start_time`、`end_time` 等其他参数的验证结果。
- 当前源码实际会把 `page_size`、`start_time`、`end_time` 正确序列化到 URL query,因此问题不是 query 未转发,而是插件暴露的参数契约不完整。

### 3. 多维表格角色列表存在废弃接口和 OAuth scope 错配

- 插件仍暴露已废弃的 `bitable.v1.appRole.list`。
- 推荐接口 `base.v2.appRole.list` 已经暴露,但插件 OAuth scopes 缺少该接口要求的 `base:role:read`,导致已连接账号无法调用新版接口。
- v1 返回 `OperationTypeError` 时,飞书官方含义是多维表格未启用或不支持高级权限,不能据此判断 v1 服务端已经停止提供服务;但官方已经明确推荐迁移到 v2。

## 根因

1. `packages/lizi-mcps/src/feishu/mcp/generated/zod/calendar_v4.ts` 中两个接口的 `page_size` 仅声明为 `z.number()`,没有整数、最小值和最大值约束。
2. `scripts/gen-feishu-ghost-ops.mts` 将 Zod/JSON Schema 压缩成参数说明时只保留字段类型,没有保留 `minimum`、`maximum` 等校验信息;生成的 `main.js` 也不会在出网前校验这些约束。
3. 直通接口生成策略没有过滤或降级标记已有替代接口的 Deprecated 工具。
4. `apps/desktop/resources/builtin-ghosts/xd-feishu/ghost.json` 申请了 `bitable:app`,但没有申请新版角色接口唯一要求的 `base:role:read`。

## 期望行为

- 两个日历接口明确展示并校验 `page_size` 为 `50–1000` 的整数。
- 无效参数在插件本地返回可读错误,不向飞书发送必然失败的请求。
- `calendar.v4.calendarEvent.list` 支持 `start_time`、`end_time` 与合法 `page_size` 的组合。
- 角色列表默认引导使用 `base.v2.appRole.list`。
- OAuth 申请 `base:role:read`,并为已连接账号提供明确的补授权路径。
- 不再把废弃 v1 接口作为普通可选接口展示;如果因兼容旧高级权限仍需保留,应明确标记适用范围和 v2 替代接口。

## 验收标准

- [ ] `page_size: 50` 和 `page_size: 1000` 可正常发起请求。
- [ ] `page_size: 1`、`page_size: 20`、`page_size: "20"` 在本地被拒绝且不出网。
- [ ] 回归测试断言两个日历接口生成的 URL 包含完整 query。
- [ ] 使用合法 `page_size` 时,`calendar.v4.calendarEvent.list` 的 `start_time`、`end_time` 可以正常传递。
- [ ] `base.v2.appRole.list` 在补授权后可正常调用。
- [ ] `list_tools` 优先展示 v2,且不会误导模型调用废弃 v1。
- [ ] 增加参数约束、Deprecated 接口处理和 OAuth scope 的回归测试。

## 实现建议

### Commit 1:补齐直通接口参数约束与本地校验

- 改动:完善 vendored schema 的同步/覆盖机制和 `scripts/gen-feishu-ghost-ops.mts`,让生成结果保留整数、最小值、最大值等约束;在 `gop` 出网前执行确定性校验,并重新生成 `xd-feishu/main.js`。
- 验证:扩展 `builtinFeishuGhost.test.ts` 和 `genToolsDispatch.test.ts`,覆盖合法边界值、非法数字、字符串类型、query 序列化以及非法参数不出网。

### Commit 2:迁移角色列表到 v2 并补齐授权

- 改动:在 `ghost.json` 增加 `base:role:read`,调整生成过滤/展示策略,优先使用 `base.v2.appRole.list`,并处理已有连接账号的补授权提示或检测。
- 验证:更新 manifest scopes 契约测试和直通工具目录测试;使用已开启高级权限的多维表格完成一次 v2 角色列表实测。

## 参考文档

- [查询日历列表](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/calendar-v4/calendar/list)
- [获取日程列表](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/calendar-v4/calendar-event/list)
- [列出自定义角色(旧版)](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/bitable-v1/app-role/list)
- [列出自定义角色(新版)](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/bitable-v1/advanced-permission/base-v2/app-role/list)

Contributor guide

Open the contributing guide

Research direction

Start with packages/lizi-mcps/src/feishu/mcp/generated/zod/calendar_v4.ts, scripts/gen-feishu-ghost-ops.mts, and apps/desktop/resources/builtin-ghosts/xd-feishu/ghost.json to trace schema constraints, tool generation, and OAuth scopes. Then read builtinFeishuGhost.test.ts and genToolsDispatch.test.ts and run the related tests. Done means local validation rejects invalid pagination without a request, valid query parameters survive, v2 role listing has the required scope, and deprecated v1 handling is covered by regression tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, authentication, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.