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.
- package/README.md +20 -4
- package/dist/appstate/WaAppStateCrypto.js +19 -26
- package/dist/appstate/WaAppStateSyncClient.js +293 -181
- package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
- package/dist/appstate/constants.js +4 -3
- package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
- package/dist/appstate/index.js +8 -6
- package/dist/appstate/utils.js +9 -34
- package/dist/auth/WaAuthClient.js +43 -61
- package/dist/auth/flow/WaAuthCredentialsFlow.js +22 -15
- package/dist/auth/index.js +1 -8
- package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
- package/dist/auth/pairing/WaPairingFlow.js +34 -26
- package/dist/auth/pairing/WaQrFlow.js +37 -24
- package/dist/client/WaClient.js +275 -324
- package/dist/client/WaClientFactory.js +500 -133
- package/dist/client/connection/WaConnectionManager.js +301 -0
- package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
- package/dist/client/connection/WaReceiptQueue.js +51 -0
- package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
- package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
- package/dist/client/coordinators/WaGroupCoordinator.js +30 -16
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +439 -701
- package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
- package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
- package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
- package/dist/client/coordinators/WaRetryCoordinator.js +242 -57
- package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
- package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
- package/dist/client/dirty.js +74 -48
- package/dist/client/events/chat.js +4 -3
- package/dist/client/events/devices.js +72 -0
- package/dist/client/events/group.js +62 -47
- package/dist/client/events/identity.js +22 -0
- package/dist/client/events/privacy-token.js +39 -0
- package/dist/client/history-sync.js +94 -63
- package/dist/client/incoming.js +60 -27
- package/dist/client/mailbox.js +24 -23
- package/dist/client/messages.js +107 -31
- package/dist/client/messaging/fanout.js +199 -0
- package/dist/client/messaging/key-protocol.js +130 -0
- package/dist/client/messaging/participants.js +193 -0
- package/dist/client/persistence/WriteBehindPersistence.js +129 -0
- package/dist/client/tokens/cs-token.js +50 -0
- package/dist/client/tokens/tc-token.js +25 -0
- package/dist/crypto/core/hkdf.js +3 -8
- package/dist/crypto/core/index.js +2 -5
- package/dist/crypto/core/keys.js +6 -7
- package/dist/crypto/core/nonce.js +2 -0
- package/dist/crypto/core/primitives.js +12 -23
- package/dist/crypto/core/random.js +26 -23
- package/dist/crypto/curves/Ed25519.js +7 -8
- package/dist/crypto/curves/X25519.js +38 -22
- package/dist/crypto/index.js +1 -3
- package/dist/crypto/math/constants.js +13 -36
- package/dist/crypto/math/edwards.js +171 -44
- package/dist/crypto/math/fe.js +706 -0
- package/dist/crypto/math/mod.js +10 -3
- package/dist/esm/appstate/WaAppStateCrypto.js +7 -14
- package/dist/esm/appstate/WaAppStateSyncClient.js +284 -172
- package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
- package/dist/esm/appstate/constants.js +3 -2
- package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
- package/dist/esm/appstate/index.js +2 -2
- package/dist/esm/appstate/utils.js +8 -30
- package/dist/esm/auth/WaAuthClient.js +43 -61
- package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +22 -15
- package/dist/esm/auth/index.js +0 -3
- package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
- package/dist/esm/auth/pairing/WaPairingFlow.js +28 -20
- package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
- package/dist/esm/client/WaClient.js +275 -324
- package/dist/esm/client/WaClientFactory.js +501 -134
- package/dist/esm/client/connection/WaConnectionManager.js +297 -0
- package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
- package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
- package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
- package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
- package/dist/esm/client/coordinators/WaGroupCoordinator.js +23 -9
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +443 -705
- package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
- package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
- package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +244 -59
- package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
- package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
- package/dist/esm/client/dirty.js +69 -43
- package/dist/esm/client/events/chat.js +4 -3
- package/dist/esm/client/events/devices.js +68 -0
- package/dist/esm/client/events/group.js +53 -39
- package/dist/esm/client/events/identity.js +19 -0
- package/dist/esm/client/events/privacy-token.js +36 -0
- package/dist/esm/client/history-sync.js +91 -60
- package/dist/esm/client/incoming.js +61 -28
- package/dist/esm/client/mailbox.js +24 -23
- package/dist/esm/client/messages.js +108 -32
- package/dist/esm/client/messaging/fanout.js +196 -0
- package/dist/esm/client/messaging/key-protocol.js +127 -0
- package/dist/esm/client/messaging/participants.js +190 -0
- package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
- package/dist/esm/client/tokens/cs-token.js +46 -0
- package/dist/esm/client/tokens/tc-token.js +18 -0
- package/dist/esm/crypto/core/hkdf.js +3 -8
- package/dist/esm/crypto/core/index.js +2 -3
- package/dist/esm/crypto/core/keys.js +3 -4
- package/dist/esm/crypto/core/nonce.js +2 -0
- package/dist/esm/crypto/core/primitives.js +12 -22
- package/dist/esm/crypto/core/random.js +25 -23
- package/dist/esm/crypto/curves/Ed25519.js +4 -5
- package/dist/esm/crypto/curves/X25519.js +35 -19
- package/dist/esm/crypto/index.js +0 -1
- package/dist/esm/crypto/math/constants.js +12 -35
- package/dist/esm/crypto/math/edwards.js +174 -47
- package/dist/esm/crypto/math/fe.js +691 -0
- package/dist/esm/crypto/math/mod.js +10 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/infra/log/ConsoleLogger.js +18 -17
- package/dist/esm/infra/log/PinoLogger.js +15 -9
- package/dist/esm/infra/log/types.js +11 -1
- package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
- package/dist/esm/infra/perf/BoundedTaskQueue.js +16 -18
- package/dist/esm/infra/perf/PromiseDedup.js +20 -0
- package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
- package/dist/esm/infra/perf/StoreLock.js +77 -0
- package/dist/esm/media/WaMediaCrypto.js +96 -16
- package/dist/esm/media/WaMediaTransferClient.js +251 -91
- package/dist/esm/media/conn.js +10 -6
- package/dist/esm/media/constants.js +6 -2
- package/dist/esm/message/WaMessageClient.js +30 -32
- package/dist/esm/message/ack.js +6 -6
- package/dist/esm/message/addon-crypto.js +59 -0
- package/dist/esm/message/content.js +195 -9
- package/dist/esm/message/icdc.js +76 -0
- package/dist/esm/message/incoming.js +129 -122
- package/dist/esm/message/index.js +2 -0
- package/dist/esm/message/phash.js +3 -1
- package/dist/esm/message/reporting-token.js +425 -0
- package/dist/esm/message/use-case-secret.js +49 -0
- package/dist/esm/protocol/appstate.js +27 -0
- package/dist/esm/protocol/browser.js +10 -18
- package/dist/esm/protocol/constants.js +6 -3
- package/dist/esm/protocol/defaults.js +6 -0
- package/dist/esm/protocol/index.js +2 -11
- package/dist/esm/protocol/jid.js +133 -52
- package/dist/esm/protocol/media.js +3 -3
- package/dist/esm/protocol/message.js +61 -1
- package/dist/esm/protocol/nodes.js +4 -0
- package/dist/esm/protocol/notification.js +3 -1
- package/dist/esm/protocol/privacy-token.js +17 -0
- package/dist/esm/protocol/privacy.js +55 -0
- package/dist/esm/protocol/stream.js +26 -1
- package/dist/esm/protocol/usync.js +11 -0
- package/dist/esm/retry/codec.js +216 -0
- package/dist/esm/retry/constants.js +1 -1
- package/dist/esm/retry/index.js +3 -2
- package/dist/esm/retry/parse.js +88 -86
- package/dist/esm/retry/replay.js +54 -51
- package/dist/esm/retry/tracker.js +94 -0
- package/dist/esm/signal/api/SignalDeviceSyncApi.js +276 -92
- package/dist/esm/signal/api/SignalDigestSyncApi.js +17 -8
- package/dist/esm/signal/api/SignalIdentitySyncApi.js +67 -37
- package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +86 -67
- package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
- package/dist/esm/signal/api/SignalSessionSyncApi.js +36 -34
- package/dist/esm/signal/api/result-map.js +10 -0
- package/dist/esm/signal/constants.js +0 -4
- package/dist/esm/signal/crypto/WaAdvSignature.js +13 -9
- package/dist/esm/signal/{store/sqlite.js → encoding.js} +93 -60
- package/dist/esm/signal/group/SenderKeyChain.js +28 -23
- package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
- package/dist/esm/signal/group/SenderKeyManager.js +144 -115
- package/dist/esm/signal/index.js +2 -0
- package/dist/esm/signal/registration/keygen.js +6 -2
- package/dist/esm/signal/registration/utils.js +1 -0
- package/dist/esm/signal/session/SignalProtocol.js +164 -53
- package/dist/esm/signal/session/SignalRatchet.js +24 -15
- package/dist/esm/signal/session/SignalSession.js +14 -9
- package/dist/esm/signal/session/resolver.js +221 -0
- package/dist/esm/store/contracts/privacy-token.store.js +1 -0
- package/dist/esm/store/createStore.js +100 -188
- package/dist/esm/store/index.js +1 -10
- package/dist/esm/store/locks/appstate.lock.js +26 -0
- package/dist/esm/store/locks/auth.lock.js +15 -0
- package/dist/esm/store/locks/contact.lock.js +20 -0
- package/dist/esm/store/locks/device-list.lock.js +20 -0
- package/dist/esm/store/locks/message.lock.js +21 -0
- package/dist/esm/store/locks/participants.lock.js +20 -0
- package/dist/esm/store/locks/privacy-token.lock.js +18 -0
- package/dist/esm/store/locks/retry.lock.js +29 -0
- package/dist/esm/store/locks/sender-key.lock.js +52 -0
- package/dist/esm/store/locks/signal.lock.js +63 -0
- package/dist/esm/store/locks/thread.lock.js +21 -0
- package/dist/esm/store/noop.store.js +4 -7
- package/dist/esm/store/providers/memory/appstate.store.js +38 -16
- package/dist/esm/store/providers/memory/contact.store.js +5 -0
- package/dist/esm/store/providers/memory/device-list.store.js +12 -34
- package/dist/esm/store/providers/memory/message.store.js +11 -5
- package/dist/esm/store/providers/memory/participants.store.js +1 -8
- package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
- package/dist/esm/store/providers/memory/retry.store.js +77 -2
- package/dist/esm/store/providers/memory/sender-key.store.js +11 -8
- package/dist/esm/store/providers/memory/signal.store.js +47 -18
- package/dist/esm/store/providers/memory/thread.store.js +5 -0
- package/dist/esm/transport/WaComms.js +28 -24
- package/dist/esm/transport/WaWebSocket.js +115 -18
- package/dist/esm/transport/binary/constants.js +0 -30
- package/dist/esm/transport/binary/decoder.js +8 -8
- package/dist/esm/transport/binary/encoder.js +10 -9
- package/dist/esm/transport/binary/index.js +0 -1
- package/dist/esm/transport/index.js +1 -0
- package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
- package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -21
- package/dist/esm/transport/node/WaNodeTransport.js +0 -3
- package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
- package/dist/esm/transport/node/builders/business.js +129 -0
- package/dist/esm/transport/node/builders/global.js +370 -0
- package/dist/esm/transport/node/builders/index.js +7 -3
- package/dist/esm/transport/node/builders/message.js +63 -230
- package/dist/esm/transport/node/builders/pairing.js +2 -27
- package/dist/esm/transport/node/builders/privacy-token.js +41 -0
- package/dist/esm/transport/node/builders/privacy.js +48 -0
- package/dist/esm/transport/node/builders/profile.js +70 -0
- package/dist/esm/transport/node/builders/retry.js +10 -22
- package/dist/esm/transport/node/builders/usync.js +45 -0
- package/dist/esm/transport/node/helpers.js +125 -5
- package/dist/esm/transport/node/usync.js +5 -0
- package/dist/esm/transport/node/xml.js +35 -14
- package/dist/esm/transport/noise/WaClientPayload.js +10 -10
- package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
- package/dist/esm/transport/noise/WaNoiseCert.js +4 -7
- package/dist/esm/transport/noise/WaNoiseSession.js +77 -29
- package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
- package/dist/esm/transport/proxy.js +27 -0
- package/dist/esm/transport/stream/parse.js +17 -48
- package/dist/esm/util/bytes.js +67 -45
- package/dist/esm/util/coercion.js +6 -14
- package/dist/esm/util/index.js +5 -0
- package/dist/esm/util/primitives.js +40 -14
- package/dist/index.js +7 -1
- package/dist/infra/log/ConsoleLogger.js +18 -17
- package/dist/infra/log/PinoLogger.js +15 -9
- package/dist/infra/log/types.js +12 -0
- package/dist/infra/perf/BackgroundQueue.js +482 -0
- package/dist/infra/perf/BoundedTaskQueue.js +16 -18
- package/dist/infra/perf/PromiseDedup.js +24 -0
- package/dist/infra/perf/SharedExclusiveGate.js +113 -0
- package/dist/infra/perf/StoreLock.js +81 -0
- package/dist/media/WaMediaCrypto.js +95 -15
- package/dist/media/WaMediaTransferClient.js +284 -91
- package/dist/media/conn.js +10 -6
- package/dist/media/constants.js +6 -2
- package/dist/message/WaMessageClient.js +31 -33
- package/dist/message/ack.js +6 -6
- package/dist/message/addon-crypto.js +65 -0
- package/dist/message/content.js +198 -9
- package/dist/message/icdc.js +81 -0
- package/dist/message/incoming.js +127 -120
- package/dist/message/index.js +2 -0
- package/dist/message/phash.js +3 -1
- package/dist/message/reporting-token.js +429 -0
- package/dist/message/use-case-secret.js +55 -0
- package/dist/protocol/appstate.js +28 -1
- package/dist/protocol/browser.js +10 -18
- package/dist/protocol/constants.js +26 -1
- package/dist/protocol/defaults.js +6 -0
- package/dist/protocol/index.js +23 -42
- package/dist/protocol/jid.js +140 -52
- package/dist/protocol/media.js +3 -3
- package/dist/protocol/message.js +62 -2
- package/dist/protocol/nodes.js +4 -0
- package/dist/protocol/notification.js +3 -1
- package/dist/protocol/privacy-token.js +20 -0
- package/dist/protocol/privacy.js +58 -0
- package/dist/protocol/stream.js +27 -2
- package/dist/protocol/usync.js +14 -0
- package/dist/retry/codec.js +220 -0
- package/dist/retry/constants.js +1 -1
- package/dist/retry/index.js +7 -5
- package/dist/retry/parse.js +88 -85
- package/dist/retry/replay.js +52 -49
- package/dist/retry/tracker.js +97 -0
- package/dist/signal/api/SignalDeviceSyncApi.js +273 -89
- package/dist/signal/api/SignalDigestSyncApi.js +17 -8
- package/dist/signal/api/SignalIdentitySyncApi.js +66 -36
- package/dist/signal/api/SignalMissingPreKeysSyncApi.js +82 -63
- package/dist/signal/api/SignalRotateKeyApi.js +4 -2
- package/dist/signal/api/SignalSessionSyncApi.js +36 -34
- package/dist/signal/api/result-map.js +13 -0
- package/dist/signal/constants.js +1 -5
- package/dist/signal/crypto/WaAdvSignature.js +11 -7
- package/dist/signal/{store/sqlite.js → encoding.js} +94 -61
- package/dist/signal/group/SenderKeyChain.js +27 -22
- package/dist/signal/group/SenderKeyCodec.js +5 -6
- package/dist/signal/group/SenderKeyManager.js +144 -115
- package/dist/signal/index.js +15 -1
- package/dist/signal/registration/keygen.js +6 -2
- package/dist/signal/registration/utils.js +1 -0
- package/dist/signal/session/SignalProtocol.js +164 -53
- package/dist/signal/session/SignalRatchet.js +24 -15
- package/dist/signal/session/SignalSession.js +14 -9
- package/dist/signal/session/resolver.js +224 -0
- package/dist/store/contracts/privacy-token.store.js +2 -0
- package/dist/store/createStore.js +100 -188
- package/dist/store/index.js +15 -33
- package/dist/store/locks/appstate.lock.js +29 -0
- package/dist/store/locks/auth.lock.js +18 -0
- package/dist/store/locks/contact.lock.js +23 -0
- package/dist/store/locks/device-list.lock.js +23 -0
- package/dist/store/locks/message.lock.js +24 -0
- package/dist/store/locks/participants.lock.js +23 -0
- package/dist/store/locks/privacy-token.lock.js +21 -0
- package/dist/store/locks/retry.lock.js +32 -0
- package/dist/store/locks/sender-key.lock.js +55 -0
- package/dist/store/locks/signal.lock.js +66 -0
- package/dist/store/locks/thread.lock.js +24 -0
- package/dist/store/noop.store.js +4 -7
- package/dist/store/providers/memory/appstate.store.js +36 -14
- package/dist/store/providers/memory/contact.store.js +5 -0
- package/dist/store/providers/memory/device-list.store.js +12 -34
- package/dist/store/providers/memory/message.store.js +11 -5
- package/dist/store/providers/memory/participants.store.js +1 -8
- package/dist/store/providers/memory/privacy-token.store.js +47 -0
- package/dist/store/providers/memory/retry.store.js +77 -2
- package/dist/store/providers/memory/sender-key.store.js +14 -11
- package/dist/store/providers/memory/signal.store.js +54 -25
- package/dist/store/providers/memory/thread.store.js +5 -0
- package/dist/transport/WaComms.js +30 -26
- package/dist/transport/WaWebSocket.js +148 -18
- package/dist/transport/binary/constants.js +1 -31
- package/dist/transport/binary/decoder.js +8 -8
- package/dist/transport/binary/encoder.js +10 -9
- package/dist/transport/binary/index.js +0 -4
- package/dist/transport/index.js +7 -1
- package/dist/transport/keepalive/WaKeepAlive.js +1 -7
- package/dist/transport/node/WaNodeOrchestrator.js +25 -21
- package/dist/transport/node/WaNodeTransport.js +0 -3
- package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
- package/dist/transport/node/builders/business.js +137 -0
- package/dist/transport/node/builders/global.js +375 -0
- package/dist/transport/node/builders/index.js +29 -17
- package/dist/transport/node/builders/message.js +64 -236
- package/dist/transport/node/builders/pairing.js +2 -29
- package/dist/transport/node/builders/privacy-token.js +46 -0
- package/dist/transport/node/builders/privacy.js +55 -0
- package/dist/transport/node/builders/profile.js +78 -0
- package/dist/transport/node/builders/retry.js +9 -21
- package/dist/transport/node/builders/usync.js +49 -0
- package/dist/transport/node/helpers.js +131 -4
- package/dist/transport/node/usync.js +8 -0
- package/dist/transport/node/xml.js +35 -14
- package/dist/transport/noise/WaClientPayload.js +13 -13
- package/dist/transport/noise/WaFrameCodec.js +47 -32
- package/dist/transport/noise/WaNoiseCert.js +5 -8
- package/dist/transport/noise/WaNoiseSession.js +77 -29
- package/dist/transport/noise/WaNoiseSocket.js +8 -4
- package/dist/transport/proxy.js +34 -0
- package/dist/transport/stream/parse.js +20 -52
- package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
- package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
- package/dist/types/appstate/constants.d.ts +1 -0
- package/dist/types/appstate/encoding.d.ts +7 -0
- package/dist/types/appstate/index.d.ts +3 -3
- package/dist/types/appstate/utils.d.ts +0 -3
- package/dist/types/auth/WaAuthClient.d.ts +10 -12
- package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
- package/dist/types/auth/index.d.ts +0 -4
- package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
- package/dist/types/auth/types.d.ts +7 -9
- package/dist/types/client/WaClient.d.ts +42 -25
- package/dist/types/client/WaClientFactory.d.ts +33 -26
- package/dist/types/client/connection/WaConnectionManager.d.ts +66 -0
- package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
- package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
- package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
- package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
- package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -2
- package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +29 -38
- package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
- package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
- package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
- package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +8 -0
- package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
- package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
- package/dist/types/client/dirty.d.ts +1 -0
- package/dist/types/client/events/devices.d.ts +20 -0
- package/dist/types/client/events/group.d.ts +2 -1
- package/dist/types/client/events/identity.d.ts +9 -0
- package/dist/types/client/events/privacy-token.d.ts +7 -0
- package/dist/types/client/history-sync.d.ts +9 -6
- package/dist/types/client/incoming.d.ts +3 -1
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/mailbox.d.ts +3 -5
- package/dist/types/client/messages.d.ts +1 -2
- package/dist/types/client/messaging/fanout.d.ts +14 -0
- package/dist/types/client/messaging/key-protocol.d.ts +18 -0
- package/dist/types/client/messaging/participants.d.ts +13 -0
- package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
- package/dist/types/client/tokens/cs-token.d.ts +10 -0
- package/dist/types/client/tokens/tc-token.d.ts +5 -0
- package/dist/types/client/types.d.ts +75 -4
- package/dist/types/crypto/core/hkdf.d.ts +0 -6
- package/dist/types/crypto/core/index.d.ts +2 -3
- package/dist/types/crypto/core/nonce.d.ts +2 -0
- package/dist/types/crypto/core/primitives.d.ts +0 -1
- package/dist/types/crypto/core/random.d.ts +2 -7
- package/dist/types/crypto/index.d.ts +0 -1
- package/dist/types/crypto/math/constants.d.ts +4 -2
- package/dist/types/crypto/math/fe.d.ts +30 -0
- package/dist/types/crypto/math/mod.d.ts +0 -2
- package/dist/types/crypto/math/types.d.ts +11 -4
- package/dist/types/index.d.ts +5 -3
- package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
- package/dist/types/infra/log/PinoLogger.d.ts +1 -1
- package/dist/types/infra/log/types.d.ts +1 -0
- package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
- package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
- package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
- package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
- package/dist/types/infra/perf/StoreLock.d.ts +10 -0
- package/dist/types/media/WaMediaCrypto.d.ts +3 -2
- package/dist/types/media/WaMediaTransferClient.d.ts +16 -15
- package/dist/types/media/constants.d.ts +1 -1
- package/dist/types/media/index.d.ts +1 -1
- package/dist/types/media/types.d.ts +15 -2
- package/dist/types/message/addon-crypto.d.ts +25 -0
- package/dist/types/message/content.d.ts +8 -0
- package/dist/types/message/icdc.d.ts +13 -0
- package/dist/types/message/index.d.ts +2 -0
- package/dist/types/message/reporting-token.d.ts +18 -0
- package/dist/types/message/types.d.ts +45 -6
- package/dist/types/message/use-case-secret.d.ts +20 -0
- package/dist/types/protocol/appstate.d.ts +47 -0
- package/dist/types/protocol/constants.d.ts +8 -3
- package/dist/types/protocol/defaults.d.ts +6 -0
- package/dist/types/protocol/index.d.ts +2 -11
- package/dist/types/protocol/jid.d.ts +22 -5
- package/dist/types/protocol/message.d.ts +60 -0
- package/dist/types/protocol/nodes.d.ts +4 -0
- package/dist/types/protocol/notification.d.ts +2 -0
- package/dist/types/protocol/privacy-token.d.ts +17 -0
- package/dist/types/protocol/privacy.d.ts +75 -0
- package/dist/types/protocol/stream.d.ts +30 -0
- package/dist/types/protocol/usync.d.ts +11 -0
- package/dist/types/retry/codec.d.ts +3 -0
- package/dist/types/retry/index.d.ts +4 -3
- package/dist/types/retry/parse.d.ts +5 -2
- package/dist/types/retry/replay.d.ts +0 -4
- package/dist/types/retry/tracker.d.ts +20 -0
- package/dist/types/retry/types.d.ts +10 -4
- package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +15 -2
- package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
- package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
- package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
- package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
- package/dist/types/signal/api/result-map.d.ts +1 -0
- package/dist/types/signal/constants.d.ts +0 -3
- package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
- package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
- package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
- package/dist/types/signal/index.d.ts +3 -0
- package/dist/types/signal/session/SignalProtocol.d.ts +19 -4
- package/dist/types/signal/session/resolver.d.ts +22 -0
- package/dist/types/store/contracts/appstate.store.d.ts +4 -1
- package/dist/types/store/contracts/contact.store.d.ts +1 -0
- package/dist/types/store/contracts/device-list.store.d.ts +0 -3
- package/dist/types/store/contracts/message.store.d.ts +1 -0
- package/dist/types/store/contracts/participants.store.d.ts +0 -1
- package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
- package/dist/types/store/contracts/retry.store.d.ts +7 -0
- package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
- package/dist/types/store/contracts/signal.store.d.ts +13 -0
- package/dist/types/store/contracts/thread.store.d.ts +1 -0
- package/dist/types/store/createStore.d.ts +1 -1
- package/dist/types/store/index.d.ts +5 -13
- package/dist/types/store/locks/appstate.lock.d.ts +3 -0
- package/dist/types/store/locks/auth.lock.d.ts +3 -0
- package/dist/types/store/locks/contact.lock.d.ts +3 -0
- package/dist/types/store/locks/device-list.lock.d.ts +2 -0
- package/dist/types/store/locks/message.lock.d.ts +3 -0
- package/dist/types/store/locks/participants.lock.d.ts +2 -0
- package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
- package/dist/types/store/locks/retry.lock.d.ts +2 -0
- package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
- package/dist/types/store/locks/signal.lock.d.ts +3 -0
- package/dist/types/store/locks/thread.lock.d.ts +3 -0
- package/dist/types/store/providers/memory/appstate.store.d.ts +3 -1
- package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
- package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
- package/dist/types/store/providers/memory/message.store.d.ts +1 -0
- package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
- package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
- package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
- package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
- package/dist/types/store/providers/memory/signal.store.d.ts +8 -1
- package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
- package/dist/types/store/types.d.ts +49 -58
- package/dist/types/transport/WaWebSocket.d.ts +3 -1
- package/dist/types/transport/binary/constants.d.ts +0 -30
- package/dist/types/transport/binary/index.d.ts +0 -1
- package/dist/types/transport/index.d.ts +2 -1
- package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
- package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
- package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
- package/dist/types/transport/node/builders/business.d.ts +29 -0
- package/dist/types/transport/node/builders/global.d.ts +102 -0
- package/dist/types/transport/node/builders/group.d.ts +4 -6
- package/dist/types/transport/node/builders/index.d.ts +7 -3
- package/dist/types/transport/node/builders/message.d.ts +20 -30
- package/dist/types/transport/node/builders/pairing.d.ts +0 -2
- package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
- package/dist/types/transport/node/builders/privacy.d.ts +7 -0
- package/dist/types/transport/node/builders/profile.d.ts +8 -0
- package/dist/types/transport/node/builders/retry.d.ts +2 -5
- package/dist/types/transport/node/builders/usync.d.ts +21 -0
- package/dist/types/transport/node/helpers.d.ts +13 -0
- package/dist/types/transport/node/usync.d.ts +2 -0
- package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
- package/dist/types/transport/noise/WaNoiseSession.d.ts +4 -2
- package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
- package/dist/types/transport/proxy.d.ts +6 -0
- package/dist/types/transport/stream/parse.d.ts +0 -1
- package/dist/types/transport/types.d.ts +18 -1
- package/dist/types/util/bytes.d.ts +5 -0
- package/dist/types/util/index.d.ts +5 -0
- package/dist/types/util/primitives.d.ts +2 -0
- package/dist/util/bytes.js +72 -46
- package/dist/util/coercion.js +6 -14
- package/dist/util/index.js +23 -0
- package/dist/util/primitives.js +42 -14
- package/package.json +52 -9
- package/proto/index.js +1 -1
- package/dist/crypto/core/constants.js +0 -4
- package/dist/crypto/core/encoding.js +0 -29
- package/dist/esm/crypto/core/constants.js +0 -1
- package/dist/esm/crypto/core/encoding.js +0 -25
- package/dist/esm/retry/outbound.js +0 -83
- package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
- package/dist/esm/store/providers/sqlite/appstate.store.js +0 -169
- package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
- package/dist/esm/store/providers/sqlite/connection.js +0 -240
- package/dist/esm/store/providers/sqlite/contact.store.js +0 -61
- package/dist/esm/store/providers/sqlite/device-list.store.js +0 -155
- package/dist/esm/store/providers/sqlite/message.store.js +0 -119
- package/dist/esm/store/providers/sqlite/migrations.js +0 -347
- package/dist/esm/store/providers/sqlite/participants.store.js +0 -85
- package/dist/esm/store/providers/sqlite/retry.store.js +0 -144
- package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -203
- package/dist/esm/store/providers/sqlite/signal.store.js +0 -353
- package/dist/esm/store/providers/sqlite/thread.store.js +0 -72
- package/dist/esm/util/base64.js +0 -18
- package/dist/esm/util/signal-address.js +0 -5
- package/dist/retry/outbound.js +0 -88
- package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
- package/dist/store/providers/sqlite/appstate.store.js +0 -173
- package/dist/store/providers/sqlite/auth.store.js +0 -180
- package/dist/store/providers/sqlite/connection.js +0 -276
- package/dist/store/providers/sqlite/contact.store.js +0 -65
- package/dist/store/providers/sqlite/device-list.store.js +0 -159
- package/dist/store/providers/sqlite/message.store.js +0 -123
- package/dist/store/providers/sqlite/migrations.js +0 -350
- package/dist/store/providers/sqlite/participants.store.js +0 -89
- package/dist/store/providers/sqlite/retry.store.js +0 -148
- package/dist/store/providers/sqlite/sender-key.store.js +0 -207
- package/dist/store/providers/sqlite/signal.store.js +0 -357
- package/dist/store/providers/sqlite/thread.store.js +0 -76
- package/dist/types/appstate/store/sqlite.d.ts +0 -21
- package/dist/types/crypto/core/constants.d.ts +0 -1
- package/dist/types/crypto/core/encoding.d.ts +0 -11
- package/dist/types/retry/outbound.d.ts +0 -4
- package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
- package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -15
- package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
- package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
- package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -10
- package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -18
- package/dist/types/store/providers/sqlite/message.store.d.ts +0 -11
- package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
- package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -13
- package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -16
- package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -25
- package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -46
- package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -11
- package/dist/types/util/base64.d.ts +0 -4
- package/dist/types/util/signal-address.d.ts +0 -2
- package/dist/util/base64.js +0 -24
- package/dist/util/signal-address.js +0 -8
- /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
|
|
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
|
|
21
|
-
|
|
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.
|
|
79
|
-
const
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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.
|
|
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
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
-
|
|
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
|
|
344
|
-
if (
|
|
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
|
|
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(
|
|
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:
|
|
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
|
|
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
|
-
|
|
427
|
-
|
|
428
|
-
|
|
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 =
|
|
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
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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 });
|