@rapidmx/web-client 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (885) hide show
  1. package/README.md +48 -14
  2. package/apps/admin/_layout.tsx +2 -2
  3. package/apps/admin/audit-log/index.tsx +4 -4
  4. package/apps/admin/branding/index.tsx +3 -3
  5. package/apps/admin/data-requests/index.tsx +8 -8
  6. package/apps/admin/distribution-lists/[uid].tsx +3 -3
  7. package/apps/admin/distribution-lists/index.tsx +4 -4
  8. package/apps/admin/distribution-lists/new/index.tsx +5 -5
  9. package/apps/admin/domains/[uid].tsx +6 -6
  10. package/apps/admin/domains/index.tsx +4 -4
  11. package/apps/admin/domains/new/index.tsx +5 -5
  12. package/apps/admin/encryption-policy/index.tsx +1 -1
  13. package/apps/admin/escrow-scopes/[uid].tsx +7 -7
  14. package/apps/admin/escrow-scopes/index.tsx +4 -4
  15. package/apps/admin/escrow-scopes/new/index.tsx +5 -5
  16. package/apps/admin/index.tsx +6 -6
  17. package/apps/admin/ingest-queue/index.tsx +4 -4
  18. package/apps/admin/mailbox-policy/index.tsx +1 -1
  19. package/apps/admin/mailboxes/[uid].tsx +5 -5
  20. package/apps/admin/quarantine/index.tsx +5 -5
  21. package/apps/admin/retention-policy/index.tsx +3 -3
  22. package/apps/admin/signing-certificates/index.tsx +5 -5
  23. package/apps/admin/transport-rules/[uid].tsx +5 -5
  24. package/apps/admin/transport-rules/_transportRuleConfig.tsx +3 -3
  25. package/apps/admin/transport-rules/index.tsx +4 -4
  26. package/apps/admin/transport-rules/new/index.tsx +5 -5
  27. package/apps/escrow/_layout.tsx +1 -1
  28. package/apps/escrow/audit-log/index.tsx +4 -4
  29. package/apps/escrow/index.tsx +4 -4
  30. package/apps/escrow/matters/[uid].tsx +10 -10
  31. package/apps/escrow/matters/new/index.tsx +6 -6
  32. package/apps/shared/appearance/AppearanceForm.tsx +3 -3
  33. package/apps/shared/appearance/AppearanceHead.tsx +1 -1
  34. package/apps/shared/appearance/AppearanceProvider.tsx +3 -3
  35. package/apps/shared/appearance/appearanceCache.ts +1 -1
  36. package/apps/shared/appearance/appearanceContext.ts +1 -1
  37. package/apps/shared/appearance/theme.ts +1 -1
  38. package/apps/shared/auth/adminAccess.ts +1 -1
  39. package/apps/shared/calendar/bookingPlugin.ts +1 -1
  40. package/apps/shared/calendar/calendarLiveUpdates.ts +1 -1
  41. package/apps/shared/calendar/calendarReminders.ts +1 -1
  42. package/apps/shared/calendar/useCalendarReminders.ts +1 -1
  43. package/apps/shared/components/admin/diagnostics/DiagnosticsManager.tsx +1 -1
  44. package/apps/shared/components/admin/diagnostics/InstalledPlugins.tsx +2 -2
  45. package/apps/shared/components/admin/diagnostics/LogsPanel.tsx +2 -2
  46. package/apps/shared/components/admin/diagnostics/PackagesTable.tsx +1 -1
  47. package/apps/shared/components/admin/diagnostics/RuntimePanel.tsx +1 -1
  48. package/apps/shared/components/admin/diagnostics/SystemPanel.tsx +2 -2
  49. package/apps/shared/components/admin/diagnostics/VersionsPanel.tsx +1 -1
  50. package/apps/shared/components/admin/diagnostics/diagnosticsApi.ts +1 -1
  51. package/apps/shared/components/admin/diagnostics/format.ts +1 -1
  52. package/apps/shared/components/admin/diagnostics/logClient.ts +1 -1
  53. package/apps/shared/components/admin/distributionLists/MemberListCard.tsx +4 -4
  54. package/apps/shared/components/admin/elevation.ts +1 -1
  55. package/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.tsx +3 -3
  56. package/apps/shared/components/admin/layout/AdminShell.tsx +8 -8
  57. package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +6 -6
  58. package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +10 -8
  59. package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +4 -4
  60. package/apps/shared/components/admin/mailboxes/MailboxTable.tsx +1 -1
  61. package/apps/shared/components/admin/mailboxes/ResourceSettingsCard.tsx +19 -14
  62. package/apps/shared/components/admin/mailboxes/ShareAccessCard.tsx +5 -5
  63. package/apps/shared/components/admin/settings/BrandingForm.tsx +5 -5
  64. package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +5 -5
  65. package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +4 -4
  66. package/apps/shared/components/admin/settings/LoadedSettingsForm.tsx +2 -2
  67. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +32 -27
  68. package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +4 -4
  69. package/apps/shared/components/admin/settings/PluginsManager.tsx +5 -5
  70. package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +5 -5
  71. package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +7 -7
  72. package/apps/shared/components/admin/setup/SetupWizard.tsx +27 -23
  73. package/apps/shared/components/admin/signOut.ts +1 -1
  74. package/apps/shared/components/admin/usePagedList.tsx +2 -2
  75. package/apps/shared/components/calendar/AppointmentQuickForm.tsx +3 -3
  76. package/apps/shared/components/calendar/CalendarListSidebar.tsx +3 -3
  77. package/apps/shared/components/calendar/DescriptionEditor.tsx +1 -1
  78. package/apps/shared/components/calendar/EventDescriptionView.tsx +1 -1
  79. package/apps/shared/components/calendar/EventDetails.tsx +16 -14
  80. package/apps/shared/components/calendar/EventEditor.tsx +54 -39
  81. package/apps/shared/components/calendar/EventExpandedForm.tsx +3 -3
  82. package/apps/shared/components/calendar/EventFormParts.tsx +2 -2
  83. package/apps/shared/components/calendar/EventModal.tsx +5 -5
  84. package/apps/shared/components/calendar/EventQuickForm.tsx +3 -3
  85. package/apps/shared/components/calendar/EventShell.tsx +1 -1
  86. package/apps/shared/components/calendar/FindATime.tsx +6 -4
  87. package/apps/shared/components/calendar/GuestInput.tsx +2 -2
  88. package/apps/shared/components/calendar/MonthView.tsx +2 -2
  89. package/apps/shared/components/calendar/QuickCreateFaces.tsx +1 -1
  90. package/apps/shared/components/calendar/QuickFaceFrame.tsx +1 -1
  91. package/apps/shared/components/calendar/RecurrenceEditor.tsx +2 -2
  92. package/apps/shared/components/calendar/RequestChangeForm.tsx +8 -6
  93. package/apps/shared/components/calendar/ResourcePicker.tsx +7 -5
  94. package/apps/shared/components/calendar/SplitDayView.tsx +1 -1
  95. package/apps/shared/components/calendar/TaskQuickForm.tsx +23 -18
  96. package/apps/shared/components/calendar/TimeGridView.tsx +2 -2
  97. package/apps/shared/components/calendar/allDay.ts +2 -2
  98. package/apps/shared/components/calendar/eventDialogFields.ts +3 -3
  99. package/apps/shared/components/calendar/eventForm.ts +3 -3
  100. package/apps/shared/components/calendar/eventFormat.ts +3 -3
  101. package/apps/shared/components/calendar/findTimeGrid.ts +2 -2
  102. package/apps/shared/components/calendar/layout/CalendarShell.tsx +11 -9
  103. package/apps/shared/components/contacts/ContactDetailPane.tsx +4 -4
  104. package/apps/shared/components/contacts/ContactForm.tsx +27 -17
  105. package/apps/shared/components/contacts/ContactsSidebar.tsx +7 -5
  106. package/apps/shared/components/contacts/KeyChangeReview.tsx +5 -5
  107. package/apps/shared/components/contacts/contactKeys.ts +3 -3
  108. package/apps/shared/components/contacts/layout/ContactsShell.tsx +9 -7
  109. package/apps/shared/components/escrow/layout/EscrowShell.tsx +6 -6
  110. package/apps/shared/components/forms/StringListField.tsx +1 -1
  111. package/apps/shared/components/layout/AppShell.tsx +12 -10
  112. package/apps/shared/components/layout/BrandingChrome.tsx +1 -1
  113. package/apps/shared/components/layout/KeyEnrollmentGate.tsx +9 -9
  114. package/apps/shared/components/layout/MailboxProvisioning.tsx +8 -6
  115. package/apps/shared/components/layout/RecoveryCodeUnlock.tsx +9 -9
  116. package/apps/shared/components/layout/ThemeSwitch.tsx +1 -1
  117. package/apps/shared/components/layout/UnlockPromptProvider.tsx +6 -6
  118. package/apps/shared/components/layout/UserMenu.tsx +6 -4
  119. package/apps/shared/components/mail/ConversationList.tsx +7 -5
  120. package/apps/shared/components/mail/ConversationThreadPane.tsx +26 -15
  121. package/apps/shared/components/mail/InviteCard.tsx +11 -9
  122. package/apps/shared/components/mail/LazyReadingPane.tsx +2 -2
  123. package/apps/shared/components/mail/MailAddress.tsx +1 -1
  124. package/apps/shared/components/mail/MailListToolbar.tsx +2 -2
  125. package/apps/shared/components/mail/MailSelectionBar.tsx +2 -2
  126. package/apps/shared/components/mail/MenuButton.tsx +1 -1
  127. package/apps/shared/components/mail/MessageDetailPane.tsx +32 -30
  128. package/apps/shared/components/mail/MoveToFolderDialog.tsx +8 -6
  129. package/apps/shared/components/mail/OutboxRowStatus.tsx +1 -1
  130. package/apps/shared/components/mail/PermanentDeleteDialog.tsx +2 -2
  131. package/apps/shared/components/mail/compose/ComposeContext.tsx +14 -3
  132. package/apps/shared/components/mail/compose/ComposeWindow.tsx +34 -30
  133. package/apps/shared/components/mail/compose/ComposeWindowPlaceholder.tsx +4 -4
  134. package/apps/shared/components/mail/compose/EmojiPicker.tsx +2 -2
  135. package/apps/shared/components/mail/compose/GifPicker.tsx +3 -3
  136. package/apps/shared/components/mail/compose/RecipientInput.tsx +1 -1
  137. package/apps/shared/components/mail/compose/ScheduleSendPicker.tsx +1 -1
  138. package/apps/shared/components/mail/compose/encryptionRequirement.ts +2 -2
  139. package/apps/shared/components/mail/compose/quotedBody.ts +5 -5
  140. package/apps/shared/components/mail/compose/recipients.ts +1 -1
  141. package/apps/shared/components/mail/invite/InviteRowChip.tsx +2 -2
  142. package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +9 -7
  143. package/apps/shared/components/mail/invite/InviteTimeline.tsx +1 -1
  144. package/apps/shared/components/mail/invite/ProposeTimeForm.tsx +2 -2
  145. package/apps/shared/components/mail/invite/inviteFormat.ts +2 -2
  146. package/apps/shared/components/mail/invite/inviteStore.ts +14 -6
  147. package/apps/shared/components/mail/labelMenu.tsx +9 -7
  148. package/apps/shared/components/mail/layout/MailShell.tsx +4 -4
  149. package/apps/shared/components/mail/listPreferences.ts +2 -2
  150. package/apps/shared/components/mail/pinnedSigners.ts +45 -19
  151. package/apps/shared/components/mail/reading/EncryptedBody.tsx +2 -2
  152. package/apps/shared/components/mail/reading/MessageBody.tsx +6 -6
  153. package/apps/shared/components/mail/reading/MessageCard.tsx +3 -3
  154. package/apps/shared/components/mail/reading/MessageSourceDialog.tsx +3 -3
  155. package/apps/shared/components/mail/reading/PendingMessageCard.tsx +1 -1
  156. package/apps/shared/components/mail/reading/bodyContent.ts +3 -3
  157. package/apps/shared/components/mail/reading/bodyHtml.ts +1 -1
  158. package/apps/shared/components/mail/reading/messageExport.ts +1 -1
  159. package/apps/shared/components/mail/reading/printMessage.ts +2 -2
  160. package/apps/shared/components/mail/reading/useMessageActions.ts +28 -21
  161. package/apps/shared/components/mail/unreadStyle.tsx +1 -1
  162. package/apps/shared/components/mail/verificationSeals.ts +16 -12
  163. package/apps/shared/components/mail/writableMailboxes.ts +14 -7
  164. package/apps/shared/components/rules/RuleBuilder.tsx +1 -1
  165. package/apps/shared/components/settings/SigningCertificateCard.tsx +4 -4
  166. package/apps/shared/components/settings/layout/SettingsShell.tsx +8 -6
  167. package/apps/shared/components/sharing/PrincipalListField.tsx +1 -1
  168. package/apps/shared/components/sharing/PrincipalPicker.tsx +1 -1
  169. package/apps/shared/components/sharing/PrincipalResolver.tsx +4 -4
  170. package/apps/shared/components/tasks/TasksSidebar.tsx +7 -5
  171. package/apps/shared/components/tasks/layout/TasksShell.tsx +9 -7
  172. package/apps/shared/keyboard/ShortcutsDialog.tsx +1 -1
  173. package/apps/shared/mail/findWellKnownFolderUid.ts +6 -4
  174. package/apps/shared/mail/folderCounts.ts +8 -4
  175. package/apps/shared/mail/folderOfType.ts +5 -3
  176. package/apps/shared/mail/folderTree.ts +1 -1
  177. package/apps/shared/mail/listSnapshots.ts +2 -2
  178. package/apps/shared/mail/messageReadState.ts +6 -5
  179. package/apps/shared/mail/newMailNotifications.ts +2 -2
  180. package/apps/shared/mail/outbox/composeBridge.ts +2 -2
  181. package/apps/shared/mail/outbox/outboxState.ts +1 -1
  182. package/apps/shared/mail/outbox/outgoingReplies.ts +2 -2
  183. package/apps/shared/mail/outbox/sendDecision.ts +2 -2
  184. package/apps/shared/mail/outbox/sendJob.ts +40 -35
  185. package/apps/shared/mail/outbox/sendOutcomes.ts +20 -15
  186. package/apps/shared/mail/outbox/useOutboxStatus.ts +5 -3
  187. package/apps/shared/mail/permanentDelete.ts +8 -7
  188. package/apps/shared/mail/primaryMailbox.ts +1 -1
  189. package/apps/shared/mail/reportNotices.ts +1 -1
  190. package/apps/shared/mail/senderBlocking.ts +36 -20
  191. package/apps/shared/mail/useMailConnection.ts +12 -10
  192. package/apps/shared/mail/useMailLiveUpdates.ts +3 -3
  193. package/apps/shared/mail/useMailboxUpdateAccess.ts +35 -11
  194. package/apps/shared/mail/useMarkMessageRead.ts +14 -7
  195. package/apps/shared/mail/useNewMailNotifications.ts +1 -1
  196. package/apps/shared/mail/usePermanentDelete.tsx +5 -3
  197. package/apps/shared/navigation/pageTitle.ts +1 -1
  198. package/apps/shared/notifications/NotificationCenter.tsx +1 -1
  199. package/apps/shared/notifications/NotificationHistoryDialog.tsx +2 -2
  200. package/apps/shared/notifications/apiErrors.ts +2 -2
  201. package/apps/shared/notifications/pushStatus.ts +1 -1
  202. package/apps/shared/notifications/systemErrors.ts +1 -1
  203. package/apps/shared/search/LocalIndexLifecycle.tsx +18 -12
  204. package/apps/shared/search/crossMailboxSearch.ts +3 -3
  205. package/apps/shared/search/localIndexBuilder.ts +24 -12
  206. package/apps/shared/search/localIndexKey.ts +1 -1
  207. package/apps/shared/search/localIndexRpcClient.ts +150 -30
  208. package/apps/shared/search/localIndexTransport.ts +84 -0
  209. package/apps/shared/search/localIndexWorker.ts +1 -1
  210. package/apps/shared/search/searchTier2.ts +3 -3
  211. package/apps/shared/signing/enrollmentTracker.ts +3 -3
  212. package/apps/shared/signing/enrollmentView.ts +1 -1
  213. package/apps/shared/signing/signingInfo.ts +1 -1
  214. package/apps/shared/signing/useSigningEnrollmentWatcher.ts +6 -4
  215. package/apps/shared/styles/app.css +14 -23
  216. package/apps/www/_layout.tsx +2 -2
  217. package/apps/www/calendar/index.tsx +20 -18
  218. package/apps/www/contacts/[uid].tsx +8 -6
  219. package/apps/www/contacts/index.tsx +19 -17
  220. package/apps/www/index.tsx +57 -48
  221. package/apps/www/messages/[uid].tsx +11 -9
  222. package/apps/www/settings/auto-reply/index.tsx +6 -4
  223. package/apps/www/settings/blocked-senders/index.tsx +9 -7
  224. package/apps/www/settings/encryption/index.tsx +38 -32
  225. package/apps/www/settings/filters/[uid].tsx +19 -14
  226. package/apps/www/settings/filters/_mailFilterRuleConfig.tsx +2 -2
  227. package/apps/www/settings/filters/index.tsx +4 -4
  228. package/apps/www/settings/filters/new/index.tsx +10 -8
  229. package/apps/www/settings/labels/index.tsx +12 -10
  230. package/apps/www/settings/privacy/index.tsx +18 -14
  231. package/apps/www/settings/profile/index.tsx +16 -11
  232. package/apps/www/settings/read-receipts/index.tsx +17 -12
  233. package/apps/www/settings/sharing/index.tsx +6 -6
  234. package/apps/www/settings/signatures/[uid].tsx +5 -5
  235. package/apps/www/settings/signatures/index.tsx +4 -4
  236. package/apps/www/settings/signatures/new/index.tsx +4 -4
  237. package/apps/www/settings/signatures/signatureDefaults.ts +1 -1
  238. package/apps/www/tasks/index.tsx +28 -23
  239. package/dist/apps/admin/_layout.d.ts +1 -1
  240. package/dist/apps/admin/_layout.js +1 -1
  241. package/dist/apps/admin/audit-log/index.d.ts +1 -1
  242. package/dist/apps/admin/audit-log/index.js +4 -4
  243. package/dist/apps/admin/branding/index.js +3 -3
  244. package/dist/apps/admin/data-requests/index.js +8 -8
  245. package/dist/apps/admin/distribution-lists/[uid].js +3 -3
  246. package/dist/apps/admin/distribution-lists/index.js +4 -4
  247. package/dist/apps/admin/distribution-lists/new/index.js +5 -5
  248. package/dist/apps/admin/domains/[uid].js +6 -6
  249. package/dist/apps/admin/domains/index.js +4 -4
  250. package/dist/apps/admin/domains/new/index.js +5 -5
  251. package/dist/apps/admin/encryption-policy/index.js +1 -1
  252. package/dist/apps/admin/escrow-scopes/[uid].d.ts +1 -1
  253. package/dist/apps/admin/escrow-scopes/[uid].js +7 -7
  254. package/dist/apps/admin/escrow-scopes/index.js +4 -4
  255. package/dist/apps/admin/escrow-scopes/new/index.js +5 -5
  256. package/dist/apps/admin/index.js +6 -6
  257. package/dist/apps/admin/ingest-queue/index.js +4 -4
  258. package/dist/apps/admin/mailbox-policy/index.js +1 -1
  259. package/dist/apps/admin/mailboxes/[uid].js +5 -5
  260. package/dist/apps/admin/quarantine/index.js +5 -5
  261. package/dist/apps/admin/retention-policy/index.js +3 -3
  262. package/dist/apps/admin/signing-certificates/index.js +5 -5
  263. package/dist/apps/admin/transport-rules/[uid].js +5 -5
  264. package/dist/apps/admin/transport-rules/_transportRuleConfig.d.ts +1 -1
  265. package/dist/apps/admin/transport-rules/_transportRuleConfig.js +2 -2
  266. package/dist/apps/admin/transport-rules/index.js +4 -4
  267. package/dist/apps/admin/transport-rules/new/index.js +5 -5
  268. package/dist/apps/escrow/_layout.d.ts +1 -1
  269. package/dist/apps/escrow/audit-log/index.d.ts +1 -1
  270. package/dist/apps/escrow/audit-log/index.js +4 -4
  271. package/dist/apps/escrow/index.js +4 -4
  272. package/dist/apps/escrow/matters/[uid].js +10 -10
  273. package/dist/apps/escrow/matters/new/index.js +6 -6
  274. package/dist/apps/shared/appearance/AppearanceForm.js +3 -3
  275. package/dist/apps/shared/appearance/AppearanceHead.js +1 -1
  276. package/dist/apps/shared/appearance/AppearanceProvider.d.ts +1 -1
  277. package/dist/apps/shared/appearance/AppearanceProvider.js +3 -3
  278. package/dist/apps/shared/appearance/appearanceCache.d.ts +1 -1
  279. package/dist/apps/shared/appearance/appearanceCache.js +1 -1
  280. package/dist/apps/shared/appearance/appearanceContext.d.ts +1 -1
  281. package/dist/apps/shared/appearance/theme.d.ts +1 -1
  282. package/dist/apps/shared/auth/adminAccess.js +1 -1
  283. package/dist/apps/shared/calendar/bookingPlugin.js +1 -1
  284. package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +1 -1
  285. package/dist/apps/shared/calendar/calendarReminders.d.ts +1 -1
  286. package/dist/apps/shared/calendar/useCalendarReminders.js +1 -1
  287. package/dist/apps/shared/components/admin/diagnostics/DiagnosticsManager.js +1 -1
  288. package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.d.ts +1 -1
  289. package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.js +2 -2
  290. package/dist/apps/shared/components/admin/diagnostics/LogsPanel.js +2 -2
  291. package/dist/apps/shared/components/admin/diagnostics/PackagesTable.js +1 -1
  292. package/dist/apps/shared/components/admin/diagnostics/RuntimePanel.js +1 -1
  293. package/dist/apps/shared/components/admin/diagnostics/SystemPanel.js +2 -2
  294. package/dist/apps/shared/components/admin/diagnostics/VersionsPanel.js +1 -1
  295. package/dist/apps/shared/components/admin/diagnostics/diagnosticsApi.js +1 -1
  296. package/dist/apps/shared/components/admin/diagnostics/format.js +1 -1
  297. package/dist/apps/shared/components/admin/diagnostics/logClient.js +1 -1
  298. package/dist/apps/shared/components/admin/distributionLists/MemberListCard.d.ts +1 -1
  299. package/dist/apps/shared/components/admin/distributionLists/MemberListCard.js +4 -4
  300. package/dist/apps/shared/components/admin/elevation.js +1 -1
  301. package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js +3 -3
  302. package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
  303. package/dist/apps/shared/components/admin/layout/AdminShell.js +7 -7
  304. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +1 -1
  305. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +6 -6
  306. package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.d.ts +1 -1
  307. package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.js +10 -8
  308. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +4 -4
  309. package/dist/apps/shared/components/admin/mailboxes/MailboxTable.d.ts +1 -1
  310. package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.d.ts +1 -1
  311. package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.js +7 -5
  312. package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.js +5 -5
  313. package/dist/apps/shared/components/admin/settings/BrandingForm.d.ts +1 -1
  314. package/dist/apps/shared/components/admin/settings/BrandingForm.js +5 -5
  315. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.d.ts +1 -1
  316. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +5 -5
  317. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.d.ts +1 -1
  318. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +4 -4
  319. package/dist/apps/shared/components/admin/settings/LoadedSettingsForm.js +2 -2
  320. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.d.ts +1 -1
  321. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +14 -12
  322. package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.d.ts +1 -1
  323. package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.js +4 -4
  324. package/dist/apps/shared/components/admin/settings/PluginsManager.js +5 -5
  325. package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.d.ts +1 -1
  326. package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.js +5 -5
  327. package/dist/apps/shared/components/admin/setup/EscrowSetupStep.js +7 -7
  328. package/dist/apps/shared/components/admin/setup/SetupWizard.js +26 -22
  329. package/dist/apps/shared/components/admin/signOut.js +1 -1
  330. package/dist/apps/shared/components/admin/usePagedList.js +2 -2
  331. package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +3 -3
  332. package/dist/apps/shared/components/calendar/CalendarListSidebar.d.ts +1 -1
  333. package/dist/apps/shared/components/calendar/CalendarListSidebar.js +2 -2
  334. package/dist/apps/shared/components/calendar/DescriptionEditor.js +1 -1
  335. package/dist/apps/shared/components/calendar/EventDescriptionView.js +1 -1
  336. package/dist/apps/shared/components/calendar/EventDetails.d.ts +2 -2
  337. package/dist/apps/shared/components/calendar/EventDetails.js +16 -14
  338. package/dist/apps/shared/components/calendar/EventEditor.d.ts +2 -2
  339. package/dist/apps/shared/components/calendar/EventEditor.js +22 -20
  340. package/dist/apps/shared/components/calendar/EventExpandedForm.js +2 -2
  341. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +1 -1
  342. package/dist/apps/shared/components/calendar/EventFormParts.js +1 -1
  343. package/dist/apps/shared/components/calendar/EventModal.d.ts +2 -2
  344. package/dist/apps/shared/components/calendar/EventModal.js +3 -3
  345. package/dist/apps/shared/components/calendar/EventQuickForm.js +3 -3
  346. package/dist/apps/shared/components/calendar/EventShell.js +1 -1
  347. package/dist/apps/shared/components/calendar/FindATime.js +6 -4
  348. package/dist/apps/shared/components/calendar/GuestInput.d.ts +2 -2
  349. package/dist/apps/shared/components/calendar/MonthView.d.ts +1 -1
  350. package/dist/apps/shared/components/calendar/MonthView.js +1 -1
  351. package/dist/apps/shared/components/calendar/QuickCreateFaces.js +1 -1
  352. package/dist/apps/shared/components/calendar/QuickFaceFrame.js +1 -1
  353. package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +1 -1
  354. package/dist/apps/shared/components/calendar/RecurrenceEditor.js +1 -1
  355. package/dist/apps/shared/components/calendar/RequestChangeForm.js +8 -6
  356. package/dist/apps/shared/components/calendar/ResourcePicker.d.ts +1 -1
  357. package/dist/apps/shared/components/calendar/ResourcePicker.js +7 -5
  358. package/dist/apps/shared/components/calendar/SplitDayView.d.ts +1 -1
  359. package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +1 -1
  360. package/dist/apps/shared/components/calendar/TaskQuickForm.js +9 -7
  361. package/dist/apps/shared/components/calendar/TimeGridView.d.ts +1 -1
  362. package/dist/apps/shared/components/calendar/TimeGridView.js +1 -1
  363. package/dist/apps/shared/components/calendar/allDay.d.ts +2 -2
  364. package/dist/apps/shared/components/calendar/allDay.js +1 -1
  365. package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +2 -2
  366. package/dist/apps/shared/components/calendar/eventDialogFields.js +2 -2
  367. package/dist/apps/shared/components/calendar/eventForm.d.ts +3 -3
  368. package/dist/apps/shared/components/calendar/eventFormat.d.ts +1 -1
  369. package/dist/apps/shared/components/calendar/eventFormat.js +2 -2
  370. package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +1 -1
  371. package/dist/apps/shared/components/calendar/findTimeGrid.js +1 -1
  372. package/dist/apps/shared/components/calendar/layout/CalendarShell.d.ts +1 -1
  373. package/dist/apps/shared/components/calendar/layout/CalendarShell.js +11 -9
  374. package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +1 -1
  375. package/dist/apps/shared/components/contacts/ContactDetailPane.js +2 -2
  376. package/dist/apps/shared/components/contacts/ContactForm.d.ts +2 -2
  377. package/dist/apps/shared/components/contacts/ContactForm.js +12 -8
  378. package/dist/apps/shared/components/contacts/ContactsSidebar.d.ts +1 -1
  379. package/dist/apps/shared/components/contacts/ContactsSidebar.js +7 -5
  380. package/dist/apps/shared/components/contacts/KeyChangeReview.d.ts +1 -1
  381. package/dist/apps/shared/components/contacts/KeyChangeReview.js +5 -5
  382. package/dist/apps/shared/components/contacts/contactKeys.d.ts +2 -2
  383. package/dist/apps/shared/components/contacts/contactKeys.js +2 -2
  384. package/dist/apps/shared/components/contacts/layout/ContactsShell.d.ts +1 -1
  385. package/dist/apps/shared/components/contacts/layout/ContactsShell.js +9 -7
  386. package/dist/apps/shared/components/escrow/layout/EscrowShell.js +6 -6
  387. package/dist/apps/shared/components/forms/StringListField.js +1 -1
  388. package/dist/apps/shared/components/layout/AppShell.d.ts +2 -2
  389. package/dist/apps/shared/components/layout/AppShell.js +11 -9
  390. package/dist/apps/shared/components/layout/BrandingChrome.d.ts +1 -1
  391. package/dist/apps/shared/components/layout/KeyEnrollmentGate.d.ts +1 -1
  392. package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +9 -9
  393. package/dist/apps/shared/components/layout/MailboxProvisioning.js +8 -6
  394. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.d.ts +1 -1
  395. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.js +9 -9
  396. package/dist/apps/shared/components/layout/UnlockPromptProvider.d.ts +2 -2
  397. package/dist/apps/shared/components/layout/UnlockPromptProvider.js +5 -5
  398. package/dist/apps/shared/components/layout/UserMenu.js +6 -4
  399. package/dist/apps/shared/components/mail/ConversationList.d.ts +2 -2
  400. package/dist/apps/shared/components/mail/ConversationList.js +6 -4
  401. package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +3 -3
  402. package/dist/apps/shared/components/mail/ConversationThreadPane.js +13 -11
  403. package/dist/apps/shared/components/mail/InviteCard.js +10 -8
  404. package/dist/apps/shared/components/mail/LazyReadingPane.js +2 -2
  405. package/dist/apps/shared/components/mail/MailAddress.d.ts +1 -1
  406. package/dist/apps/shared/components/mail/MailAddress.js +1 -1
  407. package/dist/apps/shared/components/mail/MailListToolbar.d.ts +2 -2
  408. package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +2 -2
  409. package/dist/apps/shared/components/mail/MenuButton.js +1 -1
  410. package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +3 -3
  411. package/dist/apps/shared/components/mail/MessageDetailPane.js +30 -28
  412. package/dist/apps/shared/components/mail/MoveToFolderDialog.d.ts +1 -1
  413. package/dist/apps/shared/components/mail/MoveToFolderDialog.js +8 -6
  414. package/dist/apps/shared/components/mail/OutboxRowStatus.d.ts +1 -1
  415. package/dist/apps/shared/components/mail/PermanentDeleteDialog.js +2 -2
  416. package/dist/apps/shared/components/mail/compose/ComposeContext.d.ts +10 -1
  417. package/dist/apps/shared/components/mail/compose/ComposeContext.js +4 -2
  418. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +34 -30
  419. package/dist/apps/shared/components/mail/compose/ComposeWindowPlaceholder.js +4 -4
  420. package/dist/apps/shared/components/mail/compose/EmojiPicker.js +2 -2
  421. package/dist/apps/shared/components/mail/compose/GifPicker.js +3 -3
  422. package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +1 -1
  423. package/dist/apps/shared/components/mail/compose/RecipientInput.js +1 -1
  424. package/dist/apps/shared/components/mail/compose/ScheduleSendPicker.js +1 -1
  425. package/dist/apps/shared/components/mail/compose/encryptionRequirement.d.ts +2 -2
  426. package/dist/apps/shared/components/mail/compose/encryptionRequirement.js +1 -1
  427. package/dist/apps/shared/components/mail/compose/quotedBody.d.ts +3 -3
  428. package/dist/apps/shared/components/mail/compose/quotedBody.js +3 -3
  429. package/dist/apps/shared/components/mail/compose/recipients.d.ts +1 -1
  430. package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +1 -1
  431. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +1 -1
  432. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +9 -7
  433. package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +1 -1
  434. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +1 -1
  435. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +1 -1
  436. package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +2 -2
  437. package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +9 -3
  438. package/dist/apps/shared/components/mail/invite/inviteStore.js +13 -6
  439. package/dist/apps/shared/components/mail/labelMenu.d.ts +1 -1
  440. package/dist/apps/shared/components/mail/labelMenu.js +9 -7
  441. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +1 -1
  442. package/dist/apps/shared/components/mail/layout/MailShell.js +3 -3
  443. package/dist/apps/shared/components/mail/listPreferences.d.ts +2 -2
  444. package/dist/apps/shared/components/mail/listPreferences.js +1 -1
  445. package/dist/apps/shared/components/mail/pinnedSigners.d.ts +12 -5
  446. package/dist/apps/shared/components/mail/pinnedSigners.js +37 -18
  447. package/dist/apps/shared/components/mail/reading/EncryptedBody.js +2 -2
  448. package/dist/apps/shared/components/mail/reading/MessageBody.d.ts +2 -2
  449. package/dist/apps/shared/components/mail/reading/MessageBody.js +4 -4
  450. package/dist/apps/shared/components/mail/reading/MessageCard.d.ts +1 -1
  451. package/dist/apps/shared/components/mail/reading/MessageCard.js +2 -2
  452. package/dist/apps/shared/components/mail/reading/MessageSourceDialog.js +3 -3
  453. package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +1 -1
  454. package/dist/apps/shared/components/mail/reading/bodyContent.d.ts +2 -2
  455. package/dist/apps/shared/components/mail/reading/bodyContent.js +2 -2
  456. package/dist/apps/shared/components/mail/reading/bodyHtml.js +1 -1
  457. package/dist/apps/shared/components/mail/reading/messageExport.js +1 -1
  458. package/dist/apps/shared/components/mail/reading/printMessage.d.ts +2 -2
  459. package/dist/apps/shared/components/mail/reading/useMessageActions.d.ts +1 -1
  460. package/dist/apps/shared/components/mail/reading/useMessageActions.js +18 -16
  461. package/dist/apps/shared/components/mail/unreadStyle.d.ts +1 -1
  462. package/dist/apps/shared/components/mail/verificationSeals.d.ts +27 -6
  463. package/dist/apps/shared/components/mail/verificationSeals.js +15 -11
  464. package/dist/apps/shared/components/mail/writableMailboxes.d.ts +8 -3
  465. package/dist/apps/shared/components/mail/writableMailboxes.js +12 -6
  466. package/dist/apps/shared/components/rules/RuleBuilder.js +1 -1
  467. package/dist/apps/shared/components/settings/SigningCertificateCard.d.ts +1 -1
  468. package/dist/apps/shared/components/settings/SigningCertificateCard.js +3 -3
  469. package/dist/apps/shared/components/settings/layout/SettingsShell.d.ts +1 -1
  470. package/dist/apps/shared/components/settings/layout/SettingsShell.js +8 -6
  471. package/dist/apps/shared/components/sharing/PrincipalListField.d.ts +1 -1
  472. package/dist/apps/shared/components/sharing/PrincipalPicker.d.ts +1 -1
  473. package/dist/apps/shared/components/sharing/PrincipalPicker.js +1 -1
  474. package/dist/apps/shared/components/sharing/PrincipalResolver.d.ts +1 -1
  475. package/dist/apps/shared/components/sharing/PrincipalResolver.js +3 -3
  476. package/dist/apps/shared/components/tasks/TasksSidebar.d.ts +1 -1
  477. package/dist/apps/shared/components/tasks/TasksSidebar.js +7 -5
  478. package/dist/apps/shared/components/tasks/layout/TasksShell.d.ts +1 -1
  479. package/dist/apps/shared/components/tasks/layout/TasksShell.js +9 -7
  480. package/dist/apps/shared/keyboard/ShortcutsDialog.js +1 -1
  481. package/dist/apps/shared/mail/findWellKnownFolderUid.d.ts +5 -3
  482. package/dist/apps/shared/mail/findWellKnownFolderUid.js +5 -4
  483. package/dist/apps/shared/mail/folderCounts.d.ts +1 -1
  484. package/dist/apps/shared/mail/folderCounts.js +6 -4
  485. package/dist/apps/shared/mail/folderOfType.d.ts +3 -2
  486. package/dist/apps/shared/mail/folderOfType.js +4 -4
  487. package/dist/apps/shared/mail/folderTree.d.ts +1 -1
  488. package/dist/apps/shared/mail/listSnapshots.d.ts +2 -2
  489. package/dist/apps/shared/mail/messageReadState.d.ts +4 -3
  490. package/dist/apps/shared/mail/messageReadState.js +5 -5
  491. package/dist/apps/shared/mail/newMailNotifications.d.ts +1 -1
  492. package/dist/apps/shared/mail/newMailNotifications.js +1 -1
  493. package/dist/apps/shared/mail/outbox/composeBridge.d.ts +2 -2
  494. package/dist/apps/shared/mail/outbox/outboxState.d.ts +1 -1
  495. package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +2 -2
  496. package/dist/apps/shared/mail/outbox/sendDecision.d.ts +2 -2
  497. package/dist/apps/shared/mail/outbox/sendDecision.js +1 -1
  498. package/dist/apps/shared/mail/outbox/sendJob.d.ts +10 -6
  499. package/dist/apps/shared/mail/outbox/sendJob.js +39 -35
  500. package/dist/apps/shared/mail/outbox/sendOutcomes.d.ts +6 -3
  501. package/dist/apps/shared/mail/outbox/sendOutcomes.js +19 -15
  502. package/dist/apps/shared/mail/outbox/useOutboxStatus.js +5 -3
  503. package/dist/apps/shared/mail/permanentDelete.d.ts +4 -3
  504. package/dist/apps/shared/mail/permanentDelete.js +8 -8
  505. package/dist/apps/shared/mail/primaryMailbox.d.ts +1 -1
  506. package/dist/apps/shared/mail/primaryMailbox.js +1 -1
  507. package/dist/apps/shared/mail/reportNotices.d.ts +1 -1
  508. package/dist/apps/shared/mail/senderBlocking.d.ts +5 -4
  509. package/dist/apps/shared/mail/senderBlocking.js +19 -16
  510. package/dist/apps/shared/mail/useMailConnection.d.ts +1 -1
  511. package/dist/apps/shared/mail/useMailConnection.js +12 -10
  512. package/dist/apps/shared/mail/useMailLiveUpdates.d.ts +2 -2
  513. package/dist/apps/shared/mail/useMailLiveUpdates.js +2 -2
  514. package/dist/apps/shared/mail/useMailboxUpdateAccess.d.ts +3 -2
  515. package/dist/apps/shared/mail/useMailboxUpdateAccess.js +31 -10
  516. package/dist/apps/shared/mail/useMarkMessageRead.d.ts +1 -1
  517. package/dist/apps/shared/mail/useMarkMessageRead.js +5 -3
  518. package/dist/apps/shared/mail/useNewMailNotifications.d.ts +1 -1
  519. package/dist/apps/shared/mail/usePermanentDelete.d.ts +1 -1
  520. package/dist/apps/shared/mail/usePermanentDelete.js +4 -2
  521. package/dist/apps/shared/navigation/pageTitle.d.ts +1 -1
  522. package/dist/apps/shared/notifications/NotificationCenter.js +1 -1
  523. package/dist/apps/shared/notifications/NotificationHistoryDialog.js +2 -2
  524. package/dist/apps/shared/notifications/apiErrors.js +2 -2
  525. package/dist/apps/shared/notifications/pushStatus.js +1 -1
  526. package/dist/apps/shared/notifications/systemErrors.js +1 -1
  527. package/dist/apps/shared/search/LocalIndexLifecycle.d.ts +2 -2
  528. package/dist/apps/shared/search/LocalIndexLifecycle.js +15 -10
  529. package/dist/apps/shared/search/crossMailboxSearch.d.ts +1 -1
  530. package/dist/apps/shared/search/crossMailboxSearch.js +2 -2
  531. package/dist/apps/shared/search/localIndexBuilder.d.ts +4 -3
  532. package/dist/apps/shared/search/localIndexBuilder.js +15 -12
  533. package/dist/apps/shared/search/localIndexKey.js +1 -1
  534. package/dist/apps/shared/search/localIndexRpcClient.d.ts +43 -31
  535. package/dist/apps/shared/search/localIndexRpcClient.js +113 -20
  536. package/dist/apps/shared/search/localIndexTransport.d.ts +77 -0
  537. package/dist/apps/shared/search/localIndexTransport.js +1 -0
  538. package/dist/apps/shared/search/localIndexWorker.d.ts +1 -1
  539. package/dist/apps/shared/search/searchTier2.d.ts +3 -3
  540. package/dist/apps/shared/signing/enrollmentTracker.d.ts +1 -1
  541. package/dist/apps/shared/signing/enrollmentTracker.js +3 -3
  542. package/dist/apps/shared/signing/enrollmentView.d.ts +1 -1
  543. package/dist/apps/shared/signing/signingInfo.d.ts +1 -1
  544. package/dist/apps/shared/signing/signingInfo.js +1 -1
  545. package/dist/apps/shared/signing/useSigningEnrollmentWatcher.d.ts +1 -1
  546. package/dist/apps/shared/signing/useSigningEnrollmentWatcher.js +5 -3
  547. package/dist/apps/shared/styles/app.css +14 -23
  548. package/dist/apps/www/_layout.d.ts +1 -1
  549. package/dist/apps/www/_layout.js +1 -1
  550. package/dist/apps/www/calendar/index.d.ts +1 -1
  551. package/dist/apps/www/calendar/index.js +20 -18
  552. package/dist/apps/www/contacts/[uid].d.ts +1 -1
  553. package/dist/apps/www/contacts/[uid].js +8 -6
  554. package/dist/apps/www/contacts/index.d.ts +1 -1
  555. package/dist/apps/www/contacts/index.js +19 -17
  556. package/dist/apps/www/index.d.ts +1 -1
  557. package/dist/apps/www/index.js +54 -50
  558. package/dist/apps/www/messages/[uid].d.ts +1 -1
  559. package/dist/apps/www/messages/[uid].js +11 -9
  560. package/dist/apps/www/settings/appearance/index.d.ts +1 -1
  561. package/dist/apps/www/settings/auto-reply/index.d.ts +1 -1
  562. package/dist/apps/www/settings/auto-reply/index.js +6 -4
  563. package/dist/apps/www/settings/blocked-senders/index.d.ts +1 -1
  564. package/dist/apps/www/settings/blocked-senders/index.js +6 -4
  565. package/dist/apps/www/settings/encryption/index.d.ts +1 -1
  566. package/dist/apps/www/settings/encryption/index.js +31 -29
  567. package/dist/apps/www/settings/filters/[uid].d.ts +1 -1
  568. package/dist/apps/www/settings/filters/[uid].js +11 -9
  569. package/dist/apps/www/settings/filters/_mailFilterRuleConfig.d.ts +2 -2
  570. package/dist/apps/www/settings/filters/index.d.ts +1 -1
  571. package/dist/apps/www/settings/filters/index.js +4 -4
  572. package/dist/apps/www/settings/filters/new/index.d.ts +1 -1
  573. package/dist/apps/www/settings/filters/new/index.js +10 -8
  574. package/dist/apps/www/settings/labels/index.d.ts +1 -1
  575. package/dist/apps/www/settings/labels/index.js +12 -10
  576. package/dist/apps/www/settings/privacy/index.d.ts +1 -1
  577. package/dist/apps/www/settings/privacy/index.js +18 -14
  578. package/dist/apps/www/settings/profile/index.d.ts +1 -1
  579. package/dist/apps/www/settings/profile/index.js +7 -5
  580. package/dist/apps/www/settings/read-receipts/index.d.ts +1 -1
  581. package/dist/apps/www/settings/read-receipts/index.js +5 -3
  582. package/dist/apps/www/settings/sharing/index.d.ts +1 -1
  583. package/dist/apps/www/settings/sharing/index.js +6 -6
  584. package/dist/apps/www/settings/signatures/[uid].d.ts +1 -1
  585. package/dist/apps/www/settings/signatures/[uid].js +5 -5
  586. package/dist/apps/www/settings/signatures/index.d.ts +1 -1
  587. package/dist/apps/www/settings/signatures/index.js +4 -4
  588. package/dist/apps/www/settings/signatures/new/index.d.ts +1 -1
  589. package/dist/apps/www/settings/signatures/new/index.js +4 -4
  590. package/dist/apps/www/settings/signatures/signatureDefaults.d.ts +1 -1
  591. package/dist/apps/www/settings/signatures/signatureDefaults.js +1 -1
  592. package/dist/apps/www/tasks/index.d.ts +1 -1
  593. package/dist/apps/www/tasks/index.js +17 -15
  594. package/dist/lib/admin/auditLogApi.d.ts +32 -0
  595. package/dist/lib/admin/auditLogApi.js +27 -0
  596. package/dist/lib/admin/distributionListsApi.d.ts +47 -0
  597. package/dist/lib/admin/distributionListsApi.js +34 -0
  598. package/dist/lib/admin/domainsApi.d.ts +75 -0
  599. package/dist/lib/admin/domainsApi.js +44 -0
  600. package/dist/lib/admin/escrowAccessRequestsApi.d.ts +79 -0
  601. package/dist/lib/admin/escrowAccessRequestsApi.js +46 -0
  602. package/dist/lib/admin/escrowAuditLogApi.d.ts +66 -0
  603. package/dist/lib/admin/escrowAuditLogApi.js +31 -0
  604. package/dist/lib/admin/escrowScopesApi.d.ts +78 -0
  605. package/dist/lib/admin/escrowScopesApi.js +50 -0
  606. package/dist/lib/admin/leftoverMailboxApi.d.ts +73 -0
  607. package/dist/lib/admin/leftoverMailboxApi.js +67 -0
  608. package/dist/lib/admin/mailboxPolicyApi.d.ts +27 -0
  609. package/dist/lib/admin/mailboxPolicyApi.js +21 -0
  610. package/dist/lib/admin/matterExportApi.d.ts +40 -0
  611. package/dist/lib/admin/matterExportApi.js +39 -0
  612. package/dist/lib/admin/matterSearchApi.d.ts +20 -0
  613. package/dist/lib/admin/matterSearchApi.js +27 -0
  614. package/dist/lib/admin/mattersApi.d.ts +56 -0
  615. package/dist/lib/admin/mattersApi.js +40 -0
  616. package/dist/lib/admin/pluginsApi.d.ts +265 -0
  617. package/dist/lib/admin/pluginsApi.js +102 -0
  618. package/dist/lib/admin/retentionPolicyApi.d.ts +32 -0
  619. package/dist/lib/admin/retentionPolicyApi.js +29 -0
  620. package/dist/lib/admin/setupApi.d.ts +23 -0
  621. package/dist/lib/admin/setupApi.js +26 -0
  622. package/dist/lib/admin/transportRulesApi.d.ts +66 -0
  623. package/dist/lib/admin/transportRulesApi.js +43 -0
  624. package/dist/lib/appearance/preferencesApi.d.ts +128 -0
  625. package/dist/lib/appearance/preferencesApi.js +257 -0
  626. package/dist/lib/auth/profileApi.d.ts +33 -0
  627. package/dist/lib/auth/profileApi.js +52 -0
  628. package/dist/lib/auth/session.d.ts +70 -0
  629. package/dist/lib/auth/session.js +210 -0
  630. package/dist/lib/branding/brandingApi.d.ts +47 -0
  631. package/dist/lib/branding/brandingApi.js +61 -0
  632. package/dist/lib/branding/useBranding.d.ts +23 -0
  633. package/dist/lib/branding/useBranding.js +65 -0
  634. package/dist/lib/calendar/calendarApi.d.ts +230 -0
  635. package/dist/lib/calendar/calendarApi.js +106 -0
  636. package/dist/lib/calendar/calendarColors.d.ts +18 -0
  637. package/dist/lib/calendar/calendarColors.js +39 -0
  638. package/dist/lib/calendar/calendarDragIds.d.ts +42 -0
  639. package/dist/lib/calendar/calendarDragIds.js +92 -0
  640. package/dist/lib/calendar/calendarMutations.d.ts +68 -0
  641. package/dist/lib/calendar/calendarMutations.js +190 -0
  642. package/dist/lib/calendar/eventDescription.d.ts +43 -0
  643. package/dist/lib/calendar/eventDescription.js +195 -0
  644. package/dist/lib/calendar/freeBusyApi.d.ts +100 -0
  645. package/dist/lib/calendar/freeBusyApi.js +119 -0
  646. package/dist/lib/calendar/inviteApi.d.ts +121 -0
  647. package/dist/lib/calendar/inviteApi.js +54 -0
  648. package/dist/lib/calendar/recurrence.d.ts +60 -0
  649. package/dist/lib/calendar/recurrence.js +225 -0
  650. package/dist/lib/components/avatar/ContactAvatar.d.ts +8 -0
  651. package/dist/lib/components/avatar/ContactAvatar.js +26 -0
  652. package/dist/lib/components/buttons/Button.d.ts +9 -0
  653. package/dist/lib/components/buttons/Button.js +14 -0
  654. package/dist/lib/components/buttons/CopyButton.d.ts +18 -0
  655. package/dist/lib/components/buttons/CopyButton.js +14 -0
  656. package/dist/lib/components/feedback/Alert.d.ts +4 -0
  657. package/dist/lib/components/feedback/Alert.js +4 -0
  658. package/dist/lib/components/feedback/Skeleton.d.ts +21 -0
  659. package/dist/lib/components/feedback/Skeleton.js +14 -0
  660. package/dist/lib/components/forms/FormField.d.ts +8 -0
  661. package/dist/lib/components/forms/FormField.js +5 -0
  662. package/dist/lib/components/navigation/BottomTabBar.d.ts +27 -0
  663. package/dist/lib/components/navigation/BottomTabBar.js +32 -0
  664. package/dist/lib/components/overlays/Drawer.d.ts +20 -0
  665. package/dist/lib/components/overlays/Drawer.js +27 -0
  666. package/dist/lib/components/overlays/Modal.d.ts +17 -0
  667. package/dist/lib/components/overlays/Modal.js +25 -0
  668. package/dist/lib/components/overlays/PopoverPortal.d.ts +23 -0
  669. package/dist/lib/components/overlays/PopoverPortal.js +53 -0
  670. package/dist/lib/components/overlays/overlayStack.d.ts +31 -0
  671. package/dist/lib/components/overlays/overlayStack.js +143 -0
  672. package/dist/lib/components/pickers/MiniDatePicker.d.ts +13 -0
  673. package/dist/lib/components/pickers/MiniDatePicker.js +42 -0
  674. package/dist/lib/contacts/contactsApi.d.ts +174 -0
  675. package/dist/lib/contacts/contactsApi.js +139 -0
  676. package/dist/lib/contacts/vcard.d.ts +23 -0
  677. package/dist/lib/contacts/vcard.js +179 -0
  678. package/dist/lib/crypto/composeSecurity.d.ts +67 -0
  679. package/dist/lib/crypto/composeSecurity.js +93 -0
  680. package/dist/lib/crypto/encoding.d.ts +9 -0
  681. package/dist/lib/crypto/encoding.js +32 -0
  682. package/dist/lib/crypto/escrowKeys.d.ts +25 -0
  683. package/dist/lib/crypto/escrowKeys.js +59 -0
  684. package/dist/lib/crypto/idleTimeout.d.ts +16 -0
  685. package/dist/lib/crypto/idleTimeout.js +47 -0
  686. package/dist/lib/crypto/keySession.d.ts +159 -0
  687. package/dist/lib/crypto/keySession.js +367 -0
  688. package/dist/lib/crypto/keys.d.ts +50 -0
  689. package/dist/lib/crypto/keys.js +89 -0
  690. package/dist/lib/crypto/keyvaultApi.d.ts +394 -0
  691. package/dist/lib/crypto/keyvaultApi.js +350 -0
  692. package/dist/lib/crypto/masterKey.d.ts +59 -0
  693. package/dist/lib/crypto/masterKey.js +104 -0
  694. package/dist/lib/crypto/masterKeyWraps.d.ts +108 -0
  695. package/dist/lib/crypto/masterKeyWraps.js +228 -0
  696. package/dist/lib/crypto/messageSecurity.d.ts +248 -0
  697. package/dist/lib/crypto/messageSecurity.js +367 -0
  698. package/dist/lib/crypto/mime.d.ts +143 -0
  699. package/dist/lib/crypto/mime.js +504 -0
  700. package/dist/lib/crypto/passkeyUnlock.d.ts +20 -0
  701. package/dist/lib/crypto/passkeyUnlock.js +79 -0
  702. package/dist/lib/crypto/passwordUnlock.d.ts +39 -0
  703. package/dist/lib/crypto/passwordUnlock.js +73 -0
  704. package/dist/lib/crypto/recoveryCode.d.ts +28 -0
  705. package/dist/lib/crypto/recoveryCode.js +86 -0
  706. package/dist/lib/crypto/signingProviderApi.d.ts +95 -0
  707. package/dist/lib/crypto/signingProviderApi.js +60 -0
  708. package/dist/lib/crypto/smime.d.ts +128 -0
  709. package/dist/lib/crypto/smime.js +402 -0
  710. package/dist/lib/crypto/smimeMessage.d.ts +132 -0
  711. package/dist/lib/crypto/smimeMessage.js +341 -0
  712. package/dist/lib/crypto/useIdleKeyTimeout.d.ts +10 -0
  713. package/dist/lib/crypto/useIdleKeyTimeout.js +163 -0
  714. package/dist/lib/crypto/verificationSeal.d.ts +56 -0
  715. package/dist/lib/crypto/verificationSeal.js +220 -0
  716. package/dist/lib/mail/compose/composeQuoting.d.ts +88 -0
  717. package/dist/lib/mail/compose/composeQuoting.js +204 -0
  718. package/dist/lib/mail/compose/emojiData.d.ts +9 -0
  719. package/dist/lib/mail/compose/emojiData.js +18 -0
  720. package/dist/lib/mail/compose/giphyApi.d.ts +17 -0
  721. package/dist/lib/mail/compose/giphyApi.js +20 -0
  722. package/dist/lib/mail/conversationsApi.d.ts +80 -0
  723. package/dist/lib/mail/conversationsApi.js +44 -0
  724. package/dist/lib/mail/dataExportApi.d.ts +50 -0
  725. package/dist/lib/mail/dataExportApi.js +40 -0
  726. package/dist/lib/mail/directoryApi.d.ts +49 -0
  727. package/dist/lib/mail/directoryApi.js +101 -0
  728. package/dist/lib/mail/erasureRequestApi.d.ts +45 -0
  729. package/dist/lib/mail/erasureRequestApi.js +43 -0
  730. package/dist/lib/mail/flaggedMessages.d.ts +22 -0
  731. package/dist/lib/mail/flaggedMessages.js +73 -0
  732. package/dist/lib/mail/focusedInboxOverridesApi.d.ts +37 -0
  733. package/dist/lib/mail/focusedInboxOverridesApi.js +34 -0
  734. package/dist/lib/mail/labelsApi.d.ts +47 -0
  735. package/dist/lib/mail/labelsApi.js +38 -0
  736. package/dist/lib/mail/mailAddress.d.ts +27 -0
  737. package/dist/lib/mail/mailAddress.js +54 -0
  738. package/dist/lib/mail/mailApi.d.ts +850 -0
  739. package/dist/lib/mail/mailApi.js +602 -0
  740. package/dist/lib/mail/mailDetailHooks.d.ts +10 -0
  741. package/dist/lib/mail/mailDetailHooks.js +53 -0
  742. package/dist/lib/mail/mailFilterRulesApi.d.ts +76 -0
  743. package/dist/lib/mail/mailFilterRulesApi.js +45 -0
  744. package/dist/lib/mail/mailSignaturesApi.d.ts +49 -0
  745. package/dist/lib/mail/mailSignaturesApi.js +42 -0
  746. package/dist/lib/mail/mailboxAccessApi.d.ts +74 -0
  747. package/dist/lib/mail/mailboxAccessApi.js +56 -0
  748. package/dist/lib/mail/mailboxImportApi.d.ts +53 -0
  749. package/dist/lib/mail/mailboxImportApi.js +51 -0
  750. package/dist/lib/mail/messageBodySanitizer.d.ts +16 -0
  751. package/dist/lib/mail/messageBodySanitizer.js +118 -0
  752. package/dist/lib/mail/pushClient.d.ts +106 -0
  753. package/dist/lib/mail/pushClient.js +317 -0
  754. package/dist/lib/mail/sendEvents.d.ts +33 -0
  755. package/dist/lib/mail/sendEvents.js +44 -0
  756. package/dist/lib/mail/sendFailure.d.ts +16 -0
  757. package/dist/lib/mail/sendFailure.js +86 -0
  758. package/dist/lib/mail/senderListsApi.d.ts +69 -0
  759. package/dist/lib/mail/senderListsApi.js +126 -0
  760. package/dist/lib/search/queryGrammar.d.ts +51 -0
  761. package/dist/lib/search/queryGrammar.js +111 -0
  762. package/dist/lib/search/searchApi.d.ts +100 -0
  763. package/dist/lib/search/searchApi.js +107 -0
  764. package/dist/lib/search/searchScoring.d.ts +34 -0
  765. package/dist/lib/search/searchScoring.js +44 -0
  766. package/dist/lib/search/searchTier3.d.ts +64 -0
  767. package/dist/lib/search/searchTier3.js +335 -0
  768. package/dist/lib/tasks/tasksApi.d.ts +85 -0
  769. package/dist/lib/tasks/tasksApi.js +55 -0
  770. package/dist/lib/util/api.d.ts +160 -0
  771. package/dist/lib/util/api.js +251 -0
  772. package/dist/lib/util/apiClientContext.d.ts +7 -0
  773. package/dist/lib/util/apiClientContext.js +32 -0
  774. package/dist/lib/util/apiQuery.d.ts +32 -0
  775. package/dist/lib/util/apiQuery.js +42 -0
  776. package/dist/lib/util/clipboard.d.ts +7 -0
  777. package/dist/lib/util/clipboard.js +56 -0
  778. package/dist/lib/util/dateInput.d.ts +6 -0
  779. package/dist/lib/util/dateInput.js +14 -0
  780. package/dist/lib/util/timeZone.d.ts +12 -0
  781. package/dist/lib/util/timeZone.js +32 -0
  782. package/dist/lib/util/useCopyToClipboard.d.ts +12 -0
  783. package/dist/lib/util/useCopyToClipboard.js +34 -0
  784. package/dist/lib/util/useIsMobile.d.ts +10 -0
  785. package/dist/lib/util/useIsMobile.js +29 -0
  786. package/dist/lib/videoconf/videoMeetingsApi.d.ts +116 -0
  787. package/dist/lib/videoconf/videoMeetingsApi.js +49 -0
  788. package/lib/admin/auditLogApi.ts +48 -0
  789. package/lib/admin/distributionListsApi.ts +77 -0
  790. package/lib/admin/domainsApi.ts +113 -0
  791. package/lib/admin/escrowAccessRequestsApi.ts +110 -0
  792. package/lib/admin/escrowAuditLogApi.ts +101 -0
  793. package/lib/admin/escrowScopesApi.ts +112 -0
  794. package/lib/admin/leftoverMailboxApi.ts +120 -0
  795. package/lib/admin/mailboxPolicyApi.ts +38 -0
  796. package/lib/admin/matterExportApi.ts +62 -0
  797. package/lib/admin/matterSearchApi.ts +35 -0
  798. package/lib/admin/mattersApi.ts +86 -0
  799. package/lib/admin/pluginsApi.ts +339 -0
  800. package/lib/admin/retentionPolicyApi.ts +46 -0
  801. package/lib/admin/setupApi.ts +40 -0
  802. package/lib/admin/transportRulesApi.ts +106 -0
  803. package/lib/appearance/preferencesApi.ts +335 -0
  804. package/lib/auth/profileApi.ts +77 -0
  805. package/lib/auth/session.ts +238 -0
  806. package/lib/branding/brandingApi.ts +97 -0
  807. package/lib/branding/useBranding.ts +81 -0
  808. package/lib/calendar/calendarApi.ts +309 -0
  809. package/lib/calendar/calendarColors.ts +45 -0
  810. package/lib/calendar/calendarDragIds.ts +112 -0
  811. package/lib/calendar/calendarMutations.ts +236 -0
  812. package/lib/calendar/eventDescription.ts +211 -0
  813. package/lib/calendar/freeBusyApi.ts +197 -0
  814. package/lib/calendar/inviteApi.ts +154 -0
  815. package/lib/calendar/recurrence.ts +285 -0
  816. package/lib/components/avatar/ContactAvatar.tsx +47 -0
  817. package/lib/components/buttons/Button.tsx +40 -0
  818. package/lib/components/buttons/CopyButton.tsx +45 -0
  819. package/lib/components/feedback/Alert.tsx +13 -0
  820. package/lib/components/feedback/Skeleton.tsx +38 -0
  821. package/lib/components/forms/FormField.tsx +23 -0
  822. package/lib/components/navigation/BottomTabBar.tsx +66 -0
  823. package/lib/components/overlays/Drawer.tsx +72 -0
  824. package/lib/components/overlays/Modal.tsx +64 -0
  825. package/lib/components/overlays/PopoverPortal.tsx +74 -0
  826. package/lib/components/overlays/overlayStack.ts +165 -0
  827. package/lib/components/pickers/MiniDatePicker.tsx +90 -0
  828. package/lib/contacts/contactsApi.ts +289 -0
  829. package/lib/contacts/vcard.ts +197 -0
  830. package/lib/crypto/composeSecurity.ts +140 -0
  831. package/lib/crypto/encoding.ts +36 -0
  832. package/lib/crypto/escrowKeys.ts +74 -0
  833. package/lib/crypto/idleTimeout.ts +49 -0
  834. package/lib/crypto/keySession.ts +483 -0
  835. package/lib/crypto/keys.ts +105 -0
  836. package/lib/crypto/keyvaultApi.ts +674 -0
  837. package/lib/crypto/masterKey.ts +134 -0
  838. package/lib/crypto/masterKeyWraps.ts +269 -0
  839. package/lib/crypto/messageSecurity.ts +600 -0
  840. package/lib/crypto/mime.ts +568 -0
  841. package/lib/crypto/passkeyUnlock.ts +103 -0
  842. package/lib/crypto/passwordUnlock.ts +98 -0
  843. package/lib/crypto/recoveryCode.ts +93 -0
  844. package/lib/crypto/signingProviderApi.ts +135 -0
  845. package/lib/crypto/smime.ts +459 -0
  846. package/lib/crypto/smimeMessage.ts +491 -0
  847. package/lib/crypto/useIdleKeyTimeout.ts +176 -0
  848. package/lib/crypto/verificationSeal.ts +288 -0
  849. package/lib/mail/compose/composeQuoting.ts +243 -0
  850. package/lib/mail/compose/emojiData.ts +34 -0
  851. package/lib/mail/compose/giphyApi.ts +31 -0
  852. package/lib/mail/conversationsApi.ts +123 -0
  853. package/lib/mail/dataExportApi.ts +73 -0
  854. package/lib/mail/directoryApi.ts +161 -0
  855. package/lib/mail/erasureRequestApi.ts +71 -0
  856. package/lib/mail/flaggedMessages.ts +80 -0
  857. package/lib/mail/focusedInboxOverridesApi.ts +64 -0
  858. package/lib/mail/labelsApi.ts +71 -0
  859. package/lib/mail/mailAddress.ts +76 -0
  860. package/lib/mail/mailApi.ts +1286 -0
  861. package/lib/mail/mailDetailHooks.ts +57 -0
  862. package/lib/mail/mailFilterRulesApi.ts +116 -0
  863. package/lib/mail/mailSignaturesApi.ts +84 -0
  864. package/lib/mail/mailboxAccessApi.ts +106 -0
  865. package/lib/mail/mailboxImportApi.ts +87 -0
  866. package/lib/mail/messageBodySanitizer.ts +129 -0
  867. package/lib/mail/pushClient.ts +375 -0
  868. package/lib/mail/sendEvents.ts +72 -0
  869. package/lib/mail/sendFailure.ts +98 -0
  870. package/lib/mail/senderListsApi.ts +161 -0
  871. package/lib/search/queryGrammar.ts +179 -0
  872. package/lib/search/searchApi.ts +199 -0
  873. package/lib/search/searchScoring.ts +46 -0
  874. package/lib/search/searchTier3.ts +406 -0
  875. package/lib/tasks/tasksApi.ts +128 -0
  876. package/lib/util/api.ts +318 -0
  877. package/lib/util/apiClientContext.ts +35 -0
  878. package/lib/util/apiQuery.ts +61 -0
  879. package/lib/util/clipboard.ts +55 -0
  880. package/lib/util/dateInput.ts +15 -0
  881. package/lib/util/timeZone.ts +33 -0
  882. package/lib/util/useCopyToClipboard.ts +48 -0
  883. package/lib/util/useIsMobile.ts +34 -0
  884. package/lib/videoconf/videoMeetingsApi.ts +144 -0
  885. package/package.json +10 -4
@@ -0,0 +1,159 @@
1
+ /**
2
+ * The in-memory session key store `specs/end-to-end_encryption.md`'s "Keypair Generation & Storage"
3
+ * requires: "When a user logs in ... the private keys MUST be downloaded from the server, decrypted,
4
+ * and stored locally on the device in a secure location. When the user explicitly logs out ..., the
5
+ * private keys MUST be destroyed." This module is that store — a plain module-level `Map`, deliberately
6
+ * never `localStorage`/IndexedDB (a page reload or new tab correctly starts with no unlocked keys,
7
+ * requiring the unlock credential again, matching "destroyed on explicit logout" while never
8
+ * persisting unwrapped key material anywhere durable).
9
+ *
10
+ * `KeyEnrollmentGate` (in `web-client`) is what actually prompts for the unlock credential and calls
11
+ * `unlockWithPassword()` below, once per mailbox per session, before rendering the mailbox's real
12
+ * content — see that component's own doc comment.
13
+ *
14
+ * **Password and recovery code are the unlock methods implemented so far** (`unlockWithPassword()`,
15
+ * `unlockWithRecoveryCode()`, which share one master-key-to-session step). Passkey (`passkeyUnlock.ts`)
16
+ * derivation exists and could unwrap the same `MasterKeyWrap` shape, but nothing calls it yet — a real
17
+ * follow-up, not a silent gap: a mailbox enrolled *only* with a passkey has no way to unlock through this
18
+ * module today.
19
+ */
20
+ import { type PublicKey } from "./keyvaultApi.js";
21
+ import { KeysLockedError } from "./masterKey.js";
22
+ /** AAD purpose labels — MUST exactly match what `KeyEnrollmentGate.tsx` used when it originally
23
+ * sealed each of these values, or `openWithKey()` fails (GCM authenticates the AAD, not just the
24
+ * ciphertext). Centralized here as the one place both wrapping and unwrapping refer to. */
25
+ export declare const MASTER_KEY_AAD_PURPOSE = "master-key";
26
+ export declare const SIGNING_PRIVATE_KEY_AAD_PURPOSE = "sign-private-key";
27
+ export declare const ENCRYPTION_PRIVATE_KEY_AAD_PURPOSE = "encrypt-private-key";
28
+ export { KeysLockedError };
29
+ /** How many retained (non-active) encryption keys an unlock opens at most: the most recently issued ones by
30
+ * `notBefore`. Each costs an AEAD open and a key import at unlock, and `smime.ts`'s `decryptEnvelopedDataWithKeys()`
31
+ * considers the active key plus this many (`MAX_DECRYPTION_KEYS`). Mail encrypted to a key older than the 20 most
32
+ * recent retained ones doesn't decrypt on this device; its wrapped key stays in the vault. */
33
+ export declare const MAX_RETAINED_ENCRYPTION_KEYS = 20;
34
+ /** An older encryption key an unlock opened besides the active one - see `UnlockedKeys.retainedEncryptionKeys`. */
35
+ export interface RetainedEncryptionKey {
36
+ fingerprint: string;
37
+ /** Base64-decoded DER certificate, from the mailbox's published `PublicKey.publicKey`. */
38
+ certDer: Uint8Array;
39
+ /** Non-extractable ECDH private key. */
40
+ privateKey: CryptoKey;
41
+ }
42
+ export interface UnlockedKeys {
43
+ /** `true` once `destroyUnlockedKeys()` has destroyed this object's keys (master key zeroed, private key
44
+ * handles dropped). A caller holding an `UnlockedKeys` across an `await` or a user action must treat a
45
+ * destroyed object as locked and re-read `getUnlockedKeys()` instead - `masterKey.ts`'s helpers throw
46
+ * `KeysLockedError` when handed its zeroed master key. Never set on an object still in the store. */
47
+ destroyed?: boolean;
48
+ masterKey: Uint8Array;
49
+ signingPrivateKey?: CryptoKey;
50
+ signingCertDer?: Uint8Array;
51
+ signingFingerprint?: string;
52
+ encryptionPrivateKey?: CryptoKey;
53
+ encryptionCertDer?: Uint8Array;
54
+ encryptionFingerprint?: string;
55
+ /** Every non-active encryption key the mailbox still has a wrapped private key for and a published `encrypt` key
56
+ * listed in its keys - superseded, expired *and* compromised ones - newest first, at most
57
+ * `MAX_RETAINED_ENCRYPTION_KEYS`. The spec retains an old encryption private key indefinitely on rotation, because
58
+ * discarding it makes old mail unreadable. **Decryption only:** `evaluateMessageSecurity()` tries these after the
59
+ * active key; nothing encrypts to or signs with them (`findActivePublicKey()` still picks the only key used for
60
+ * that). A compromised key is kept because reading one's own mail encrypted to it is still needed. Absent when there
61
+ * are none. */
62
+ retainedEncryptionKeys?: RetainedEncryptionKey[];
63
+ }
64
+ /** What changed in the session store — passed to every `subscribeKeySession()` listener. */
65
+ export interface KeySessionEvent {
66
+ mailboxUid: string;
67
+ /** `"unlocked"` when keys were stored (a first unlock, or a re-unlock replacing existing keys, e.g.
68
+ * after a key rotation); `"locked"` when they were destroyed. */
69
+ state: "unlocked" | "locked";
70
+ }
71
+ export type KeySessionListener = (event: KeySessionEvent) => void;
72
+ /**
73
+ * Subscribes to session store changes: fires once per mailbox whenever its keys are unlocked (stored)
74
+ * or destroyed, so a UI can e.g. clear already-decrypted content the moment keys go away instead of
75
+ * polling `getUnlockedKeys()`. A `destroyUnlockedKeys()` call that finds nothing to destroy fires
76
+ * nothing. Returns an unsubscribe function.
77
+ */
78
+ export declare function subscribeKeySession(listener: KeySessionListener): () => void;
79
+ /** Reads back a mailbox's already-unlocked keys this session, or `undefined` if it hasn't been
80
+ * unlocked yet (or was destroyed). Never triggers an unlock itself. */
81
+ export declare function getUnlockedKeys(mailboxUid: string): UnlockedKeys | undefined;
82
+ /**
83
+ * Destroys one mailbox's unlocked keys, or every mailbox's if called with no argument — the spec's
84
+ * "destroyed on explicit logout" / "session revocation" / "configurable idle period" triggers.
85
+ *
86
+ * The master key's bytes are overwritten with zeros in place before the entry is dropped, so any
87
+ * `UnlockedKeys` object a caller is still holding no longer carries usable key material either (and the
88
+ * bytes don't linger until garbage collection). That object is also marked `destroyed: true` and its
89
+ * private key `CryptoKey` handles are removed (their material is never exposed to JS, so there is nothing
90
+ * to zero - but a stale holder must not keep signing/decrypting with them after a lock). Sealing/opening
91
+ * with the zeroed master key throws `KeysLockedError` (see `masterKey.ts`).
92
+ *
93
+ * Every object handed out for the mailbox is destroyed - including ones a re-unlock already replaced in the
94
+ * store - and an `unlockWithPassword()`/`unlockWithRecoveryCode()` still in flight for it when this runs throws `KeysLockedError`
95
+ * instead of restoring keys after the lock.
96
+ */
97
+ export declare function destroyUnlockedKeys(mailboxUid?: string): void;
98
+ /** What `unlockWithPassword()` resolves with (and the base of `unlockWithRecoveryCode()`'s result). */
99
+ export interface UnlockResult {
100
+ /** Fingerprints of the active *signing* key and any retained (non-active) *encryption* keys whose wrapped private
101
+ * key couldn't be opened or imported with the (correctly unwrapped) master key - e.g. a wrap sealed under a master
102
+ * key a later rekey replaced. The unlock still succeeds without them (no `signingPrivateKey`; the retained key is
103
+ * left out of `retainedEncryptionKeys`), so a user isn't locked out of reading mail by a key they can't use. Empty
104
+ * when every key opened. */
105
+ unopenableKeys: string[];
106
+ }
107
+ /**
108
+ * Thrown by `unlockWithPassword()` when the password was right (the master key unwrapped) but the active
109
+ * *encryption* key's wrapped private key couldn't be opened or imported with it. Distinct from the
110
+ * wrong-password failure (which rejects with the underlying AEAD error from opening the password wrap), so a
111
+ * UI can say "your encryption key can't be opened" instead of "incorrect password".
112
+ */
113
+ export declare class UnopenableEncryptionKeyError extends Error {
114
+ readonly fingerprint: string;
115
+ /** The underlying AEAD/import failure. */
116
+ readonly cause: unknown;
117
+ constructor(fingerprint: string, cause?: unknown);
118
+ }
119
+ /**
120
+ * Unlocks a mailbox's key vault with its password unlock method: fetches the vault, derives the
121
+ * wrapping key from `password` using the *exact* KDF parameters that wrap was created with, unwraps
122
+ * the master key, then unwraps and imports whichever signing/encryption private keys the mailbox has
123
+ * currently-active public keys for, plus the retained older encryption keys (`UnlockedKeys.retainedEncryptionKeys`).
124
+ * Stores the result in this module's in-memory session store.
125
+ *
126
+ * Throws (never silently no-ops) when there's no password wrap enrolled, or when the password is
127
+ * wrong (AEAD authentication failure opening the password wrap) — callers should present this as
128
+ * "incorrect password," not a generic error, but this module doesn't presume a specific UI's error copy.
129
+ * Once the master key has opened, the password is known to be right: an active signing key that then
130
+ * won't open is skipped and listed in `UnlockResult.unopenableKeys` (so is a retained encryption key); an active
131
+ * encryption key that won't
132
+ * open still fails the unlock, with `UnopenableEncryptionKeyError`. Throws `KeysLockedError` when
133
+ * `destroyUnlockedKeys()` locked this mailbox (or all mailboxes) while the unlock was in flight.
134
+ */
135
+ export declare function unlockWithPassword(mailboxUid: string, mailboxKeys: PublicKey[], password: string): Promise<UnlockResult>;
136
+ /** What `unlockWithRecoveryCode()` resolves with. */
137
+ export interface RecoveryUnlockResult extends UnlockResult {
138
+ /** The `methodId` of the recovery wrap the code opened (e.g. `"recovery-3"`). Recovery codes are single-use:
139
+ * pass it to `masterKeyWraps.ts`'s `consumeRecoveryCode()` once the unlock flow is done. Absent only for a
140
+ * recovery wrap stored without a `methodId`, which `buildRecoveryWraps()` never produces. */
141
+ recoveryMethodId?: string;
142
+ /** How many *other* recovery wraps the vault holds - the codes left once this one is consumed. */
143
+ remainingRecoveryCodes: number;
144
+ }
145
+ /**
146
+ * Unlocks a mailbox's key vault with one of its recovery codes: fetches the vault, tries every `"recovery"` wrap
147
+ * (`kdf: "hkdf-sha256"`) with `deriveFromRecoveryCode(code, salt)` until one opens the master key, then opens the
148
+ * signing/encryption private keys and stores the session exactly as `unlockWithPassword()` does - the same
149
+ * `unopenableKeys` handling, `UnopenableEncryptionKeyError`, `KeysLockedError` on a lock mid-unlock, and
150
+ * `subscribeKeySession()` notification. `code` is normalized first (case, spacing, dashes, O/I/L slips).
151
+ *
152
+ * A wrong code and a vault with no recovery wraps both reject with the same plain `Error` (never saying which
153
+ * wrap was tried or failed) - the recovery-code counterpart of `unlockWithPassword()`'s wrong-password rejection.
154
+ *
155
+ * A recovery code is single-use, but this function writes nothing: the caller removes the used wrap afterwards
156
+ * with `consumeRecoveryCode(mailboxUid, result.recoveryMethodId)` (and may first offer a new password via
157
+ * `replacePasswordWrap()` - see that function for why that order is the safe one).
158
+ */
159
+ export declare function unlockWithRecoveryCode(mailboxUid: string, mailboxKeys: PublicKey[], code: string): Promise<RecoveryUnlockResult>;
@@ -0,0 +1,367 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * The in-memory session key store `specs/end-to-end_encryption.md`'s "Keypair Generation & Storage"
7
+ * requires: "When a user logs in ... the private keys MUST be downloaded from the server, decrypted,
8
+ * and stored locally on the device in a secure location. When the user explicitly logs out ..., the
9
+ * private keys MUST be destroyed." This module is that store — a plain module-level `Map`, deliberately
10
+ * never `localStorage`/IndexedDB (a page reload or new tab correctly starts with no unlocked keys,
11
+ * requiring the unlock credential again, matching "destroyed on explicit logout" while never
12
+ * persisting unwrapped key material anywhere durable).
13
+ *
14
+ * `KeyEnrollmentGate` (in `web-client`) is what actually prompts for the unlock credential and calls
15
+ * `unlockWithPassword()` below, once per mailbox per session, before rendering the mailbox's real
16
+ * content — see that component's own doc comment.
17
+ *
18
+ * **Password and recovery code are the unlock methods implemented so far** (`unlockWithPassword()`,
19
+ * `unlockWithRecoveryCode()`, which share one master-key-to-session step). Passkey (`passkeyUnlock.ts`)
20
+ * derivation exists and could unwrap the same `MasterKeyWrap` shape, but nothing calls it yet — a real
21
+ * follow-up, not a silent gap: a mailbox enrolled *only* with a passkey has no way to unlock through this
22
+ * module today.
23
+ */
24
+ import { findActivePublicKey, getKeyVault } from "./keyvaultApi.js";
25
+ import { fromBase64 } from "./encoding.js";
26
+ import { importPrivateKeyPkcs8 } from "./keys.js";
27
+ import { KeysLockedError, buildAad, openWithKey } from "./masterKey.js";
28
+ import { deriveFromPassword, parseArgon2idKdfLabel } from "./passwordUnlock.js";
29
+ import { RECOVERY_KDF_LABEL, deriveFromRecoveryCode } from "./recoveryCode.js";
30
+ /** AAD purpose labels — MUST exactly match what `KeyEnrollmentGate.tsx` used when it originally
31
+ * sealed each of these values, or `openWithKey()` fails (GCM authenticates the AAD, not just the
32
+ * ciphertext). Centralized here as the one place both wrapping and unwrapping refer to. */
33
+ export const MASTER_KEY_AAD_PURPOSE = "master-key";
34
+ export const SIGNING_PRIVATE_KEY_AAD_PURPOSE = "sign-private-key";
35
+ export const ENCRYPTION_PRIVATE_KEY_AAD_PURPOSE = "encrypt-private-key";
36
+ export { KeysLockedError };
37
+ /** How many retained (non-active) encryption keys an unlock opens at most: the most recently issued ones by
38
+ * `notBefore`. Each costs an AEAD open and a key import at unlock, and `smime.ts`'s `decryptEnvelopedDataWithKeys()`
39
+ * considers the active key plus this many (`MAX_DECRYPTION_KEYS`). Mail encrypted to a key older than the 20 most
40
+ * recent retained ones doesn't decrypt on this device; its wrapped key stays in the vault. */
41
+ export const MAX_RETAINED_ENCRYPTION_KEYS = 20;
42
+ const sessions = new Map();
43
+ /** A weak reference to `target` where the runtime has `WeakRef` (every supported browser and Node), otherwise a
44
+ * strong one - a missing `WeakRef` must never make a lock skip an object. */
45
+ function weakHandle(target) {
46
+ const WeakRefCtor = globalThis.WeakRef;
47
+ return WeakRefCtor ? new WeakRefCtor(target) : { deref: () => target };
48
+ }
49
+ /** Every `UnlockedKeys` object this store has handed out per mailbox and not yet destroyed - a re-unlock
50
+ * replaces the store entry but leaves the previous object usable for in-flight consumers, so a lock must
51
+ * reach all of them, not only the newest. Held *weakly*: the current object is kept alive by `sessions`, and a
52
+ * replaced one (e.g. holding a pre-rotation master key) only for as long as some consumer still references it -
53
+ * once nothing does, it can be collected instead of lingering until the next lock. A lock destroys every one
54
+ * still reachable, which is every one anybody could still use. */
55
+ const issued = new Map();
56
+ /** Bumped by every `destroyUnlockedKeys()` call for that mailbox (`lockAllGeneration` for a destroy-all),
57
+ * so an unlock still awaiting the vault/KDF when a lock happens can tell and discard what it unwrapped. */
58
+ const lockGenerations = new Map();
59
+ let lockAllGeneration = 0;
60
+ function lockGeneration(mailboxUid) {
61
+ return `${lockAllGeneration}:${lockGenerations.get(mailboxUid) ?? 0}`;
62
+ }
63
+ const listeners = new Set();
64
+ function notify(event) {
65
+ // Iterate a snapshot so a listener that unsubscribes (or subscribes another) mid-dispatch can't skip
66
+ // or double-deliver. A throwing listener must never stop the rest - especially on "locked", where a
67
+ // later listener may be the one clearing decrypted content from the screen - so its error is
68
+ // rethrown asynchronously instead, still surfacing as an uncaught error without aborting delivery.
69
+ for (const listener of [...listeners]) {
70
+ try {
71
+ listener(event);
72
+ }
73
+ catch (err) {
74
+ queueMicrotask(() => {
75
+ throw err;
76
+ });
77
+ }
78
+ }
79
+ }
80
+ /**
81
+ * Subscribes to session store changes: fires once per mailbox whenever its keys are unlocked (stored)
82
+ * or destroyed, so a UI can e.g. clear already-decrypted content the moment keys go away instead of
83
+ * polling `getUnlockedKeys()`. A `destroyUnlockedKeys()` call that finds nothing to destroy fires
84
+ * nothing. Returns an unsubscribe function.
85
+ */
86
+ export function subscribeKeySession(listener) {
87
+ listeners.add(listener);
88
+ return () => {
89
+ listeners.delete(listener);
90
+ };
91
+ }
92
+ /** Reads back a mailbox's already-unlocked keys this session, or `undefined` if it hasn't been
93
+ * unlocked yet (or was destroyed). Never triggers an unlock itself. */
94
+ export function getUnlockedKeys(mailboxUid) {
95
+ return sessions.get(mailboxUid);
96
+ }
97
+ /**
98
+ * Destroys one mailbox's unlocked keys, or every mailbox's if called with no argument — the spec's
99
+ * "destroyed on explicit logout" / "session revocation" / "configurable idle period" triggers.
100
+ *
101
+ * The master key's bytes are overwritten with zeros in place before the entry is dropped, so any
102
+ * `UnlockedKeys` object a caller is still holding no longer carries usable key material either (and the
103
+ * bytes don't linger until garbage collection). That object is also marked `destroyed: true` and its
104
+ * private key `CryptoKey` handles are removed (their material is never exposed to JS, so there is nothing
105
+ * to zero - but a stale holder must not keep signing/decrypting with them after a lock). Sealing/opening
106
+ * with the zeroed master key throws `KeysLockedError` (see `masterKey.ts`).
107
+ *
108
+ * Every object handed out for the mailbox is destroyed - including ones a re-unlock already replaced in the
109
+ * store - and an `unlockWithPassword()`/`unlockWithRecoveryCode()` still in flight for it when this runs throws `KeysLockedError`
110
+ * instead of restoring keys after the lock.
111
+ */
112
+ export function destroyUnlockedKeys(mailboxUid) {
113
+ if (mailboxUid) {
114
+ lockGenerations.set(mailboxUid, (lockGenerations.get(mailboxUid) ?? 0) + 1);
115
+ }
116
+ else {
117
+ lockAllGeneration++;
118
+ }
119
+ const uids = mailboxUid ? [mailboxUid] : [...issued.keys()];
120
+ for (const uid of uids) {
121
+ const objects = issued.get(uid);
122
+ if (!objects) {
123
+ continue;
124
+ }
125
+ for (const handle of objects) {
126
+ const unlocked = handle.deref();
127
+ if (unlocked) {
128
+ destroyObject(unlocked);
129
+ }
130
+ }
131
+ issued.delete(uid);
132
+ sessions.delete(uid);
133
+ notify({ mailboxUid: uid, state: "locked" });
134
+ }
135
+ }
136
+ function destroyObject(unlocked) {
137
+ unlocked.masterKey.fill(0);
138
+ unlocked.destroyed = true;
139
+ delete unlocked.signingPrivateKey;
140
+ delete unlocked.encryptionPrivateKey;
141
+ if (unlocked.retainedEncryptionKeys) {
142
+ // Emptied in place as well as removed, so a consumer that captured the array itself loses the handles too.
143
+ unlocked.retainedEncryptionKeys.length = 0;
144
+ delete unlocked.retainedEncryptionKeys;
145
+ }
146
+ }
147
+ /** Finds the wrapped private key whose fingerprint matches a given published public key. */
148
+ function findWrappedPrivateKey(vault, fingerprint) {
149
+ return vault.wrappedKeys.find((k) => k.fingerprint === fingerprint);
150
+ }
151
+ /**
152
+ * Thrown by `unlockWithPassword()` when the password was right (the master key unwrapped) but the active
153
+ * *encryption* key's wrapped private key couldn't be opened or imported with it. Distinct from the
154
+ * wrong-password failure (which rejects with the underlying AEAD error from opening the password wrap), so a
155
+ * UI can say "your encryption key can't be opened" instead of "incorrect password".
156
+ */
157
+ export class UnopenableEncryptionKeyError extends Error {
158
+ constructor(fingerprint, cause) {
159
+ super(`The encryption key ${fingerprint} for this mailbox couldn't be opened with its master key.`);
160
+ this.name = "UnopenableEncryptionKeyError";
161
+ this.fingerprint = fingerprint;
162
+ this.cause = cause;
163
+ }
164
+ }
165
+ /** Opens one wrapped PKCS#8 private key under `masterKey` and imports it (non-extractable by default, like
166
+ * `importPrivateKeyPkcs8()` itself), zeroing the transient plaintext whether or not the import succeeds. */
167
+ async function openPrivateKey(masterKey, wrapped, aad, algorithm, usages, extractable = false) {
168
+ const raw = await openWithKey(masterKey, wrapped, aad);
169
+ try {
170
+ return await importPrivateKeyPkcs8(raw, algorithm, usages, extractable);
171
+ }
172
+ finally {
173
+ raw.fill(0);
174
+ }
175
+ }
176
+ /**
177
+ * Opens the retained encryption keys onto `unlocked.retainedEncryptionKeys`: every published `encrypt` key in
178
+ * `mailboxKeys` other than the active one (`activeFingerprint`), whatever its revocation or expiry, that has a wrapped
179
+ * private key in the vault - de-duplicated by fingerprint, newest `notBefore` first, at most
180
+ * `MAX_RETAINED_ENCRYPTION_KEYS`. A key that won't open or import, or whose certificate won't decode, is skipped and
181
+ * added to `unopenableKeys`. Retained keys are imported non-extractable. Each key is attached as it opens, so a failed
182
+ * unlock's `destroyObject()` drops those too.
183
+ */
184
+ async function openRetainedEncryptionKeys(mailboxUid, mailboxKeys, vault, unlocked, activeFingerprint, unopenableKeys) {
185
+ const seen = new Set(activeFingerprint !== undefined ? [activeFingerprint] : []);
186
+ const candidates = [];
187
+ for (const publicKey of [...mailboxKeys].sort((a, b) => b.notBefore - a.notBefore)) {
188
+ const wrapped = publicKey.useType === "encrypt" && !seen.has(publicKey.fingerprint) ? findWrappedPrivateKey(vault, publicKey.fingerprint) : undefined;
189
+ if (!wrapped) {
190
+ continue;
191
+ }
192
+ seen.add(publicKey.fingerprint);
193
+ candidates.push({ publicKey, wrapped });
194
+ if (candidates.length === MAX_RETAINED_ENCRYPTION_KEYS) {
195
+ break;
196
+ }
197
+ }
198
+ const aad = buildAad(mailboxUid, ENCRYPTION_PRIVATE_KEY_AAD_PURPOSE);
199
+ for (const { publicKey, wrapped } of candidates) {
200
+ try {
201
+ const certDer = fromBase64(publicKey.publicKey);
202
+ const privateKey = await openPrivateKey(unlocked.masterKey, wrapped, aad, { name: "ECDH", namedCurve: "P-256" }, ["deriveBits"], false);
203
+ (unlocked.retainedEncryptionKeys ?? (unlocked.retainedEncryptionKeys = [])).push({ fingerprint: publicKey.fingerprint, certDer, privateKey });
204
+ }
205
+ catch {
206
+ unopenableKeys.push(publicKey.fingerprint);
207
+ }
208
+ }
209
+ }
210
+ /**
211
+ * Unlocks a mailbox's key vault with its password unlock method: fetches the vault, derives the
212
+ * wrapping key from `password` using the *exact* KDF parameters that wrap was created with, unwraps
213
+ * the master key, then unwraps and imports whichever signing/encryption private keys the mailbox has
214
+ * currently-active public keys for, plus the retained older encryption keys (`UnlockedKeys.retainedEncryptionKeys`).
215
+ * Stores the result in this module's in-memory session store.
216
+ *
217
+ * Throws (never silently no-ops) when there's no password wrap enrolled, or when the password is
218
+ * wrong (AEAD authentication failure opening the password wrap) — callers should present this as
219
+ * "incorrect password," not a generic error, but this module doesn't presume a specific UI's error copy.
220
+ * Once the master key has opened, the password is known to be right: an active signing key that then
221
+ * won't open is skipped and listed in `UnlockResult.unopenableKeys` (so is a retained encryption key); an active
222
+ * encryption key that won't
223
+ * open still fails the unlock, with `UnopenableEncryptionKeyError`. Throws `KeysLockedError` when
224
+ * `destroyUnlockedKeys()` locked this mailbox (or all mailboxes) while the unlock was in flight.
225
+ */
226
+ export async function unlockWithPassword(mailboxUid, mailboxKeys, password) {
227
+ const generation = lockGeneration(mailboxUid);
228
+ const vault = await getKeyVault(mailboxUid);
229
+ const passwordWrap = vault.masterKeyWraps.find((w) => w.method === "password");
230
+ if (!passwordWrap) {
231
+ throw new Error("This mailbox has no password unlock method enrolled.");
232
+ }
233
+ const kdfParams = parseArgon2idKdfLabel(passwordWrap.kdf);
234
+ if (!kdfParams) {
235
+ throw new Error(`Unrecognized KDF for this mailbox's password wrap: ${passwordWrap.kdf}`);
236
+ }
237
+ const salt = fromBase64(passwordWrap.salt);
238
+ const { wrappingKey } = await deriveFromPassword(password, salt, kdfParams);
239
+ const masterKey = await openWithKey(wrappingKey, { ciphertext: passwordWrap.ciphertext, nonce: passwordWrap.nonce }, buildAad(mailboxUid, MASTER_KEY_AAD_PURPOSE));
240
+ return openSession(mailboxUid, mailboxKeys, vault, masterKey, generation);
241
+ }
242
+ /** The one rejection for a recovery code that opens nothing - a wrong code and a vault with no recovery wraps
243
+ * alike, so a UI can say "that recovery code didn't work" without learning (or revealing) which it was. */
244
+ const RECOVERY_CODE_REJECTED = "That recovery code didn't unlock this mailbox.";
245
+ /**
246
+ * Unlocks a mailbox's key vault with one of its recovery codes: fetches the vault, tries every `"recovery"` wrap
247
+ * (`kdf: "hkdf-sha256"`) with `deriveFromRecoveryCode(code, salt)` until one opens the master key, then opens the
248
+ * signing/encryption private keys and stores the session exactly as `unlockWithPassword()` does - the same
249
+ * `unopenableKeys` handling, `UnopenableEncryptionKeyError`, `KeysLockedError` on a lock mid-unlock, and
250
+ * `subscribeKeySession()` notification. `code` is normalized first (case, spacing, dashes, O/I/L slips).
251
+ *
252
+ * A wrong code and a vault with no recovery wraps both reject with the same plain `Error` (never saying which
253
+ * wrap was tried or failed) - the recovery-code counterpart of `unlockWithPassword()`'s wrong-password rejection.
254
+ *
255
+ * A recovery code is single-use, but this function writes nothing: the caller removes the used wrap afterwards
256
+ * with `consumeRecoveryCode(mailboxUid, result.recoveryMethodId)` (and may first offer a new password via
257
+ * `replacePasswordWrap()` - see that function for why that order is the safe one).
258
+ */
259
+ export async function unlockWithRecoveryCode(mailboxUid, mailboxKeys, code) {
260
+ const generation = lockGeneration(mailboxUid);
261
+ const vault = await getKeyVault(mailboxUid);
262
+ const recoveryWraps = vault.masterKeyWraps.filter((w) => w.method === "recovery");
263
+ const aad = buildAad(mailboxUid, MASTER_KEY_AAD_PURPOSE);
264
+ let opened;
265
+ for (const wrap of recoveryWraps) {
266
+ if (wrap.kdf !== RECOVERY_KDF_LABEL) {
267
+ continue;
268
+ }
269
+ let wrappingKey;
270
+ try {
271
+ wrappingKey = await deriveFromRecoveryCode(code, fromBase64(wrap.salt));
272
+ opened = { masterKey: await openWithKey(wrappingKey, { ciphertext: wrap.ciphertext, nonce: wrap.nonce }, aad), methodId: wrap.methodId };
273
+ }
274
+ catch {
275
+ // Wrong code for this wrap (AEAD failure), an empty code, or a corrupt wrap - all just "not this one".
276
+ }
277
+ finally {
278
+ wrappingKey?.fill(0);
279
+ }
280
+ if (opened) {
281
+ break;
282
+ }
283
+ }
284
+ if (!opened) {
285
+ throw new Error(RECOVERY_CODE_REJECTED);
286
+ }
287
+ const result = await openSession(mailboxUid, mailboxKeys, vault, opened.masterKey, generation);
288
+ return {
289
+ ...result,
290
+ ...(opened.methodId !== undefined ? { recoveryMethodId: opened.methodId } : {}),
291
+ remainingRecoveryCodes: recoveryWraps.length - 1,
292
+ };
293
+ }
294
+ /**
295
+ * Shared tail of every unlock method once its wrap has yielded `masterKey`: opens and imports the active signing and
296
+ * encryption private keys and the retained encryption keys (`openRetainedEncryptionKeys()`), aborts with `KeysLockedError` if the mailbox was locked since `generation` was taken, then
297
+ * stores the result (tracked weakly in `issued`) and notifies. Zeroes `masterKey` on any failure.
298
+ */
299
+ async function openSession(mailboxUid, mailboxKeys, vault, masterKey, generation) {
300
+ const unlocked = { masterKey };
301
+ const unopenableKeys = [];
302
+ // The active private keys are imported *non-extractable*, same as the retained encryption keys below (round-5
303
+ // review; previously imported extractable, on the reasoning that an XSS able to call `exportKey()` on these
304
+ // handles could equally call `openWithKey()` with the in-memory master key - but that framing missed that
305
+ // `exportKey()` yields raw bytes an attacker can copy out and keep *after* the session ends (logout, master-key
306
+ // zeroing), whereas the master-key-access path only works while the session is live. Their one former consumer,
307
+ // `keyRotation.ts`'s `rewrapPrivateKeysUnderNewMasterKey()`, was removed (2026-09-15; it re-wrapped only the
308
+ // active keys, and web-client's rotation re-seals every vault wrap itself) - confirmed nothing in this package
309
+ // or in `web-client`/`electron-client` calls `exportKey()` on a session key at all, so nothing depends on this
310
+ // being extractable. The transient PKCS#8 plaintext buffers are zeroed as soon as WebCrypto has copied them
311
+ // into a `CryptoKey` either way.
312
+ try {
313
+ const signingPublicKey = findActivePublicKey(mailboxKeys, "sign");
314
+ const wrappedSigningKey = signingPublicKey && findWrappedPrivateKey(vault, signingPublicKey.fingerprint);
315
+ if (signingPublicKey && wrappedSigningKey) {
316
+ try {
317
+ const aad = buildAad(mailboxUid, SIGNING_PRIVATE_KEY_AAD_PURPOSE);
318
+ unlocked.signingPrivateKey = await openPrivateKey(masterKey, wrappedSigningKey, aad, { name: "ECDSA", namedCurve: "P-256" }, ["sign"]);
319
+ unlocked.signingCertDer = fromBase64(signingPublicKey.publicKey);
320
+ unlocked.signingFingerprint = signingPublicKey.fingerprint;
321
+ }
322
+ catch {
323
+ unopenableKeys.push(signingPublicKey.fingerprint);
324
+ }
325
+ }
326
+ const encryptionPublicKey = findActivePublicKey(mailboxKeys, "encrypt");
327
+ const wrappedEncryptionKey = encryptionPublicKey && findWrappedPrivateKey(vault, encryptionPublicKey.fingerprint);
328
+ if (encryptionPublicKey && wrappedEncryptionKey) {
329
+ try {
330
+ const aad = buildAad(mailboxUid, ENCRYPTION_PRIVATE_KEY_AAD_PURPOSE);
331
+ unlocked.encryptionPrivateKey = await openPrivateKey(masterKey, wrappedEncryptionKey, aad, { name: "ECDH", namedCurve: "P-256" }, ["deriveBits"]);
332
+ }
333
+ catch (err) {
334
+ throw new UnopenableEncryptionKeyError(encryptionPublicKey.fingerprint, err);
335
+ }
336
+ unlocked.encryptionCertDer = fromBase64(encryptionPublicKey.publicKey);
337
+ unlocked.encryptionFingerprint = encryptionPublicKey.fingerprint;
338
+ }
339
+ await openRetainedEncryptionKeys(mailboxUid, mailboxKeys, vault, unlocked, encryptionPublicKey?.fingerprint, unopenableKeys);
340
+ if (lockGeneration(mailboxUid) !== generation) {
341
+ // Locked (e.g. logout) while this unlock was awaiting - never restore keys after that.
342
+ throw new KeysLockedError();
343
+ }
344
+ }
345
+ catch (err) {
346
+ // A failed unlock never reaches the session store, so nothing else would ever zero this.
347
+ destroyObject(unlocked);
348
+ throw err;
349
+ }
350
+ // A re-unlock replacing existing keys (e.g. `settings/encryption`'s post-rotation refresh) deliberately
351
+ // does NOT zero the previous entry's master key: an in-flight consumer that captured the old
352
+ // `UnlockedKeys` object (e.g. a local-index build pass) is still legitimately using it, and nothing
353
+ // "destroyed" the session - only `destroyUnlockedKeys()` does that, and it destroys every issued object still
354
+ // reachable. The store itself keeps the replaced object only weakly (see `issued`).
355
+ sessions.set(mailboxUid, unlocked);
356
+ const objects = issued.get(mailboxUid) ?? new Set();
357
+ // Drop handles whose object was already collected, so repeated re-unlocks don't grow the set.
358
+ for (const handle of objects) {
359
+ if (!handle.deref()) {
360
+ objects.delete(handle);
361
+ }
362
+ }
363
+ objects.add(weakHandle(unlocked));
364
+ issued.set(mailboxUid, objects);
365
+ notify({ mailboxUid, state: "unlocked" });
366
+ return { unopenableKeys };
367
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Client-side keypair generation for `specs/end-to-end_encryption.md`'s "Keypair Generation & Storage":
3
+ * on first sign-in, the client generates two ECC P-256 keypairs (signing, encryption) and builds a
4
+ * PKCS#10 CSR for each — `keyvaultApi.ts`'s `enrollKey()` then either submits the encryption CSR to the
5
+ * server's internal CA (`useType: "encrypt"`), or, for signing, the CSR is sent through the separate,
6
+ * asynchronous public-CA enrollment flow this repo doesn't drive directly (`useType: "sign"` expects an
7
+ * already-issued certificate — see `keyvaultApi.ts`'s `EnrollKeyInput` doc comment).
8
+ *
9
+ * Both keys are generated as WebCrypto `ECDSA` keypairs (`sign`/`verify` usages) even though the
10
+ * encryption key is only ever used, once issued, for key-agreement operations, never for signing a
11
+ * message — a PKCS#10 CSR must itself be signed by the key it certifies (proof of possession), which
12
+ * requires a signing-capable `CryptoKey`. The issued certificate's own `keyUsage` extension (set
13
+ * server-side — see `@rapidmx/restapi`'s `LocalX509CertificateAuthority`) is what actually restricts the
14
+ * encryption key to key-agreement use; nothing in this module relies on that restriction, it only
15
+ * generates the keypair and proves possession of it. The same underlying P-256 key material is
16
+ * re-imported under the `ECDH` algorithm tag by `crypto/smime.ts` when it's actually used to encrypt/
17
+ * decrypt (see `exportPrivateKeyPkcs8()`'s own doc comment) — WebCrypto ties an algorithm to a
18
+ * `CryptoKey` object, not to the underlying key material itself, so this is the same key, re-imported.
19
+ *
20
+ * ECC P-256, not RSA, per the spec: "roughly halves the size of the Autocrypt-style header carried on
21
+ * every outgoing message" versus RSA-2048.
22
+ */
23
+ export interface GeneratedKeyPair {
24
+ keyPair: CryptoKeyPair;
25
+ /** PEM-encoded PKCS#10 CSR, ready to pass as `keyvaultApi.ts`'s `EnrollKeyInput.csr`. */
26
+ csrPem: string;
27
+ }
28
+ /**
29
+ * Generates a fresh P-256 keypair and a self-signed PKCS#10 CSR naming `mailboxAddress` as the subject
30
+ * common name. `useType` only affects the CSR's own extensions (`emailProtection` EKU either way, since
31
+ * both signing and encryption certs are used for S/MIME) — actual key-usage restriction happens
32
+ * server-side at issuance, not here; this function only proves possession of the generated key.
33
+ */
34
+ export declare function generateKeyPairWithCsr(mailboxAddress: string, useType: "sign" | "encrypt"): Promise<GeneratedKeyPair>;
35
+ /** Exports a private key as raw PKCS#8 bytes — the form AEAD-sealed under MK (see `masterKey.ts`) before
36
+ * being uploaded via `keyvaultApi.ts`'s `enrollKey()`. */
37
+ export declare function exportPrivateKeyPkcs8(privateKey: CryptoKey): Promise<Uint8Array>;
38
+ /**
39
+ * Re-imports a PKCS#8 private key for a specific algorithm/usage — used both to restore a signing key
40
+ * after unwrapping it (`algorithm: "ECDSA"`, `usages: ["sign"]`) and, by `crypto/smime.ts`, to reinterpret
41
+ * the same P-256 encryption key material for actual key-agreement operations (`algorithm: "ECDH"`,
42
+ * `usages: ["deriveBits"]`) — see this module's own doc comment for why one physical key supports both.
43
+ *
44
+ * Imported **non-extractable by default**: signing/ECDH (including pkijs's own `SignedData.sign()`/
45
+ * `EnvelopedData.decrypt()`, which use a `CryptoKey` recipient key directly) never need to read the key
46
+ * material back out, so a script that obtains the `CryptoKey` object can use it but not exfiltrate it.
47
+ * Pass `extractable: true` only for a path that genuinely has to re-export the PKCS#8 bytes (see
48
+ * `keySession.ts`'s `unlockWithPassword()` for the one current case, and why).
49
+ */
50
+ export declare function importPrivateKeyPkcs8(raw: Uint8Array, algorithm: EcKeyImportParams, usages: KeyUsage[], extractable?: boolean): Promise<CryptoKey>;