@wireapp/core 46.46.6-beta.14.f6fd03fe6 → 46.46.6

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 (195) hide show
  1. package/lib/Account.d.ts +156 -51
  2. package/lib/Account.d.ts.map +1 -1
  3. package/lib/Account.js +503 -127
  4. package/lib/Account.test.js +158 -147
  5. package/lib/broadcast/AvailabilityType.d.ts +1 -1
  6. package/lib/broadcast/AvailabilityType.d.ts.map +1 -1
  7. package/lib/broadcast/BroadcastService.d.ts +1 -1
  8. package/lib/broadcast/BroadcastService.d.ts.map +1 -1
  9. package/lib/broadcast/BroadcastService.js +1 -1
  10. package/lib/client/ClientService.d.ts +4 -3
  11. package/lib/client/ClientService.d.ts.map +1 -1
  12. package/lib/client/ClientService.js +19 -5
  13. package/lib/conversation/AbortReason.d.ts +1 -1
  14. package/lib/conversation/AbortReason.d.ts.map +1 -1
  15. package/lib/conversation/AssetService/AssetService.d.ts +12 -30
  16. package/lib/conversation/AssetService/AssetService.d.ts.map +1 -1
  17. package/lib/conversation/AssetService/AssetService.js +1 -10
  18. package/lib/conversation/AssetService/AssetService.test.js +8 -3
  19. package/lib/conversation/ClientActionType.d.ts +1 -1
  20. package/lib/conversation/ClientActionType.d.ts.map +1 -1
  21. package/lib/conversation/ClientActionType.js +1 -1
  22. package/lib/conversation/ConversationService/ConversationService.d.ts +98 -14
  23. package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
  24. package/lib/conversation/ConversationService/ConversationService.js +314 -101
  25. package/lib/conversation/ConversationService/ConversationService.test.js +441 -47
  26. package/lib/conversation/ConversationService/ConversationService.types.d.ts +5 -4
  27. package/lib/conversation/ConversationService/ConversationService.types.d.ts.map +1 -1
  28. package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.d.ts.map +1 -1
  29. package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.js +6 -3
  30. package/lib/conversation/SubconversationService/SubconversationService.d.ts.map +1 -1
  31. package/lib/conversation/SubconversationService/SubconversationService.js +158 -11
  32. package/lib/conversation/SubconversationService/SubconversationService.test.js +8 -2
  33. package/lib/conversation/content/AssetContent.d.ts +1 -1
  34. package/lib/conversation/content/AssetContent.d.ts.map +1 -1
  35. package/lib/conversation/content/ButtonActionConfirmationContent.d.ts +1 -1
  36. package/lib/conversation/content/ButtonActionConfirmationContent.d.ts.map +1 -1
  37. package/lib/conversation/content/ButtonActionContent.d.ts +1 -1
  38. package/lib/conversation/content/ButtonActionContent.d.ts.map +1 -1
  39. package/lib/conversation/content/ClearedContent.d.ts +1 -1
  40. package/lib/conversation/content/ClearedContent.d.ts.map +1 -1
  41. package/lib/conversation/content/ClientActionContent.d.ts +1 -1
  42. package/lib/conversation/content/ClientActionContent.d.ts.map +1 -1
  43. package/lib/conversation/content/CompositeContent.d.ts +1 -1
  44. package/lib/conversation/content/CompositeContent.d.ts.map +1 -1
  45. package/lib/conversation/content/ConfirmationContent.d.ts +1 -1
  46. package/lib/conversation/content/ConfirmationContent.d.ts.map +1 -1
  47. package/lib/conversation/content/DeletedContent.d.ts +1 -1
  48. package/lib/conversation/content/DeletedContent.d.ts.map +1 -1
  49. package/lib/conversation/content/HiddenContent.d.ts +1 -1
  50. package/lib/conversation/content/HiddenContent.d.ts.map +1 -1
  51. package/lib/conversation/content/KnockContent.d.ts +1 -1
  52. package/lib/conversation/content/KnockContent.d.ts.map +1 -1
  53. package/lib/conversation/content/LinkPreviewContent.d.ts +1 -1
  54. package/lib/conversation/content/LinkPreviewContent.d.ts.map +1 -1
  55. package/lib/conversation/content/MentionContent.d.ts +1 -1
  56. package/lib/conversation/content/MentionContent.d.ts.map +1 -1
  57. package/lib/conversation/content/MultipartContent.d.ts +1 -1
  58. package/lib/conversation/content/MultipartContent.d.ts.map +1 -1
  59. package/lib/conversation/content/QuoteContent.d.ts +1 -1
  60. package/lib/conversation/content/QuoteContent.d.ts.map +1 -1
  61. package/lib/conversation/content/TweetContent.d.ts +1 -1
  62. package/lib/conversation/content/TweetContent.d.ts.map +1 -1
  63. package/lib/conversation/content/index.d.ts +1 -1
  64. package/lib/conversation/content/index.d.ts.map +1 -1
  65. package/lib/conversation/content/index.js +1 -1
  66. package/lib/conversation/message/MessageBuilder.d.ts +1 -1
  67. package/lib/conversation/message/MessageBuilder.d.ts.map +1 -1
  68. package/lib/conversation/message/MessageBuilder.js +1 -1
  69. package/lib/conversation/message/MessageService.d.ts.map +1 -1
  70. package/lib/conversation/message/MessageService.js +1 -1
  71. package/lib/conversation/message/MessageService.test.js +7 -1
  72. package/lib/conversation/message/MessageToProtoMapper.d.ts +1 -1
  73. package/lib/conversation/message/MessageToProtoMapper.d.ts.map +1 -1
  74. package/lib/conversation/message/MessageToProtoMapper.js +1 -1
  75. package/lib/conversation/message/messageSender.js +2 -2
  76. package/lib/cryptography/AssetCryptography/EncryptedAsset.d.ts +2 -2
  77. package/lib/cryptography/AssetCryptography/EncryptedAsset.d.ts.map +1 -1
  78. package/lib/messagingProtocols/common.types.d.ts +9 -0
  79. package/lib/messagingProtocols/common.types.d.ts.map +1 -1
  80. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.d.ts +2 -2
  81. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.d.ts.map +1 -1
  82. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.js +2 -1
  83. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.d.ts +1 -1
  84. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.d.ts.map +1 -1
  85. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.js +13 -11
  86. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.test.js +21 -16
  87. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts +9 -3
  88. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts.map +1 -1
  89. package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.js +31 -12
  90. package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts +6 -0
  91. package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts.map +1 -1
  92. package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.js +19 -1
  93. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts +7 -0
  94. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts.map +1 -0
  95. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.js +48 -0
  96. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/index.d.ts +2 -0
  97. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingMessagesQueue → IncomingProposalsQueue}/index.d.ts.map +1 -1
  98. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingMessagesQueue → IncomingProposalsQueue}/index.js +1 -1
  99. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts +0 -1
  100. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts.map +1 -1
  101. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.js +0 -1
  102. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts.map +1 -1
  103. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.js +23 -14
  104. package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.d.ts.map +1 -1
  105. package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.js +5 -2
  106. package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.test.js +13 -3
  107. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts +38 -2
  108. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts.map +1 -1
  109. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.js +41 -6
  110. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts +2 -0
  111. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts.map +1 -0
  112. package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.js +124 -0
  113. package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +38 -34
  114. package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
  115. package/lib/messagingProtocols/mls/MLSService/MLSService.js +267 -208
  116. package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +157 -160
  117. package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.js +3 -3
  118. package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.test.js +5 -5
  119. package/lib/messagingProtocols/mls/conversationRejoinQueue.js +2 -2
  120. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts +78 -0
  121. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts.map +1 -0
  122. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.js +173 -0
  123. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts +2 -0
  124. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts.map +1 -0
  125. package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.js +117 -0
  126. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts +167 -0
  127. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts.map +1 -0
  128. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.js +317 -0
  129. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts +2 -0
  130. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts.map +1 -0
  131. package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.js +248 -0
  132. package/lib/messagingProtocols/mls/recovery/index.d.ts +5 -0
  133. package/lib/messagingProtocols/mls/recovery/index.d.ts.map +1 -0
  134. package/lib/messagingProtocols/mls/recovery/index.js +28 -0
  135. package/lib/messagingProtocols/mls/types.d.ts +0 -8
  136. package/lib/messagingProtocols/mls/types.d.ts.map +1 -1
  137. package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.d.ts.map +1 -1
  138. package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.js +7 -1
  139. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts +8 -15
  140. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts.map +1 -1
  141. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.js +97 -62
  142. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts +0 -6
  143. package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts.map +1 -1
  144. package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts +1 -6
  145. package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts.map +1 -1
  146. package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.js +19 -22
  147. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts +5 -3
  148. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts.map +1 -1
  149. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.js +11 -24
  150. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts +1 -0
  151. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts.map +1 -1
  152. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.js +11 -2
  153. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +13 -9
  154. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts +3 -2
  155. package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts.map +1 -1
  156. package/lib/messagingProtocols/proteus/ProteusService/WithMockedGenerics.test.js +11 -4
  157. package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts +0 -4
  158. package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts.map +1 -1
  159. package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.js +0 -5
  160. package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts +2 -1
  161. package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts.map +1 -1
  162. package/lib/messagingProtocols/proteus/ProteusService/identityClearer.js +8 -2
  163. package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.test.js +4 -0
  164. package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts +1 -1
  165. package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts.map +1 -1
  166. package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.js +1 -1
  167. package/lib/notification/NotificationService.d.ts +20 -6
  168. package/lib/notification/NotificationService.d.ts.map +1 -1
  169. package/lib/notification/NotificationService.js +23 -14
  170. package/lib/notification/NotificationService.test.js +8 -0
  171. package/lib/secretStore/secretKeyGenerator.d.ts +1 -0
  172. package/lib/secretStore/secretKeyGenerator.d.ts.map +1 -1
  173. package/lib/secretStore/secretKeyGenerator.js +3 -1
  174. package/lib/self/SelfService.d.ts +2 -2
  175. package/lib/self/SelfService.d.ts.map +1 -1
  176. package/lib/self/SelfService.test.js +5 -2
  177. package/lib/team/TeamService.d.ts +5 -2
  178. package/lib/team/TeamService.d.ts.map +1 -1
  179. package/lib/team/TeamService.js +12 -2
  180. package/lib/test/StoreHelper.d.ts +2 -0
  181. package/lib/test/StoreHelper.d.ts.map +1 -0
  182. package/lib/test/StoreHelper.js +27 -0
  183. package/lib/user/UserService.d.ts +2 -2
  184. package/lib/user/UserService.d.ts.map +1 -1
  185. package/lib/user/UserService.js +3 -3
  186. package/lib/util/TypePredicateUtil.d.ts.map +1 -1
  187. package/lib/util/TypePredicateUtil.js +2 -2
  188. package/package.json +3 -3
  189. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts +0 -4
  190. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts.map +0 -1
  191. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.js +0 -69
  192. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/index.d.ts +0 -2
  193. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts +0 -2
  194. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts.map +0 -1
  195. package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.js +0 -98
@@ -18,24 +18,20 @@
18
18
  *
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.MLSService = exports.optionalToUint8Array = void 0;
22
- const http_1 = require("@wireapp/api-client/lib/http");
23
- const TimeUtil_1 = require("@wireapp/commons/lib/util/TimeUtil");
21
+ exports.MLSService = exports.MLSServiceEvents = exports.optionalToUint8Array = void 0;
22
+ const conversation_1 = require("@wireapp/api-client/lib/conversation");
24
23
  const bazinga64_1 = require("bazinga64");
25
24
  const commons_1 = require("@wireapp/commons");
26
25
  const core_crypto_1 = require("@wireapp/core-crypto");
27
- const priority_queue_1 = require("@wireapp/priority-queue");
28
26
  const ClientMLSError_1 = require("./ClientMLSError");
29
27
  const CoreCryptoMLSError_1 = require("./CoreCryptoMLSError");
30
- const conversation_1 = require("../../../conversation");
31
- const messageSender_1 = require("../../../conversation/message/messageSender");
28
+ const conversation_2 = require("../../../conversation");
32
29
  const fullyQualifiedClientIdUtils_1 = require("../../../util/fullyQualifiedClientIdUtils");
33
30
  const numberToHex_1 = require("../../../util/numberToHex");
34
31
  const TaskScheduler_1 = require("../../../util/TaskScheduler");
35
32
  const E2EIServiceInternal_1 = require("../E2EIdentityService/E2EIServiceInternal");
36
33
  const Helper_1 = require("../E2EIdentityService/Helper");
37
34
  const events_1 = require("../EventHandler/events");
38
- const messageAdd_1 = require("../EventHandler/events/messageAdd");
39
35
  const MLSId_1 = require("../utils/MLSId");
40
36
  //@todo: this function is temporary, we wait for the update from core-crypto side
41
37
  //they are returning regular array instead of Uint8Array for commit and welcome messages
@@ -44,9 +40,17 @@ const optionalToUint8Array = (array) => {
44
40
  };
45
41
  exports.optionalToUint8Array = optionalToUint8Array;
46
42
  const defaultConfig = {
47
- keyingMaterialUpdateThreshold: 1000 * 60 * 60 * 24 * 30, //30 days
43
+ keyingMaterialUpdateThreshold: commons_1.TimeUtil.TimeInMillis.DAY * 30,
48
44
  nbKeyPackages: 100,
49
45
  };
46
+ var MLSServiceEvents;
47
+ (function (MLSServiceEvents) {
48
+ MLSServiceEvents["NEW_EPOCH"] = "newEpoch";
49
+ MLSServiceEvents["MLS_CLIENT_MISMATCH"] = "mlsClientMismatch";
50
+ MLSServiceEvents["NEW_CRL_DISTRIBUTION_POINTS"] = "newCrlDistributionPoints";
51
+ MLSServiceEvents["MLS_EVENT_DISTRIBUTED"] = "mlsEventDistributed";
52
+ MLSServiceEvents["KEY_MATERIAL_UPDATE_FAILURE"] = "keyMaterialUpdateFailure";
53
+ })(MLSServiceEvents || (exports.MLSServiceEvents = MLSServiceEvents = {}));
50
54
  class MLSService extends commons_1.TypedEventEmitter {
51
55
  apiClient;
52
56
  coreCryptoClient;
@@ -56,18 +60,31 @@ class MLSService extends commons_1.TypedEventEmitter {
56
60
  _config;
57
61
  textEncoder = new TextEncoder();
58
62
  textDecoder = new TextDecoder();
59
- conflictBackoffQueue = new priority_queue_1.PriorityQueue({
60
- maxRetries: 10,
61
- retryDelay: 500,
62
- maxRetryDelay: TimeUtil_1.TimeInMillis.SECOND * 32,
63
- shouldRetry: error => error instanceof http_1.BackendError && error.code === http_1.StatusCode.CONFLICT,
64
- });
65
63
  constructor(apiClient, coreCryptoClient, coreDatabase, recurringTaskScheduler) {
66
64
  super();
67
65
  this.apiClient = apiClient;
68
66
  this.coreCryptoClient = coreCryptoClient;
69
67
  this.coreDatabase = coreDatabase;
70
68
  this.recurringTaskScheduler = recurringTaskScheduler;
69
+ const mlsTransport = {
70
+ sendCommitBundle: this._uploadCommitBundle,
71
+ // Info: This is not used for now, but we need to implement it to be able to use the mls transport
72
+ sendMessage: async () => {
73
+ return 'success';
74
+ },
75
+ prepareForTransport: async () => {
76
+ throw new Error('Method not implemented.');
77
+ },
78
+ };
79
+ const epochObserver = {
80
+ epochChanged: async (groupId, epoch) => {
81
+ const groupIdStr = bazinga64_1.Encoder.toBase64(groupId.copyBytes()).asString;
82
+ this.logger.info(`Epoch changed for group ${groupIdStr}, new epoch: ${epoch}`);
83
+ this.emit(MLSServiceEvents.NEW_EPOCH, { epoch, groupId: groupIdStr });
84
+ },
85
+ };
86
+ void this.coreCryptoClient.registerEpochObserver(epochObserver);
87
+ void this.coreCryptoClient.provideTransport(mlsTransport);
71
88
  }
72
89
  /**
73
90
  * return true if the MLS service if configured and ready to be used
@@ -97,24 +114,39 @@ class MLSService extends commons_1.TypedEventEmitter {
97
114
  ...defaultConfig,
98
115
  ...filteredMLSConfig,
99
116
  };
100
- await this.coreCryptoClient.mlsInit((0, MLSId_1.generateMLSDeviceId)(userId, client.id), this.config.ciphersuites, this.config.nbKeyPackages);
101
- await this.coreCryptoClient.registerCallbacks({
102
- // All authorization/membership rules are enforced on backend
103
- clientIsExistingGroupUser: async () => true,
104
- authorize: async () => true,
105
- userAuthorize: async () => true,
117
+ await this.coreCryptoClient.transaction(cx => {
118
+ const clientId = new core_crypto_1.ClientId((0, MLSId_1.generateMLSDeviceId)(userId, client.id));
119
+ return cx.mlsInit(clientId, this.config.ciphersuites, this.config.nbKeyPackages);
106
120
  });
107
- const isFreshMLSSelfClient = !this.isInitializedMLSClient(client);
108
- const shouldinitIdentity = !(isFreshMLSSelfClient && skipInitIdentity);
109
- if (shouldinitIdentity) {
110
- // We need to make sure keypackages and public key are uploaded to the backend
111
- if (isFreshMLSSelfClient) {
112
- await this.uploadMLSPublicKeys(client);
121
+ try {
122
+ const ccClientSignature = await this.getCCClientSignatureString();
123
+ const mlsDeviceStatus = (0, Helper_1.getMLSDeviceStatus)(client, this.config.defaultCiphersuite, ccClientSignature);
124
+ switch (mlsDeviceStatus) {
125
+ case Helper_1.MLSDeviceStatus.REGISTERED:
126
+ if (!skipInitIdentity) {
127
+ await this.verifyRemoteMLSKeyPackagesAmount(client.id);
128
+ }
129
+ else {
130
+ this.logger.info(`Blocked initial key package upload for client ${client.id} as E2EI is enabled`);
131
+ }
132
+ break;
133
+ case Helper_1.MLSDeviceStatus.MISMATCH:
134
+ this.logger.error(`Client ${client.id} is registered but with a different signature`);
135
+ this.emit(MLSServiceEvents.MLS_CLIENT_MISMATCH);
136
+ break;
137
+ case Helper_1.MLSDeviceStatus.FRESH:
138
+ if (!skipInitIdentity) {
139
+ await this.uploadMLSPublicKeys(client);
140
+ }
141
+ else {
142
+ this.logger.info(`Blocked initial key package upload for client ${client.id} as E2EI is enabled`);
143
+ }
144
+ break;
113
145
  }
114
- await this.verifyRemoteMLSKeyPackagesAmount(client.id);
115
146
  }
116
- else {
117
- this.logger.info(`Blocked initial key package upload for client ${client.id} as E2EI is enabled`);
147
+ catch (error) {
148
+ this.logger.error(`Error while initializing client ${client.id}`, error);
149
+ throw error;
118
150
  }
119
151
  }
120
152
  /**
@@ -127,46 +159,62 @@ class MLSService extends commons_1.TypedEventEmitter {
127
159
  ? core_crypto_1.CredentialType.X509
128
160
  : core_crypto_1.CredentialType.Basic;
129
161
  }
130
- uploadCommitBundle = async (groupId, commitBundle, { isExternalCommit = false, regenerateCommitBundle } = {}) => {
162
+ _uploadCommitBundle = async ({ commit, groupInfo, welcome, }) => {
163
+ const bundlePayload = new Uint8Array([
164
+ ...commit,
165
+ ...groupInfo.payload.copyBytes(),
166
+ ...(welcome?.copyBytes() || []),
167
+ ]);
131
168
  try {
132
- return await this._uploadCommitBundle(groupId, async () => commitBundle, isExternalCommit);
169
+ const response = await this.apiClient.api.conversation.postMlsCommitBundle(bundlePayload);
170
+ if (response.failed_to_send) {
171
+ this.logger.warn(`Failed to send commit bundle to backend`);
172
+ return 'retry';
173
+ }
174
+ const { events, time } = response;
175
+ this.emit(MLSServiceEvents.MLS_EVENT_DISTRIBUTED, { events, time });
176
+ return 'success';
133
177
  }
134
178
  catch (error) {
135
- if (error instanceof http_1.BackendError && error.code === http_1.StatusCode.CONFLICT && regenerateCommitBundle) {
136
- return this.conflictBackoffQueue.add(async () => this._uploadCommitBundle(groupId, regenerateCommitBundle, isExternalCommit));
179
+ this.logger.warn(`Failed to upload commit bundle`, error);
180
+ if (error instanceof conversation_1.MLSInvalidLeafNodeSignatureError || error instanceof conversation_1.MLSInvalidLeafNodeIndexError) {
181
+ this.logger.info('Aborting commit bundle upload due to broken MLS conversation');
182
+ return {
183
+ abort: {
184
+ reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({
185
+ message: CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.BROKEN_MLS_CONVERSATION,
186
+ }),
187
+ },
188
+ };
137
189
  }
138
- throw error;
139
- }
140
- };
141
- _uploadCommitBundle = async (groupId, generateCommitBundle, isExternalCommit) => {
142
- const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
143
- // We need to lock the incoming mls messages queue while we are uploading the commit bundle
144
- // it's possible that we will be sent some mls messages before we receive the response from backend and accept a commit locally.
145
- return (0, messageAdd_1.withLockedMLSMessagesQueue)(groupIdStr, async () => {
146
- const { commit, groupInfo, welcome } = await generateCommitBundle();
147
- const bundlePayload = new Uint8Array([...commit, ...groupInfo.payload, ...(welcome || [])]);
148
- try {
149
- const response = await this.apiClient.api.conversation.postMlsCommitBundle(bundlePayload);
150
- if (isExternalCommit) {
151
- await this.coreCryptoClient.mergePendingGroupFromExternalCommit(groupId);
152
- }
153
- else {
154
- await this.coreCryptoClient.commitAccepted(groupId);
155
- }
156
- const newEpoch = await this.getEpoch(groupId);
157
- this.emit('newEpoch', { epoch: newEpoch, groupId: groupIdStr });
158
- return response;
190
+ if (error instanceof conversation_1.MLSStaleMessageError) {
191
+ this.logger.info('Aborting commit bundle upload due to stale MLS message');
192
+ return {
193
+ abort: {
194
+ reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({ message: CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.MLS_STALE_MESSAGE }),
195
+ },
196
+ };
159
197
  }
160
- catch (error) {
161
- if (isExternalCommit) {
162
- await this.coreCryptoClient.clearPendingGroupFromExternalCommit(groupId);
163
- }
164
- else {
165
- await this.coreCryptoClient.clearPendingCommit(groupId);
166
- }
167
- throw error;
198
+ if (error instanceof conversation_1.MLSGroupOutOfSyncError) {
199
+ this.logger.info('Aborting commit bundle upload due to group out of sync');
200
+ return {
201
+ abort: {
202
+ reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({
203
+ message: CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.MLS_GROUP_OUT_OF_SYNC,
204
+ missing_users: error.missing_users,
205
+ }),
206
+ },
207
+ };
168
208
  }
169
- });
209
+ this.logger.info('Aborting commit bundle upload due to unknown error');
210
+ return {
211
+ abort: {
212
+ reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({
213
+ message: error instanceof Error ? error.message : CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.OTHER,
214
+ }),
215
+ },
216
+ };
217
+ }
170
218
  };
171
219
  /**
172
220
  * Will add users to an existing MLS group and send a commit bundle to backend.
@@ -180,25 +228,26 @@ class MLSService extends commons_1.TypedEventEmitter {
180
228
  if (keyPackages.length < 1) {
181
229
  throw new Error('Empty list of keys provided to addUsersToExistingConversation');
182
230
  }
183
- //TODO: handle federation error when sending a commit bundle to backend like we do in ProteusService
184
- const response = await this.processCommitAction(groupIdBytes, async () => {
185
- const commitBundle = await this.coreCryptoClient.addClientsToConversation(groupIdBytes, keyPackages);
186
- this.dispatchNewCrlDistributionPoints(commitBundle);
187
- return commitBundle;
188
- });
189
- const failedUsers = response.failed;
190
- const failures = failedUsers
191
- ? [
192
- {
193
- users: failedUsers,
194
- backends: failedUsers.map(({ domain }) => domain),
195
- reason: conversation_1.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
196
- },
197
- ]
198
- : [];
199
- return { ...response, failures };
231
+ const crlNewDistributionPoints = await this.coreCryptoClient.transaction(cx => cx.addClientsToConversation(new core_crypto_1.ConversationId(groupIdBytes), keyPackages));
232
+ this.dispatchNewCrlDistributionPoints(crlNewDistributionPoints);
200
233
  }
201
- async getKeyPackagesPayload(qualifiedUsers) {
234
+ /**
235
+ * Will return a list of client ids which are already in the group at core crypto level
236
+ *
237
+ * @param groupId - the group id of the MLS group
238
+ * @returns list of client ids
239
+ */
240
+ async getClientIdsInGroup(groupId) {
241
+ const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
242
+ const currentClientIdsInGroup = [];
243
+ for (const clientId of await this.coreCryptoClient.getClientIds(new core_crypto_1.ConversationId(groupIdBytes))) {
244
+ // [user-id]:[client-id]@[domain] -> [client-id]
245
+ // example: fb880fac-b549-4d8b-9398-4246324c7b85:67f41928e2844b6c@staging.zinfra.io -> 67f41928e2844b6c
246
+ currentClientIdsInGroup.push(bazinga64_1.Converter.arrayBufferViewToStringUTF8(clientId.copyBytes()).split('@')[0].split(':')[1]);
247
+ }
248
+ return currentClientIdsInGroup;
249
+ }
250
+ async getKeyPackagesPayload(qualifiedUsers, skipClientIds = []) {
202
251
  /**
203
252
  * @note We need to fetch key packages for all the users
204
253
  * we want to add to the new MLS conversations,
@@ -238,18 +287,20 @@ class MLSService extends commons_1.TypedEventEmitter {
238
287
  if (key_packages.length > 0) {
239
288
  return [
240
289
  ...previousValue,
241
- ...key_packages.map(keyPackage => bazinga64_1.Decoder.fromBase64(keyPackage.key_package).asBytes),
290
+ ...key_packages
291
+ .filter(keyPackage => !skipClientIds.includes(keyPackage.client))
292
+ .map(keyPackage => bazinga64_1.Decoder.fromBase64(keyPackage.key_package).asBytes),
242
293
  ];
243
294
  }
244
295
  return previousValue;
245
296
  }, []);
246
297
  const failures = [];
247
298
  if (emptyKeyPackagesUsers.length > 0) {
248
- failures.push({ reason: conversation_1.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG, users: emptyKeyPackagesUsers });
299
+ failures.push({ reason: conversation_2.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG, users: emptyKeyPackagesUsers });
249
300
  }
250
301
  if (failedToFetchKeyPackages.length > 0) {
251
302
  failures.push({
252
- reason: conversation_1.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
303
+ reason: conversation_2.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
253
304
  users: failedToFetchKeyPackages,
254
305
  backends: failedToFetchKeyPackages.map(({ domain }) => domain),
255
306
  });
@@ -258,92 +309,98 @@ class MLSService extends commons_1.TypedEventEmitter {
258
309
  }
259
310
  getEpoch(groupId) {
260
311
  const groupIdBytes = typeof groupId === 'string' ? bazinga64_1.Decoder.fromBase64(groupId).asBytes : groupId;
261
- return this.coreCryptoClient.conversationEpoch(groupIdBytes);
262
- }
263
- async newProposal(proposalType, args) {
264
- return this.coreCryptoClient.newProposal(proposalType, args);
312
+ return this.coreCryptoClient.conversationEpoch(new core_crypto_1.ConversationId(groupIdBytes));
265
313
  }
266
314
  async joinByExternalCommit(getGroupInfo) {
267
- const credentialType = await this.getCredentialType();
268
- const generateCommit = async () => {
315
+ try {
316
+ this.logger.info('Trying to join MLS group via external commit');
317
+ const credentialType = await this.getCredentialType();
269
318
  const groupInfo = await getGroupInfo();
270
- const joinRequest = await this.coreCryptoClient.joinByExternalCommit(groupInfo, credentialType);
271
- this.dispatchNewCrlDistributionPoints(joinRequest);
272
- const { conversationId, ...commitBundle } = joinRequest;
273
- return { groupId: conversationId, commitBundle };
274
- };
275
- const { commitBundle, groupId } = await generateCommit();
276
- const mlsResponse = await this.uploadCommitBundle(groupId, commitBundle, {
277
- isExternalCommit: true,
278
- regenerateCommitBundle: async () => (await generateCommit()).commitBundle,
279
- });
280
- if (mlsResponse) {
281
- //after we've successfully joined via external commit, we schedule periodic key material renewal
282
- const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
283
- await this.scheduleKeyMaterialRenewal(groupIdStr);
319
+ const welcomeBundle = await this.coreCryptoClient.transaction(cx => cx.joinByExternalCommit(new core_crypto_1.GroupInfo(groupInfo), credentialType));
320
+ await this.dispatchNewCrlDistributionPoints(welcomeBundle.crlNewDistributionPoints);
321
+ this.logger.info('welcome bundle after joining via external commit');
322
+ if (welcomeBundle.id) {
323
+ //after we've successfully joined via external commit, we schedule periodic key material renewal
324
+ const groupIdStr = bazinga64_1.Encoder.toBase64(welcomeBundle.id.copyBytes()).asString;
325
+ const newEpoch = await this.getEpoch(groupIdStr);
326
+ // Schedule the next key material renewal
327
+ await this.scheduleKeyMaterialRenewal(groupIdStr);
328
+ // Notify subscribers about the new epoch
329
+ this.emit(MLSServiceEvents.NEW_EPOCH, { groupId: groupIdStr, epoch: newEpoch });
330
+ this.logger.info(`Joined MLS group with id ${groupIdStr} via external commit, new epoch: ${newEpoch}`);
331
+ }
332
+ }
333
+ catch (error) {
334
+ this.logger.warn('Failed to join MLS group via external commit', error);
335
+ throw error;
284
336
  }
285
- return mlsResponse;
286
337
  }
287
338
  async exportSecretKey(groupId, keyLength) {
288
339
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
289
- const key = await this.coreCryptoClient.exportSecretKey(groupIdBytes, keyLength);
340
+ const key = await this.coreCryptoClient.exportSecretKey(new core_crypto_1.ConversationId(groupIdBytes), keyLength);
290
341
  return bazinga64_1.Encoder.toBase64(key).asString;
291
342
  }
292
- dispatchNewCrlDistributionPoints(payload) {
293
- const { crlNewDistributionPoints } = payload;
343
+ dispatchNewCrlDistributionPoints(crlNewDistributionPoints) {
294
344
  if (crlNewDistributionPoints && crlNewDistributionPoints.length > 0) {
295
- this.emit('newCrlDistributionPoints', crlNewDistributionPoints);
345
+ this.emit(MLSServiceEvents.NEW_CRL_DISTRIBUTION_POINTS, crlNewDistributionPoints);
296
346
  }
297
347
  }
298
348
  async processWelcomeMessage(welcomeMessage) {
299
- const welcomeBundle = await this.coreCryptoClient.processWelcomeMessage(welcomeMessage);
300
- this.dispatchNewCrlDistributionPoints(welcomeBundle);
349
+ const welcomeBundle = await this.coreCryptoClient.transaction(cx => cx.processWelcomeMessage(new core_crypto_1.Welcome(welcomeMessage)));
350
+ this.dispatchNewCrlDistributionPoints(welcomeBundle.crlNewDistributionPoints);
301
351
  return welcomeBundle.id;
302
352
  }
303
353
  async decryptMessage(conversationId, payload) {
304
- return await this.coreCryptoClient.transaction(async (cx) => {
305
- try {
306
- const decryptedMessage = await cx.decryptMessage(conversationId, payload);
307
- this.dispatchNewCrlDistributionPoints(decryptedMessage);
308
- return decryptedMessage;
309
- }
310
- catch (error) {
311
- // According to CoreCrypto JS doc on .decryptMessage method, we should ignore some errors (corecrypto handle them internally)
312
- if ((0, CoreCryptoMLSError_1.shouldMLSDecryptionErrorBeIgnored)(error)) {
313
- return {
314
- hasEpochChanged: false,
315
- isActive: false,
316
- proposals: [],
317
- };
318
- }
319
- throw error;
354
+ try {
355
+ const start = Date.now();
356
+ this.logger.info('Decrypting message', { conversationId });
357
+ const decryptedMessage = await this.coreCryptoClient.transaction(cx => cx.decryptMessage(conversationId, payload));
358
+ this.dispatchNewCrlDistributionPoints(decryptedMessage.crlNewDistributionPoints);
359
+ this.logger.info('Message decrypted successfully', { conversationId, duration: Date.now() - start });
360
+ return decryptedMessage;
361
+ }
362
+ catch (error) {
363
+ this.logger.warn('Failed to decrypt MLS message', { conversationId, error });
364
+ // According to CoreCrypto JS doc on .decryptMessage method, we should ignore some errors (corecrypto handle them internally)
365
+ if ((0, CoreCryptoMLSError_1.shouldMLSDecryptionErrorBeIgnored)(error)) {
366
+ return {
367
+ hasEpochChanged: false,
368
+ isActive: false,
369
+ };
320
370
  }
321
- });
371
+ throw error;
372
+ }
322
373
  }
323
374
  async encryptMessage(conversationId, message) {
324
- return this.coreCryptoClient.encryptMessage(conversationId, message);
375
+ return this.coreCryptoClient.transaction(cx => cx.encryptMessage(conversationId, message));
325
376
  }
326
- /**
327
- * Will wrap a coreCrypto call that generates a CommitBundle and do all the necessary work so that commitbundle is handled the right way.
328
- * It does:
329
- * - commit the pending proposal
330
- * - then generates the commitBundle with the given function
331
- * - uploads the commitBundle to backend
332
- * - warns coreCrypto that the commit was successfully processed
333
- * @param groupId
334
- * @param generateCommit The function that will generate a coreCrypto CommitBundle
335
- */
336
- async processCommitAction(groupId, generateCommit) {
337
- const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
338
- return (0, messageSender_1.sendMessage)(async () => {
339
- await this.commitPendingProposals(groupIdStr);
340
- const commitBundle = await generateCommit();
341
- return this.uploadCommitBundle(groupId, commitBundle, { regenerateCommitBundle: generateCommit });
342
- });
343
- }
344
- updateKeyingMaterial(groupId) {
345
- const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
346
- return this.processCommitAction(groupIdBytes, () => this.coreCryptoClient.updateKeyingMaterial(groupIdBytes));
377
+ async updateKeyingMaterial(groupId, retry = true) {
378
+ try {
379
+ const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
380
+ await this.coreCryptoClient.transaction(cx => cx.updateKeyingMaterial(new core_crypto_1.ConversationId(groupIdBytes)));
381
+ }
382
+ catch (error) {
383
+ if (!retry) {
384
+ this.logger.error(`Failed to update keying material for group retrying did not fix the issue`, {
385
+ error,
386
+ groupId,
387
+ });
388
+ throw error;
389
+ }
390
+ this.logger.warn(`Failed to update keying material for group`, { error, groupId });
391
+ this.emit(MLSServiceEvents.KEY_MATERIAL_UPDATE_FAILURE, { error, groupId });
392
+ setTimeout(async () => {
393
+ try {
394
+ await this.updateKeyingMaterial(groupId, false);
395
+ }
396
+ catch (error) {
397
+ this.logger.error(`Failed to update keying material for group on retry`, {
398
+ error,
399
+ groupId,
400
+ });
401
+ }
402
+ }, commons_1.TimeUtil.TimeInMillis.SECOND * 10); // retry after 10 seconds
403
+ }
347
404
  }
348
405
  /**
349
406
  * Will create an empty conversation inside of coreCrypto.
@@ -355,7 +412,9 @@ class MLSService extends commons_1.TypedEventEmitter {
355
412
  let externalSenders = [];
356
413
  if (parentGroupId) {
357
414
  const parentGroupIdBytes = bazinga64_1.Decoder.fromBase64(parentGroupId).asBytes;
358
- externalSenders = [await this.coreCryptoClient.getExternalSender(parentGroupIdBytes)];
415
+ externalSenders = [
416
+ new core_crypto_1.ExternalSenderKey(await this.coreCryptoClient.getExternalSender(new core_crypto_1.ConversationId(parentGroupIdBytes))),
417
+ ];
359
418
  }
360
419
  else {
361
420
  const mlsKeys = (await this.apiClient.api.client.getPublicKeys()).removal;
@@ -364,14 +423,14 @@ class MLSService extends commons_1.TypedEventEmitter {
364
423
  if (!removalKeyForSignature) {
365
424
  throw new Error(`Cannot create conversation: No backend removal key found for the signature ${ciphersuiteSignature}`);
366
425
  }
367
- externalSenders = [bazinga64_1.Decoder.fromBase64(removalKeyForSignature).asBytes];
426
+ externalSenders = [new core_crypto_1.ExternalSenderKey(bazinga64_1.Decoder.fromBase64(removalKeyForSignature).asBytes)];
368
427
  }
369
428
  const configuration = {
370
429
  externalSenders,
371
430
  ciphersuite: this.config.defaultCiphersuite,
372
431
  };
373
432
  const credentialType = await this.getCredentialType();
374
- return this.coreCryptoClient.createConversation(groupIdBytes, credentialType, configuration);
433
+ return this.coreCryptoClient.transaction(cx => cx.createConversation(new core_crypto_1.ConversationId(groupIdBytes), credentialType, configuration));
375
434
  }
376
435
  /**
377
436
  * Will create a conversation inside of coreCrypto, add users to it or update the keying material if empty key packages list is provided.
@@ -395,19 +454,18 @@ class MLSService extends commons_1.TypedEventEmitter {
395
454
  }));
396
455
  if (keyPackages.length <= 0) {
397
456
  // If there are no clients to add, just update the keying material
398
- const response = await this.updateKeyingMaterial(groupId);
457
+ await this.updateKeyingMaterial(groupId);
399
458
  await this.scheduleKeyMaterialRenewal(groupId);
400
- return { ...response, failures: keysClaimingFailures };
459
+ return keysClaimingFailures;
401
460
  }
402
- const response = await this.addUsersToExistingConversation(groupId, keyPackages);
461
+ await this.addUsersToExistingConversation(groupId, keyPackages);
403
462
  // We schedule a periodic key material renewal
404
463
  await this.scheduleKeyMaterialRenewal(groupId);
405
464
  /**
406
465
  * @note If we can't fetch a user's key packages then we can not add them to mls conversation
407
466
  * so we're adding them to the list of failed users.
408
467
  */
409
- response.failures = [...keysClaimingFailures, ...response.failures];
410
- return response;
468
+ return keysClaimingFailures;
411
469
  }
412
470
  /**
413
471
  * Will create a 1:1 conversation inside of coreCrypto, try claiming key packages for user and (if succesfull) add them to the MLS group.
@@ -423,21 +481,17 @@ class MLSService extends commons_1.TypedEventEmitter {
423
481
  // If we're missing key packages for the user we want to add, we can't register the conversation
424
482
  if (otherUserKeyPackages.length <= 0) {
425
483
  if (otherUserKeysClaimingFailures.length > 0 &&
426
- otherUserKeysClaimingFailures.some(({ reason }) => reason === conversation_1.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG)) {
484
+ otherUserKeysClaimingFailures.some(({ reason }) => reason === conversation_2.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG)) {
427
485
  throw new ClientMLSError_1.ClientMLSError(ClientMLSError_1.ClientMLSErrorLabel.NO_KEY_PACKAGES_AVAILABLE);
428
486
  }
429
487
  }
430
488
  const { keyPackages: selfKeyPackages, failures: selfKeysClaimingFailures } = await this.getKeyPackagesPayload([
431
489
  { ...selfUser.user, skipOwnClientId: selfUser.client },
432
490
  ]);
433
- const response = await this.addUsersToExistingConversation(groupId, [
434
- ...otherUserKeyPackages,
435
- ...selfKeyPackages,
436
- ]);
491
+ await this.addUsersToExistingConversation(groupId, [...otherUserKeyPackages, ...selfKeyPackages]);
437
492
  // We schedule a periodic key material renewal
438
493
  await this.scheduleKeyMaterialRenewal(groupId);
439
- response.failures = [...otherUserKeysClaimingFailures, ...selfKeysClaimingFailures, ...response.failures];
440
- return response;
494
+ return [...otherUserKeysClaimingFailures, ...selfKeysClaimingFailures];
441
495
  }
442
496
  catch (error) {
443
497
  await this.wipeConversation(groupId);
@@ -464,6 +518,7 @@ class MLSService extends commons_1.TypedEventEmitter {
464
518
  return true;
465
519
  }
466
520
  catch (error) {
521
+ this.logger.warn("Couldn't establish the MLS group", error);
467
522
  // If conversation already existed, locally, nothing more to do, we've received a welcome message.
468
523
  if ((0, CoreCryptoMLSError_1.isCoreCryptoMLSConversationAlreadyExistsError)(error)) {
469
524
  this.logger.debug(`MLS Group with id ${groupId} already exists, skipping the initialisation.`);
@@ -483,7 +538,7 @@ class MLSService extends commons_1.TypedEventEmitter {
483
538
  */
484
539
  removeClientsFromConversation(groupId, clientIds) {
485
540
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
486
- return this.processCommitAction(groupIdBytes, () => this.coreCryptoClient.removeClientsFromConversation(groupIdBytes, clientIds.map(id => this.textEncoder.encode(id))));
541
+ return this.coreCryptoClient.transaction(cx => cx.removeClientsFromConversation(new core_crypto_1.ConversationId(groupIdBytes), clientIds.map(id => new core_crypto_1.ClientId(this.textEncoder.encode(id)))));
487
542
  }
488
543
  /**
489
544
  * Will check if mls group exists in corecrypto.
@@ -491,7 +546,7 @@ class MLSService extends commons_1.TypedEventEmitter {
491
546
  */
492
547
  async conversationExists(groupId) {
493
548
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
494
- return this.coreCryptoClient.conversationExists(groupIdBytes);
549
+ return this.coreCryptoClient.conversationExists(new core_crypto_1.ConversationId(groupIdBytes));
495
550
  }
496
551
  /**
497
552
  * Will check if mls group is established in coreCrypto.
@@ -504,11 +559,11 @@ class MLSService extends commons_1.TypedEventEmitter {
504
559
  }
505
560
  async clientValidKeypackagesCount() {
506
561
  const credentialType = await this.getCredentialType();
507
- return this.coreCryptoClient.clientValidKeypackagesCount(this.config.defaultCiphersuite, credentialType);
562
+ return this.coreCryptoClient.transaction(cx => cx.clientValidKeypackagesCount(this.config.defaultCiphersuite, credentialType));
508
563
  }
509
564
  async clientKeypackages(amountRequested) {
510
565
  const credentialType = await this.getCredentialType();
511
- return this.coreCryptoClient.clientKeypackages(this.config.defaultCiphersuite, credentialType, amountRequested);
566
+ return this.coreCryptoClient.transaction(cx => cx.clientKeypackages(this.config.defaultCiphersuite, credentialType, amountRequested));
512
567
  }
513
568
  /**
514
569
  * Will send an empty commit into a group (renew key material)
@@ -610,6 +665,14 @@ class MLSService extends commons_1.TypedEventEmitter {
610
665
  async getRemoteMLSKeyPackageCount(clientId) {
611
666
  return this.apiClient.api.client.getMLSKeyPackageCount(clientId, (0, numberToHex_1.numberToHex)(this.config.defaultCiphersuite));
612
667
  }
668
+ async getCCClientSignatureString() {
669
+ const credentialType = await this.getCredentialType();
670
+ const publicKey = await this.coreCryptoClient.clientPublicKey(this.config.defaultCiphersuite, credentialType);
671
+ if (!publicKey) {
672
+ throw new Error('No public key found for client');
673
+ }
674
+ return btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(publicKey));
675
+ }
613
676
  /**
614
677
  * Will update the given client on backend with its public key.
615
678
  *
@@ -618,13 +681,18 @@ class MLSService extends commons_1.TypedEventEmitter {
618
681
  */
619
682
  async uploadMLSPublicKeys(client) {
620
683
  // If we've already updated a client with its public key, there's no need to do it again.
621
- const credentialType = await this.getCredentialType();
622
- const publicKey = await this.coreCryptoClient.clientPublicKey(this.config.defaultCiphersuite, credentialType);
623
- return this.apiClient.api.client.putClient(client.id, {
624
- mls_public_keys: {
625
- [(0, Helper_1.getSignatureAlgorithmForCiphersuite)(this.config.defaultCiphersuite)]: btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(publicKey)),
626
- },
627
- });
684
+ try {
685
+ const clientSignature = await this.getCCClientSignatureString();
686
+ return this.apiClient.api.client.putClient(client.id, {
687
+ mls_public_keys: {
688
+ [(0, Helper_1.getSignatureAlgorithmForCiphersuite)(this.config.defaultCiphersuite)]: clientSignature,
689
+ },
690
+ });
691
+ }
692
+ catch (error) {
693
+ this.logger.error(`Failed to upload public keys for client ${client.id}`, error);
694
+ throw error;
695
+ }
628
696
  }
629
697
  async replaceKeyPackages(clientId, keyPackages) {
630
698
  return this.apiClient.api.client.replaceMLSKeyPackages(clientId, keyPackages.map(keyPackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keyPackage))), (0, numberToHex_1.numberToHex)(this.config.defaultCiphersuite));
@@ -633,7 +701,6 @@ class MLSService extends commons_1.TypedEventEmitter {
633
701
  return this.apiClient.api.client.uploadMLSKeyPackages(clientId, keyPackages.map(keyPackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keyPackage))));
634
702
  }
635
703
  async wipeConversation(groupId) {
636
- (0, messageAdd_1.deleteMLSMessagesQueue)(groupId);
637
704
  await this.cancelKeyMaterialRenewal(groupId);
638
705
  await this.cancelPendingProposalsTask(groupId);
639
706
  const doesConversationExist = await this.conversationExists(groupId);
@@ -642,7 +709,7 @@ class MLSService extends commons_1.TypedEventEmitter {
642
709
  return;
643
710
  }
644
711
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
645
- return this.coreCryptoClient.wipeConversation(groupIdBytes);
712
+ return this.coreCryptoClient.transaction(cx => cx.wipeConversation(new core_crypto_1.ConversationId(groupIdBytes)));
646
713
  }
647
714
  /**
648
715
  * If there are pending proposals, we need to either process them,
@@ -682,25 +749,29 @@ class MLSService extends commons_1.TypedEventEmitter {
682
749
  *
683
750
  * @param groupId groupId of the conversation
684
751
  */
685
- async commitPendingProposals(groupId, shouldRetry = true) {
752
+ async commitPendingProposals(groupId, shouldRetry = true, params) {
753
+ this.logger.info(`Committing pending proposals for groupId ${groupId}`, { shouldRetry, params });
686
754
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
687
755
  try {
688
- const commitBundle = await this.coreCryptoClient.commitPendingProposals(groupIdBytes);
689
- if (commitBundle) {
690
- await this.uploadCommitBundle(groupIdBytes, commitBundle);
691
- }
756
+ await this.coreCryptoClient.transaction(cx => cx.commitPendingProposals(new core_crypto_1.ConversationId(groupIdBytes)));
692
757
  await this.cancelPendingProposalsTask(groupId);
693
758
  }
694
759
  catch (error) {
695
760
  if (!shouldRetry) {
696
761
  throw error;
697
762
  }
698
- this.logger.warn('Failed to commit proposals, clearing the pending commit and retrying', error);
699
- // If we failed to commit the proposals, we need to clear the pending commit and retry
700
- // this is to avoid a situation where we are stuck with pending proposals that we can't commit.
701
- // If there's nothing to clear the methods might throw an error, which we can ignore.
702
- await this.coreCryptoClient.clearPendingCommit(groupIdBytes).catch(() => undefined);
703
- await this.coreCryptoClient.clearPendingGroupFromExternalCommit(groupIdBytes).catch(() => undefined);
763
+ if ((0, core_crypto_1.isMlsMessageRejectedError)(error)) {
764
+ this.logger.warn('Failed to commit proposals, conversation is broken, letting the error bubble up', {
765
+ error,
766
+ groupId,
767
+ });
768
+ throw error;
769
+ }
770
+ this.logger.warn('Failed to commit proposals, clearing the pending commit and retrying', {
771
+ error,
772
+ groupId,
773
+ shouldRetry,
774
+ });
704
775
  return this.commitPendingProposals(groupId, false);
705
776
  }
706
777
  }
@@ -731,9 +802,9 @@ class MLSService extends commons_1.TypedEventEmitter {
731
802
  */
732
803
  async getClientIds(groupId) {
733
804
  const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
734
- const rawClientIds = await this.coreCryptoClient.getClientIds(groupIdBytes);
805
+ const rawClientIds = await this.coreCryptoClient.getClientIds(new core_crypto_1.ConversationId(groupIdBytes));
735
806
  const clientIds = rawClientIds.map(id => {
736
- const { user, client, domain } = (0, fullyQualifiedClientIdUtils_1.parseFullQualifiedClientId)(this.textDecoder.decode(id));
807
+ const { user, client, domain } = (0, fullyQualifiedClientIdUtils_1.parseFullQualifiedClientId)(this.textDecoder.decode(id.copyBytes()));
737
808
  return { userId: user, clientId: client, domain };
738
809
  });
739
810
  return clientIds;
@@ -745,7 +816,7 @@ class MLSService extends commons_1.TypedEventEmitter {
745
816
  if (!groupId) {
746
817
  throw new Error(`Could not find a group_id for conversation ${qualifiedConversationId.id}@${qualifiedConversationId.domain}${event.subconv ? `/subconversation:${event.subconv}` : ''}`);
747
818
  }
748
- return (0, messageAdd_1.queueIncomingMLSMessage)(groupId, () => (0, events_1.handleMLSMessageAdd)({ event, mlsService: this, groupId }));
819
+ return (0, events_1.handleMLSMessageAdd)({ event, mlsService: this, groupId });
749
820
  }
750
821
  async handleMLSWelcomeMessageEvent(event, clientId) {
751
822
  // Every time we've received a welcome message, it means that our key package was consumed,
@@ -769,32 +840,20 @@ class MLSService extends commons_1.TypedEventEmitter {
769
840
  * @param oAuthIdToken The OAuth id token if the user is already authenticated
770
841
  * @returns AcmeChallenge if the user is not authenticated, true if the user is authenticated
771
842
  */
772
- async enrollE2EI(discoveryUrl, user, client, nbPrekeys, certificateTtl, getOAuthToken) {
843
+ async enrollE2EI(discoveryUrl, user, client, nbPrekeys, certificateTtl, getOAuthToken, getAllConversations) {
773
844
  const isCertificateRenewal = await this.coreCryptoClient.e2eiIsEnabled(this.config.defaultCiphersuite);
774
845
  const e2eiServiceInternal = new E2EIServiceInternal_1.E2EIServiceInternal(this.coreDatabase, this.coreCryptoClient, this.apiClient, certificateTtl, nbPrekeys, { user, clientId: client.id, discoveryUrl });
775
- const rotateBundle = await e2eiServiceInternal.generateCertificate(getOAuthToken, isCertificateRenewal, this.config.defaultCiphersuite);
776
- this.dispatchNewCrlDistributionPoints(rotateBundle);
846
+ const { keyPackages, newCrlDistributionPoints } = await e2eiServiceInternal.generateCertificate(getOAuthToken, isCertificateRenewal, getAllConversations, this.config.defaultCiphersuite);
847
+ this.dispatchNewCrlDistributionPoints(newCrlDistributionPoints);
777
848
  // upload the clients public keys
778
849
  if (!this.isInitializedMLSClient(client)) {
779
850
  // we only upload public keys for the initial certification process if the device is not already a registered MLS device.
780
851
  await this.uploadMLSPublicKeys(client);
781
852
  }
782
853
  // replace old key packages with new key packages with x509 certificate
783
- await this.replaceKeyPackages(client.id, rotateBundle.newKeyPackages);
854
+ await this.replaceKeyPackages(client.id, keyPackages);
784
855
  // Verify that we have enough key packages
785
856
  await this.verifyRemoteMLSKeyPackagesAmount(client.id);
786
- // Update keying material
787
- for (const [groupId, commitBundle] of rotateBundle.commits) {
788
- const groupIdAsBytes = bazinga64_1.Converter.hexStringToArrayBufferView(groupId);
789
- // manual copy of the commit bundle data because of a problem while cloning it
790
- const newCommitBundle = {
791
- commit: commitBundle.commit,
792
- // @ts-ignore
793
- groupInfo: commitBundle?.group_info || commitBundle.groupInfo,
794
- welcome: commitBundle?.welcome,
795
- };
796
- await this.uploadCommitBundle(groupIdAsBytes, newCommitBundle);
797
- }
798
857
  }
799
858
  }
800
859
  exports.MLSService = MLSService;