zapo-js 0.1.1 → 0.2.0

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.
Files changed (589) hide show
  1. package/README.md +20 -4
  2. package/dist/appstate/WaAppStateCrypto.js +19 -26
  3. package/dist/appstate/WaAppStateSyncClient.js +293 -181
  4. package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
  5. package/dist/appstate/constants.js +4 -3
  6. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  7. package/dist/appstate/index.js +8 -6
  8. package/dist/appstate/utils.js +9 -34
  9. package/dist/auth/WaAuthClient.js +43 -61
  10. package/dist/auth/flow/WaAuthCredentialsFlow.js +22 -15
  11. package/dist/auth/index.js +1 -8
  12. package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
  13. package/dist/auth/pairing/WaPairingFlow.js +34 -26
  14. package/dist/auth/pairing/WaQrFlow.js +37 -24
  15. package/dist/client/WaClient.js +275 -324
  16. package/dist/client/WaClientFactory.js +500 -133
  17. package/dist/client/connection/WaConnectionManager.js +301 -0
  18. package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
  19. package/dist/client/connection/WaReceiptQueue.js +51 -0
  20. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
  21. package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
  22. package/dist/client/coordinators/WaGroupCoordinator.js +30 -16
  23. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  24. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +439 -701
  25. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  26. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  27. package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
  28. package/dist/client/coordinators/WaRetryCoordinator.js +242 -57
  29. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  30. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
  31. package/dist/client/dirty.js +74 -48
  32. package/dist/client/events/chat.js +4 -3
  33. package/dist/client/events/devices.js +72 -0
  34. package/dist/client/events/group.js +62 -47
  35. package/dist/client/events/identity.js +22 -0
  36. package/dist/client/events/privacy-token.js +39 -0
  37. package/dist/client/history-sync.js +94 -63
  38. package/dist/client/incoming.js +60 -27
  39. package/dist/client/mailbox.js +24 -23
  40. package/dist/client/messages.js +107 -31
  41. package/dist/client/messaging/fanout.js +199 -0
  42. package/dist/client/messaging/key-protocol.js +130 -0
  43. package/dist/client/messaging/participants.js +193 -0
  44. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  45. package/dist/client/tokens/cs-token.js +50 -0
  46. package/dist/client/tokens/tc-token.js +25 -0
  47. package/dist/crypto/core/hkdf.js +3 -8
  48. package/dist/crypto/core/index.js +2 -5
  49. package/dist/crypto/core/keys.js +6 -7
  50. package/dist/crypto/core/nonce.js +2 -0
  51. package/dist/crypto/core/primitives.js +12 -23
  52. package/dist/crypto/core/random.js +26 -23
  53. package/dist/crypto/curves/Ed25519.js +7 -8
  54. package/dist/crypto/curves/X25519.js +38 -22
  55. package/dist/crypto/index.js +1 -3
  56. package/dist/crypto/math/constants.js +13 -36
  57. package/dist/crypto/math/edwards.js +171 -44
  58. package/dist/crypto/math/fe.js +706 -0
  59. package/dist/crypto/math/mod.js +10 -3
  60. package/dist/esm/appstate/WaAppStateCrypto.js +7 -14
  61. package/dist/esm/appstate/WaAppStateSyncClient.js +284 -172
  62. package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
  63. package/dist/esm/appstate/constants.js +3 -2
  64. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  65. package/dist/esm/appstate/index.js +2 -2
  66. package/dist/esm/appstate/utils.js +8 -30
  67. package/dist/esm/auth/WaAuthClient.js +43 -61
  68. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +22 -15
  69. package/dist/esm/auth/index.js +0 -3
  70. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
  71. package/dist/esm/auth/pairing/WaPairingFlow.js +28 -20
  72. package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
  73. package/dist/esm/client/WaClient.js +275 -324
  74. package/dist/esm/client/WaClientFactory.js +501 -134
  75. package/dist/esm/client/connection/WaConnectionManager.js +297 -0
  76. package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
  77. package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
  78. package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
  79. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
  80. package/dist/esm/client/coordinators/WaGroupCoordinator.js +23 -9
  81. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  82. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +443 -705
  83. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  84. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  85. package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
  86. package/dist/esm/client/coordinators/WaRetryCoordinator.js +244 -59
  87. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  88. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
  89. package/dist/esm/client/dirty.js +69 -43
  90. package/dist/esm/client/events/chat.js +4 -3
  91. package/dist/esm/client/events/devices.js +68 -0
  92. package/dist/esm/client/events/group.js +53 -39
  93. package/dist/esm/client/events/identity.js +19 -0
  94. package/dist/esm/client/events/privacy-token.js +36 -0
  95. package/dist/esm/client/history-sync.js +91 -60
  96. package/dist/esm/client/incoming.js +61 -28
  97. package/dist/esm/client/mailbox.js +24 -23
  98. package/dist/esm/client/messages.js +108 -32
  99. package/dist/esm/client/messaging/fanout.js +196 -0
  100. package/dist/esm/client/messaging/key-protocol.js +127 -0
  101. package/dist/esm/client/messaging/participants.js +190 -0
  102. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  103. package/dist/esm/client/tokens/cs-token.js +46 -0
  104. package/dist/esm/client/tokens/tc-token.js +18 -0
  105. package/dist/esm/crypto/core/hkdf.js +3 -8
  106. package/dist/esm/crypto/core/index.js +2 -3
  107. package/dist/esm/crypto/core/keys.js +3 -4
  108. package/dist/esm/crypto/core/nonce.js +2 -0
  109. package/dist/esm/crypto/core/primitives.js +12 -22
  110. package/dist/esm/crypto/core/random.js +25 -23
  111. package/dist/esm/crypto/curves/Ed25519.js +4 -5
  112. package/dist/esm/crypto/curves/X25519.js +35 -19
  113. package/dist/esm/crypto/index.js +0 -1
  114. package/dist/esm/crypto/math/constants.js +12 -35
  115. package/dist/esm/crypto/math/edwards.js +174 -47
  116. package/dist/esm/crypto/math/fe.js +691 -0
  117. package/dist/esm/crypto/math/mod.js +10 -1
  118. package/dist/esm/index.js +1 -1
  119. package/dist/esm/infra/log/ConsoleLogger.js +18 -17
  120. package/dist/esm/infra/log/PinoLogger.js +15 -9
  121. package/dist/esm/infra/log/types.js +11 -1
  122. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  123. package/dist/esm/infra/perf/BoundedTaskQueue.js +16 -18
  124. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  125. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  126. package/dist/esm/infra/perf/StoreLock.js +77 -0
  127. package/dist/esm/media/WaMediaCrypto.js +96 -16
  128. package/dist/esm/media/WaMediaTransferClient.js +251 -91
  129. package/dist/esm/media/conn.js +10 -6
  130. package/dist/esm/media/constants.js +6 -2
  131. package/dist/esm/message/WaMessageClient.js +30 -32
  132. package/dist/esm/message/ack.js +6 -6
  133. package/dist/esm/message/addon-crypto.js +59 -0
  134. package/dist/esm/message/content.js +195 -9
  135. package/dist/esm/message/icdc.js +76 -0
  136. package/dist/esm/message/incoming.js +129 -122
  137. package/dist/esm/message/index.js +2 -0
  138. package/dist/esm/message/phash.js +3 -1
  139. package/dist/esm/message/reporting-token.js +425 -0
  140. package/dist/esm/message/use-case-secret.js +49 -0
  141. package/dist/esm/protocol/appstate.js +27 -0
  142. package/dist/esm/protocol/browser.js +10 -18
  143. package/dist/esm/protocol/constants.js +6 -3
  144. package/dist/esm/protocol/defaults.js +6 -0
  145. package/dist/esm/protocol/index.js +2 -11
  146. package/dist/esm/protocol/jid.js +133 -52
  147. package/dist/esm/protocol/media.js +3 -3
  148. package/dist/esm/protocol/message.js +61 -1
  149. package/dist/esm/protocol/nodes.js +4 -0
  150. package/dist/esm/protocol/notification.js +3 -1
  151. package/dist/esm/protocol/privacy-token.js +17 -0
  152. package/dist/esm/protocol/privacy.js +55 -0
  153. package/dist/esm/protocol/stream.js +26 -1
  154. package/dist/esm/protocol/usync.js +11 -0
  155. package/dist/esm/retry/codec.js +216 -0
  156. package/dist/esm/retry/constants.js +1 -1
  157. package/dist/esm/retry/index.js +3 -2
  158. package/dist/esm/retry/parse.js +88 -86
  159. package/dist/esm/retry/replay.js +54 -51
  160. package/dist/esm/retry/tracker.js +94 -0
  161. package/dist/esm/signal/api/SignalDeviceSyncApi.js +276 -92
  162. package/dist/esm/signal/api/SignalDigestSyncApi.js +17 -8
  163. package/dist/esm/signal/api/SignalIdentitySyncApi.js +67 -37
  164. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +86 -67
  165. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  166. package/dist/esm/signal/api/SignalSessionSyncApi.js +36 -34
  167. package/dist/esm/signal/api/result-map.js +10 -0
  168. package/dist/esm/signal/constants.js +0 -4
  169. package/dist/esm/signal/crypto/WaAdvSignature.js +13 -9
  170. package/dist/esm/signal/{store/sqlite.js → encoding.js} +93 -60
  171. package/dist/esm/signal/group/SenderKeyChain.js +28 -23
  172. package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
  173. package/dist/esm/signal/group/SenderKeyManager.js +144 -115
  174. package/dist/esm/signal/index.js +2 -0
  175. package/dist/esm/signal/registration/keygen.js +6 -2
  176. package/dist/esm/signal/registration/utils.js +1 -0
  177. package/dist/esm/signal/session/SignalProtocol.js +164 -53
  178. package/dist/esm/signal/session/SignalRatchet.js +24 -15
  179. package/dist/esm/signal/session/SignalSession.js +14 -9
  180. package/dist/esm/signal/session/resolver.js +221 -0
  181. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  182. package/dist/esm/store/createStore.js +100 -188
  183. package/dist/esm/store/index.js +1 -10
  184. package/dist/esm/store/locks/appstate.lock.js +26 -0
  185. package/dist/esm/store/locks/auth.lock.js +15 -0
  186. package/dist/esm/store/locks/contact.lock.js +20 -0
  187. package/dist/esm/store/locks/device-list.lock.js +20 -0
  188. package/dist/esm/store/locks/message.lock.js +21 -0
  189. package/dist/esm/store/locks/participants.lock.js +20 -0
  190. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  191. package/dist/esm/store/locks/retry.lock.js +29 -0
  192. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  193. package/dist/esm/store/locks/signal.lock.js +63 -0
  194. package/dist/esm/store/locks/thread.lock.js +21 -0
  195. package/dist/esm/store/noop.store.js +4 -7
  196. package/dist/esm/store/providers/memory/appstate.store.js +38 -16
  197. package/dist/esm/store/providers/memory/contact.store.js +5 -0
  198. package/dist/esm/store/providers/memory/device-list.store.js +12 -34
  199. package/dist/esm/store/providers/memory/message.store.js +11 -5
  200. package/dist/esm/store/providers/memory/participants.store.js +1 -8
  201. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  202. package/dist/esm/store/providers/memory/retry.store.js +77 -2
  203. package/dist/esm/store/providers/memory/sender-key.store.js +11 -8
  204. package/dist/esm/store/providers/memory/signal.store.js +47 -18
  205. package/dist/esm/store/providers/memory/thread.store.js +5 -0
  206. package/dist/esm/transport/WaComms.js +28 -24
  207. package/dist/esm/transport/WaWebSocket.js +115 -18
  208. package/dist/esm/transport/binary/constants.js +0 -30
  209. package/dist/esm/transport/binary/decoder.js +8 -8
  210. package/dist/esm/transport/binary/encoder.js +10 -9
  211. package/dist/esm/transport/binary/index.js +0 -1
  212. package/dist/esm/transport/index.js +1 -0
  213. package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
  214. package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -21
  215. package/dist/esm/transport/node/WaNodeTransport.js +0 -3
  216. package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
  217. package/dist/esm/transport/node/builders/business.js +129 -0
  218. package/dist/esm/transport/node/builders/global.js +370 -0
  219. package/dist/esm/transport/node/builders/index.js +7 -3
  220. package/dist/esm/transport/node/builders/message.js +63 -230
  221. package/dist/esm/transport/node/builders/pairing.js +2 -27
  222. package/dist/esm/transport/node/builders/privacy-token.js +41 -0
  223. package/dist/esm/transport/node/builders/privacy.js +48 -0
  224. package/dist/esm/transport/node/builders/profile.js +70 -0
  225. package/dist/esm/transport/node/builders/retry.js +10 -22
  226. package/dist/esm/transport/node/builders/usync.js +45 -0
  227. package/dist/esm/transport/node/helpers.js +125 -5
  228. package/dist/esm/transport/node/usync.js +5 -0
  229. package/dist/esm/transport/node/xml.js +35 -14
  230. package/dist/esm/transport/noise/WaClientPayload.js +10 -10
  231. package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
  232. package/dist/esm/transport/noise/WaNoiseCert.js +4 -7
  233. package/dist/esm/transport/noise/WaNoiseSession.js +77 -29
  234. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  235. package/dist/esm/transport/proxy.js +27 -0
  236. package/dist/esm/transport/stream/parse.js +17 -48
  237. package/dist/esm/util/bytes.js +67 -45
  238. package/dist/esm/util/coercion.js +6 -14
  239. package/dist/esm/util/index.js +5 -0
  240. package/dist/esm/util/primitives.js +40 -14
  241. package/dist/index.js +7 -1
  242. package/dist/infra/log/ConsoleLogger.js +18 -17
  243. package/dist/infra/log/PinoLogger.js +15 -9
  244. package/dist/infra/log/types.js +12 -0
  245. package/dist/infra/perf/BackgroundQueue.js +482 -0
  246. package/dist/infra/perf/BoundedTaskQueue.js +16 -18
  247. package/dist/infra/perf/PromiseDedup.js +24 -0
  248. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  249. package/dist/infra/perf/StoreLock.js +81 -0
  250. package/dist/media/WaMediaCrypto.js +95 -15
  251. package/dist/media/WaMediaTransferClient.js +284 -91
  252. package/dist/media/conn.js +10 -6
  253. package/dist/media/constants.js +6 -2
  254. package/dist/message/WaMessageClient.js +31 -33
  255. package/dist/message/ack.js +6 -6
  256. package/dist/message/addon-crypto.js +65 -0
  257. package/dist/message/content.js +198 -9
  258. package/dist/message/icdc.js +81 -0
  259. package/dist/message/incoming.js +127 -120
  260. package/dist/message/index.js +2 -0
  261. package/dist/message/phash.js +3 -1
  262. package/dist/message/reporting-token.js +429 -0
  263. package/dist/message/use-case-secret.js +55 -0
  264. package/dist/protocol/appstate.js +28 -1
  265. package/dist/protocol/browser.js +10 -18
  266. package/dist/protocol/constants.js +26 -1
  267. package/dist/protocol/defaults.js +6 -0
  268. package/dist/protocol/index.js +23 -42
  269. package/dist/protocol/jid.js +140 -52
  270. package/dist/protocol/media.js +3 -3
  271. package/dist/protocol/message.js +62 -2
  272. package/dist/protocol/nodes.js +4 -0
  273. package/dist/protocol/notification.js +3 -1
  274. package/dist/protocol/privacy-token.js +20 -0
  275. package/dist/protocol/privacy.js +58 -0
  276. package/dist/protocol/stream.js +27 -2
  277. package/dist/protocol/usync.js +14 -0
  278. package/dist/retry/codec.js +220 -0
  279. package/dist/retry/constants.js +1 -1
  280. package/dist/retry/index.js +7 -5
  281. package/dist/retry/parse.js +88 -85
  282. package/dist/retry/replay.js +52 -49
  283. package/dist/retry/tracker.js +97 -0
  284. package/dist/signal/api/SignalDeviceSyncApi.js +273 -89
  285. package/dist/signal/api/SignalDigestSyncApi.js +17 -8
  286. package/dist/signal/api/SignalIdentitySyncApi.js +66 -36
  287. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +82 -63
  288. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  289. package/dist/signal/api/SignalSessionSyncApi.js +36 -34
  290. package/dist/signal/api/result-map.js +13 -0
  291. package/dist/signal/constants.js +1 -5
  292. package/dist/signal/crypto/WaAdvSignature.js +11 -7
  293. package/dist/signal/{store/sqlite.js → encoding.js} +94 -61
  294. package/dist/signal/group/SenderKeyChain.js +27 -22
  295. package/dist/signal/group/SenderKeyCodec.js +5 -6
  296. package/dist/signal/group/SenderKeyManager.js +144 -115
  297. package/dist/signal/index.js +15 -1
  298. package/dist/signal/registration/keygen.js +6 -2
  299. package/dist/signal/registration/utils.js +1 -0
  300. package/dist/signal/session/SignalProtocol.js +164 -53
  301. package/dist/signal/session/SignalRatchet.js +24 -15
  302. package/dist/signal/session/SignalSession.js +14 -9
  303. package/dist/signal/session/resolver.js +224 -0
  304. package/dist/store/contracts/privacy-token.store.js +2 -0
  305. package/dist/store/createStore.js +100 -188
  306. package/dist/store/index.js +15 -33
  307. package/dist/store/locks/appstate.lock.js +29 -0
  308. package/dist/store/locks/auth.lock.js +18 -0
  309. package/dist/store/locks/contact.lock.js +23 -0
  310. package/dist/store/locks/device-list.lock.js +23 -0
  311. package/dist/store/locks/message.lock.js +24 -0
  312. package/dist/store/locks/participants.lock.js +23 -0
  313. package/dist/store/locks/privacy-token.lock.js +21 -0
  314. package/dist/store/locks/retry.lock.js +32 -0
  315. package/dist/store/locks/sender-key.lock.js +55 -0
  316. package/dist/store/locks/signal.lock.js +66 -0
  317. package/dist/store/locks/thread.lock.js +24 -0
  318. package/dist/store/noop.store.js +4 -7
  319. package/dist/store/providers/memory/appstate.store.js +36 -14
  320. package/dist/store/providers/memory/contact.store.js +5 -0
  321. package/dist/store/providers/memory/device-list.store.js +12 -34
  322. package/dist/store/providers/memory/message.store.js +11 -5
  323. package/dist/store/providers/memory/participants.store.js +1 -8
  324. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  325. package/dist/store/providers/memory/retry.store.js +77 -2
  326. package/dist/store/providers/memory/sender-key.store.js +14 -11
  327. package/dist/store/providers/memory/signal.store.js +54 -25
  328. package/dist/store/providers/memory/thread.store.js +5 -0
  329. package/dist/transport/WaComms.js +30 -26
  330. package/dist/transport/WaWebSocket.js +148 -18
  331. package/dist/transport/binary/constants.js +1 -31
  332. package/dist/transport/binary/decoder.js +8 -8
  333. package/dist/transport/binary/encoder.js +10 -9
  334. package/dist/transport/binary/index.js +0 -4
  335. package/dist/transport/index.js +7 -1
  336. package/dist/transport/keepalive/WaKeepAlive.js +1 -7
  337. package/dist/transport/node/WaNodeOrchestrator.js +25 -21
  338. package/dist/transport/node/WaNodeTransport.js +0 -3
  339. package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
  340. package/dist/transport/node/builders/business.js +137 -0
  341. package/dist/transport/node/builders/global.js +375 -0
  342. package/dist/transport/node/builders/index.js +29 -17
  343. package/dist/transport/node/builders/message.js +64 -236
  344. package/dist/transport/node/builders/pairing.js +2 -29
  345. package/dist/transport/node/builders/privacy-token.js +46 -0
  346. package/dist/transport/node/builders/privacy.js +55 -0
  347. package/dist/transport/node/builders/profile.js +78 -0
  348. package/dist/transport/node/builders/retry.js +9 -21
  349. package/dist/transport/node/builders/usync.js +49 -0
  350. package/dist/transport/node/helpers.js +131 -4
  351. package/dist/transport/node/usync.js +8 -0
  352. package/dist/transport/node/xml.js +35 -14
  353. package/dist/transport/noise/WaClientPayload.js +13 -13
  354. package/dist/transport/noise/WaFrameCodec.js +47 -32
  355. package/dist/transport/noise/WaNoiseCert.js +5 -8
  356. package/dist/transport/noise/WaNoiseSession.js +77 -29
  357. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  358. package/dist/transport/proxy.js +34 -0
  359. package/dist/transport/stream/parse.js +20 -52
  360. package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
  361. package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
  362. package/dist/types/appstate/constants.d.ts +1 -0
  363. package/dist/types/appstate/encoding.d.ts +7 -0
  364. package/dist/types/appstate/index.d.ts +3 -3
  365. package/dist/types/appstate/utils.d.ts +0 -3
  366. package/dist/types/auth/WaAuthClient.d.ts +10 -12
  367. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
  368. package/dist/types/auth/index.d.ts +0 -4
  369. package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
  370. package/dist/types/auth/types.d.ts +7 -9
  371. package/dist/types/client/WaClient.d.ts +42 -25
  372. package/dist/types/client/WaClientFactory.d.ts +33 -26
  373. package/dist/types/client/connection/WaConnectionManager.d.ts +66 -0
  374. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
  375. package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
  376. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
  377. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  378. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -2
  379. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +29 -38
  380. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
  381. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  382. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
  383. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +8 -0
  384. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  385. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
  386. package/dist/types/client/dirty.d.ts +1 -0
  387. package/dist/types/client/events/devices.d.ts +20 -0
  388. package/dist/types/client/events/group.d.ts +2 -1
  389. package/dist/types/client/events/identity.d.ts +9 -0
  390. package/dist/types/client/events/privacy-token.d.ts +7 -0
  391. package/dist/types/client/history-sync.d.ts +9 -6
  392. package/dist/types/client/incoming.d.ts +3 -1
  393. package/dist/types/client/index.d.ts +1 -1
  394. package/dist/types/client/mailbox.d.ts +3 -5
  395. package/dist/types/client/messages.d.ts +1 -2
  396. package/dist/types/client/messaging/fanout.d.ts +14 -0
  397. package/dist/types/client/messaging/key-protocol.d.ts +18 -0
  398. package/dist/types/client/messaging/participants.d.ts +13 -0
  399. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  400. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  401. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  402. package/dist/types/client/types.d.ts +75 -4
  403. package/dist/types/crypto/core/hkdf.d.ts +0 -6
  404. package/dist/types/crypto/core/index.d.ts +2 -3
  405. package/dist/types/crypto/core/nonce.d.ts +2 -0
  406. package/dist/types/crypto/core/primitives.d.ts +0 -1
  407. package/dist/types/crypto/core/random.d.ts +2 -7
  408. package/dist/types/crypto/index.d.ts +0 -1
  409. package/dist/types/crypto/math/constants.d.ts +4 -2
  410. package/dist/types/crypto/math/fe.d.ts +30 -0
  411. package/dist/types/crypto/math/mod.d.ts +0 -2
  412. package/dist/types/crypto/math/types.d.ts +11 -4
  413. package/dist/types/index.d.ts +5 -3
  414. package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
  415. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  416. package/dist/types/infra/log/types.d.ts +1 -0
  417. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  418. package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
  419. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  420. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  421. package/dist/types/infra/perf/StoreLock.d.ts +10 -0
  422. package/dist/types/media/WaMediaCrypto.d.ts +3 -2
  423. package/dist/types/media/WaMediaTransferClient.d.ts +16 -15
  424. package/dist/types/media/constants.d.ts +1 -1
  425. package/dist/types/media/index.d.ts +1 -1
  426. package/dist/types/media/types.d.ts +15 -2
  427. package/dist/types/message/addon-crypto.d.ts +25 -0
  428. package/dist/types/message/content.d.ts +8 -0
  429. package/dist/types/message/icdc.d.ts +13 -0
  430. package/dist/types/message/index.d.ts +2 -0
  431. package/dist/types/message/reporting-token.d.ts +18 -0
  432. package/dist/types/message/types.d.ts +45 -6
  433. package/dist/types/message/use-case-secret.d.ts +20 -0
  434. package/dist/types/protocol/appstate.d.ts +47 -0
  435. package/dist/types/protocol/constants.d.ts +8 -3
  436. package/dist/types/protocol/defaults.d.ts +6 -0
  437. package/dist/types/protocol/index.d.ts +2 -11
  438. package/dist/types/protocol/jid.d.ts +22 -5
  439. package/dist/types/protocol/message.d.ts +60 -0
  440. package/dist/types/protocol/nodes.d.ts +4 -0
  441. package/dist/types/protocol/notification.d.ts +2 -0
  442. package/dist/types/protocol/privacy-token.d.ts +17 -0
  443. package/dist/types/protocol/privacy.d.ts +75 -0
  444. package/dist/types/protocol/stream.d.ts +30 -0
  445. package/dist/types/protocol/usync.d.ts +11 -0
  446. package/dist/types/retry/codec.d.ts +3 -0
  447. package/dist/types/retry/index.d.ts +4 -3
  448. package/dist/types/retry/parse.d.ts +5 -2
  449. package/dist/types/retry/replay.d.ts +0 -4
  450. package/dist/types/retry/tracker.d.ts +20 -0
  451. package/dist/types/retry/types.d.ts +10 -4
  452. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +15 -2
  453. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
  454. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
  455. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  456. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  457. package/dist/types/signal/api/result-map.d.ts +1 -0
  458. package/dist/types/signal/constants.d.ts +0 -3
  459. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
  460. package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
  461. package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
  462. package/dist/types/signal/index.d.ts +3 -0
  463. package/dist/types/signal/session/SignalProtocol.d.ts +19 -4
  464. package/dist/types/signal/session/resolver.d.ts +22 -0
  465. package/dist/types/store/contracts/appstate.store.d.ts +4 -1
  466. package/dist/types/store/contracts/contact.store.d.ts +1 -0
  467. package/dist/types/store/contracts/device-list.store.d.ts +0 -3
  468. package/dist/types/store/contracts/message.store.d.ts +1 -0
  469. package/dist/types/store/contracts/participants.store.d.ts +0 -1
  470. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  471. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  472. package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
  473. package/dist/types/store/contracts/signal.store.d.ts +13 -0
  474. package/dist/types/store/contracts/thread.store.d.ts +1 -0
  475. package/dist/types/store/createStore.d.ts +1 -1
  476. package/dist/types/store/index.d.ts +5 -13
  477. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  478. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  479. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  480. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  481. package/dist/types/store/locks/message.lock.d.ts +3 -0
  482. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  483. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  484. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  485. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  486. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  487. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  488. package/dist/types/store/providers/memory/appstate.store.d.ts +3 -1
  489. package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
  490. package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
  491. package/dist/types/store/providers/memory/message.store.d.ts +1 -0
  492. package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
  493. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  494. package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
  495. package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
  496. package/dist/types/store/providers/memory/signal.store.d.ts +8 -1
  497. package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
  498. package/dist/types/store/types.d.ts +49 -58
  499. package/dist/types/transport/WaWebSocket.d.ts +3 -1
  500. package/dist/types/transport/binary/constants.d.ts +0 -30
  501. package/dist/types/transport/binary/index.d.ts +0 -1
  502. package/dist/types/transport/index.d.ts +2 -1
  503. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
  504. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
  505. package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
  506. package/dist/types/transport/node/builders/business.d.ts +29 -0
  507. package/dist/types/transport/node/builders/global.d.ts +102 -0
  508. package/dist/types/transport/node/builders/group.d.ts +4 -6
  509. package/dist/types/transport/node/builders/index.d.ts +7 -3
  510. package/dist/types/transport/node/builders/message.d.ts +20 -30
  511. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  512. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  513. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  514. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  515. package/dist/types/transport/node/builders/retry.d.ts +2 -5
  516. package/dist/types/transport/node/builders/usync.d.ts +21 -0
  517. package/dist/types/transport/node/helpers.d.ts +13 -0
  518. package/dist/types/transport/node/usync.d.ts +2 -0
  519. package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
  520. package/dist/types/transport/noise/WaNoiseSession.d.ts +4 -2
  521. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  522. package/dist/types/transport/proxy.d.ts +6 -0
  523. package/dist/types/transport/stream/parse.d.ts +0 -1
  524. package/dist/types/transport/types.d.ts +18 -1
  525. package/dist/types/util/bytes.d.ts +5 -0
  526. package/dist/types/util/index.d.ts +5 -0
  527. package/dist/types/util/primitives.d.ts +2 -0
  528. package/dist/util/bytes.js +72 -46
  529. package/dist/util/coercion.js +6 -14
  530. package/dist/util/index.js +23 -0
  531. package/dist/util/primitives.js +42 -14
  532. package/package.json +52 -9
  533. package/proto/index.js +1 -1
  534. package/dist/crypto/core/constants.js +0 -4
  535. package/dist/crypto/core/encoding.js +0 -29
  536. package/dist/esm/crypto/core/constants.js +0 -1
  537. package/dist/esm/crypto/core/encoding.js +0 -25
  538. package/dist/esm/retry/outbound.js +0 -83
  539. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  540. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -169
  541. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  542. package/dist/esm/store/providers/sqlite/connection.js +0 -240
  543. package/dist/esm/store/providers/sqlite/contact.store.js +0 -61
  544. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -155
  545. package/dist/esm/store/providers/sqlite/message.store.js +0 -119
  546. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  547. package/dist/esm/store/providers/sqlite/participants.store.js +0 -85
  548. package/dist/esm/store/providers/sqlite/retry.store.js +0 -144
  549. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -203
  550. package/dist/esm/store/providers/sqlite/signal.store.js +0 -353
  551. package/dist/esm/store/providers/sqlite/thread.store.js +0 -72
  552. package/dist/esm/util/base64.js +0 -18
  553. package/dist/esm/util/signal-address.js +0 -5
  554. package/dist/retry/outbound.js +0 -88
  555. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  556. package/dist/store/providers/sqlite/appstate.store.js +0 -173
  557. package/dist/store/providers/sqlite/auth.store.js +0 -180
  558. package/dist/store/providers/sqlite/connection.js +0 -276
  559. package/dist/store/providers/sqlite/contact.store.js +0 -65
  560. package/dist/store/providers/sqlite/device-list.store.js +0 -159
  561. package/dist/store/providers/sqlite/message.store.js +0 -123
  562. package/dist/store/providers/sqlite/migrations.js +0 -350
  563. package/dist/store/providers/sqlite/participants.store.js +0 -89
  564. package/dist/store/providers/sqlite/retry.store.js +0 -148
  565. package/dist/store/providers/sqlite/sender-key.store.js +0 -207
  566. package/dist/store/providers/sqlite/signal.store.js +0 -357
  567. package/dist/store/providers/sqlite/thread.store.js +0 -76
  568. package/dist/types/appstate/store/sqlite.d.ts +0 -21
  569. package/dist/types/crypto/core/constants.d.ts +0 -1
  570. package/dist/types/crypto/core/encoding.d.ts +0 -11
  571. package/dist/types/retry/outbound.d.ts +0 -4
  572. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  573. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -15
  574. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  575. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  576. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -10
  577. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -18
  578. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -11
  579. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  580. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -13
  581. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -16
  582. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -25
  583. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -46
  584. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -11
  585. package/dist/types/util/base64.d.ts +0 -4
  586. package/dist/types/util/signal-address.d.ts +0 -2
  587. package/dist/util/base64.js +0 -24
  588. package/dist/util/signal-address.js +0 -8
  589. /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
@@ -5,20 +5,26 @@ const _proto_1 = require("../../proto.js");
5
5
  const constants_1 = require("../../protocol/constants");
6
6
  const jid_1 = require("../../protocol/jid");
7
7
  const constants_2 = require("../../retry/constants");
8
- const outbound_1 = require("../../retry/outbound");
9
8
  const parse_1 = require("../../retry/parse");
10
9
  const reason_1 = require("../../retry/reason");
11
10
  const replay_1 = require("../../retry/replay");
12
11
  const keygen_1 = require("../../signal/registration/keygen");
13
- const message_1 = require("../../transport/node/builders/message");
12
+ const global_1 = require("../../transport/node/builders/global");
14
13
  const retry_1 = require("../../transport/node/builders/retry");
14
+ const bytes_1 = require("../../util/bytes");
15
+ const collections_1 = require("../../util/collections");
15
16
  const primitives_1 = require("../../util/primitives");
17
+ const RETRY_CLEANUP_INTERVAL_MS = 30000;
18
+ const RETRY_SESSION_BASE_KEY_CACHE_MAX_ENTRIES = 8192;
16
19
  function getRetryReasonName(code) {
17
20
  if (code === undefined) {
18
21
  return undefined;
19
22
  }
20
- const entry = Object.entries(constants_2.RETRY_REASON).find(([, value]) => value === code);
21
- return entry ? entry[0] : 'unknown';
23
+ for (const reasonName in constants_2.RETRY_REASON) {
24
+ if (constants_2.RETRY_REASON[reasonName] === code)
25
+ return reasonName;
26
+ }
27
+ return 'unknown';
22
28
  }
23
29
  function getRemoteRetryReasonLogFields(reason) {
24
30
  return {
@@ -29,6 +35,7 @@ function getRemoteRetryReasonLogFields(reason) {
29
35
  }
30
36
  class WaRetryCoordinator {
31
37
  constructor(options) {
38
+ this.nextRetryCleanupAtMs = 0;
32
39
  this.logger = options.logger;
33
40
  this.retryStore = options.retryStore;
34
41
  this.retryTtlMs = this.retryStore.getTtlMs?.() ?? constants_2.RETRY_OUTBOUND_TTL_MS;
@@ -50,6 +57,7 @@ class WaRetryCoordinator {
50
57
  getCurrentSignedIdentity: this.getCurrentSignedIdentity
51
58
  });
52
59
  this.retryProcessingByMessageId = new Map();
60
+ this.retrySessionBaseKeys = new Map();
53
61
  }
54
62
  async onDecryptFailure(context, error) {
55
63
  try {
@@ -74,12 +82,23 @@ class WaRetryCoordinator {
74
82
  if (!this.isRetryReceiptNode(receiptNode)) {
75
83
  return;
76
84
  }
85
+ let shouldAck = false;
77
86
  try {
78
- await this.retryStore.cleanupExpired(Date.now());
79
- const request = (0, parse_1.parseRetryReceiptRequest)(receiptNode);
87
+ await this.maybeCleanupRetryStore(Date.now());
88
+ const expectedToJids = [];
89
+ const meJid = this.getCurrentMeJid()?.trim();
90
+ const meLid = this.getCurrentMeLid()?.trim();
91
+ if (meJid) {
92
+ expectedToJids.push(meJid);
93
+ }
94
+ if (meLid) {
95
+ expectedToJids.push(meLid);
96
+ }
97
+ const request = (0, parse_1.parseRetryReceiptRequest)(receiptNode, expectedToJids.length > 0 ? { expectedToJids } : undefined);
80
98
  if (!request) {
81
99
  return;
82
100
  }
101
+ shouldAck = true;
83
102
  await this.handleParsedRetryRequest(receiptNode, request);
84
103
  }
85
104
  catch (error) {
@@ -91,7 +110,9 @@ class WaRetryCoordinator {
91
110
  });
92
111
  }
93
112
  finally {
94
- await this.sendRetryAckSafe(receiptNode);
113
+ if (shouldAck) {
114
+ await this.sendRetryAckSafe(receiptNode);
115
+ }
95
116
  }
96
117
  }
97
118
  isRetryReceiptNode(node) {
@@ -100,10 +121,7 @@ class WaRetryCoordinator {
100
121
  }
101
122
  async prepareDecryptFailureRetry(context, error) {
102
123
  const nowMs = Date.now();
103
- const [, registrationInfo] = await Promise.all([
104
- this.retryStore.cleanupExpired(nowMs),
105
- this.signalStore.getRegistrationInfo()
106
- ]);
124
+ const registrationInfo = await this.signalStore.getRegistrationInfo();
107
125
  if (!registrationInfo) {
108
126
  this.logger.warn('retry receipt skipped: missing local registration info', {
109
127
  id: context.stanzaId,
@@ -130,7 +148,6 @@ class WaRetryCoordinator {
130
148
  to: context.from,
131
149
  participant: context.participant,
132
150
  recipient: context.recipient,
133
- from: this.getCurrentMeJid() ?? undefined,
134
151
  originalMsgId: context.stanzaId,
135
152
  retryCount: prepared.retryCount,
136
153
  t: prepared.timestamp,
@@ -198,6 +215,22 @@ class WaRetryCoordinator {
198
215
  });
199
216
  return null;
200
217
  }
218
+ let requesterAddress;
219
+ let requesterNormalizedDeviceJid;
220
+ try {
221
+ const requesterParsed = (0, jid_1.parseJidFull)(requesterJid);
222
+ requesterAddress = requesterParsed.address;
223
+ requesterNormalizedDeviceJid = requesterParsed.normalizedJid;
224
+ }
225
+ catch (error) {
226
+ this.logger.info('retry request rejected: invalid requester jid', {
227
+ id: request.stanzaId,
228
+ originalMsgId: request.originalMsgId,
229
+ requester: requesterJid,
230
+ message: (0, primitives_1.toError)(error).message
231
+ });
232
+ return null;
233
+ }
201
234
  if (request.retryCount >= constants_2.MAX_RETRY_ATTEMPTS) {
202
235
  this.logger.info('retry request rejected: retry count exceeded', {
203
236
  id: request.stanzaId,
@@ -217,7 +250,7 @@ class WaRetryCoordinator {
217
250
  });
218
251
  return null;
219
252
  }
220
- const sessionReady = await this.updateLocalSessionFromRetryRequest(request, requesterJid);
253
+ const sessionReady = await this.updateLocalSessionFromRetryRequest(request, requesterJid, requesterAddress, requesterNormalizedDeviceJid);
221
254
  if (!sessionReady) {
222
255
  this.logger.info('retry request rejected: missing compatible session', {
223
256
  id: request.stanzaId,
@@ -228,7 +261,7 @@ class WaRetryCoordinator {
228
261
  });
229
262
  return null;
230
263
  }
231
- const authorization = await this.authorizeRetryRequest(request, outbound, requesterJid);
264
+ const authorization = await this.authorizeRetryRequest(request, outbound, requesterJid, requesterAddress, requesterNormalizedDeviceJid);
232
265
  if (!authorization.authorized) {
233
266
  this.logger.info('retry request rejected', {
234
267
  id: request.stanzaId,
@@ -242,6 +275,8 @@ class WaRetryCoordinator {
242
275
  }
243
276
  return {
244
277
  requesterJid,
278
+ requesterAddress,
279
+ requesterNormalizedDeviceJid,
245
280
  outbound
246
281
  };
247
282
  }
@@ -261,20 +296,36 @@ class WaRetryCoordinator {
261
296
  if (!nextState) {
262
297
  return;
263
298
  }
264
- const current = await this.retryStore.getOutboundMessage(messageId);
265
- if (!current) {
266
- return;
267
- }
268
- const merged = (0, outbound_1.pickRetryStateMax)(current.state, nextState);
269
- if (merged === current.state) {
270
- return;
271
- }
272
- const nowMs = Date.now();
273
- await this.retryStore.updateOutboundMessageState(messageId, merged, nowMs, nowMs + this.retryTtlMs);
299
+ await this.runRetryTaskSerialized(messageId, async () => {
300
+ const current = await this.retryStore.getOutboundMessage(messageId);
301
+ if (!current) {
302
+ return;
303
+ }
304
+ const nowMs = Date.now();
305
+ const expiresAtMs = nowMs + this.retryTtlMs;
306
+ const merged = (0, parse_1.pickRetryStateMax)(current.state, nextState);
307
+ if (merged !== current.state) {
308
+ await this.retryStore.updateOutboundMessageState(messageId, merged, nowMs, expiresAtMs);
309
+ }
310
+ const requesterJid = receiptNode.attrs.participant ?? receiptNode.attrs.from;
311
+ if (!requesterJid) {
312
+ return;
313
+ }
314
+ try {
315
+ await this.retryStore.markOutboundRequesterDelivered(messageId, (0, jid_1.normalizeDeviceJid)(requesterJid), nowMs, expiresAtMs);
316
+ }
317
+ catch (error) {
318
+ this.logger.warn('failed to update outbound requester delivery state', {
319
+ id: messageId,
320
+ requester: requesterJid,
321
+ message: (0, primitives_1.toError)(error).message
322
+ });
323
+ }
324
+ });
274
325
  }
275
326
  async runRetryTaskSerialized(messageId, task) {
276
327
  const previous = this.retryProcessingByMessageId.get(messageId) ?? Promise.resolve();
277
- const current = previous.catch(() => undefined).then(async () => task());
328
+ const current = previous.then(task);
278
329
  const tracker = current.then(() => undefined, () => undefined);
279
330
  this.retryProcessingByMessageId.set(messageId, tracker);
280
331
  try {
@@ -314,18 +365,47 @@ class WaRetryCoordinator {
314
365
  : undefined
315
366
  };
316
367
  }
317
- async updateLocalSessionFromRetryRequest(request, requesterJid) {
318
- await this.markRetryRequesterSenderKeyAsStale(request, requesterJid);
319
- const address = (0, jid_1.parseSignalAddressFromJid)(requesterJid);
320
- const currentSession = await this.signalStore.getSession(address);
321
- if (currentSession && request.regId > 0 && currentSession.remote.regId !== request.regId) {
322
- await this.signalStore.deleteSession(address);
368
+ async updateLocalSessionFromRetryRequest(request, requesterJid, requesterAddress, requesterNormalizedDeviceJid) {
369
+ const [, currentSession] = await Promise.all([
370
+ this.markRetryRequesterSenderKeyAsStale(request, requesterJid, requesterAddress),
371
+ this.signalStore.getSession(requesterAddress)
372
+ ]);
373
+ const regIdMismatch = !!currentSession && request.regId > 0 && currentSession.remote.regId !== request.regId;
374
+ if (regIdMismatch && !request.keyBundle) {
375
+ await this.signalStore.deleteSession(requesterAddress);
323
376
  }
324
377
  if (request.keyBundle) {
325
- if (!request.keyBundle.key) {
378
+ if (!request.keyBundle.key || !request.keyBundle.skey.signature) {
326
379
  return false;
327
380
  }
328
- await this.signalProtocol.establishOutgoingSession(address, {
381
+ if (request.offline) {
382
+ if (!currentSession) {
383
+ this.logger.info('retry request rejected: offline retry missing existing session', {
384
+ id: request.stanzaId,
385
+ originalMsgId: request.originalMsgId,
386
+ requester: requesterJid,
387
+ remoteRetryCount: request.retryCount,
388
+ ...getRemoteRetryReasonLogFields(request.retryReason)
389
+ });
390
+ await this.signalStore.deleteSession(requesterAddress);
391
+ return false;
392
+ }
393
+ if (regIdMismatch) {
394
+ this.logger.info('retry request rejected: offline retry registration id mismatch', {
395
+ id: request.stanzaId,
396
+ originalMsgId: request.originalMsgId,
397
+ requester: requesterJid,
398
+ remoteRetryCount: request.retryCount,
399
+ ...getRemoteRetryReasonLogFields(request.retryReason)
400
+ });
401
+ await this.signalStore.deleteSession(requesterAddress);
402
+ return false;
403
+ }
404
+ }
405
+ else if (regIdMismatch) {
406
+ await this.signalStore.deleteSession(requesterAddress);
407
+ }
408
+ await this.signalProtocol.establishOutgoingSession(requesterAddress, {
329
409
  regId: request.regId,
330
410
  identity: request.keyBundle.identity,
331
411
  signedKey: {
@@ -338,25 +418,57 @@ class WaRetryCoordinator {
338
418
  publicKey: request.keyBundle.key.publicKey
339
419
  }
340
420
  });
421
+ return this.applySessionBaseKeyPolicy(request, requesterJid, requesterAddress, requesterNormalizedDeviceJid);
422
+ }
423
+ const sessionStillExists = currentSession !== null && !regIdMismatch;
424
+ if (sessionStillExists) {
425
+ return this.applySessionBaseKeyPolicy(request, requesterJid, requesterAddress, requesterNormalizedDeviceJid);
426
+ }
427
+ const fetched = await this.fetchMissingPreKeysSession(requesterJid, requesterAddress, requesterNormalizedDeviceJid, request.regId);
428
+ if (!fetched) {
429
+ return false;
430
+ }
431
+ await this.signalProtocol.establishOutgoingSession(requesterAddress, fetched);
432
+ return this.applySessionBaseKeyPolicy(request, requesterJid, requesterAddress, requesterNormalizedDeviceJid);
433
+ }
434
+ async applySessionBaseKeyPolicy(request, requesterJid, requesterAddress, requesterNormalizedDeviceJid) {
435
+ if (request.retryCount < 2) {
436
+ return true;
437
+ }
438
+ const currentSession = await this.signalStore.getSession(requesterAddress);
439
+ const sessionBaseKey = currentSession?.aliceBaseKey ?? null;
440
+ if (!sessionBaseKey) {
341
441
  return true;
342
442
  }
343
- const hasSession = await this.signalProtocol.hasSession(address);
344
- if (hasSession) {
443
+ const expiresAtMs = Date.now() + this.retryTtlMs;
444
+ if (request.retryCount === 2) {
445
+ this.setRetrySessionBaseKey(request.originalMsgId, requesterNormalizedDeviceJid, sessionBaseKey, expiresAtMs);
345
446
  return true;
346
447
  }
347
- const fetched = await this.fetchMissingPreKeysSession(requesterJid, request.regId);
448
+ const saved = this.getRetrySessionBaseKey(request.originalMsgId, requesterNormalizedDeviceJid);
449
+ if (!saved || !(0, bytes_1.uint8Equal)(saved.baseKey, sessionBaseKey)) {
450
+ return true;
451
+ }
452
+ await this.signalStore.deleteSession(requesterAddress);
453
+ this.logger.info('retry request forcing session refresh due to repeated base key', {
454
+ id: request.stanzaId,
455
+ originalMsgId: request.originalMsgId,
456
+ requester: requesterJid,
457
+ remoteRetryCount: request.retryCount,
458
+ ...getRemoteRetryReasonLogFields(request.retryReason)
459
+ });
460
+ const fetched = await this.fetchMissingPreKeysSession(requesterJid, requesterAddress, requesterNormalizedDeviceJid, request.regId);
348
461
  if (!fetched) {
349
462
  return false;
350
463
  }
351
- await this.signalProtocol.establishOutgoingSession(address, fetched);
464
+ await this.signalProtocol.establishOutgoingSession(requesterAddress, fetched);
352
465
  return true;
353
466
  }
354
- async markRetryRequesterSenderKeyAsStale(request, requesterJid) {
467
+ async markRetryRequesterSenderKeyAsStale(request, requesterJid, requesterAddress) {
355
468
  if (!(0, jid_1.isGroupOrBroadcastJid)(request.from)) {
356
469
  return;
357
470
  }
358
471
  try {
359
- const requesterAddress = (0, jid_1.parseSignalAddressFromJid)(requesterJid);
360
472
  const deleted = await this.senderKeyStore.markForgetSenderKey(request.from, [
361
473
  requesterAddress
362
474
  ]);
@@ -374,12 +486,11 @@ class WaRetryCoordinator {
374
486
  });
375
487
  }
376
488
  }
377
- async fetchMissingPreKeysSession(requesterJid, requesterRegistrationId) {
489
+ async fetchMissingPreKeysSession(requesterJid, requesterAddress, requesterNormalizedDeviceJid, requesterRegistrationId) {
378
490
  try {
379
- const requesterAddress = (0, jid_1.parseSignalAddressFromJid)(requesterJid);
380
491
  const results = await this.signalMissingPreKeysSync.fetchMissingPreKeys([
381
492
  {
382
- userJid: (0, jid_1.toUserJid)(requesterJid),
493
+ userJid: `${requesterAddress.user}@${requesterAddress.server}`,
383
494
  devices: [
384
495
  {
385
496
  deviceId: requesterAddress.device,
@@ -396,8 +507,7 @@ class WaRetryCoordinator {
396
507
  });
397
508
  return null;
398
509
  }
399
- const requesterDeviceJid = (0, jid_1.normalizeDeviceJid)(requesterJid);
400
- const matched = first.devices.find((device) => (0, jid_1.normalizeDeviceJid)(device.deviceJid) === requesterDeviceJid);
510
+ const matched = first.devices.find((device) => (0, jid_1.normalizeDeviceJid)(device.deviceJid) === requesterNormalizedDeviceJid);
401
511
  if (!matched) {
402
512
  this.logger.warn('missing prekeys fetch did not return requested device', {
403
513
  requester: requesterJid,
@@ -415,33 +525,59 @@ class WaRetryCoordinator {
415
525
  return null;
416
526
  }
417
527
  }
418
- async authorizeRetryRequest(request, outbound, requesterJid) {
528
+ async authorizeRetryRequest(request, outbound, requesterJid, requesterAddress, requesterNormalizedDeviceJid) {
419
529
  if (outbound.state === 'ineligible') {
420
530
  return { authorized: false, reason: `state_${outbound.state}` };
421
531
  }
532
+ let requesterStatus = null;
533
+ try {
534
+ requesterStatus = await this.retryStore.getOutboundRequesterStatus(outbound.messageId, requesterNormalizedDeviceJid);
535
+ }
536
+ catch (error) {
537
+ this.logger.warn('failed to resolve outbound requester status from retry store', {
538
+ id: request.stanzaId,
539
+ originalMsgId: request.originalMsgId,
540
+ requester: requesterJid,
541
+ message: (0, primitives_1.toError)(error).message
542
+ });
543
+ }
544
+ if (requesterStatus) {
545
+ if (!requesterStatus.eligible) {
546
+ return { authorized: false, reason: 'requester_device_not_eligible' };
547
+ }
548
+ if (requesterStatus.delivered) {
549
+ return { authorized: false, reason: 'requester_already_delivered' };
550
+ }
551
+ }
422
552
  const isGroupOutbound = (0, jid_1.isGroupOrBroadcastJid)(outbound.toJid);
423
553
  if (!isGroupOutbound && (outbound.state === 'read' || outbound.state === 'played')) {
424
554
  return { authorized: false, reason: `state_${outbound.state}` };
425
555
  }
426
- const requesterAuthorized = await this.isRequesterAuthorizedDevice(requesterJid);
427
- if (!requesterAuthorized) {
428
- return { authorized: false, reason: 'requester_device_not_authorized' };
556
+ if (!requesterStatus) {
557
+ const requesterAuthorized = await this.isRequesterAuthorizedDevice(requesterJid, requesterAddress, requesterNormalizedDeviceJid);
558
+ if (!requesterAuthorized) {
559
+ return { authorized: false, reason: 'requester_device_not_authorized' };
560
+ }
429
561
  }
430
562
  return { authorized: true };
431
563
  }
432
- async isRequesterAuthorizedDevice(requesterJid) {
564
+ async isRequesterAuthorizedDevice(requesterJid, requesterAddress, requesterNormalizedDeviceJid) {
433
565
  try {
434
- const requesterUser = (0, jid_1.toUserJid)(requesterJid);
566
+ const requesterUser = `${requesterAddress.user}@${requesterAddress.server}`;
567
+ if (requesterNormalizedDeviceJid === (0, jid_1.normalizeDeviceJid)(requesterUser)) {
568
+ return true;
569
+ }
435
570
  const synced = await this.signalDeviceSync.syncDeviceList([requesterUser]);
436
571
  const target = synced.find((entry) => entry.jid === requesterUser);
437
- const authorized = new Set();
438
- authorized.add((0, jid_1.normalizeDeviceJid)(requesterUser));
439
- if (target) {
440
- for (let index = 0; index < target.deviceJids.length; index += 1) {
441
- authorized.add((0, jid_1.normalizeDeviceJid)(target.deviceJids[index]));
572
+ if (!target) {
573
+ return false;
574
+ }
575
+ for (let index = 0; index < target.deviceJids.length; index += 1) {
576
+ if ((0, jid_1.normalizeDeviceJid)(target.deviceJids[index]) === requesterNormalizedDeviceJid) {
577
+ return true;
442
578
  }
443
579
  }
444
- return authorized.has((0, jid_1.normalizeDeviceJid)(requesterJid));
580
+ return false;
445
581
  }
446
582
  catch (error) {
447
583
  this.logger.warn('retry authorization failed while syncing requester device list', {
@@ -479,7 +615,11 @@ class WaRetryCoordinator {
479
615
  return;
480
616
  }
481
617
  try {
482
- await this.sendNode((0, message_1.buildInboundRetryReceiptAckNode)(receiptNode));
618
+ await this.sendNode((0, global_1.buildAckNode)({
619
+ kind: 'receipt',
620
+ node: receiptNode,
621
+ retryType: true
622
+ }));
483
623
  }
484
624
  catch (error) {
485
625
  this.logger.warn('failed to send retry ack', {
@@ -490,5 +630,50 @@ class WaRetryCoordinator {
490
630
  });
491
631
  }
492
632
  }
633
+ async maybeCleanupRetryStore(nowMs) {
634
+ if (nowMs < this.nextRetryCleanupAtMs) {
635
+ return;
636
+ }
637
+ this.nextRetryCleanupAtMs = nowMs + RETRY_CLEANUP_INTERVAL_MS;
638
+ this.cleanupRetrySessionBaseKeys(nowMs);
639
+ try {
640
+ await this.retryStore.cleanupExpired(nowMs);
641
+ }
642
+ catch (error) {
643
+ this.logger.warn('retry store cleanup failed', {
644
+ message: (0, primitives_1.toError)(error).message
645
+ });
646
+ }
647
+ }
648
+ retrySessionBaseKeyMapKey(originalMsgId, requesterNormalizedDeviceJid) {
649
+ return `${originalMsgId}|${requesterNormalizedDeviceJid}`;
650
+ }
651
+ setRetrySessionBaseKey(originalMsgId, requesterNormalizedDeviceJid, baseKey, expiresAtMs) {
652
+ const key = this.retrySessionBaseKeyMapKey(originalMsgId, requesterNormalizedDeviceJid);
653
+ (0, collections_1.setBoundedMapEntry)(this.retrySessionBaseKeys, key, {
654
+ baseKey: Uint8Array.from(baseKey),
655
+ expiresAtMs
656
+ }, RETRY_SESSION_BASE_KEY_CACHE_MAX_ENTRIES);
657
+ }
658
+ getRetrySessionBaseKey(originalMsgId, requesterNormalizedDeviceJid) {
659
+ const key = this.retrySessionBaseKeyMapKey(originalMsgId, requesterNormalizedDeviceJid);
660
+ const entry = this.retrySessionBaseKeys.get(key);
661
+ if (!entry) {
662
+ return null;
663
+ }
664
+ if (entry.expiresAtMs <= Date.now()) {
665
+ this.retrySessionBaseKeys.delete(key);
666
+ return null;
667
+ }
668
+ return entry;
669
+ }
670
+ cleanupRetrySessionBaseKeys(nowMs) {
671
+ for (const [key, entry] of this.retrySessionBaseKeys) {
672
+ if (entry.expiresAtMs > nowMs) {
673
+ continue;
674
+ }
675
+ this.retrySessionBaseKeys.delete(key);
676
+ }
677
+ }
493
678
  }
494
679
  exports.WaRetryCoordinator = WaRetryCoordinator;
@@ -19,7 +19,7 @@ function createStreamControlHandler(options) {
19
19
  const restartBackendAfterStreamControl = async (reason) => {
20
20
  logger.info('restarting backend after stream control', { reason });
21
21
  try {
22
- await connect();
22
+ await connect(constants_1.WA_CONNECTION_REASONS.RECONNECTED);
23
23
  }
24
24
  catch (error) {
25
25
  logger.warn('failed to restart backend after stream control', {
@@ -46,29 +46,36 @@ function createStreamControlHandler(options) {
46
46
  });
47
47
  }
48
48
  };
49
+ const stopCommsImmediately = () => {
50
+ void getComms()?.stopComms();
51
+ };
49
52
  const forceLoginDueToStreamError = async (code) => {
50
- await runStreamControlLifecycle(`stream_error_code_${code}`, async () => {
53
+ const reason = constants_1.WA_DISCONNECT_REASONS.STREAM_ERROR_FORCE_LOGIN;
54
+ stopCommsImmediately();
55
+ await runStreamControlLifecycle(reason, async () => {
51
56
  logger.warn('received forced login stream error; starting login lifecycle', {
52
57
  code
53
58
  });
54
- await disconnect();
59
+ await disconnect(reason, true, code);
55
60
  await clearStoredCredentials();
56
- await restartBackendAfterStreamControl(`stream_error_code_${code}`);
61
+ await restartBackendAfterStreamControl(reason);
57
62
  });
58
63
  };
59
- const disconnectDueToStreamError = async (reason) => {
64
+ const disconnectDueToStreamError = async (reason, code) => {
65
+ stopCommsImmediately();
60
66
  await runStreamControlLifecycle(reason, async () => {
61
67
  logger.warn('disconnecting due to stream control node', { reason });
62
- await disconnect();
68
+ await disconnect(reason, false, code);
63
69
  });
64
70
  };
65
- const logoutDueToStreamError = async (reason, shouldRestartBackend) => {
71
+ const logoutDueToStreamError = async (reason, code, shouldRestartBackend) => {
72
+ stopCommsImmediately();
66
73
  await runStreamControlLifecycle(reason, async () => {
67
74
  logger.warn('logging out due to stream control node', {
68
75
  reason,
69
76
  shouldRestartBackend
70
77
  });
71
- await disconnect();
78
+ await disconnect(reason, true, code);
72
79
  await clearStoredCredentials();
73
80
  if (shouldRestartBackend) {
74
81
  await restartBackendAfterStreamControl(reason);
@@ -89,7 +96,7 @@ function createStreamControlHandler(options) {
89
96
  return;
90
97
  }
91
98
  if (result.code === constants_1.WA_STREAM_SIGNALING.FORCE_LOGOUT_CODE) {
92
- await logoutDueToStreamError(`stream_error_code_${constants_1.WA_STREAM_SIGNALING.FORCE_LOGOUT_CODE}`, true);
99
+ await logoutDueToStreamError(constants_1.WA_DISCONNECT_REASONS.STREAM_ERROR_FORCE_LOGOUT, result.code, true);
93
100
  return;
94
101
  }
95
102
  }
@@ -97,11 +104,11 @@ function createStreamControlHandler(options) {
97
104
  return;
98
105
  case 'stream_error_replaced':
99
106
  logger.warn('received stream:error replaced, stopping client');
100
- await disconnectDueToStreamError(constants_1.WA_DISCONNECT_REASONS.STREAM_ERROR_REPLACED);
107
+ await disconnectDueToStreamError(constants_1.WA_DISCONNECT_REASONS.STREAM_ERROR_REPLACED, null);
101
108
  return;
102
109
  case 'stream_error_device_removed':
103
110
  logger.warn('received stream:error device removed, logging out');
104
- await logoutDueToStreamError(constants_1.WA_DISCONNECT_REASONS.STREAM_ERROR_DEVICE_REMOVED, false);
111
+ await logoutDueToStreamError(constants_1.WA_DISCONNECT_REASONS.STREAM_ERROR_DEVICE_REMOVED, null, false);
105
112
  return;
106
113
  case 'stream_error_ack':
107
114
  logger.warn('received stream:error ack', { id: result.id });