问题
Feishu worker 当前把 WSClient.start() 的 Promise resolve 当成“长连接已鉴权并 ready”。但 SDK 的真正连接生命周期由 onReady / onError 等回调表达;当前实现未接这些信号,start() 返回后就无条件写 connected: true,随后 worker 输出 bridge online。
已保存的 dummy-credential smoke 证明:同一份 stderr 可以同时出现 failed to obtain token 与 [feishu:worker] bridge online,worker 仍长期存活。因此文档和运维会把一个本地启动标记误判成飞书鉴权 / WebSocket 成功。
Related: #261(其 liveness 范围更广;本 issue 聚焦启动成功契约与鉴权失败健康状态)。
代码与实测证据
安全复现(不发消息)
优先用 Mock WSClient:
- 让
start() resolve,但触发 onError(new Error('auth failed')),不触发 onReady。
- 当前行为:adapter
connected=true、worker 输出 bridge online、进程继续存活。
- 另可用纯假 App ID / Secret 做隔离连接层 smoke,复现报告中的
failed to obtain token + bridge online;到鉴权 / 连接层即止,绝不发送消息。
期望修复 / 验收标准
startFeishuBridge() 只有在 SDK onReady(真实 WS handshake ready)后才 resolve / 宣告成功;WSClient.start() resolve 本身不构成成功。
- 全进程只有一条权威成功行,例如现有
[feishu:worker] bridge online ...,且只从首次 onReady 路径输出一次;鉴权失败、connecting、reconnecting 时不得出现。
- 首次连接
onError / 鉴权失败:adapter health 保持 connected=false 并记录 scrub 后的 lastError;worker 输出明确失败行并非零退出,让父 supervisor 将其视为不健康。
- 已 ready 后进入 reconnect 时标记非健康 / 非 connected;
onReconnected 后恢复;terminal onError 不能留下长期存活的绿色 worker。
- 启动等待有有界超时,避免 DNS / proxy 卡死时永久假健康;任何日志都不得包含 App Secret。
- 单元测试覆盖:start resolve 但未 onReady、onReady、onError before ready、onError after ready、reconnect / reconnected、成功行 exactly once、secret scrub。
- Docker 分层 smoke 只验连接 / 鉴权层并保存报告;无测试 App 时真实 ready 用例必须明确 SKIP / 🚫,不能拿 dummy 凭据进程存活代替 PASS。
安全边界
不得向任何 live 飞书群 / 真实用户发消息;不得触碰生产 Feishu 节点、配置或 PID。默认使用 mock;若后续提供纯测试企业 App,也只验到 onReady 后立即停止,不触发消息事件。
文档已在 98f3b7ee 明确标注 bridge online 当前不是连接成功证据。
问题
Feishu worker 当前把
WSClient.start()的 Promise resolve 当成“长连接已鉴权并 ready”。但 SDK 的真正连接生命周期由onReady/onError等回调表达;当前实现未接这些信号,start()返回后就无条件写connected: true,随后 worker 输出bridge online。已保存的 dummy-credential smoke 证明:同一份 stderr 可以同时出现
failed to obtain token与[feishu:worker] bridge online,worker 仍长期存活。因此文档和运维会把一个本地启动标记误判成飞书鉴权 / WebSocket 成功。Related: #261(其 liveness 范围更广;本 issue 聚焦启动成功契约与鉴权失败健康状态)。
代码与实测证据
onReady/onError;await start()后无条件connected: true。startFeishuBridge()resolve 后立即输出bridge online;只有 Promise reject 才退出 1。failed to obtain token与bridge online,worker 12 秒后仍存活;真实 WS / reconnect 用例被 SKIP。@larksuiteoapi/node-sdk@1.67.0;该版本提供onReady,onError, reconnect 生命周期与连接状态接口。安全复现(不发消息)
优先用 Mock WSClient:
start()resolve,但触发onError(new Error('auth failed')),不触发onReady。connected=true、worker 输出bridge online、进程继续存活。failed to obtain token+bridge online;到鉴权 / 连接层即止,绝不发送消息。期望修复 / 验收标准
startFeishuBridge()只有在 SDKonReady(真实 WS handshake ready)后才 resolve / 宣告成功;WSClient.start()resolve 本身不构成成功。[feishu:worker] bridge online ...,且只从首次onReady路径输出一次;鉴权失败、connecting、reconnecting 时不得出现。onError/ 鉴权失败:adapter health 保持connected=false并记录 scrub 后的lastError;worker 输出明确失败行并非零退出,让父 supervisor 将其视为不健康。onReconnected后恢复;terminalonError不能留下长期存活的绿色 worker。安全边界
不得向任何 live 飞书群 / 真实用户发消息;不得触碰生产 Feishu 节点、配置或 PID。默认使用 mock;若后续提供纯测试企业 App,也只验到
onReady后立即停止,不触发消息事件。文档已在 98f3b7ee 明确标注
bridge online当前不是连接成功证据。