zapo-js 0.1.2 → 0.3.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 (630) hide show
  1. package/README.md +16 -4
  2. package/dist/appstate/WaAppStateCrypto.js +50 -42
  3. package/dist/appstate/WaAppStateSyncClient.js +215 -133
  4. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  5. package/dist/appstate/index.js +9 -7
  6. package/dist/appstate/utils.js +0 -5
  7. package/dist/auth/WaAuthClient.js +55 -57
  8. package/dist/auth/credentials-flow.js +195 -0
  9. package/dist/auth/index.js +1 -6
  10. package/dist/auth/pairing/WaPairingFlow.js +39 -32
  11. package/dist/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +35 -17
  12. package/dist/client/WaClient.js +338 -174
  13. package/dist/client/WaClientFactory.js +399 -66
  14. package/dist/client/connection/WaConnectionManager.js +23 -11
  15. package/dist/client/coordinators/WaAbPropsCoordinator.js +141 -0
  16. package/dist/client/coordinators/WaBusinessCoordinator.js +232 -0
  17. package/dist/client/coordinators/WaEmailCoordinator.js +63 -0
  18. package/dist/client/coordinators/WaGroupCoordinator.js +11 -7
  19. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +34 -8
  20. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +341 -118
  21. package/dist/client/coordinators/WaOfflineResumeCoordinator.js +114 -0
  22. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +97 -36
  23. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  24. package/dist/client/coordinators/WaProfileCoordinator.js +214 -0
  25. package/dist/client/coordinators/WaRetryCoordinator.js +184 -30
  26. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  27. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +184 -0
  28. package/dist/client/dirty.js +41 -21
  29. package/dist/client/events/abprops.js +43 -0
  30. package/dist/client/events/devices.js +72 -0
  31. package/dist/client/events/group.js +3 -11
  32. package/dist/client/events/identity.js +22 -0
  33. package/dist/client/events/privacy-token.js +38 -0
  34. package/dist/client/events/registration.js +42 -0
  35. package/dist/client/history-sync.js +50 -9
  36. package/dist/client/incoming.js +74 -7
  37. package/dist/client/mailbox.js +40 -23
  38. package/dist/client/media.js +243 -0
  39. package/dist/client/messages.js +245 -92
  40. package/dist/client/messaging/fanout.js +21 -11
  41. package/dist/client/messaging/participants.js +6 -4
  42. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  43. package/dist/client/tokens/cs-token.js +50 -0
  44. package/dist/client/tokens/tc-token.js +25 -0
  45. package/dist/crypto/core/index.js +5 -2
  46. package/dist/crypto/core/keys.js +4 -4
  47. package/dist/crypto/core/nonce.js +2 -0
  48. package/dist/crypto/core/primitives.js +0 -8
  49. package/dist/crypto/core/random.js +24 -8
  50. package/dist/crypto/core/xeddsa.js +57 -0
  51. package/dist/crypto/curves/X25519.js +43 -6
  52. package/dist/crypto/curves/constants.js +2 -1
  53. package/dist/crypto/index.js +3 -0
  54. package/dist/crypto/math/constants.js +13 -36
  55. package/dist/crypto/math/edwards.js +171 -44
  56. package/dist/crypto/math/fe.js +706 -0
  57. package/dist/crypto/math/mod.js +10 -3
  58. package/dist/esm/appstate/WaAppStateCrypto.js +40 -32
  59. package/dist/esm/appstate/WaAppStateSyncClient.js +206 -124
  60. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  61. package/dist/esm/appstate/index.js +2 -2
  62. package/dist/esm/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +1 -1
  63. package/dist/esm/appstate/utils.js +2 -5
  64. package/dist/esm/auth/WaAuthClient.js +52 -54
  65. package/dist/esm/auth/credentials-flow.js +190 -0
  66. package/dist/esm/auth/index.js +0 -2
  67. package/dist/esm/auth/pairing/WaPairingFlow.js +39 -32
  68. package/dist/esm/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +26 -10
  69. package/dist/esm/client/WaClient.js +339 -175
  70. package/dist/esm/client/WaClientFactory.js +401 -68
  71. package/dist/esm/client/connection/WaConnectionManager.js +23 -11
  72. package/dist/esm/client/coordinators/WaAbPropsCoordinator.js +137 -0
  73. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +229 -0
  74. package/dist/esm/client/coordinators/WaEmailCoordinator.js +60 -0
  75. package/dist/esm/client/coordinators/WaGroupCoordinator.js +11 -7
  76. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +36 -10
  77. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +337 -114
  78. package/dist/esm/client/coordinators/WaOfflineResumeCoordinator.js +110 -0
  79. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +97 -36
  80. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  81. package/dist/esm/client/coordinators/WaProfileCoordinator.js +211 -0
  82. package/dist/esm/client/coordinators/WaRetryCoordinator.js +186 -32
  83. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  84. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +180 -0
  85. package/dist/esm/client/dirty.js +41 -21
  86. package/dist/esm/client/events/abprops.js +40 -0
  87. package/dist/esm/client/events/devices.js +68 -0
  88. package/dist/esm/client/events/group.js +3 -11
  89. package/dist/esm/client/events/identity.js +19 -0
  90. package/dist/esm/client/events/privacy-token.js +35 -0
  91. package/dist/esm/client/events/registration.js +39 -0
  92. package/dist/esm/client/history-sync.js +50 -9
  93. package/dist/esm/client/incoming.js +74 -8
  94. package/dist/esm/client/mailbox.js +40 -23
  95. package/dist/esm/client/media.js +234 -0
  96. package/dist/esm/client/messages.js +244 -91
  97. package/dist/esm/client/messaging/fanout.js +22 -12
  98. package/dist/esm/client/messaging/participants.js +6 -4
  99. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  100. package/dist/esm/client/tokens/cs-token.js +46 -0
  101. package/dist/esm/client/tokens/tc-token.js +18 -0
  102. package/dist/esm/crypto/core/index.js +3 -2
  103. package/dist/esm/crypto/core/keys.js +1 -1
  104. package/dist/esm/crypto/core/nonce.js +2 -0
  105. package/dist/esm/crypto/core/primitives.js +0 -7
  106. package/dist/esm/crypto/core/random.js +23 -7
  107. package/dist/esm/crypto/core/xeddsa.js +53 -0
  108. package/dist/esm/crypto/curves/X25519.js +45 -8
  109. package/dist/esm/crypto/curves/constants.js +1 -0
  110. package/dist/esm/crypto/index.js +1 -0
  111. package/dist/esm/crypto/math/constants.js +12 -35
  112. package/dist/esm/crypto/math/edwards.js +174 -47
  113. package/dist/esm/crypto/math/fe.js +691 -0
  114. package/dist/esm/crypto/math/mod.js +10 -1
  115. package/dist/esm/index.js +1 -1
  116. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  117. package/dist/esm/infra/perf/BoundedTaskQueue.js +3 -1
  118. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  119. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  120. package/dist/esm/infra/perf/StoreLock.js +80 -0
  121. package/dist/esm/media/WaMediaCrypto.js +332 -55
  122. package/dist/esm/media/WaMediaTransferClient.js +69 -220
  123. package/dist/esm/media/constants.js +4 -1
  124. package/dist/esm/media/processor.js +1 -0
  125. package/dist/esm/message/WaMessageClient.js +26 -19
  126. package/dist/esm/message/addon-crypto.js +130 -3
  127. package/dist/esm/message/content.js +206 -14
  128. package/dist/esm/message/icdc.js +76 -0
  129. package/dist/esm/message/incoming.js +38 -24
  130. package/dist/esm/message/phash.js +35 -13
  131. package/dist/esm/message/reporting-token.js +17 -30
  132. package/dist/esm/message/use-case-secret.js +1 -1
  133. package/dist/esm/protocol/abprops.js +159 -0
  134. package/dist/esm/protocol/appstate.js +9 -40
  135. package/dist/esm/protocol/browser.js +24 -18
  136. package/dist/esm/protocol/constants.js +8 -4
  137. package/dist/esm/protocol/defaults.js +6 -0
  138. package/dist/esm/protocol/email.js +30 -0
  139. package/dist/esm/protocol/index.js +1 -2
  140. package/dist/esm/protocol/jid.js +142 -39
  141. package/dist/esm/protocol/message.js +61 -1
  142. package/dist/esm/protocol/nodes.js +8 -2
  143. package/dist/esm/protocol/notification.js +9 -1
  144. package/dist/esm/protocol/privacy-token.js +17 -0
  145. package/dist/esm/protocol/privacy.js +55 -0
  146. package/dist/esm/protocol/stream.js +26 -1
  147. package/dist/esm/retry/codec.js +216 -0
  148. package/dist/esm/retry/constants.js +1 -1
  149. package/dist/esm/retry/index.js +2 -2
  150. package/dist/esm/retry/parse.js +50 -30
  151. package/dist/esm/retry/reason.js +1 -1
  152. package/dist/esm/retry/replay.js +11 -7
  153. package/dist/esm/retry/tracker.js +50 -12
  154. package/dist/esm/signal/api/SignalDeviceSyncApi.js +52 -32
  155. package/dist/esm/signal/api/SignalDigestSyncApi.js +21 -15
  156. package/dist/esm/signal/api/SignalIdentitySyncApi.js +30 -15
  157. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +19 -8
  158. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  159. package/dist/esm/signal/api/SignalSessionSyncApi.js +17 -8
  160. package/dist/esm/signal/api/result-map.js +10 -0
  161. package/dist/esm/signal/constants.js +0 -4
  162. package/dist/esm/signal/crypto/WaAdvSignature.js +5 -45
  163. package/dist/esm/signal/crypto/constants.js +0 -4
  164. package/dist/esm/signal/{store/sqlite.js → encoding.js} +40 -29
  165. package/dist/esm/signal/group/SenderKeyChain.js +3 -3
  166. package/dist/esm/signal/group/SenderKeyCodec.js +8 -8
  167. package/dist/esm/signal/group/SenderKeyManager.js +131 -109
  168. package/dist/esm/signal/index.js +1 -0
  169. package/dist/esm/signal/registration/keygen.js +8 -5
  170. package/dist/esm/signal/registration/utils.js +3 -2
  171. package/dist/esm/signal/session/SignalProtocol.js +158 -81
  172. package/dist/esm/signal/session/SignalRatchet.js +21 -10
  173. package/dist/esm/signal/session/SignalSerializer.js +5 -6
  174. package/dist/esm/signal/session/SignalSession.js +11 -9
  175. package/dist/esm/signal/session/resolver.js +140 -105
  176. package/dist/esm/store/contracts/identity.store.js +1 -0
  177. package/dist/esm/store/contracts/message-secret.store.js +1 -0
  178. package/dist/esm/store/contracts/pre-key.store.js +1 -0
  179. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  180. package/dist/esm/store/contracts/session.store.js +1 -0
  181. package/dist/esm/store/createStore.js +143 -193
  182. package/dist/esm/store/index.js +5 -10
  183. package/dist/esm/store/locks/appstate.lock.js +26 -0
  184. package/dist/esm/store/locks/auth.lock.js +15 -0
  185. package/dist/esm/store/locks/contact.lock.js +20 -0
  186. package/dist/esm/store/locks/device-list.lock.js +20 -0
  187. package/dist/esm/store/locks/identity.lock.js +16 -0
  188. package/dist/esm/store/locks/message-secret.lock.js +17 -0
  189. package/dist/esm/store/locks/message.lock.js +21 -0
  190. package/dist/esm/store/locks/participants.lock.js +20 -0
  191. package/dist/esm/store/locks/pre-key.lock.js +27 -0
  192. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  193. package/dist/esm/store/locks/retry.lock.js +29 -0
  194. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  195. package/dist/esm/store/locks/session.lock.js +19 -0
  196. package/dist/esm/store/locks/signal.lock.js +39 -0
  197. package/dist/esm/store/locks/thread.lock.js +21 -0
  198. package/dist/esm/store/noop.store.js +21 -1
  199. package/dist/esm/store/providers/memory/appstate.store.js +22 -24
  200. package/dist/esm/store/providers/memory/device-list.store.js +13 -5
  201. package/dist/esm/store/providers/memory/identity.store.js +31 -0
  202. package/dist/esm/store/providers/memory/message-secret.store.js +81 -0
  203. package/dist/esm/store/providers/memory/participants.store.js +3 -0
  204. package/dist/esm/store/providers/memory/pre-key.store.js +97 -0
  205. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  206. package/dist/esm/store/providers/memory/retry.store.js +99 -10
  207. package/dist/esm/store/providers/memory/sender-key.store.js +6 -1
  208. package/dist/esm/store/providers/memory/session.store.js +45 -0
  209. package/dist/esm/store/providers/memory/signal.store.js +1 -147
  210. package/dist/esm/transport/WaComms.js +7 -4
  211. package/dist/esm/transport/WaWebSocket.js +9 -7
  212. package/dist/esm/transport/binary/constants.js +0 -30
  213. package/dist/esm/transport/binary/decoder.js +4 -4
  214. package/dist/esm/transport/binary/encoder.js +8 -15
  215. package/dist/esm/transport/binary/index.js +0 -1
  216. package/dist/esm/transport/index.js +6 -0
  217. package/dist/esm/transport/keepalive/WaKeepAlive.js +17 -8
  218. package/dist/esm/transport/node/WaMobileTcpSocket.js +114 -0
  219. package/dist/esm/transport/node/WaNodeOrchestrator.js +37 -22
  220. package/dist/esm/transport/node/builders/abprops.js +20 -0
  221. package/dist/esm/transport/node/builders/business.js +129 -0
  222. package/dist/esm/transport/node/builders/device.js +11 -0
  223. package/dist/esm/transport/node/builders/email.js +65 -0
  224. package/dist/esm/transport/node/builders/global.js +370 -0
  225. package/dist/esm/transport/node/builders/message.js +63 -239
  226. package/dist/esm/transport/node/builders/offline.js +14 -0
  227. package/dist/esm/transport/node/builders/pairing.js +0 -24
  228. package/dist/esm/transport/node/builders/prekeys.js +37 -40
  229. package/dist/esm/transport/node/builders/presence.js +13 -0
  230. package/dist/esm/transport/node/builders/privacy-token.js +37 -0
  231. package/dist/esm/transport/node/builders/privacy.js +48 -0
  232. package/dist/esm/transport/node/builders/profile.js +70 -0
  233. package/dist/esm/transport/node/builders/retry.js +11 -23
  234. package/dist/esm/transport/node/builders/usync.js +6 -2
  235. package/dist/esm/transport/node/helpers.js +43 -1
  236. package/dist/esm/transport/node/mex/argo-decoder.js +152 -0
  237. package/dist/esm/transport/node/mex/client.js +83 -0
  238. package/dist/esm/transport/node/mex/persist-ids.js +10 -0
  239. package/dist/esm/transport/node/usync.js +3 -33
  240. package/dist/esm/transport/node/xml.js +35 -14
  241. package/dist/esm/transport/noise/WaClientPayload.js +24 -19
  242. package/dist/esm/transport/noise/WaFrameCodec.js +2 -2
  243. package/dist/esm/transport/noise/WaMobileClientPayload.js +53 -0
  244. package/dist/esm/transport/noise/WaNoiseCert.js +9 -27
  245. package/dist/esm/transport/noise/WaNoiseSession.js +76 -34
  246. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  247. package/dist/esm/transport/stream/parse.js +8 -4
  248. package/dist/esm/util/bytes.js +22 -18
  249. package/dist/esm/util/index.js +5 -0
  250. package/dist/esm/util/primitives.js +3 -2
  251. package/dist/index.js +7 -1
  252. package/dist/infra/perf/BackgroundQueue.js +482 -0
  253. package/dist/infra/perf/BoundedTaskQueue.js +3 -1
  254. package/dist/infra/perf/PromiseDedup.js +24 -0
  255. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  256. package/dist/infra/perf/StoreLock.js +84 -0
  257. package/dist/media/WaMediaCrypto.js +328 -51
  258. package/dist/media/WaMediaTransferClient.js +72 -253
  259. package/dist/media/constants.js +5 -2
  260. package/dist/media/processor.js +2 -0
  261. package/dist/message/WaMessageClient.js +26 -19
  262. package/dist/message/addon-crypto.js +131 -0
  263. package/dist/message/content.js +211 -14
  264. package/dist/message/icdc.js +81 -0
  265. package/dist/message/incoming.js +38 -24
  266. package/dist/message/phash.js +35 -13
  267. package/dist/message/reporting-token.js +16 -30
  268. package/dist/message/use-case-secret.js +1 -1
  269. package/dist/protocol/abprops.js +163 -0
  270. package/dist/protocol/appstate.js +10 -41
  271. package/dist/protocol/browser.js +25 -18
  272. package/dist/protocol/constants.js +33 -2
  273. package/dist/protocol/defaults.js +6 -0
  274. package/dist/protocol/email.js +33 -0
  275. package/dist/protocol/index.js +8 -5
  276. package/dist/protocol/jid.js +149 -39
  277. package/dist/protocol/message.js +62 -2
  278. package/dist/protocol/nodes.js +8 -2
  279. package/dist/protocol/notification.js +10 -2
  280. package/dist/protocol/privacy-token.js +20 -0
  281. package/dist/protocol/privacy.js +58 -0
  282. package/dist/protocol/stream.js +27 -2
  283. package/dist/retry/codec.js +220 -0
  284. package/dist/retry/constants.js +1 -1
  285. package/dist/retry/index.js +5 -5
  286. package/dist/retry/parse.js +51 -30
  287. package/dist/retry/reason.js +1 -1
  288. package/dist/retry/replay.js +10 -6
  289. package/dist/retry/tracker.js +50 -12
  290. package/dist/signal/api/SignalDeviceSyncApi.js +51 -31
  291. package/dist/signal/api/SignalDigestSyncApi.js +21 -15
  292. package/dist/signal/api/SignalIdentitySyncApi.js +29 -14
  293. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +17 -6
  294. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  295. package/dist/signal/api/SignalSessionSyncApi.js +16 -7
  296. package/dist/signal/api/result-map.js +13 -0
  297. package/dist/signal/constants.js +1 -5
  298. package/dist/signal/crypto/WaAdvSignature.js +2 -44
  299. package/dist/signal/crypto/constants.js +1 -5
  300. package/dist/signal/{store/sqlite.js → encoding.js} +41 -25
  301. package/dist/signal/group/SenderKeyChain.js +2 -2
  302. package/dist/signal/group/SenderKeyCodec.js +8 -8
  303. package/dist/signal/group/SenderKeyManager.js +130 -108
  304. package/dist/signal/index.js +13 -1
  305. package/dist/signal/registration/keygen.js +7 -4
  306. package/dist/signal/registration/utils.js +3 -2
  307. package/dist/signal/session/SignalProtocol.js +158 -81
  308. package/dist/signal/session/SignalRatchet.js +19 -8
  309. package/dist/signal/session/SignalSerializer.js +5 -6
  310. package/dist/signal/session/SignalSession.js +11 -9
  311. package/dist/signal/session/resolver.js +138 -103
  312. package/dist/store/contracts/identity.store.js +2 -0
  313. package/dist/store/contracts/message-secret.store.js +2 -0
  314. package/dist/store/contracts/pre-key.store.js +2 -0
  315. package/dist/store/contracts/privacy-token.store.js +2 -0
  316. package/dist/store/contracts/session.store.js +2 -0
  317. package/dist/store/createStore.js +142 -192
  318. package/dist/store/index.js +23 -33
  319. package/dist/store/locks/appstate.lock.js +29 -0
  320. package/dist/store/locks/auth.lock.js +18 -0
  321. package/dist/store/locks/contact.lock.js +23 -0
  322. package/dist/store/locks/device-list.lock.js +23 -0
  323. package/dist/store/locks/identity.lock.js +19 -0
  324. package/dist/store/locks/message-secret.lock.js +20 -0
  325. package/dist/store/locks/message.lock.js +24 -0
  326. package/dist/store/locks/participants.lock.js +23 -0
  327. package/dist/store/locks/pre-key.lock.js +30 -0
  328. package/dist/store/locks/privacy-token.lock.js +21 -0
  329. package/dist/store/locks/retry.lock.js +32 -0
  330. package/dist/store/locks/sender-key.lock.js +55 -0
  331. package/dist/store/locks/session.lock.js +22 -0
  332. package/dist/store/locks/signal.lock.js +42 -0
  333. package/dist/store/locks/thread.lock.js +24 -0
  334. package/dist/store/noop.store.js +22 -2
  335. package/dist/store/providers/memory/appstate.store.js +22 -24
  336. package/dist/store/providers/memory/device-list.store.js +13 -5
  337. package/dist/store/providers/memory/identity.store.js +35 -0
  338. package/dist/store/providers/memory/message-secret.store.js +85 -0
  339. package/dist/store/providers/memory/participants.store.js +3 -0
  340. package/dist/store/providers/memory/pre-key.store.js +101 -0
  341. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  342. package/dist/store/providers/memory/retry.store.js +98 -9
  343. package/dist/store/providers/memory/sender-key.store.js +6 -1
  344. package/dist/store/providers/memory/session.store.js +49 -0
  345. package/dist/store/providers/memory/signal.store.js +1 -147
  346. package/dist/transport/WaComms.js +7 -4
  347. package/dist/transport/WaWebSocket.js +9 -7
  348. package/dist/transport/binary/constants.js +1 -31
  349. package/dist/transport/binary/decoder.js +4 -4
  350. package/dist/transport/binary/encoder.js +8 -15
  351. package/dist/transport/binary/index.js +0 -4
  352. package/dist/transport/index.js +17 -1
  353. package/dist/transport/keepalive/WaKeepAlive.js +17 -8
  354. package/dist/transport/node/WaMobileTcpSocket.js +118 -0
  355. package/dist/transport/node/WaNodeOrchestrator.js +36 -21
  356. package/dist/transport/node/builders/abprops.js +23 -0
  357. package/dist/transport/node/builders/business.js +137 -0
  358. package/dist/transport/node/builders/device.js +14 -0
  359. package/dist/transport/node/builders/email.js +72 -0
  360. package/dist/transport/node/builders/global.js +375 -0
  361. package/dist/transport/node/builders/message.js +64 -245
  362. package/dist/transport/node/builders/offline.js +17 -0
  363. package/dist/transport/node/builders/pairing.js +0 -26
  364. package/dist/transport/node/builders/prekeys.js +36 -39
  365. package/dist/transport/node/builders/presence.js +16 -0
  366. package/dist/transport/node/builders/privacy-token.js +42 -0
  367. package/dist/transport/node/builders/privacy.js +55 -0
  368. package/dist/transport/node/builders/profile.js +78 -0
  369. package/dist/transport/node/builders/retry.js +10 -22
  370. package/dist/transport/node/builders/usync.js +6 -2
  371. package/dist/transport/node/helpers.js +46 -1
  372. package/dist/transport/node/mex/argo-decoder.js +189 -0
  373. package/dist/transport/node/mex/client.js +86 -0
  374. package/dist/transport/node/mex/persist-ids.js +13 -0
  375. package/dist/transport/node/usync.js +2 -32
  376. package/dist/transport/node/xml.js +35 -14
  377. package/dist/transport/noise/WaClientPayload.js +26 -21
  378. package/dist/transport/noise/WaFrameCodec.js +1 -1
  379. package/dist/transport/noise/WaMobileClientPayload.js +56 -0
  380. package/dist/transport/noise/WaNoiseCert.js +8 -26
  381. package/dist/transport/noise/WaNoiseSession.js +75 -33
  382. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  383. package/dist/transport/stream/parse.js +7 -3
  384. package/dist/types/appstate/WaAppStateCrypto.d.ts +11 -8
  385. package/dist/types/appstate/WaAppStateSyncClient.d.ts +6 -2
  386. package/dist/types/appstate/encoding.d.ts +7 -0
  387. package/dist/types/appstate/index.d.ts +3 -3
  388. package/dist/types/appstate/{WaAppStateSyncResponseParser.d.ts → response-parser.d.ts} +1 -1
  389. package/dist/types/appstate/types.d.ts +1 -1
  390. package/dist/types/appstate/utils.d.ts +0 -2
  391. package/dist/types/auth/WaAuthClient.d.ts +9 -3
  392. package/dist/types/auth/credentials-flow.d.ts +20 -0
  393. package/dist/types/auth/index.d.ts +0 -2
  394. package/dist/types/auth/pairing/WaPairingFlow.d.ts +3 -2
  395. package/dist/types/auth/pairing/{WaPairingCodeCrypto.d.ts → pairing-code-crypto.d.ts} +6 -1
  396. package/dist/types/auth/types.d.ts +41 -0
  397. package/dist/types/client/WaClient.d.ts +44 -18
  398. package/dist/types/client/WaClientFactory.d.ts +22 -8
  399. package/dist/types/client/connection/WaConnectionManager.d.ts +2 -0
  400. package/dist/types/client/coordinators/WaAbPropsCoordinator.d.ts +26 -0
  401. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  402. package/dist/types/client/coordinators/WaEmailCoordinator.d.ts +24 -0
  403. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +9 -2
  404. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +29 -2
  405. package/dist/types/client/coordinators/WaOfflineResumeCoordinator.d.ts +31 -0
  406. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +16 -1
  407. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  408. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +38 -0
  409. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +12 -0
  410. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  411. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +55 -0
  412. package/dist/types/client/dirty.d.ts +3 -1
  413. package/dist/types/client/events/abprops.d.ts +14 -0
  414. package/dist/types/client/events/devices.d.ts +20 -0
  415. package/dist/types/client/events/identity.d.ts +9 -0
  416. package/dist/types/client/events/privacy-token.d.ts +7 -0
  417. package/dist/types/client/events/registration.d.ts +17 -0
  418. package/dist/types/client/history-sync.d.ts +9 -6
  419. package/dist/types/client/incoming.d.ts +9 -2
  420. package/dist/types/client/index.d.ts +1 -1
  421. package/dist/types/client/mailbox.d.ts +5 -5
  422. package/dist/types/client/media.d.ts +31 -0
  423. package/dist/types/client/messages.d.ts +3 -2
  424. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  425. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  426. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  427. package/dist/types/client/types.d.ts +151 -4
  428. package/dist/types/crypto/core/index.d.ts +3 -2
  429. package/dist/types/crypto/core/nonce.d.ts +2 -0
  430. package/dist/types/crypto/core/primitives.d.ts +1 -2
  431. package/dist/types/crypto/core/random.d.ts +2 -1
  432. package/dist/types/crypto/core/xeddsa.d.ts +2 -0
  433. package/dist/types/crypto/curves/constants.d.ts +1 -0
  434. package/dist/types/crypto/index.d.ts +2 -0
  435. package/dist/types/crypto/math/constants.d.ts +4 -2
  436. package/dist/types/crypto/math/fe.d.ts +30 -0
  437. package/dist/types/crypto/math/mod.d.ts +0 -2
  438. package/dist/types/crypto/math/types.d.ts +11 -4
  439. package/dist/types/index.d.ts +6 -3
  440. package/dist/types/infra/log/ConsoleLogger.d.ts +1 -1
  441. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  442. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  443. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  444. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  445. package/dist/types/infra/perf/StoreLock.d.ts +11 -0
  446. package/dist/types/media/WaMediaCrypto.d.ts +16 -6
  447. package/dist/types/media/WaMediaTransferClient.d.ts +6 -23
  448. package/dist/types/media/constants.d.ts +3 -1
  449. package/dist/types/media/index.d.ts +2 -1
  450. package/dist/types/media/processor.d.ts +28 -0
  451. package/dist/types/media/types.d.ts +19 -5
  452. package/dist/types/message/addon-crypto.d.ts +34 -3
  453. package/dist/types/message/content.d.ts +11 -1
  454. package/dist/types/message/icdc.d.ts +13 -0
  455. package/dist/types/message/reporting-token.d.ts +0 -1
  456. package/dist/types/message/types.d.ts +42 -11
  457. package/dist/types/protocol/abprops.d.ts +142 -0
  458. package/dist/types/protocol/appstate.d.ts +0 -11
  459. package/dist/types/protocol/browser.d.ts +1 -0
  460. package/dist/types/protocol/constants.d.ts +12 -4
  461. package/dist/types/protocol/defaults.d.ts +6 -0
  462. package/dist/types/protocol/email.d.ts +32 -0
  463. package/dist/types/protocol/index.d.ts +1 -2
  464. package/dist/types/protocol/jid.d.ts +20 -2
  465. package/dist/types/protocol/message.d.ts +60 -0
  466. package/dist/types/protocol/nodes.d.ts +6 -0
  467. package/dist/types/protocol/notification.d.ts +8 -0
  468. package/dist/types/protocol/privacy-token.d.ts +17 -0
  469. package/dist/types/protocol/privacy.d.ts +75 -0
  470. package/dist/types/protocol/stream.d.ts +31 -0
  471. package/dist/types/retry/codec.d.ts +3 -0
  472. package/dist/types/retry/index.d.ts +3 -3
  473. package/dist/types/retry/parse.d.ts +5 -2
  474. package/dist/types/retry/reason.d.ts +1 -1
  475. package/dist/types/retry/tracker.d.ts +1 -0
  476. package/dist/types/retry/types.d.ts +6 -1
  477. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +2 -1
  478. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +9 -0
  479. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +5 -3
  480. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  481. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  482. package/dist/types/signal/api/result-map.d.ts +1 -0
  483. package/dist/types/signal/constants.d.ts +0 -3
  484. package/dist/types/signal/crypto/WaAdvSignature.d.ts +0 -2
  485. package/dist/types/signal/crypto/constants.d.ts +0 -1
  486. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +9 -3
  487. package/dist/types/signal/group/SenderKeyChain.d.ts +1 -1
  488. package/dist/types/signal/group/SenderKeyManager.d.ts +17 -7
  489. package/dist/types/signal/index.d.ts +2 -0
  490. package/dist/types/signal/registration/utils.d.ts +2 -1
  491. package/dist/types/signal/session/SignalProtocol.d.ts +21 -6
  492. package/dist/types/signal/session/SignalSerializer.d.ts +2 -1
  493. package/dist/types/signal/session/resolver.d.ts +11 -4
  494. package/dist/types/signal/types.d.ts +16 -4
  495. package/dist/types/store/contracts/appstate.store.d.ts +1 -1
  496. package/dist/types/store/contracts/identity.store.d.ts +11 -0
  497. package/dist/types/store/contracts/message-secret.store.d.ts +16 -0
  498. package/dist/types/store/contracts/pre-key.store.d.ts +13 -0
  499. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  500. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  501. package/dist/types/store/contracts/session.store.d.ts +14 -0
  502. package/dist/types/store/contracts/signal.store.d.ts +1 -27
  503. package/dist/types/store/createStore.d.ts +1 -1
  504. package/dist/types/store/index.d.ts +12 -12
  505. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  506. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  507. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  508. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  509. package/dist/types/store/locks/identity.lock.d.ts +3 -0
  510. package/dist/types/store/locks/message-secret.lock.d.ts +3 -0
  511. package/dist/types/store/locks/message.lock.d.ts +3 -0
  512. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  513. package/dist/types/store/locks/pre-key.lock.d.ts +3 -0
  514. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  515. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  516. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  517. package/dist/types/store/locks/session.lock.d.ts +3 -0
  518. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  519. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  520. package/dist/types/store/noop.store.d.ts +4 -0
  521. package/dist/types/store/providers/memory/appstate.store.d.ts +1 -1
  522. package/dist/types/store/providers/memory/identity.store.d.ts +18 -0
  523. package/dist/types/store/providers/memory/message-secret.store.d.ts +21 -0
  524. package/dist/types/store/providers/memory/pre-key.store.d.ts +23 -0
  525. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  526. package/dist/types/store/providers/memory/retry.store.d.ts +15 -1
  527. package/dist/types/store/providers/memory/session.store.d.ts +21 -0
  528. package/dist/types/store/providers/memory/signal.store.d.ts +2 -43
  529. package/dist/types/store/providers/memory/thread.store.d.ts +1 -1
  530. package/dist/types/store/types.d.ts +69 -61
  531. package/dist/types/transport/WaWebSocket.d.ts +1 -1
  532. package/dist/types/transport/binary/constants.d.ts +0 -30
  533. package/dist/types/transport/binary/index.d.ts +0 -1
  534. package/dist/types/transport/index.d.ts +8 -1
  535. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +4 -1
  536. package/dist/types/transport/node/WaMobileTcpSocket.d.ts +18 -0
  537. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +9 -6
  538. package/dist/types/transport/node/builders/abprops.d.ts +5 -0
  539. package/dist/types/transport/node/builders/business.d.ts +29 -0
  540. package/dist/types/transport/node/builders/device.d.ts +2 -0
  541. package/dist/types/transport/node/builders/email.d.ts +11 -0
  542. package/dist/types/transport/node/builders/global.d.ts +102 -0
  543. package/dist/types/transport/node/builders/message.d.ts +8 -7
  544. package/dist/types/transport/node/builders/offline.d.ts +2 -0
  545. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  546. package/dist/types/transport/node/builders/prekeys.d.ts +4 -3
  547. package/dist/types/transport/node/builders/presence.d.ts +6 -0
  548. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  549. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  550. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  551. package/dist/types/transport/node/builders/retry.d.ts +0 -1
  552. package/dist/types/transport/node/helpers.d.ts +8 -0
  553. package/dist/types/transport/node/mex/argo-decoder.d.ts +11 -0
  554. package/dist/types/transport/node/mex/client.d.ts +18 -0
  555. package/dist/types/transport/node/mex/persist-ids.d.ts +14 -0
  556. package/dist/types/transport/noise/WaMobileClientPayload.d.ts +29 -0
  557. package/dist/types/transport/noise/WaNoiseCert.d.ts +7 -1
  558. package/dist/types/transport/noise/WaNoiseSession.d.ts +4 -2
  559. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  560. package/dist/types/transport/types.d.ts +8 -0
  561. package/dist/types/util/bytes.d.ts +1 -1
  562. package/dist/types/util/index.d.ts +5 -0
  563. package/dist/types/util/primitives.d.ts +0 -1
  564. package/dist/util/bytes.js +22 -18
  565. package/dist/util/index.js +23 -0
  566. package/dist/util/primitives.js +2 -2
  567. package/package.json +34 -10
  568. package/proto/index.js +1 -1
  569. package/dist/auth/flow/WaAuthCredentialsFlow.js +0 -130
  570. package/dist/auth/pairing/constants.js +0 -5
  571. package/dist/client/connection/WaKeyShareCoordinator.js +0 -63
  572. package/dist/crypto/core/constants.js +0 -4
  573. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +0 -125
  574. package/dist/esm/auth/pairing/constants.js +0 -2
  575. package/dist/esm/client/connection/WaKeyShareCoordinator.js +0 -59
  576. package/dist/esm/crypto/core/constants.js +0 -1
  577. package/dist/esm/retry/outbound.js +0 -82
  578. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  579. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -250
  580. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  581. package/dist/esm/store/providers/sqlite/connection.js +0 -245
  582. package/dist/esm/store/providers/sqlite/contact.store.js +0 -74
  583. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -127
  584. package/dist/esm/store/providers/sqlite/message.store.js +0 -132
  585. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  586. package/dist/esm/store/providers/sqlite/participants.store.js +0 -77
  587. package/dist/esm/store/providers/sqlite/retry.store.js +0 -141
  588. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -198
  589. package/dist/esm/store/providers/sqlite/signal.store.js +0 -435
  590. package/dist/esm/store/providers/sqlite/table-names.js +0 -107
  591. package/dist/esm/store/providers/sqlite/thread.store.js +0 -85
  592. package/dist/esm/transport/node/builders/index.js +0 -8
  593. package/dist/retry/outbound.js +0 -87
  594. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  595. package/dist/store/providers/sqlite/appstate.store.js +0 -254
  596. package/dist/store/providers/sqlite/auth.store.js +0 -180
  597. package/dist/store/providers/sqlite/connection.js +0 -281
  598. package/dist/store/providers/sqlite/contact.store.js +0 -78
  599. package/dist/store/providers/sqlite/device-list.store.js +0 -131
  600. package/dist/store/providers/sqlite/message.store.js +0 -136
  601. package/dist/store/providers/sqlite/migrations.js +0 -350
  602. package/dist/store/providers/sqlite/participants.store.js +0 -81
  603. package/dist/store/providers/sqlite/retry.store.js +0 -145
  604. package/dist/store/providers/sqlite/sender-key.store.js +0 -202
  605. package/dist/store/providers/sqlite/signal.store.js +0 -439
  606. package/dist/store/providers/sqlite/table-names.js +0 -113
  607. package/dist/store/providers/sqlite/thread.store.js +0 -89
  608. package/dist/transport/node/builders/index.js +0 -42
  609. package/dist/types/appstate/store/sqlite.d.ts +0 -7
  610. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +0 -14
  611. package/dist/types/auth/pairing/constants.d.ts +0 -2
  612. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +0 -14
  613. package/dist/types/crypto/core/constants.d.ts +0 -1
  614. package/dist/types/retry/outbound.d.ts +0 -4
  615. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  616. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -17
  617. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  618. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  619. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -12
  620. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -15
  621. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -13
  622. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  623. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -12
  624. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -15
  625. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -24
  626. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -53
  627. package/dist/types/store/providers/sqlite/table-names.d.ts +0 -5
  628. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -13
  629. package/dist/types/transport/node/builders/index.d.ts +0 -8
  630. /package/dist/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +0 -0
@@ -3,7 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SignalProtocol = void 0;
4
4
  const _crypto_1 = require("../../crypto/index.js");
5
5
  const ConsoleLogger_1 = require("../../infra/log/ConsoleLogger");
6
+ const StoreLock_1 = require("../../infra/perf/StoreLock");
6
7
  const constants_1 = require("../constants");
8
+ const encoding_1 = require("../encoding");
7
9
  const SignalRatchet_1 = require("../session/SignalRatchet");
8
10
  const SignalSerializer_1 = require("../session/SignalSerializer");
9
11
  const SignalSession_1 = require("../session/SignalSession");
@@ -11,26 +13,37 @@ const bytes_1 = require("../../util/bytes");
11
13
  function signalAddressMapKey(address) {
12
14
  return `${address.user}\u0001${address.server ?? ''}\u0001${address.device}`;
13
15
  }
16
+ function signalAddressLockKey(address) {
17
+ return `signal:${signalAddressMapKey(address)}`;
18
+ }
14
19
  class SignalProtocol {
15
- constructor(store, logger = new ConsoleLogger_1.ConsoleLogger('info')) {
16
- this.store = store;
20
+ constructor(stores, logger = new ConsoleLogger_1.ConsoleLogger('info')) {
21
+ this.stores = stores;
17
22
  this.logger = logger;
23
+ this.sessionMutationLock = new StoreLock_1.StoreLock();
18
24
  }
19
- async hasSession(address) {
20
- return this.store.hasSession(address);
21
- }
22
- async hasSessions(addresses) {
23
- return this.store.hasSessions(addresses);
24
- }
25
- async establishOutgoingSession(address, remoteBundle) {
26
- const [local, localOneTimeBase] = await Promise.all([
27
- (0, SignalSession_1.requireLocalIdentity)(this.store),
28
- (0, SignalSession_1.generateSerializedKeyPair)()
29
- ]);
30
- const session = await (0, SignalSession_1.initiateSessionOutgoing)(local, remoteBundle, localOneTimeBase);
31
- await this.store.setRemoteIdentity(address, session.remote.pubKey);
32
- await this.store.setSession(address, session);
33
- return session;
25
+ async establishOutgoingSession(address, remoteBundle, options = {}) {
26
+ return this.runWithAddressLock(address, async () => {
27
+ if (options.reuseExisting) {
28
+ const existing = await this.stores.session.getSession(address);
29
+ if (existing) {
30
+ const remoteIdentity = (0, _crypto_1.toSerializedPubKey)(remoteBundle.identity);
31
+ if (!(0, bytes_1.uint8Equal)(existing.remote.pubKey, remoteIdentity)) {
32
+ throw new Error('identity mismatch');
33
+ }
34
+ return existing;
35
+ }
36
+ }
37
+ const [local, localOneTimeBase] = await Promise.all([
38
+ (0, SignalSession_1.requireLocalIdentity)(this.stores.signal),
39
+ (0, SignalSession_1.generateSerializedKeyPair)()
40
+ ]);
41
+ const session = await (0, SignalSession_1.initiateSessionOutgoing)(local, remoteBundle, localOneTimeBase);
42
+ // Keep writes ordered: a stored session without matching remote identity causes false mismatch checks.
43
+ await this.stores.identity.setRemoteIdentity(address, session.remote.pubKey);
44
+ await this.stores.session.setSession(address, session);
45
+ return session;
46
+ });
34
47
  }
35
48
  async encryptMessage(address, plaintext, expectedIdentity) {
36
49
  const [encrypted] = await this.encryptMessagesBatch([
@@ -38,77 +51,140 @@ class SignalProtocol {
38
51
  ]);
39
52
  return encrypted;
40
53
  }
41
- async encryptMessagesBatch(requests) {
54
+ async encryptMessagesBatch(requests, prefetchedSessions) {
42
55
  if (requests.length === 0) {
43
56
  return [];
44
57
  }
45
- const addresses = requests.map((request) => request.address);
46
- const storedSessions = await this.store.getSessionsBatch(addresses);
47
- const latestSessionByAddress = new Map();
48
- const sessionUpdatesByAddress = new Map();
49
- const identityUpdatesByAddress = new Map();
50
- const results = new Array(requests.length);
51
- for (let index = 0; index < requests.length; index += 1) {
52
- const request = requests[index];
53
- const address = request.address;
54
- const addressKey = signalAddressMapKey(address);
55
- const session = latestSessionByAddress.get(addressKey) ?? storedSessions[index];
56
- if (!session) {
57
- throw new Error('signal session not found');
58
+ const lockKeySet = new Set();
59
+ for (let i = 0; i < requests.length; i += 1)
60
+ lockKeySet.add(signalAddressLockKey(requests[i].address));
61
+ const lockKeys = [...lockKeySet];
62
+ return this.sessionMutationLock.runMany(lockKeys, async () => {
63
+ const prefetchedByAddress = new Map();
64
+ if (prefetchedSessions && prefetchedSessions.length > 0) {
65
+ for (let index = 0; index < prefetchedSessions.length; index += 1) {
66
+ const entry = prefetchedSessions[index];
67
+ prefetchedByAddress.set(signalAddressMapKey(entry.address), entry.session);
68
+ }
58
69
  }
59
- if (request.expectedIdentity &&
60
- !(0, bytes_1.uint8Equal)((0, _crypto_1.toSerializedPubKey)(request.expectedIdentity), session.remote.pubKey)) {
61
- throw new Error('identity mismatch');
70
+ const uniqueAddressKeys = new Array(requests.length);
71
+ const uniqueAddresses = new Array(requests.length);
72
+ let uniqueAddressCount = 0;
73
+ for (let index = 0; index < requests.length; index += 1) {
74
+ const address = requests[index].address;
75
+ const addressKey = signalAddressMapKey(address);
76
+ let isDuplicate = false;
77
+ for (let dedupIndex = 0; dedupIndex < uniqueAddressCount; dedupIndex += 1) {
78
+ if (uniqueAddressKeys[dedupIndex] === addressKey) {
79
+ isDuplicate = true;
80
+ break;
81
+ }
82
+ }
83
+ if (isDuplicate) {
84
+ continue;
85
+ }
86
+ uniqueAddressKeys[uniqueAddressCount] = addressKey;
87
+ uniqueAddresses[uniqueAddressCount] = address;
88
+ uniqueAddressCount += 1;
62
89
  }
63
- const [updatedSession, encrypted] = await (0, SignalRatchet_1.encryptMsg)(session, request.plaintext);
64
- latestSessionByAddress.set(addressKey, updatedSession);
65
- sessionUpdatesByAddress.set(addressKey, {
66
- address,
67
- session: updatedSession
68
- });
69
- if (!(0, bytes_1.uint8Equal)(updatedSession.remote.pubKey, session.remote.pubKey)) {
70
- identityUpdatesByAddress.set(addressKey, {
90
+ uniqueAddressKeys.length = uniqueAddressCount;
91
+ uniqueAddresses.length = uniqueAddressCount;
92
+ const currentSessions = await this.stores.session.getSessionsBatch(uniqueAddresses);
93
+ const latestSessionByAddress = new Map();
94
+ for (let index = 0; index < uniqueAddressCount; index += 1) {
95
+ const addressKey = uniqueAddressKeys[index];
96
+ const current = currentSessions[index];
97
+ if (current) {
98
+ latestSessionByAddress.set(addressKey, current);
99
+ continue;
100
+ }
101
+ const prefetched = prefetchedByAddress.get(addressKey);
102
+ if (prefetched) {
103
+ latestSessionByAddress.set(addressKey, prefetched);
104
+ }
105
+ }
106
+ const sessionUpdatesByAddress = new Map();
107
+ const identityUpdatesByAddress = new Map();
108
+ const results = new Array(requests.length);
109
+ for (let index = 0; index < requests.length; index += 1) {
110
+ const request = requests[index];
111
+ const address = request.address;
112
+ const addressKey = signalAddressMapKey(address);
113
+ const session = latestSessionByAddress.get(addressKey);
114
+ if (!session) {
115
+ throw new Error('signal session not found');
116
+ }
117
+ if (request.expectedIdentity &&
118
+ !(0, bytes_1.uint8Equal)((0, _crypto_1.toSerializedPubKey)(request.expectedIdentity), session.remote.pubKey)) {
119
+ throw new Error('identity mismatch');
120
+ }
121
+ const [updatedSession, encrypted] = await (0, SignalRatchet_1.encryptMsg)(session, request.plaintext);
122
+ latestSessionByAddress.set(addressKey, updatedSession);
123
+ sessionUpdatesByAddress.set(addressKey, {
71
124
  address,
72
- identityKey: updatedSession.remote.pubKey
125
+ session: updatedSession
73
126
  });
127
+ if (!(0, bytes_1.uint8Equal)(updatedSession.remote.pubKey, session.remote.pubKey)) {
128
+ identityUpdatesByAddress.set(addressKey, {
129
+ address,
130
+ identityKey: updatedSession.remote.pubKey
131
+ });
132
+ }
133
+ results[index] = {
134
+ ...encrypted,
135
+ baseKey: updatedSession.aliceBaseKey
136
+ };
74
137
  }
75
- results[index] = {
76
- ...encrypted,
77
- baseKey: updatedSession.aliceBaseKey
78
- };
79
- }
80
- await this.store.setSessionsBatch([...sessionUpdatesByAddress.values()]);
81
- if (identityUpdatesByAddress.size > 0) {
82
- await this.store.setRemoteIdentities([...identityUpdatesByAddress.values()]);
83
- }
84
- return results;
138
+ // Persist remote identities first when needed so session writes never commit ahead of identity data.
139
+ if (identityUpdatesByAddress.size > 0) {
140
+ const identityUpdates = new Array(identityUpdatesByAddress.size);
141
+ let identityIndex = 0;
142
+ for (const update of identityUpdatesByAddress.values()) {
143
+ identityUpdates[identityIndex] = update;
144
+ identityIndex += 1;
145
+ }
146
+ await this.stores.identity.setRemoteIdentities(identityUpdates);
147
+ }
148
+ const sessionUpdates = new Array(sessionUpdatesByAddress.size);
149
+ let sessionIndex = 0;
150
+ for (const update of sessionUpdatesByAddress.values()) {
151
+ sessionUpdates[sessionIndex] = update;
152
+ sessionIndex += 1;
153
+ }
154
+ await this.stores.session.setSessionsBatch(sessionUpdates);
155
+ return results;
156
+ });
85
157
  }
86
158
  async decryptMessage(address, envelope) {
87
- const currentSession = await this.store.getSession(address);
88
- let outcome;
89
- if (envelope.type === 'pkmsg') {
90
- const parsedPk = (0, SignalSerializer_1.deserializePkMsg)(envelope.ciphertext);
91
- outcome = await this.decryptPkMsg(currentSession, parsedPk);
92
- }
93
- else {
94
- const parsed = (0, SignalSerializer_1.deserializeMsg)(envelope.ciphertext);
95
- outcome = await this.decryptMsgInternal(currentSession, parsed);
96
- }
97
- const nextRemoteIdentity = outcome.newSessionInfo?.newIdentity ?? outcome.updatedSession.remote.pubKey;
98
- if (!currentSession || !(0, bytes_1.uint8Equal)(currentSession.remote.pubKey, nextRemoteIdentity)) {
99
- await this.store.setRemoteIdentity(address, nextRemoteIdentity);
100
- }
101
- await this.store.setSession(address, outcome.updatedSession);
102
- return outcome.plaintext;
103
- }
104
- async decryptMsgInternal(session, parsed) {
105
- return (0, SignalRatchet_1.decryptMsg)(session, parsed, (error, previousSessionIndex) => {
106
- this.logger.debug('signal decrypt fallback session failed', {
107
- previousSessionIndex,
108
- message: error.message
109
- });
159
+ return this.runWithAddressLock(address, async () => {
160
+ const currentSession = await this.stores.session.getSession(address);
161
+ let outcome;
162
+ if (envelope.type === 'pkmsg') {
163
+ const parsedPk = (0, SignalSerializer_1.deserializePkMsg)(envelope.ciphertext);
164
+ outcome = await this.decryptPkMsg(currentSession, parsedPk);
165
+ }
166
+ else {
167
+ const parsed = (0, SignalSerializer_1.deserializeMsg)(envelope.ciphertext);
168
+ outcome = await (0, SignalRatchet_1.decryptMsg)(currentSession, parsed, (error, previousSessionIndex) => {
169
+ this.logger.debug('signal decrypt fallback session failed', {
170
+ previousSessionIndex,
171
+ message: error.message
172
+ });
173
+ });
174
+ }
175
+ const nextRemoteIdentity = outcome.newSessionInfo?.newIdentity ?? outcome.updatedSession.remote.pubKey;
176
+ const identityChanged = !currentSession || !(0, bytes_1.uint8Equal)(currentSession.remote.pubKey, nextRemoteIdentity);
177
+ // Keep writes ordered for consistency with resolver identity checks.
178
+ if (identityChanged) {
179
+ await this.stores.identity.setRemoteIdentity(address, nextRemoteIdentity);
180
+ }
181
+ await this.stores.session.setSession(address, outcome.updatedSession);
182
+ return outcome.plaintext;
110
183
  });
111
184
  }
185
+ runWithAddressLock(address, task) {
186
+ return this.sessionMutationLock.run(signalAddressLockKey(address), task);
187
+ }
112
188
  async decryptPkMsg(currentSession, parsed) {
113
189
  const matchingSession = (0, SignalSession_1.findMatchingSession)(currentSession, parsed.sessionBaseKey);
114
190
  if (matchingSession) {
@@ -120,11 +196,11 @@ class SignalProtocol {
120
196
  };
121
197
  }
122
198
  const [local, signedPreKey, oneTimePreKey] = await Promise.all([
123
- (0, SignalSession_1.requireLocalIdentity)(this.store),
124
- (0, SignalSerializer_1.requireSignedPreKey)(this.store, parsed.localSignedPreKeyId),
199
+ (0, SignalSession_1.requireLocalIdentity)(this.stores.signal),
200
+ (0, SignalSerializer_1.requireSignedPreKey)(this.stores.signal, parsed.localSignedPreKeyId),
125
201
  parsed.localOneTimeKeyId === null || parsed.localOneTimeKeyId === undefined
126
202
  ? Promise.resolve(null)
127
- : (0, SignalSerializer_1.requirePreKey)(this.store, parsed.localOneTimeKeyId)
203
+ : (0, SignalSerializer_1.requirePreKey)(this.stores.preKey, parsed.localOneTimeKeyId)
128
204
  ]);
129
205
  const incoming = await (0, SignalSession_1.initiateSessionIncoming)(local, parsed.remote, parsed.sessionBaseKey, {
130
206
  signed: (0, SignalSession_1.toSerializedKeyPair)(signedPreKey.keyPair),
@@ -138,14 +214,15 @@ class SignalProtocol {
138
214
  ? {
139
215
  ...incoming,
140
216
  prevSessions: [
141
- (0, SignalSession_1.detachSession)(currentSession),
217
+ (0, encoding_1.encodeSignalSessionSnapshot)((0, SignalSession_1.detachSession)(currentSession)),
142
218
  ...currentSession.prevSessions.slice(0, constants_1.MAX_PREV_SESSIONS - 1)
143
219
  ]
144
220
  }
145
221
  : incoming;
146
222
  const [updatedSession, plaintext] = await (0, SignalRatchet_1.decryptMsgFromSession)(baseSession, parsed);
223
+ // Only consume one-time prekeys after successful decrypt/session materialization.
147
224
  if (parsed.localOneTimeKeyId !== null && parsed.localOneTimeKeyId !== undefined) {
148
- await this.store.consumePreKeyById(parsed.localOneTimeKeyId);
225
+ await this.stores.preKey.consumePreKeyById(parsed.localOneTimeKeyId);
149
226
  }
150
227
  return {
151
228
  updatedSession,
@@ -9,6 +9,7 @@ exports.decryptMsgFromSession = decryptMsgFromSession;
9
9
  const _crypto_1 = require("../../crypto/index.js");
10
10
  const _proto_1 = require("../../proto.js");
11
11
  const constants_1 = require("../constants");
12
+ const encoding_1 = require("../encoding");
12
13
  const SignalSession_1 = require("../session/SignalSession");
13
14
  const bytes_1 = require("../../util/bytes");
14
15
  const primitives_1 = require("../../util/primitives");
@@ -43,7 +44,7 @@ async function selectMessageKey(chain, targetCounter) {
43
44
  if (idx === -1) {
44
45
  throw new Error('duplicate message');
45
46
  }
46
- const messageKey = unused[idx];
47
+ const messageKey = (0, encoding_1.decodeSignalMessageKey)(unused[idx], `unusedMsgKeys[${idx}]`);
47
48
  const nextUnused = (0, bytes_1.removeAt)(unused, idx);
48
49
  return {
49
50
  messageKey,
@@ -81,7 +82,12 @@ async function selectMessageKey(chain, targetCounter) {
81
82
  overflow -= 1;
82
83
  }
83
84
  else {
84
- nextUnused.push(currentMessageKey);
85
+ nextUnused.push({
86
+ index: currentMessageKey.index,
87
+ cipherKey: currentMessageKey.cipherKey,
88
+ macKey: currentMessageKey.macKey,
89
+ iv: currentMessageKey.iv
90
+ });
85
91
  }
86
92
  const derived = await deriveMsgKeyFromState(counter, chainState);
87
93
  currentMessageKey = derived.messageKey;
@@ -182,13 +188,14 @@ async function decryptMsg(session, parsed, onPrevSessionDecryptError) {
182
188
  }
183
189
  catch (error) {
184
190
  for (let i = 0; i < session.prevSessions.length; i += 1) {
185
- const prevSession = (0, SignalSession_1.snapshotToRecord)(session.prevSessions[i]);
191
+ const decodedPrev = (0, encoding_1.decodeSignalSessionSnapshot)(session.prevSessions[i], `prevSessions[${i}]`);
192
+ const prevSession = (0, SignalSession_1.snapshotToRecord)(decodedPrev);
186
193
  try {
187
194
  const [updatedPrev, plaintext] = await decryptMsgFromSession(prevSession, parsed);
188
195
  const updatedSession = {
189
196
  ...updatedPrev,
190
197
  prevSessions: [
191
- (0, SignalSession_1.detachSession)(session),
198
+ (0, encoding_1.encodeSignalSessionSnapshot)((0, SignalSession_1.detachSession)(session)),
192
199
  ...session.prevSessions.slice(0, i),
193
200
  ...session.prevSessions.slice(i + 1)
194
201
  ]
@@ -215,7 +222,10 @@ async function decryptMsg(session, parsed, onPrevSessionDecryptError) {
215
222
  }
216
223
  async function decryptMsgFromSession(session, message) {
217
224
  const ratchetPubKey = (0, _crypto_1.toSerializedPubKey)(message.ratchetPubKey);
218
- const recvChainIndex = session.recvChains.findIndex((entry) => (0, bytes_1.uint8Equal)(entry.ratchetPubKey, ratchetPubKey));
225
+ const recvChainIndex = session.recvChains.findIndex((raw) => {
226
+ const key = raw.senderRatchetKey;
227
+ return key !== null && key !== undefined && (0, bytes_1.uint8Equal)(key, ratchetPubKey);
228
+ });
219
229
  let selectedMessageKey;
220
230
  let updatedSession;
221
231
  if (recvChainIndex === -1) {
@@ -233,7 +243,7 @@ async function decryptMsgFromSession(session, message) {
233
243
  selectedMessageKey = selected.messageKey;
234
244
  const sendRatchet = await (0, SignalSession_1.calculateRatchet)(recvRatchet.rootKey, newSendRatchet, ratchetPubKey);
235
245
  const nextRecvChains = session.recvChains.slice(-MAX_TRACKED_RECV_CHAINS);
236
- nextRecvChains.push(selected.updatedChain);
246
+ nextRecvChains.push((0, encoding_1.encodeSignalRecvChain)(selected.updatedChain));
237
247
  updatedSession = {
238
248
  ...session,
239
249
  rootKey: sendRatchet.rootKey,
@@ -248,10 +258,11 @@ async function decryptMsgFromSession(session, message) {
248
258
  };
249
259
  }
250
260
  else {
251
- const selected = await selectMessageKey(session.recvChains[recvChainIndex], message.counter);
261
+ const decoded = (0, encoding_1.decodeSignalRecvChain)(session.recvChains[recvChainIndex], `recvChains[${recvChainIndex}]`);
262
+ const selected = await selectMessageKey(decoded, message.counter);
252
263
  selectedMessageKey = selected.messageKey;
253
264
  const nextRecvChains = session.recvChains.slice();
254
- nextRecvChains[recvChainIndex] = selected.updatedChain;
265
+ nextRecvChains[recvChainIndex] = (0, encoding_1.encodeSignalRecvChain)(selected.updatedChain);
255
266
  updatedSession = {
256
267
  ...session,
257
268
  recvChains: nextRecvChains
@@ -7,7 +7,6 @@ exports.requirePreKey = requirePreKey;
7
7
  const _crypto_1 = require("../../crypto/index.js");
8
8
  const _proto_1 = require("../../proto.js");
9
9
  const constants_1 = require("../constants");
10
- const bytes_1 = require("../../util/bytes");
11
10
  function deserializeMsg(versionContentMac) {
12
11
  const content = (0, _crypto_1.readVersionedContent)(versionContentMac, constants_1.SIGNAL_VERSION, constants_1.SIGNAL_MAC_SIZE);
13
12
  const parsed = _proto_1.proto.SignalMessage.decode(content);
@@ -20,9 +19,9 @@ function deserializeMsg(versionContentMac) {
20
19
  throw new Error('invalid signal message');
21
20
  }
22
21
  return {
23
- ratchetPubKey: (0, _crypto_1.toSerializedPubKey)((0, bytes_1.toBytesView)(parsed.ratchetKey)),
22
+ ratchetPubKey: (0, _crypto_1.toSerializedPubKey)(parsed.ratchetKey),
24
23
  counter: parsed.counter,
25
- ciphertext: (0, bytes_1.toBytesView)(parsed.ciphertext),
24
+ ciphertext: parsed.ciphertext,
26
25
  versionContentMac
27
26
  };
28
27
  }
@@ -41,14 +40,14 @@ function deserializePkMsg(versionContent) {
41
40
  parsed.message === undefined) {
42
41
  throw new Error('invalid prekey signal message');
43
42
  }
44
- const signal = deserializeMsg((0, bytes_1.toBytesView)(parsed.message));
43
+ const signal = deserializeMsg(parsed.message);
45
44
  return {
46
45
  ...signal,
47
46
  remote: {
48
47
  regId: parsed.registrationId,
49
- pubKey: (0, _crypto_1.toSerializedPubKey)((0, bytes_1.toBytesView)(parsed.identityKey))
48
+ pubKey: (0, _crypto_1.toSerializedPubKey)(parsed.identityKey)
50
49
  },
51
- sessionBaseKey: (0, _crypto_1.toSerializedPubKey)((0, bytes_1.toBytesView)(parsed.baseKey)),
50
+ sessionBaseKey: (0, _crypto_1.toSerializedPubKey)(parsed.baseKey),
52
51
  localSignedPreKeyId: parsed.signedPreKeyId,
53
52
  localOneTimeKeyId: parsed.preKeyId ?? null
54
53
  };
@@ -12,6 +12,7 @@ exports.toSerializedKeyPair = toSerializedKeyPair;
12
12
  exports.ecdh = ecdh;
13
13
  const _crypto_1 = require("../../crypto/index.js");
14
14
  const constants_1 = require("../constants");
15
+ const encoding_1 = require("../encoding");
15
16
  const bytes_1 = require("../../util/bytes");
16
17
  function snapshotToRecord(snapshot) {
17
18
  return {
@@ -33,19 +34,21 @@ function findMatchingSession(session, sessionBaseKey) {
33
34
  return session;
34
35
  }
35
36
  for (let index = 0; index < session.prevSessions.length; index += 1) {
36
- const previousSession = session.prevSessions[index];
37
- if (!previousSession.aliceBaseKey ||
38
- !(0, bytes_1.uint8Equal)(previousSession.aliceBaseKey, serializedBaseKey)) {
37
+ const rawPrev = session.prevSessions[index];
38
+ if (!rawPrev.aliceBaseKey || !(0, bytes_1.uint8Equal)(rawPrev.aliceBaseKey, serializedBaseKey)) {
39
39
  continue;
40
40
  }
41
- const prevSessions = [detachSession(session)];
41
+ const decoded = (0, encoding_1.decodeSignalSessionSnapshot)(rawPrev, `prevSessions[${index}]`);
42
+ const prevSessions = [
43
+ (0, encoding_1.encodeSignalSessionSnapshot)(detachSession(session))
44
+ ];
42
45
  for (let i = 0; i < session.prevSessions.length; i += 1) {
43
46
  if (i !== index) {
44
47
  prevSessions.push(session.prevSessions[i]);
45
48
  }
46
49
  }
47
50
  return {
48
- ...previousSession,
51
+ ...decoded,
49
52
  prevSessions
50
53
  };
51
54
  }
@@ -85,10 +88,9 @@ async function initiateSessionOutgoing(local, remoteBundle, localOneTimeBase) {
85
88
  ]);
86
89
  const [rootKey, chainKey] = await (0, _crypto_1.hkdfSplit)(secret, null, 'WhisperText');
87
90
  const recvChain = {
88
- ratchetPubKey: remoteRatchetKey,
89
- nextMsgIndex: 0,
90
- chainKey,
91
- unusedMsgKeys: []
91
+ senderRatchetKey: remoteRatchetKey,
92
+ chainKey: { index: 0, key: chainKey },
93
+ messageKeys: []
92
94
  };
93
95
  const sendRatchet = await generateSerializedKeyPair();
94
96
  const sendRatchetResult = await calculateRatchet(rootKey, sendRatchet, remoteRatchetKey);