@agentunion/fastaun-browser 0.4.12 → 0.4.13

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/CHANGELOG.md CHANGED
@@ -6,6 +6,33 @@
6
6
 
7
7
  ---
8
8
 
9
+ ## 0.4.13 — 2026-06-09
10
+
11
+ ### 新功能
12
+ - **发送结果回填 envelope**:`message.send` / `group.send` / `message.thought.put` / `group.thought.put` 的返回结果新增规范化 `envelope` 字段,使发送方回执与接收端信封元数据一致;新增 `APP_SEND_ENVELOPE_METHODS` 与 `sendResultEnvelope()` / `attachSendResultEnvelope()`,rpc-pipeline 在 `postprocess` 后统一附加,V2 加密路径经 `_skipSendResultEnvelope` 标志跳过明文附加、由外层 V2 协调器在加密后补挂避免重复(四语言对齐)
13
+
14
+ ### 修复
15
+ - **refresh_token 失效自愈**:新增需重登判定(命中 `relogin_required` 或 `missing refresh_token` / `invalid_or_expired_refresh_token` / `refresh not supported`)与清缓存逻辑;刷新失败需重登时清空本地 `access_token`/`refresh_token`/`kite_token` 并持久化,client 层 token 刷新循环检测到需重登时发布 `token.refresh_exhausted` 事件(带 `relogin_required: true`)、断连触发重连,下次 `connectSession` 因无可用 token 自动走两步登录;refresh RPC 补传 `aid`/`device_id`/`slot_id`/`access_token`/`sdk_lang`/`sdk_version`,`AuthError` 携带 `data` 透传服务端响应(四语言对齐)
16
+ - **token 刷新日志文案修正**:修复连续刷新失败日志拼写错误(`token refreshconsecutivefailed` → 规范文案),token 循环中 `publish`/`_handleTransportDisconnect` 补齐 `await`
17
+ - **protected_headers 类型归一**:V2 发送方法的 envelope 元数据归一时识别 `ProtectedHeaders` 对象(经 `toObject()` 探测)并转 dict,修复传入对象(非 dict)时 protected_headers 被丢弃的问题(四语言对齐)
18
+
19
+ ### 优化
20
+ - **app_message_envelope 字段收窄**:envelope 键收窄为可转发元数据(`from`/`to`/`group_id`/`type`/`kind`/`version`/`timestamp`/`encrypted`/`context`/`protected_headers`/`payload_type`),移除 `message_id`/`seq`/`device_id`/`slot_id` 等本地与传输层字段,不再向应用层泄漏内部字段并剔除 `_auth`(四语言对齐)
21
+ - **RPC 日志 token 脱敏**:短 RPC 请求/响应 debug 日志对 `access_token`/`refresh_token`/`kite_token`/`token` 及 `_token` 结尾键递归脱敏,避免明文 token 落日志;浏览器环境受 crypto 限制只输出 `<redacted len=N>`(不含 sha256,与 Node/Go 略有差异)
22
+
23
+ ### 测试
24
+ - `refresh 业务失败且要求重登时应清掉本地 token 缓存`
25
+ - `connectSession 在 refresh 失败后应继续走两步登录`
26
+ - `应用层消息 envelope 只保留可转发字段并归一化 headers`
27
+ - 更新 `publishAppEvent` 与群撤回相关用例断言 envelope 收窄、不含 `message_id`/`seq`/`device_id`/`slot_id`
28
+
29
+ ### 服务端协同(本版本配套)
30
+ - **`auth.refresh_token` 响应结构化**:新增 `relogin_required` / `retryable` / `diagnostic` / `aid` / `refresh_count` 字段,SDK 据 `relogin_required`/`retryable` 区分"重新登录"与"退避重试",不再单纯按 `error` 字符串判断
31
+ - **JWT 老 SDK 兼容与即时吊销**:`AUN_JWT_LEGACY_ACCESS_TOKEN_COMPAT`(默认开)放行合法 JWT 避免迁移期重连风暴;`auth.token.revoked` 事件携带 `jti`/`expires_at`,gateway 按真实 TTL 缓存吊销
32
+ - **V2 P2P 写入幂等**:服务端 `v2_write_peer_message`/`v2_write_peer_wrap` 捕获唯一键冲突逐字段比对,重发相同 message_id 幂等返回、不再产生 seq 空洞;自发自收跳过重复 self-sync 推送
33
+
34
+ ---
35
+
9
36
  ## 0.4.12 — 2026-06-08
10
37
 
11
38
  ### 新功能
@@ -6,6 +6,33 @@
6
6
 
7
7
  ---
8
8
 
9
+ ## 0.4.13 — 2026-06-09
10
+
11
+ ### 新功能
12
+ - **发送结果回填 envelope**:`message.send` / `group.send` / `message.thought.put` / `group.thought.put` 的返回结果新增规范化 `envelope` 字段,使发送方回执与接收端信封元数据一致;新增 `APP_SEND_ENVELOPE_METHODS` 与 `sendResultEnvelope()` / `attachSendResultEnvelope()`,rpc-pipeline 在 `postprocess` 后统一附加,V2 加密路径经 `_skipSendResultEnvelope` 标志跳过明文附加、由外层 V2 协调器在加密后补挂避免重复(四语言对齐)
13
+
14
+ ### 修复
15
+ - **refresh_token 失效自愈**:新增需重登判定(命中 `relogin_required` 或 `missing refresh_token` / `invalid_or_expired_refresh_token` / `refresh not supported`)与清缓存逻辑;刷新失败需重登时清空本地 `access_token`/`refresh_token`/`kite_token` 并持久化,client 层 token 刷新循环检测到需重登时发布 `token.refresh_exhausted` 事件(带 `relogin_required: true`)、断连触发重连,下次 `connectSession` 因无可用 token 自动走两步登录;refresh RPC 补传 `aid`/`device_id`/`slot_id`/`access_token`/`sdk_lang`/`sdk_version`,`AuthError` 携带 `data` 透传服务端响应(四语言对齐)
16
+ - **token 刷新日志文案修正**:修复连续刷新失败日志拼写错误(`token refreshconsecutivefailed` → 规范文案),token 循环中 `publish`/`_handleTransportDisconnect` 补齐 `await`
17
+ - **protected_headers 类型归一**:V2 发送方法的 envelope 元数据归一时识别 `ProtectedHeaders` 对象(经 `toObject()` 探测)并转 dict,修复传入对象(非 dict)时 protected_headers 被丢弃的问题(四语言对齐)
18
+
19
+ ### 优化
20
+ - **app_message_envelope 字段收窄**:envelope 键收窄为可转发元数据(`from`/`to`/`group_id`/`type`/`kind`/`version`/`timestamp`/`encrypted`/`context`/`protected_headers`/`payload_type`),移除 `message_id`/`seq`/`device_id`/`slot_id` 等本地与传输层字段,不再向应用层泄漏内部字段并剔除 `_auth`(四语言对齐)
21
+ - **RPC 日志 token 脱敏**:短 RPC 请求/响应 debug 日志对 `access_token`/`refresh_token`/`kite_token`/`token` 及 `_token` 结尾键递归脱敏,避免明文 token 落日志;浏览器环境受 crypto 限制只输出 `<redacted len=N>`(不含 sha256,与 Node/Go 略有差异)
22
+
23
+ ### 测试
24
+ - `refresh 业务失败且要求重登时应清掉本地 token 缓存`
25
+ - `connectSession 在 refresh 失败后应继续走两步登录`
26
+ - `应用层消息 envelope 只保留可转发字段并归一化 headers`
27
+ - 更新 `publishAppEvent` 与群撤回相关用例断言 envelope 收窄、不含 `message_id`/`seq`/`device_id`/`slot_id`
28
+
29
+ ### 服务端协同(本版本配套)
30
+ - **`auth.refresh_token` 响应结构化**:新增 `relogin_required` / `retryable` / `diagnostic` / `aid` / `refresh_count` 字段,SDK 据 `relogin_required`/`retryable` 区分"重新登录"与"退避重试",不再单纯按 `error` 字符串判断
31
+ - **JWT 老 SDK 兼容与即时吊销**:`AUN_JWT_LEGACY_ACCESS_TOKEN_COMPAT`(默认开)放行合法 JWT 避免迁移期重连风暴;`auth.token.revoked` 事件携带 `jti`/`expires_at`,gateway 按真实 TTL 缓存吊销
32
+ - **V2 P2P 写入幂等**:服务端 `v2_write_peer_message`/`v2_write_peer_wrap` 捕获唯一键冲突逐字段比对,重发相同 message_id 幂等返回、不再产生 seq 空洞;自发自收跳过重复 self-sync 推送
33
+
34
+ ---
35
+
9
36
  ## 0.4.12 — 2026-06-08
10
37
 
11
38
  ### 新功能
@@ -2082,11 +2082,9 @@ SDK 收到后自动调用 `group.pull` 拉取最新消息并逐条解密后交
2082
2082
  {
2083
2083
  "envelope": {
2084
2084
  "group_id": "g-abc123.agentid.pub",
2085
- "seq": 42,
2086
- "message_id": "uuid",
2087
- "sender_aid": "alice.agentid.pub",
2088
- "message_type": "group.message",
2089
- "dispatch_mode": "broadcast"
2085
+ "from": "alice.agentid.pub",
2086
+ "type": "text",
2087
+ "timestamp": 1234567890000
2090
2088
  },
2091
2089
  "group_id": "g-abc123.agentid.pub",
2092
2090
  "seq": 42,
@@ -2098,7 +2096,7 @@ SDK 收到后自动调用 `group.pull` 拉取最新消息并逐条解密后交
2098
2096
  }
2099
2097
  ```
2100
2098
 
2101
- SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;群消息信封字段统一放在 `envelope`。0.4.x 兼容期仍保留顶层 `group_id` / `seq` / `message_id` / `sender_aid` 等别名,下一个大版本 0.5.* 将移除这些顶层别名,请通过 `msg["envelope"]["message_id"]` 等路径访问。
2099
+ SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;群消息信封字段统一放在 `envelope`。`envelope` 只保留可转发的归一化元数据,`from` 由 `sender_aid` 归一化而来,`timestamp` 由 `created_at` / `t_server` 归一化而来。0.4.x 兼容期仍保留顶层 `group_id` / `seq` / `message_id` / `sender_aid` / `dispatch_mode` 等别名,下一个大版本 0.5.* 将移除这些顶层别名;请通过 `msg["envelope"]["from"]`、`msg["envelope"]["timestamp"]` 等路径访问。
2102
2100
 
2103
2101
  ### event/group.message_recalled
2104
2102
 
@@ -2109,11 +2107,11 @@ SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;群消息信
2109
2107
  ```json
2110
2108
  {
2111
2109
  "envelope": {
2112
- "module_id": "group",
2113
2110
  "group_id": "g-abc123.agentid.pub",
2114
- "seq": 43,
2115
- "message_id": "grm-uuid",
2116
- "sender_aid": "alice.agentid.pub"
2111
+ "from": "alice.agentid.pub",
2112
+ "type": "group.message_recalled",
2113
+ "kind": "group.message_recalled",
2114
+ "timestamp": 1234567890000
2117
2115
  },
2118
2116
  "module_id": "group",
2119
2117
  "group_id": "g-abc123.agentid.pub",
@@ -2130,11 +2128,11 @@ SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;群消息信
2130
2128
  }
2131
2129
  ```
2132
2130
 
2133
- SDK 交付给应用层的撤回事件同样带 `envelope`。`envelope` 表示当前交付的撤回 tombstone / 通知自身信封,不是被撤回原消息的信封;业务侧被撤回的原消息列表继续使用 `message_ids` / `target_message_seqs`。0.4.x 兼容期仍保留顶层 `group_id` / `seq` / `message_id` / `sender_aid` 等别名,下一个大版本 0.5.* 将移除这些顶层别名。
2131
+ SDK 交付给应用层的撤回事件同样带 `envelope`。`envelope` 表示当前交付的撤回 tombstone / 通知自身信封,不是被撤回原消息的信封;业务侧被撤回的原消息列表继续使用 `message_ids` / `target_message_seqs`。`message_id` / `seq` 继续只保留在顶层兼容字段中,不进入 `envelope`。0.4.x 兼容期仍保留顶层 `group_id` / `seq` / `message_id` / `sender_aid` 等别名,下一个大版本 0.5.* 将移除这些顶层别名。
2134
2132
 
2135
2133
  | 字段 | 类型 | 说明 |
2136
2134
  |------|------|------|
2137
- | `envelope` | object | 撤回 tombstone / 通知自身信封,包含 `module_id`、`group_id`、`seq`、`message_id`、`sender_aid`、`device_id`、`slot_id` 等存在的字段 |
2135
+ | `envelope` | object | 撤回 tombstone / 通知自身信封,包含 `group_id`、`from`、`type`、`kind`、`timestamp`、`encrypted`、`context`、`protected_headers` 等存在的字段 |
2138
2136
  | `module_id` | string | 固定 `"group"` |
2139
2137
  | `group_id` | string | 群组 ID |
2140
2138
  | `seq` | integer | 当前交付的撤回 tombstone / 通知 seq;在线 push 为 notice_seq,原 seq 占位 tombstone 为原消息 seq |
@@ -513,10 +513,9 @@ result = await client.call("message.ack", {"seq": 150})
513
513
  ```json
514
514
  {
515
515
  "envelope": {
516
- "message_id": "uuid-1",
517
516
  "from": "alice.agentid.pub",
518
517
  "to": "bob.agentid.pub",
519
- "seq": 42,
518
+ "type": "text",
520
519
  "timestamp": 1234567890000,
521
520
  "encrypted": false
522
521
  },
@@ -531,7 +530,7 @@ result = await client.call("message.ack", {"seq": 150})
531
530
  }
532
531
  ```
533
532
 
534
- SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;信封字段统一放在 `envelope`。0.4.x 兼容期仍保留顶层 `message_id` / `from` / `to` / `seq` / `timestamp` 等别名,下一个大版本 0.5.* 将移除这些顶层别名,请通过 `msg["envelope"]["seq"]` 等路径访问。
533
+ SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;信封字段统一放在 `envelope`。`envelope` 只保留可转发的归一化元数据,`from` 由 `from_aid` / `sender_aid` 归一化而来,`timestamp` 由 `created_at` / `t_server` 归一化而来。0.4.x 兼容期仍保留顶层 `message_id` / `from` / `to` / `seq` / `timestamp` 等别名,下一个大版本 0.5.* 将移除这些顶层别名;请通过 `msg["envelope"]["from"]`、`msg["envelope"]["timestamp"]` 等路径访问。
535
534
 
536
535
  ### 订阅
537
536
 
@@ -550,10 +549,10 @@ client.on("message.received", lambda msg: print(msg["payload"]))
550
549
  ```json
551
550
  {
552
551
  "envelope": {
553
- "message_id": "recall-uuid",
554
552
  "from": "alice.agentid.pub",
555
553
  "to": "bob.agentid.pub",
556
- "seq": 43,
554
+ "type": "message.recalled",
555
+ "kind": "message.recalled",
557
556
  "timestamp": 1234567890000
558
557
  },
559
558
  "message_id": "recall-uuid",
@@ -565,11 +564,11 @@ client.on("message.received", lambda msg: print(msg["payload"]))
565
564
  }
566
565
  ```
567
566
 
568
- SDK 交付给应用层的撤回事件同样带 `envelope`。`envelope` 表示撤回 tombstone / 通知自身的信封,不是被撤回原消息的信封;被撤回的原消息继续通过 `message_ids` 表达。0.4.x 兼容期仍保留顶层 `message_id` / `from` / `to` / `seq` / `timestamp` 等别名,下一个大版本 0.5.* 将移除这些顶层别名。
567
+ SDK 交付给应用层的撤回事件同样带 `envelope`。`envelope` 表示撤回 tombstone / 通知自身的信封,不是被撤回原消息的信封;被撤回的原消息继续通过 `message_ids` 表达。`message_id` / `seq` 继续只保留在顶层兼容字段中,不进入 `envelope`。0.4.x 兼容期仍保留顶层 `message_id` / `from` / `to` / `seq` / `timestamp` 等别名,下一个大版本 0.5.* 将移除这些顶层别名。
569
568
 
570
569
  | 字段 | 类型 | 说明 |
571
570
  |------|------|------|
572
- | `envelope` | object | 撤回 tombstone / 通知自身信封,包含 `message_id`、`from`、`to`、`seq`、`timestamp`、`device_id`、`slot_id` 等存在的字段 |
571
+ | `envelope` | object | 撤回 tombstone / 通知自身信封,包含 `from`、`to`、`type`、`kind`、`timestamp`、`encrypted`、`context`、`protected_headers` 等存在的字段 |
573
572
  | `message_id` | string | 撤回 tombstone / 通知自身的 message_id |
574
573
  | `tombstone_message_id` | string | 兼容别名,等同于撤回 tombstone / 通知自身的 `message_id` |
575
574
  | `from` | string | 发送方(撤回者)AID |
package/dist/auth.d.ts CHANGED
@@ -159,6 +159,8 @@ export declare class AuthFlow {
159
159
  addTrustedRootPem(pem: string): void;
160
160
  private _loadTrustedRoots;
161
161
  private _rememberTokens;
162
+ private _refreshFailureRequiresRelogin;
163
+ private _clearCachedTokens;
162
164
  /** 验证服务端返回的 new_cert,通过后正式接受 */
163
165
  private _validateNewCert;
164
166
  /** 获取缓存的有效 access_token */
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,cAAc,EAAkE,MAAM,aAAa,CAAC;AAQ7G,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,UAAU,EAEf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAwFpB,UAAU,WAAY,SAAQ,UAAU;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,UAAU,aAAa;IACrB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CAC7D;AAqTD;;;;;;;;GAQG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,IAAI,CAA0B;IACtC,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI;IAElC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAKnC;IAEX,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,YAAY,CAA+B;IAGnD,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,kBAAkB,CAAoC;IAC9D,OAAO,CAAC,gBAAgB,CAAkF;IAC1G,OAAO,CAAC,iBAAiB,CAAkF;IAC3G,OAAO,CAAC,mBAAmB,CAAkC;IAC7D,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,kBAAkB,CAAmC;gBAEjD,IAAI,EAAE;QAChB,UAAU,EAAE,UAAU,CAAC;QACvB,MAAM,EAAE,cAAc,CAAC;QACvB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB;IAaD,4CAA4C;IAC5C,WAAW,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI;IAKlD,eAAe;IACT,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuBzD,uBAAuB;IACjB,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAQtE,2CAA2C;IACrC,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAItE,2BAA2B;IAC3B,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAM7D,kBAAkB,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKrE;;;;;OAKG;IACG,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAsEzE;;OAEG;IACG,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA6BnE;;OAEG;IACG,mBAAmB,CACvB,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,UAAU,GAAG,IAAI,EAC5B,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,YAAY,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;QACjC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC,GACA,OAAO,CAAC,UAAU,CAAC;IA2BtB;;OAEG;IACG,cAAc,CAClB,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,UAAU,GAAG,IAAI,EAC5B,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,GAAG;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,YAAY,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;QACjC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC,GACA,OAAO,CAAC,WAAW,CAAC;IA0IvB;;OAEG;IACG,mBAAmB,CACvB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC;IAkB1B;;OAEG;IACG,qBAAqB,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAkChB,sDAAsD;YACxC,SAAS;IA+EvB,qBAAqB;YACP,UAAU;IAexB,wBAAwB;YACV,UAAU;IAoBxB;;;;;;;;;;;;;;OAcG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI5E,oCAAoC;YACtB,uBAAuB;IAWrC,4CAA4C;IAC5C,OAAO,CAAC,8BAA8B;IAmBtC,oBAAoB;YACN,uBAAuB;YAyBvB,MAAM;IAiCpB,sBAAsB;YACR,mBAAmB;IAajC,yCAAyC;YAC3B,kBAAkB;YAqElB,qBAAqB;YAiDrB,oBAAoB;IAqElC,2BAA2B;YACb,mBAAmB;IAUjC,8BAA8B;YAChB,oBAAoB;YAQpB,yBAAyB;IA2BvC,2BAA2B;YACb,0BAA0B;IAcxC,gCAAgC;YAClB,gBAAgB;YA2ChB,mBAAmB;IAcjC,sBAAsB;YACR,sBAAsB;IAqBpC,oCAAoC;YACtB,uBAAuB;IAyCrC,8BAA8B;IAC9B,kBAAkB,IAAI,MAAM;IAQ5B,iCAAiC;IACjC,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQpC,OAAO,CAAC,iBAAiB;IAmCzB,OAAO,CAAC,eAAe;IAqBvB,gCAAgC;YAClB,gBAAgB;IA4E9B,2BAA2B;IAC3B,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAiC;IAErE,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAY1C,sBAAsB;IAItB,wBAAwB;YACV,oBAAoB;YA0BpB,kBAAkB;YAOlB,gBAAgB;IAgC9B,kCAAkC;IAClC,kBAAkB,IAAI,IAAI;CAe3B"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/auth.js CHANGED
@@ -7,6 +7,32 @@ import { ROOT_CA_PEM } from './certs/root.js';
7
7
  import { VERSION as AUN_SDK_VERSION } from './version.js';
8
8
  const _noopLog = { error: () => { }, warn: () => { }, info: () => { }, debug: () => { } };
9
9
  const AUN_SDK_LANG = 'javascript';
10
+ const SENSITIVE_RPC_LOG_KEYS = new Set([
11
+ 'access_token',
12
+ 'refresh_token',
13
+ 'kite_token',
14
+ 'token',
15
+ ]);
16
+ function redactRpcLogPayload(value, key = '', depth = 0) {
17
+ const keyLower = key.toLowerCase();
18
+ if (SENSITIVE_RPC_LOG_KEYS.has(keyLower) || keyLower.endsWith('_token')) {
19
+ const text = String(value ?? '');
20
+ return text ? `<redacted len=${text.length}>` : '';
21
+ }
22
+ if (depth >= 6)
23
+ return '<max-depth>';
24
+ if (Array.isArray(value)) {
25
+ return value.map((item) => redactRpcLogPayload(item, '', depth + 1));
26
+ }
27
+ if (value && typeof value === 'object') {
28
+ const out = {};
29
+ for (const [childKey, childValue] of Object.entries(value)) {
30
+ out[childKey] = redactRpcLogPayload(childValue, childKey, depth + 1);
31
+ }
32
+ return out;
33
+ }
34
+ return value;
35
+ }
10
36
  import { isJsonObject, } from './types.js';
11
37
  // ── ASN.1 / PEM 工具 ────────────────────────────────────
12
38
  /** 拆分 PEM bundle 为独立的 PEM 字符串数组 */
@@ -669,6 +695,9 @@ export class AuthFlow {
669
695
  catch (e) {
670
696
  if (!(e instanceof AuthError))
671
697
  throw e;
698
+ if (this._refreshFailureRequiresRelogin(e)) {
699
+ await this._clearCachedTokens(identity, e.message);
700
+ }
672
701
  // refresh 失败,重新登录
673
702
  }
674
703
  }
@@ -702,9 +731,11 @@ export class AuthFlow {
702
731
  this._log.debug(`refreshCachedTokens enter: aid=${identity.aid} gateway=${gatewayUrl}`);
703
732
  try {
704
733
  const refreshToken = String(identity.refresh_token ?? '');
705
- if (!refreshToken)
734
+ if (!refreshToken) {
735
+ await this._clearCachedTokens(identity, 'missing refresh_token');
706
736
  throw new AuthError('missing refresh_token');
707
- const refreshed = await this._refreshAccessToken(gatewayUrl, refreshToken);
737
+ }
738
+ const refreshed = await this._refreshAccessToken(gatewayUrl, refreshToken, identity);
708
739
  this._rememberTokens(identity, refreshed);
709
740
  await this._validateNewCert(identity, gatewayUrl);
710
741
  await this._persistIdentity(identity);
@@ -712,6 +743,9 @@ export class AuthFlow {
712
743
  return identity;
713
744
  }
714
745
  catch (err) {
746
+ if (this._refreshFailureRequiresRelogin(err)) {
747
+ await this._clearCachedTokens(identity, err instanceof Error ? err.message : String(err));
748
+ }
715
749
  this._log.debug(`refreshCachedTokens exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
716
750
  throw err;
717
751
  }
@@ -798,13 +832,13 @@ export class AuthFlow {
798
832
  method,
799
833
  params,
800
834
  });
801
- this._log.debug(`short RPC request full: ${requestPayload}`);
835
+ this._log.debug(`short RPC request full: ${JSON.stringify(redactRpcLogPayload(JSON.parse(requestPayload)))}`);
802
836
  ws.send(requestPayload);
803
837
  return;
804
838
  }
805
839
  // 第二条消息是 RPC 响应
806
840
  globalThis.clearTimeout(timeout);
807
- this._log.debug(`short RPC response full: method=${method} ${JSON.stringify(msg)}`);
841
+ this._log.debug(`short RPC response full: method=${method} ${JSON.stringify(redactRpcLogPayload(msg))}`);
808
842
  try {
809
843
  ws.close();
810
844
  }
@@ -819,7 +853,7 @@ export class AuthFlow {
819
853
  return;
820
854
  }
821
855
  if (result.success === false) {
822
- reject(new AuthError(String(result.error ?? `${method} failed`)));
856
+ reject(new AuthError(String(result.error ?? `${method} failed`), { data: result }));
823
857
  return;
824
858
  }
825
859
  resolve(result);
@@ -963,12 +997,32 @@ export class AuthFlow {
963
997
  return phase2;
964
998
  }
965
999
  /** 刷新 access token */
966
- async _refreshAccessToken(gatewayUrl, refreshToken) {
967
- const result = await this._shortRpc(gatewayUrl, 'auth.refresh_token', {
1000
+ async _refreshAccessToken(gatewayUrl, refreshToken, identity) {
1001
+ const params = {
968
1002
  refresh_token: refreshToken,
969
- });
1003
+ sdk_lang: AUN_SDK_LANG,
1004
+ sdk_version: AUN_SDK_VERSION,
1005
+ };
1006
+ if (identity) {
1007
+ const aid = String(identity.aid ?? '').trim();
1008
+ const deviceId = String(identity.device_id ?? '').trim();
1009
+ const slotId = String(identity.slot_id ?? '').trim();
1010
+ const accessToken = String(identity.access_token ?? '').trim();
1011
+ if (aid)
1012
+ params.aid = aid;
1013
+ if (deviceId)
1014
+ params.device_id = deviceId;
1015
+ if (slotId)
1016
+ params.slot_id = slotId;
1017
+ if (accessToken)
1018
+ params.access_token = accessToken;
1019
+ if (typeof identity.access_token_expires_at === 'number') {
1020
+ params.access_token_expires_at = identity.access_token_expires_at;
1021
+ }
1022
+ }
1023
+ const result = await this._shortRpc(gatewayUrl, 'auth.refresh_token', params);
970
1024
  if (!result.success) {
971
- throw new AuthError(String(result.error ?? 'refresh failed'));
1025
+ throw new AuthError(String(result.error ?? 'refresh failed'), { data: result });
972
1026
  }
973
1027
  return result;
974
1028
  }
@@ -1354,6 +1408,41 @@ export class AuthFlow {
1354
1408
  if (typeof activeCert === 'string' && activeCert)
1355
1409
  identity._pending_active_cert = activeCert;
1356
1410
  }
1411
+ _refreshFailureRequiresRelogin(err) {
1412
+ if (!(err instanceof AuthError))
1413
+ return false;
1414
+ const data = err.data;
1415
+ if (isJsonObject(data)) {
1416
+ if (data.relogin_required === true)
1417
+ return true;
1418
+ const error = String(data.error ?? '').trim().toLowerCase();
1419
+ return ['missing refresh_token', 'invalid_or_expired_refresh_token', 'refresh not supported'].includes(error);
1420
+ }
1421
+ const message = err.message.trim().toLowerCase();
1422
+ return ['missing refresh_token', 'invalid_or_expired_refresh_token', 'refresh not supported'].includes(message);
1423
+ }
1424
+ async _clearCachedTokens(identity, reason = '') {
1425
+ const aid = String(identity.aid ?? '');
1426
+ const hadToken = Boolean(identity.access_token ||
1427
+ identity.refresh_token ||
1428
+ identity.kite_token ||
1429
+ identity.token ||
1430
+ identity.access_token_expires_at);
1431
+ if (!hadToken)
1432
+ return;
1433
+ identity.access_token = '';
1434
+ identity.refresh_token = '';
1435
+ identity.kite_token = '';
1436
+ identity.token = '';
1437
+ identity.access_token_expires_at = 0;
1438
+ try {
1439
+ await this._persistIdentity(identity);
1440
+ this._log.warn(`cleared cached tokens after refresh failure: aid=${aid} reason=${reason}`);
1441
+ }
1442
+ catch (persistErr) {
1443
+ this._log.warn(`failed to persist token cleanup: aid=${aid} err=${persistErr instanceof Error ? persistErr.message : String(persistErr)}`);
1444
+ }
1445
+ }
1357
1446
  /** 验证服务端返回的 new_cert,通过后正式接受 */
1358
1447
  async _validateNewCert(identity, gatewayUrl = '') {
1359
1448
  const newCertPem = identity._pending_new_cert;