@lark-apaas/coding-steering 0.1.61 → 0.1.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/coding-steering",
3
- "version": "0.1.61",
3
+ "version": "0.1.62",
4
4
  "description": "Stack-specific steering content for miaoda-coding templates",
5
5
  "type": "module",
6
6
  "files": [
@@ -88,7 +88,7 @@ interface UserSimpleDTO {
88
88
  larkUserID?: number; // 飞书内部数字 ID,禁用(飞书 API 不认)
89
89
  department?: DepartmentSimpleDTO;
90
90
  employeeID?: string; // 飞书企业内 user_id,调飞书开放平台 API 用它
91
- larkID?: string; // 飞书用户全局唯一 ID(larkUserID 别名),禁用
91
+ larkID?: string; // 飞书用户全局唯一 ID(larkUserID 别名),禁传飞书 API;转妙搭 userId 用 AuthNPaasService.getBatchMiaodaUserIdsByLarkIds
92
92
  miaodaUserID?: string; // 妙搭用户 ID(userID 别名)
93
93
  }
94
94
 
@@ -198,7 +198,7 @@ interface SearchUserEntity {
198
198
  email?: string;
199
199
  userStatus?: number;
200
200
  employeeID?: string; // 飞书企业内 user_id,调飞书开放平台 API 用它
201
- larkID?: string; // larkUserID 别名,禁用
201
+ larkID?: string; // larkUserID 别名,禁传飞书 API(转妙搭 userId 见上)
202
202
  miaodaUserID?: string; // userID 别名
203
203
  }
204
204
 
@@ -60,11 +60,11 @@ match-template-name: nestjs-react-fullstack
60
60
 
61
61
  | 兼容字段 | 标准替代 | 为什么禁用 |
62
62
  |---|---|---|
63
- | **lark_id** | employee_id | 纯数字内部 ID,飞书开放平台 API 无法识别,传入报错或返回空 |
63
+ | **lark_id** | employee_id | 纯数字 LarkID(飞书全局 ID),飞书开放平台 API 无法识别,传入报错或返回空。**唯一例外**:要把 LarkID 转成妙搭 userId 时,用 `AuthNPaasService.getBatchMiaodaUserIdsByLarkIds`(见 `user-identity`) |
64
64
  | **lark_department_id** | open_department_id | 纯数字内部 ID,飞书 API 只接受 od- 格式 |
65
65
  | **lark_chat_id** | open_chat_id | 纯数字内部 ID,飞书 IM API 只接受 oc_ 格式 |
66
66
 
67
- > 搜人返回里同时有 `lark_id` 和 `employee_id` 时,**必须取 `employee_id`**;用户提到 lark_id 时主动纠正。
67
+ > 搜人返回里同时有 `lark_id` 和 `employee_id` 时,调飞书 API **必须取 `employee_id`**;用户提到 lark_id 时先问用途:调飞书 API → 纠正为 employee_id;要转妙搭 userId(或反向)→ 按 `user-identity` 用 `AuthNPaasService` 的 LarkID 方法。
68
68
 
69
69
  ### 1.5 废弃名称映射
70
70
 
@@ -139,7 +139,7 @@ match-template-name: nestjs-react-fullstack
139
139
 
140
140
  ### ID 转换接口
141
141
 
142
- 外部用户 / 取 open_id·union_id 时用 `id_convert`,详见 [`feishu` skill › references/id-convert.md](../../../feishu/references/id-convert.md)。
142
+ 外部用户 / 取 open_id·union_id:模板内用 `AuthNPaasService.getBatchOpenIds` / `getBatchUnionIds`(反向 `getBatchMiaodaUserIdsByOpenIds` / `ByUnionIds`,见 `user-identity`);模板外才用 [`feishu` › id-convert.md](../../../feishu/references/id-convert.md)。
143
143
 
144
144
  ---
145
145
 
@@ -160,7 +160,7 @@ match-template-name: nestjs-react-fullstack
160
160
 
161
161
  | 字段 | 获取方式 |
162
162
  |---|---|
163
- | open_id / union_id | id_convert 接口 + 开放平台应用凭证(见 feishu › id-convert.md) |
163
+ | open_id / union_id | 模板内 `AuthNPaasService.getBatchOpenIds` / `getBatchUnionIds`(`feishuClientId` 传 open_id 所属飞书应用 App ID,见 `user-identity`);模板外 id_convert + 开放平台应用凭证 |
164
164
 
165
165
  ### Level 4 — 搜人拿不到的字段(需开放平台通讯录 API + 字段权限)
166
166
 
@@ -197,7 +197,7 @@ match-template-name: nestjs-react-fullstack
197
197
  |---|---|
198
198
  | 工号 / 手机号 / 职位 / 性别 / 直属上级 | 搜人带 **needFullFields=true**(Level 2,无需开平,follow admin 权限) |
199
199
  | 在职状态 / 入职时间 / 自定义字段 | 引导开平应用 → 通讯录 API(场景 B,Level 4) |
200
- | open_id / union_id | 引导配置应用 → id_convert(场景 A,Level 3) |
200
+ | open_id / union_id | 模板内 `AuthNPaasService`(Level 3),无需引导配置开平应用 |
201
201
  | 部门信息 | 直接取 open_department_id |
202
202
  | 发消息给某人 | 取 miaoda_user_id 传插件 |
203
203
  | 批量同步部门/全员、定时同步 | 引导配置应用 → 通讯录 API(场景 A) |
@@ -276,7 +276,7 @@ export class TicketService {
276
276
  ---
277
277
 
278
278
  ## 七、禁止行为
279
- 1. **禁用兼容字段**:任何调用不得用 lark_id / lark_department_id / lark_chat_id
279
+ 1. **禁用兼容字段**:调飞书 API / 插件不得用 lark_id / lark_department_id / lark_chat_id(LarkID ↔ 妙搭 userId 互转除外,见 `user-identity`)
280
280
  2. **禁止混用废弃名**:不得用 userID / suda_user_id / larkUserId 等旧名
281
281
  3. **禁止给飞书内置插件传 employee_id**:插件入参必须是 miaoda_user_id
282
282
  4. **禁止让用户手动做 ID 转换**:Agent 自动判断并执行
@@ -290,7 +290,7 @@ export class TicketService {
290
290
  |---|---|
291
291
  | 用户说"获取 user_id" | 追问:妙搭 miaoda_user_id 还是飞书 employee_id? |
292
292
  | 用户说要 `lark_user_id` / "飞书用户ID" / "飞书 ID" | 多数指**可用的飞书 user_id = `employee_id`**。搜人/选择器结果里**没有**叫 lark_user_id 的字段、可用的就是 `employee_id`,**别返回禁用的纯数字 `lark_id`**;当前登录用户场景取 `useCurrentUserProfile().lark_user_id`(== employee_id)。歧义时确认"是调飞书 API 用吗",是则一律 employee_id |
293
- | 用户用了 lark_id | 纠正:"lark_id 是禁用兼容字段,飞书 API 不认,请用 employee_id(搜人已默认返回)" |
293
+ | 用户用了 lark_id | 若是传飞书 API:纠正"lark_id 飞书 API 不认,请用 employee_id(搜人已默认返回)";若是要转成妙搭 userId:用 `AuthNPaasService.getBatchMiaodaUserIdsByLarkIds`(见 `user-identity`) |
294
294
  | 用户用了 lark_department_id | 纠正:"请用 open_department_id(od- 格式)" |
295
295
  | 用户用了 lark_chat_id | 纠正:"请用 open_chat_id(oc_ 格式)" |
296
296
  | 外部用户请求 employee_id | 说明外部用户无 employee_id,建议 open_id(需 id_convert) |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: user-identity
3
- description: "当前登录用户「我是谁」+ 妙搭 ↔ 飞书 ID 转换。Use when getting current user info/profile, displaying user name/avatar/email, converting miaoda userId ↔ lark_user_id (both directions via AuthNPaasService ID-conversion methods), or reading req.userContext fields (userId/roles/tenantId): useCurrentUserProfile, FeishuID conversion. ⚠️ 按 userId 查他人姓名/头像请用 contacts-service 第六节。触发词:用户身份, 用户信息, 用户资料, 当前用户, userProfile, useCurrentUserProfile, 飞书ID, FeishuID, 飞书用户ID, lark_user_id, 用户ID转换, AuthNPaasService ID 转换, getCurrentUserLarkUserId, getBatchLarkUserIds, getBatchMiaodaUserIds, 飞书ID转妙搭, employee_id 转 userId, 用户上下文, userContext, userContext.roles, 用户角色, 当前用户角色, 获取请求者角色, 展示当前用户, 我是谁"
3
+ description: "当前登录用户「我是谁」+ 妙搭 ↔ 飞书 ID 转换。Use when getting current user info/profile, displaying user name/avatar/email, converting miaoda userId ↔ lark_user_id / LarkID / open_id / union_id (both directions via AuthNPaasService ID-conversion methods), or reading req.userContext fields (userId/roles/tenantId): useCurrentUserProfile, FeishuID conversion. ⚠️ 按 userId 查他人姓名/头像请用 contacts-service 第六节。触发词:用户身份, 用户信息, 用户资料, 当前用户, userProfile, useCurrentUserProfile, 飞书ID, FeishuID, 飞书用户ID, lark_user_id, 用户ID转换, AuthNPaasService ID 转换, getCurrentUserLarkUserId, getBatchLarkUserIds, getBatchMiaodaUserIds, 飞书ID转妙搭, employee_id 转 userId, LarkID, lark_id, larkID, LarkID转妙搭用户ID, lark_id 转 userId, getBatchLarkIds, getBatchMiaodaUserIdsByLarkIds, open_id 转妙搭, union_id 转妙搭, 妙搭ID转open_id, getBatchOpenIds, getBatchUnionIds, getBatchMiaodaUserIdsByOpenIds, getBatchMiaodaUserIdsByUnionIds, 用户上下文, userContext, userContext.roles, 用户角色, 当前用户角色, 获取请求者角色, 展示当前用户, 我是谁"
4
4
  steering: true
5
5
  steering-topic: user_identity
6
6
  match-template-name: nestjs-react-fullstack
@@ -18,7 +18,7 @@ match-template-name: nestjs-react-fullstack
18
18
 
19
19
  ## 零、ID 体系警告(CRITICAL)
20
20
 
21
- ⚠️ "user_id" 这个字面在本项目里指**三个不同的东西**,必须先区分清楚再写代码:
21
+ ⚠️ "user_id" 这个字面在本项目里指**多个不同的东西**,必须先区分清楚再写代码:
22
22
 
23
23
  **作为身份 ID 字段名(指代具体某个用户的 ID 值):**
24
24
 
@@ -26,6 +26,7 @@ match-template-name: nestjs-react-fullstack
26
26
  |---|---|---|
27
27
  | `useCurrentUserProfile().user_id`、`req.userContext.userId` | 妙搭用户 ID(纯数字字符串) | 妙搭 |
28
28
  | `useCurrentUserProfile().lark_user_id`、`AuthNPaasService.getCurrentUserLarkUserId()` 返回值 | 飞书 user_id(== `employee_id`,企业内身份,**无固定前缀**) | 飞书 |
29
+ | 搜人返回的 `lark_id`、SDK 类型的 `larkID`、用户说的"LarkID" | **LarkID**:飞书全局用户 ID(纯数字,如 `7311528002225963027`),≠ employee_id,飞书 OpenAPI 不认。⚠️ `lark_user_id` / `getBatchLarkUserIds` 名字带 LarkUserId,值却是 employee_id,**不是** LarkID | 飞书 |
29
30
 
30
31
  **作为 API 参数的取值(不是一个 ID,而是告诉接口"我传入哪种类型的 ID"):**
31
32
 
@@ -78,17 +79,20 @@ match-template-name: nestjs-react-fullstack
78
79
  │ └─ 是 ──→ AuthNPaasService.getBatchLarkUserIds()(第三节)
79
80
  │
80
81
  ├─ 需要 飞书 open_id(`ou_` 开头)/ union_id(`on_` 开头)?
81
- │ └─ ⚠️ **AuthNPaasService 不产出 open_id/union_id**,只能 user_id
82
- │ └─ 跳到 `feishu` skill 的 `references/id-convert.md`(spark id_convert type 10/11)
82
+ │ └─ 后端 ──→ `getBatchOpenIds()` / `getBatchUnionIds()`(第三节,convertType 10/11),open_id 属于哪个飞书应用就传 `{ feishuClientId: '<该应用 App ID,cli_ 开头>' }`
83
+ │ (复用 `FeishuService` 源码里的 `FEISHU_APP_ID` **常量**,不是环境变量,别用 `process.env` / `ConfigService` 读;不传 = 妙搭应用视角,拿去调你自己应用的 OpenAPI 会不认)
83
84
  │
84
85
  ├─ 需要把 飞书 open_id / union_id 反查成 妙搭 userId?
85
- │ └─ 跳到 `feishu` skill 的 `references/id-convert.md`(spark id_convert type 20/21)
86
+ │ └─ 后端 ──→ `getBatchMiaodaUserIdsByOpenIds()` / `getBatchMiaodaUserIdsByUnionIds()`(convertType 20/21),`feishuClientId` 同上;模板外才走 `feishu` skill 的 spark id_convert
86
87
  │
87
88
  ├─ 需要把 飞书 user_id(employee_id)反查成 妙搭 userId?
88
89
  │ └─ 后端 ──→ `AuthNPaasService.getBatchMiaodaUserIds()`(第三节,SDK 一步,convertType 31);非模板项目 ──→ `feishu` skill 两步兜底
89
90
  │
91
+ ├─ **LarkID**(`lark_id` / `larkID`,纯数字全局 ID)↔ 妙搭 userId?(不要用上面 employee_id 的方法)
92
+ │ └─ 后端 ──→ LarkID → 妙搭 userId 用 `getBatchMiaodaUserIdsByLarkIds()`,反向用 `getBatchLarkIds()`(第三节,convertType 41 / 40)
93
+ │
90
94
  └─ 需要自定义飞书 ID 转换接口?
91
- └─ 是 ──→ 注入 AuthNPaasService 编写 Controller(第四节,仅适用于 user_id)
95
+ └─ 是 ──→ 注入 AuthNPaasService 编写 Controller(第四节,适用于所有转换方向)
92
96
  ```
93
97
 
94
98
  > **相关技能**:接口认证/守卫/401 参见 `authn-guide`;登录/登出/获取用户信息等 Dataloom SDK 操作参见 `client-builtins-user-service`;**搜人 / 人员·部门·群组选择器返回的 ID 处理与字段获取**(employee_id / open_department_id、禁用字段、id_convert)参见 `contacts-service`;**"用户能做什么"**(角色/权限点位鉴权)参见 `authz-guide`。本 skill 只解决**"用户是谁"**(当前登录用户),其 `lark_user_id` == `employee_id`。
@@ -133,9 +137,9 @@ Controller 将校验后的 `roles` 显式传给 Service。`AuthorizationSDK.role
133
137
 
134
138
  妙搭平台的用户 ID(`userId`)与飞书用户 ID 是两套独立体系。调用飞书 OpenAPI 时需要传入某种飞书侧 ID(`open_id` / `union_id` / `user_id` 任选其一,具体通过哪个参数指定取决于 API:消息 API 用 `receive_id_type`,多数其他 API 用 `user_id_type`,文档协作者用 `member_id_type`)。
135
139
 
136
- `AuthNPaasService` 暴露的飞书 ID 是 **`user_id`**(即 `employee_id`,飞书企业内的用户标识)这一种,支持 **妙搭 userId ↔ 飞书 user_id 双向**转换(正向 `getBatchLarkUserIds`/`getCurrentUserLarkUserId`,反向 `getBatchMiaodaUserIds`)。
140
+ `AuthNPaasService` 支持飞书 ID 与妙搭 userId 双向互转:**飞书 user_id**(即 `employee_id`)正向 `getBatchLarkUserIds` / `getCurrentUserLarkUserId`、反向 `getBatchMiaodaUserIds`;**LarkID**(搜人返回里的 `lark_id`)正向 `getBatchLarkIds`、反向 `getBatchMiaodaUserIdsByLarkIds`;**open_id / union_id** 正向 `getBatchOpenIds` / `getBatchUnionIds`、反向 `getBatchMiaodaUserIdsByOpenIds` / `getBatchMiaodaUserIdsByUnionIds`。
137
141
 
138
- > 如果需要 `open_id` / `union_id`(无论正反向),请改用飞书开放平台 `spark id_convert` 接口,参见 `feishu` skill 的 `references/id-convert.md`。`employee_id` ↔ 妙搭 userId 双向都在本 SDK 内(见下方方法表)。
142
+ > 模板内所有方向都走本 SDK(见下方方法表),**不要**再手写 spark `id_convert`(它要开放平台应用凭证 + 额外权限);只有不在 nestjs-react-fullstack 模板内的项目才参见 `feishu` skill 的 `references/id-convert.md`。
139
143
 
140
144
  ### 后端 API
141
145
 
@@ -168,6 +172,8 @@ export class MyService {
168
172
  | `getCurrentUserLarkUserId` | `() → Promise<string \| null>` | 从请求上下文获取当前用户的飞书 ID |
169
173
  | `getBatchLarkUserIds` | `(userIds: string[]) → Promise<(string \| null)[]>` | 批量转换,最多 100 个,与输入顺序一一对应 |
170
174
  | `getBatchMiaodaUserIds` | `(employeeIds: string[]) → Promise<(string \| null)[]>` | 反向:批量把飞书 user_id(employee_id)转为妙搭 userId,最多 100 个,顺序一一对应,失败项 `null`(底层 convertType 31) |
175
+ | `getBatchLarkIds` / `getBatchMiaodaUserIdsByLarkIds` | `(ids: string[]) → Promise<(string \| null)[]>` | 妙搭 userId → LarkID / LarkID → 妙搭 userId,最多 100 个,顺序一一对应,失败项 `null`(底层 convertType 40 / 41);**不要**把 LarkID 传给 `getBatchMiaodaUserIds`(只收 employee_id) |
176
+ | `getBatchOpenIds` / `getBatchUnionIds` / `getBatchMiaodaUserIdsByOpenIds` / `getBatchMiaodaUserIdsByUnionIds` | `(ids: string[], options?: { feishuClientId?: string }) → Promise<(string \| null)[]>` | 妙搭 userId ↔ open_id / union_id(convertType 10 / 11 / 20 / 21),最多 100 个,顺序一一对应,失败项 `null`;`feishuClientId` = open_id 所属飞书应用的 App ID(`cli_`),不传用妙搭应用 |
171
177
 
172
178
  ### 内置接口
173
179
 
@@ -241,7 +247,7 @@ export class FeishuIdController {
241
247
  }
242
248
  ```
243
249
 
244
- > 反向转换(employee_id → 妙搭 userId)同理,把 `getBatchLarkUserIds` 换成 `getBatchMiaodaUserIds` 即可,无需新增 Controller。
250
+ > 其他方向同理,把 `getBatchLarkUserIds` 换成对应方法即可:employee_id → 妙搭 userId 用 `getBatchMiaodaUserIds`,LarkID → 妙搭 userId 用 `getBatchMiaodaUserIdsByLarkIds`,妙搭 userId → LarkID 用 `getBatchLarkIds`。
245
251
 
246
252
  前端调用示例:
247
253
 
@@ -272,8 +278,8 @@ const { larkUserIds } = await request<{ larkUserIds: (string | null)[] }>({
272
278
  | 用 `if (!userInfo)` 判断加载状态 | 初始值为空对象(truthy),必须用 `if (!userInfo?.user_id)` |
273
279
  | 手动实例化 `AuthNPaasService` | 通过 NestJS 依赖注入获取:`constructor(private readonly authnService: AuthNPaasService)` |
274
280
  | 单独注册 `AuthNPaasModule.forRoot()` | 已通过 `PlatformModule.forRoot()` 自动注册,无需手动导入 |
275
- | 自行调用平台 `/v1/app/{appId}/account/user/convert` 接口 | 必须使用 `AuthNPaasService` 的方法,内置错误处理和可观测性 |
276
- | `getBatchLarkUserIds` 传入超过 100 个 ID | 分批调用,每批最多 100 个 |
281
+ | 自行调用平台 `/v1/app/{appId}/account/user/convert` 接口,或模板内手写 spark `id_convert` | 必须使用 `AuthNPaasService` 的方法,内置错误处理和可观测性。LarkID / open_id / union_id 方法 TS 报不存在时把 `@lark-apaas/fullstack-nestjs-core` 升到最新,仍没有就**报告阻塞**,不要加直接依赖绕过 |
282
+ | 批量转换方法传入超过 100 个 ID | 分批调用,每批最多 100 个 |
277
283
  | 在前端自行封装飞书 ID 转换请求 | 使用 `useCurrentUserProfile()` 获取当前用户飞书 ID;批量转换通过后端接口 |
278
284
 
279
285
  ---
@@ -88,7 +88,7 @@ interface UserSimpleDTO {
88
88
  larkUserID?: number; // 飞书内部数字 ID,禁用(飞书 API 不认)
89
89
  department?: DepartmentSimpleDTO;
90
90
  employeeID?: string; // 飞书企业内 user_id,调飞书开放平台 API 用它
91
- larkID?: string; // 飞书用户全局唯一 ID(larkUserID 别名),禁用
91
+ larkID?: string; // 飞书用户全局唯一 ID(larkUserID 别名),禁传飞书 API;转妙搭 userId 用 AuthNPaasService.getBatchMiaodaUserIdsByLarkIds
92
92
  miaodaUserID?: string; // 妙搭用户 ID(userID 别名)
93
93
  }
94
94
 
@@ -198,7 +198,7 @@ interface SearchUserEntity {
198
198
  email?: string;
199
199
  userStatus?: number;
200
200
  employeeID?: string; // 飞书企业内 user_id,调飞书开放平台 API 用它
201
- larkID?: string; // larkUserID 别名,禁用
201
+ larkID?: string; // larkUserID 别名,禁传飞书 API(转妙搭 userId 见上)
202
202
  miaodaUserID?: string; // userID 别名
203
203
  }
204
204