@rapidmx/web-client 0.21.0 → 0.23.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 (897) 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 +28 -24
  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 +5 -3
  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 +25 -10
  120. package/apps/shared/components/mail/ConversationThreadPane.tsx +33 -17
  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 +69 -48
  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 +10 -14
  142. package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +11 -9
  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/conversationPrint.ts +76 -0
  159. package/apps/shared/components/mail/reading/messageExport.ts +1 -1
  160. package/apps/shared/components/mail/reading/printMessage.ts +46 -9
  161. package/apps/shared/components/mail/reading/useMessageActions.ts +28 -21
  162. package/apps/shared/components/mail/unreadStyle.tsx +1 -1
  163. package/apps/shared/components/mail/verificationSeals.ts +16 -12
  164. package/apps/shared/components/mail/writableMailboxes.ts +14 -7
  165. package/apps/shared/components/rules/RuleBuilder.tsx +1 -1
  166. package/apps/shared/components/settings/SigningCertificateCard.tsx +4 -4
  167. package/apps/shared/components/settings/layout/SettingsShell.tsx +8 -6
  168. package/apps/shared/components/sharing/PrincipalListField.tsx +1 -1
  169. package/apps/shared/components/sharing/PrincipalPicker.tsx +1 -1
  170. package/apps/shared/components/sharing/PrincipalResolver.tsx +4 -4
  171. package/apps/shared/components/tasks/TasksSidebar.tsx +7 -5
  172. package/apps/shared/components/tasks/layout/TasksShell.tsx +9 -7
  173. package/apps/shared/keyboard/ShortcutsDialog.tsx +1 -1
  174. package/apps/shared/keyboard/keymap.ts +1 -0
  175. package/apps/shared/mail/decryptedMessages.ts +116 -0
  176. package/apps/shared/mail/findWellKnownFolderUid.ts +6 -4
  177. package/apps/shared/mail/folderCounts.ts +8 -4
  178. package/apps/shared/mail/folderOfType.ts +5 -3
  179. package/apps/shared/mail/folderTree.ts +1 -1
  180. package/apps/shared/mail/listSnapshots.ts +2 -2
  181. package/apps/shared/mail/messageReadState.ts +6 -5
  182. package/apps/shared/mail/newMailNotifications.ts +2 -2
  183. package/apps/shared/mail/outbox/composeBridge.ts +2 -2
  184. package/apps/shared/mail/outbox/outboxState.ts +1 -1
  185. package/apps/shared/mail/outbox/outgoingReplies.ts +2 -2
  186. package/apps/shared/mail/outbox/sendDecision.ts +2 -2
  187. package/apps/shared/mail/outbox/sendJob.ts +40 -35
  188. package/apps/shared/mail/outbox/sendOutcomes.ts +20 -15
  189. package/apps/shared/mail/outbox/useOutboxStatus.ts +5 -3
  190. package/apps/shared/mail/permanentDelete.ts +8 -7
  191. package/apps/shared/mail/primaryMailbox.ts +1 -1
  192. package/apps/shared/mail/reportNotices.ts +1 -1
  193. package/apps/shared/mail/senderBlocking.ts +36 -20
  194. package/apps/shared/mail/useMailConnection.ts +12 -10
  195. package/apps/shared/mail/useMailLiveUpdates.ts +3 -3
  196. package/apps/shared/mail/useMailboxUpdateAccess.ts +35 -11
  197. package/apps/shared/mail/useMarkMessageRead.ts +14 -7
  198. package/apps/shared/mail/useNewMailNotifications.ts +1 -1
  199. package/apps/shared/mail/usePermanentDelete.tsx +5 -3
  200. package/apps/shared/navigation/pageTitle.ts +1 -1
  201. package/apps/shared/notifications/NotificationCenter.tsx +1 -1
  202. package/apps/shared/notifications/NotificationHistoryDialog.tsx +2 -2
  203. package/apps/shared/notifications/apiErrors.ts +2 -2
  204. package/apps/shared/notifications/pushStatus.ts +1 -1
  205. package/apps/shared/notifications/systemErrors.ts +1 -1
  206. package/apps/shared/search/LocalIndexLifecycle.tsx +18 -12
  207. package/apps/shared/search/crossMailboxSearch.ts +3 -3
  208. package/apps/shared/search/localIndexBuilder.ts +24 -12
  209. package/apps/shared/search/localIndexKey.ts +1 -1
  210. package/apps/shared/search/localIndexRpcClient.ts +150 -30
  211. package/apps/shared/search/localIndexTransport.ts +84 -0
  212. package/apps/shared/search/localIndexWorker.ts +1 -1
  213. package/apps/shared/search/searchTier2.ts +3 -3
  214. package/apps/shared/signing/enrollmentTracker.ts +3 -3
  215. package/apps/shared/signing/enrollmentView.ts +1 -1
  216. package/apps/shared/signing/signingInfo.ts +1 -1
  217. package/apps/shared/signing/useSigningEnrollmentWatcher.ts +6 -4
  218. package/apps/shared/styles/app.css +14 -23
  219. package/apps/www/_layout.tsx +2 -2
  220. package/apps/www/calendar/index.tsx +20 -18
  221. package/apps/www/contacts/[uid].tsx +8 -6
  222. package/apps/www/contacts/index.tsx +19 -17
  223. package/apps/www/index.tsx +68 -48
  224. package/apps/www/messages/[uid].tsx +11 -9
  225. package/apps/www/settings/auto-reply/index.tsx +6 -4
  226. package/apps/www/settings/blocked-senders/index.tsx +9 -7
  227. package/apps/www/settings/encryption/index.tsx +38 -32
  228. package/apps/www/settings/filters/[uid].tsx +19 -14
  229. package/apps/www/settings/filters/_mailFilterRuleConfig.tsx +2 -2
  230. package/apps/www/settings/filters/index.tsx +4 -4
  231. package/apps/www/settings/filters/new/index.tsx +10 -8
  232. package/apps/www/settings/labels/index.tsx +12 -10
  233. package/apps/www/settings/privacy/index.tsx +18 -14
  234. package/apps/www/settings/profile/index.tsx +16 -11
  235. package/apps/www/settings/read-receipts/index.tsx +17 -12
  236. package/apps/www/settings/sharing/index.tsx +6 -6
  237. package/apps/www/settings/signatures/[uid].tsx +5 -5
  238. package/apps/www/settings/signatures/index.tsx +4 -4
  239. package/apps/www/settings/signatures/new/index.tsx +4 -4
  240. package/apps/www/settings/signatures/signatureDefaults.ts +1 -1
  241. package/apps/www/tasks/index.tsx +28 -23
  242. package/dist/apps/admin/_layout.d.ts +1 -1
  243. package/dist/apps/admin/_layout.js +1 -1
  244. package/dist/apps/admin/audit-log/index.d.ts +1 -1
  245. package/dist/apps/admin/audit-log/index.js +4 -4
  246. package/dist/apps/admin/branding/index.js +3 -3
  247. package/dist/apps/admin/data-requests/index.js +8 -8
  248. package/dist/apps/admin/distribution-lists/[uid].js +3 -3
  249. package/dist/apps/admin/distribution-lists/index.js +4 -4
  250. package/dist/apps/admin/distribution-lists/new/index.js +5 -5
  251. package/dist/apps/admin/domains/[uid].js +6 -6
  252. package/dist/apps/admin/domains/index.js +4 -4
  253. package/dist/apps/admin/domains/new/index.js +5 -5
  254. package/dist/apps/admin/encryption-policy/index.js +1 -1
  255. package/dist/apps/admin/escrow-scopes/[uid].d.ts +1 -1
  256. package/dist/apps/admin/escrow-scopes/[uid].js +7 -7
  257. package/dist/apps/admin/escrow-scopes/index.js +4 -4
  258. package/dist/apps/admin/escrow-scopes/new/index.js +5 -5
  259. package/dist/apps/admin/index.js +6 -6
  260. package/dist/apps/admin/ingest-queue/index.js +4 -4
  261. package/dist/apps/admin/mailbox-policy/index.js +1 -1
  262. package/dist/apps/admin/mailboxes/[uid].js +5 -5
  263. package/dist/apps/admin/quarantine/index.js +5 -5
  264. package/dist/apps/admin/retention-policy/index.js +3 -3
  265. package/dist/apps/admin/signing-certificates/index.js +5 -5
  266. package/dist/apps/admin/transport-rules/[uid].js +5 -5
  267. package/dist/apps/admin/transport-rules/_transportRuleConfig.d.ts +1 -1
  268. package/dist/apps/admin/transport-rules/_transportRuleConfig.js +2 -2
  269. package/dist/apps/admin/transport-rules/index.js +4 -4
  270. package/dist/apps/admin/transport-rules/new/index.js +5 -5
  271. package/dist/apps/escrow/_layout.d.ts +1 -1
  272. package/dist/apps/escrow/audit-log/index.d.ts +1 -1
  273. package/dist/apps/escrow/audit-log/index.js +4 -4
  274. package/dist/apps/escrow/index.js +4 -4
  275. package/dist/apps/escrow/matters/[uid].js +10 -10
  276. package/dist/apps/escrow/matters/new/index.js +6 -6
  277. package/dist/apps/shared/appearance/AppearanceForm.js +3 -3
  278. package/dist/apps/shared/appearance/AppearanceHead.js +1 -1
  279. package/dist/apps/shared/appearance/AppearanceProvider.d.ts +1 -1
  280. package/dist/apps/shared/appearance/AppearanceProvider.js +3 -3
  281. package/dist/apps/shared/appearance/appearanceCache.d.ts +1 -1
  282. package/dist/apps/shared/appearance/appearanceCache.js +1 -1
  283. package/dist/apps/shared/appearance/appearanceContext.d.ts +1 -1
  284. package/dist/apps/shared/appearance/theme.d.ts +1 -1
  285. package/dist/apps/shared/auth/adminAccess.js +1 -1
  286. package/dist/apps/shared/calendar/bookingPlugin.js +1 -1
  287. package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +1 -1
  288. package/dist/apps/shared/calendar/calendarReminders.d.ts +1 -1
  289. package/dist/apps/shared/calendar/useCalendarReminders.js +1 -1
  290. package/dist/apps/shared/components/admin/diagnostics/DiagnosticsManager.js +1 -1
  291. package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.d.ts +1 -1
  292. package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.js +2 -2
  293. package/dist/apps/shared/components/admin/diagnostics/LogsPanel.js +2 -2
  294. package/dist/apps/shared/components/admin/diagnostics/PackagesTable.js +1 -1
  295. package/dist/apps/shared/components/admin/diagnostics/RuntimePanel.js +1 -1
  296. package/dist/apps/shared/components/admin/diagnostics/SystemPanel.js +2 -2
  297. package/dist/apps/shared/components/admin/diagnostics/VersionsPanel.js +1 -1
  298. package/dist/apps/shared/components/admin/diagnostics/diagnosticsApi.js +1 -1
  299. package/dist/apps/shared/components/admin/diagnostics/format.js +1 -1
  300. package/dist/apps/shared/components/admin/diagnostics/logClient.js +1 -1
  301. package/dist/apps/shared/components/admin/distributionLists/MemberListCard.d.ts +1 -1
  302. package/dist/apps/shared/components/admin/distributionLists/MemberListCard.js +4 -4
  303. package/dist/apps/shared/components/admin/elevation.js +1 -1
  304. package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js +3 -3
  305. package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
  306. package/dist/apps/shared/components/admin/layout/AdminShell.js +7 -7
  307. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +1 -1
  308. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +6 -6
  309. package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.d.ts +1 -1
  310. package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.js +10 -8
  311. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +4 -4
  312. package/dist/apps/shared/components/admin/mailboxes/MailboxTable.d.ts +1 -1
  313. package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.d.ts +1 -1
  314. package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.js +7 -5
  315. package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.js +5 -5
  316. package/dist/apps/shared/components/admin/settings/BrandingForm.d.ts +1 -1
  317. package/dist/apps/shared/components/admin/settings/BrandingForm.js +5 -5
  318. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.d.ts +1 -1
  319. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +5 -5
  320. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.d.ts +1 -1
  321. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +4 -4
  322. package/dist/apps/shared/components/admin/settings/LoadedSettingsForm.js +2 -2
  323. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.d.ts +1 -1
  324. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +14 -12
  325. package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.d.ts +1 -1
  326. package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.js +4 -4
  327. package/dist/apps/shared/components/admin/settings/PluginsManager.js +5 -5
  328. package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.d.ts +1 -1
  329. package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.js +5 -5
  330. package/dist/apps/shared/components/admin/setup/EscrowSetupStep.js +7 -7
  331. package/dist/apps/shared/components/admin/setup/SetupWizard.d.ts +4 -4
  332. package/dist/apps/shared/components/admin/setup/SetupWizard.js +27 -23
  333. package/dist/apps/shared/components/admin/signOut.js +1 -1
  334. package/dist/apps/shared/components/admin/usePagedList.js +2 -2
  335. package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +3 -3
  336. package/dist/apps/shared/components/calendar/CalendarListSidebar.d.ts +1 -1
  337. package/dist/apps/shared/components/calendar/CalendarListSidebar.js +2 -2
  338. package/dist/apps/shared/components/calendar/DescriptionEditor.js +1 -1
  339. package/dist/apps/shared/components/calendar/EventDescriptionView.js +1 -1
  340. package/dist/apps/shared/components/calendar/EventDetails.d.ts +2 -2
  341. package/dist/apps/shared/components/calendar/EventDetails.js +16 -14
  342. package/dist/apps/shared/components/calendar/EventEditor.d.ts +2 -2
  343. package/dist/apps/shared/components/calendar/EventEditor.js +22 -20
  344. package/dist/apps/shared/components/calendar/EventExpandedForm.js +2 -2
  345. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +1 -1
  346. package/dist/apps/shared/components/calendar/EventFormParts.js +1 -1
  347. package/dist/apps/shared/components/calendar/EventModal.d.ts +2 -2
  348. package/dist/apps/shared/components/calendar/EventModal.js +3 -3
  349. package/dist/apps/shared/components/calendar/EventQuickForm.js +3 -3
  350. package/dist/apps/shared/components/calendar/EventShell.js +1 -1
  351. package/dist/apps/shared/components/calendar/FindATime.js +6 -4
  352. package/dist/apps/shared/components/calendar/GuestInput.d.ts +2 -2
  353. package/dist/apps/shared/components/calendar/MonthView.d.ts +1 -1
  354. package/dist/apps/shared/components/calendar/MonthView.js +1 -1
  355. package/dist/apps/shared/components/calendar/QuickCreateFaces.js +1 -1
  356. package/dist/apps/shared/components/calendar/QuickFaceFrame.js +1 -1
  357. package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +1 -1
  358. package/dist/apps/shared/components/calendar/RecurrenceEditor.js +1 -1
  359. package/dist/apps/shared/components/calendar/RequestChangeForm.js +8 -6
  360. package/dist/apps/shared/components/calendar/ResourcePicker.d.ts +1 -1
  361. package/dist/apps/shared/components/calendar/ResourcePicker.js +7 -5
  362. package/dist/apps/shared/components/calendar/SplitDayView.d.ts +1 -1
  363. package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +1 -1
  364. package/dist/apps/shared/components/calendar/TaskQuickForm.js +9 -7
  365. package/dist/apps/shared/components/calendar/TimeGridView.d.ts +1 -1
  366. package/dist/apps/shared/components/calendar/TimeGridView.js +2 -2
  367. package/dist/apps/shared/components/calendar/allDay.d.ts +2 -2
  368. package/dist/apps/shared/components/calendar/allDay.js +1 -1
  369. package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +2 -2
  370. package/dist/apps/shared/components/calendar/eventDialogFields.js +2 -2
  371. package/dist/apps/shared/components/calendar/eventForm.d.ts +3 -3
  372. package/dist/apps/shared/components/calendar/eventFormat.d.ts +1 -1
  373. package/dist/apps/shared/components/calendar/eventFormat.js +2 -2
  374. package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +1 -1
  375. package/dist/apps/shared/components/calendar/findTimeGrid.js +1 -1
  376. package/dist/apps/shared/components/calendar/layout/CalendarShell.d.ts +1 -1
  377. package/dist/apps/shared/components/calendar/layout/CalendarShell.js +11 -9
  378. package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +1 -1
  379. package/dist/apps/shared/components/contacts/ContactDetailPane.js +2 -2
  380. package/dist/apps/shared/components/contacts/ContactForm.d.ts +2 -2
  381. package/dist/apps/shared/components/contacts/ContactForm.js +12 -8
  382. package/dist/apps/shared/components/contacts/ContactsSidebar.d.ts +1 -1
  383. package/dist/apps/shared/components/contacts/ContactsSidebar.js +7 -5
  384. package/dist/apps/shared/components/contacts/KeyChangeReview.d.ts +1 -1
  385. package/dist/apps/shared/components/contacts/KeyChangeReview.js +5 -5
  386. package/dist/apps/shared/components/contacts/contactKeys.d.ts +2 -2
  387. package/dist/apps/shared/components/contacts/contactKeys.js +2 -2
  388. package/dist/apps/shared/components/contacts/layout/ContactsShell.d.ts +1 -1
  389. package/dist/apps/shared/components/contacts/layout/ContactsShell.js +9 -7
  390. package/dist/apps/shared/components/escrow/layout/EscrowShell.js +6 -6
  391. package/dist/apps/shared/components/forms/StringListField.js +1 -1
  392. package/dist/apps/shared/components/layout/AppShell.d.ts +2 -2
  393. package/dist/apps/shared/components/layout/AppShell.js +11 -9
  394. package/dist/apps/shared/components/layout/BrandingChrome.d.ts +1 -1
  395. package/dist/apps/shared/components/layout/KeyEnrollmentGate.d.ts +1 -1
  396. package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +9 -9
  397. package/dist/apps/shared/components/layout/MailboxProvisioning.js +8 -6
  398. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.d.ts +1 -1
  399. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.js +9 -9
  400. package/dist/apps/shared/components/layout/UnlockPromptProvider.d.ts +2 -2
  401. package/dist/apps/shared/components/layout/UnlockPromptProvider.js +5 -5
  402. package/dist/apps/shared/components/layout/UserMenu.js +6 -4
  403. package/dist/apps/shared/components/mail/ConversationList.d.ts +2 -2
  404. package/dist/apps/shared/components/mail/ConversationList.js +23 -8
  405. package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +3 -3
  406. package/dist/apps/shared/components/mail/ConversationThreadPane.js +19 -13
  407. package/dist/apps/shared/components/mail/InviteCard.js +10 -8
  408. package/dist/apps/shared/components/mail/LazyReadingPane.js +2 -2
  409. package/dist/apps/shared/components/mail/MailAddress.d.ts +1 -1
  410. package/dist/apps/shared/components/mail/MailAddress.js +1 -1
  411. package/dist/apps/shared/components/mail/MailListToolbar.d.ts +2 -2
  412. package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +2 -2
  413. package/dist/apps/shared/components/mail/MenuButton.js +1 -1
  414. package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +3 -3
  415. package/dist/apps/shared/components/mail/MessageDetailPane.js +61 -46
  416. package/dist/apps/shared/components/mail/MoveToFolderDialog.d.ts +1 -1
  417. package/dist/apps/shared/components/mail/MoveToFolderDialog.js +8 -6
  418. package/dist/apps/shared/components/mail/OutboxRowStatus.d.ts +1 -1
  419. package/dist/apps/shared/components/mail/PermanentDeleteDialog.js +2 -2
  420. package/dist/apps/shared/components/mail/compose/ComposeContext.d.ts +10 -1
  421. package/dist/apps/shared/components/mail/compose/ComposeContext.js +4 -2
  422. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +34 -30
  423. package/dist/apps/shared/components/mail/compose/ComposeWindowPlaceholder.js +4 -4
  424. package/dist/apps/shared/components/mail/compose/EmojiPicker.js +2 -2
  425. package/dist/apps/shared/components/mail/compose/GifPicker.js +3 -3
  426. package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +1 -1
  427. package/dist/apps/shared/components/mail/compose/RecipientInput.js +1 -1
  428. package/dist/apps/shared/components/mail/compose/ScheduleSendPicker.js +1 -1
  429. package/dist/apps/shared/components/mail/compose/encryptionRequirement.d.ts +2 -2
  430. package/dist/apps/shared/components/mail/compose/encryptionRequirement.js +1 -1
  431. package/dist/apps/shared/components/mail/compose/quotedBody.d.ts +3 -3
  432. package/dist/apps/shared/components/mail/compose/quotedBody.js +3 -3
  433. package/dist/apps/shared/components/mail/compose/recipients.d.ts +1 -1
  434. package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +3 -3
  435. package/dist/apps/shared/components/mail/invite/InviteRowChip.js +7 -9
  436. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +2 -2
  437. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +11 -9
  438. package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +1 -1
  439. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +1 -1
  440. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +1 -1
  441. package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +2 -2
  442. package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +9 -3
  443. package/dist/apps/shared/components/mail/invite/inviteStore.js +13 -6
  444. package/dist/apps/shared/components/mail/labelMenu.d.ts +1 -1
  445. package/dist/apps/shared/components/mail/labelMenu.js +9 -7
  446. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +1 -1
  447. package/dist/apps/shared/components/mail/layout/MailShell.js +3 -3
  448. package/dist/apps/shared/components/mail/listPreferences.d.ts +2 -2
  449. package/dist/apps/shared/components/mail/listPreferences.js +1 -1
  450. package/dist/apps/shared/components/mail/pinnedSigners.d.ts +12 -5
  451. package/dist/apps/shared/components/mail/pinnedSigners.js +37 -18
  452. package/dist/apps/shared/components/mail/reading/EncryptedBody.js +2 -2
  453. package/dist/apps/shared/components/mail/reading/MessageBody.d.ts +2 -2
  454. package/dist/apps/shared/components/mail/reading/MessageBody.js +4 -4
  455. package/dist/apps/shared/components/mail/reading/MessageCard.d.ts +1 -1
  456. package/dist/apps/shared/components/mail/reading/MessageCard.js +2 -2
  457. package/dist/apps/shared/components/mail/reading/MessageSourceDialog.js +3 -3
  458. package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +1 -1
  459. package/dist/apps/shared/components/mail/reading/bodyContent.d.ts +2 -2
  460. package/dist/apps/shared/components/mail/reading/bodyContent.js +2 -2
  461. package/dist/apps/shared/components/mail/reading/bodyHtml.js +1 -1
  462. package/dist/apps/shared/components/mail/reading/conversationPrint.d.ts +15 -0
  463. package/dist/apps/shared/components/mail/reading/conversationPrint.js +69 -0
  464. package/dist/apps/shared/components/mail/reading/messageExport.js +1 -1
  465. package/dist/apps/shared/components/mail/reading/printMessage.d.ts +9 -3
  466. package/dist/apps/shared/components/mail/reading/printMessage.js +33 -6
  467. package/dist/apps/shared/components/mail/reading/useMessageActions.d.ts +1 -1
  468. package/dist/apps/shared/components/mail/reading/useMessageActions.js +18 -16
  469. package/dist/apps/shared/components/mail/unreadStyle.d.ts +1 -1
  470. package/dist/apps/shared/components/mail/verificationSeals.d.ts +27 -6
  471. package/dist/apps/shared/components/mail/verificationSeals.js +15 -11
  472. package/dist/apps/shared/components/mail/writableMailboxes.d.ts +8 -3
  473. package/dist/apps/shared/components/mail/writableMailboxes.js +12 -6
  474. package/dist/apps/shared/components/rules/RuleBuilder.js +1 -1
  475. package/dist/apps/shared/components/settings/SigningCertificateCard.d.ts +1 -1
  476. package/dist/apps/shared/components/settings/SigningCertificateCard.js +3 -3
  477. package/dist/apps/shared/components/settings/layout/SettingsShell.d.ts +1 -1
  478. package/dist/apps/shared/components/settings/layout/SettingsShell.js +8 -6
  479. package/dist/apps/shared/components/sharing/PrincipalListField.d.ts +1 -1
  480. package/dist/apps/shared/components/sharing/PrincipalPicker.d.ts +1 -1
  481. package/dist/apps/shared/components/sharing/PrincipalPicker.js +1 -1
  482. package/dist/apps/shared/components/sharing/PrincipalResolver.d.ts +1 -1
  483. package/dist/apps/shared/components/sharing/PrincipalResolver.js +3 -3
  484. package/dist/apps/shared/components/tasks/TasksSidebar.d.ts +1 -1
  485. package/dist/apps/shared/components/tasks/TasksSidebar.js +7 -5
  486. package/dist/apps/shared/components/tasks/layout/TasksShell.d.ts +1 -1
  487. package/dist/apps/shared/components/tasks/layout/TasksShell.js +9 -7
  488. package/dist/apps/shared/keyboard/ShortcutsDialog.js +1 -1
  489. package/dist/apps/shared/keyboard/keymap.d.ts +6 -0
  490. package/dist/apps/shared/keyboard/keymap.js +1 -0
  491. package/dist/apps/shared/mail/decryptedMessages.d.ts +27 -0
  492. package/dist/apps/shared/mail/decryptedMessages.js +97 -0
  493. package/dist/apps/shared/mail/findWellKnownFolderUid.d.ts +5 -3
  494. package/dist/apps/shared/mail/findWellKnownFolderUid.js +5 -4
  495. package/dist/apps/shared/mail/folderCounts.d.ts +1 -1
  496. package/dist/apps/shared/mail/folderCounts.js +6 -4
  497. package/dist/apps/shared/mail/folderOfType.d.ts +3 -2
  498. package/dist/apps/shared/mail/folderOfType.js +4 -4
  499. package/dist/apps/shared/mail/folderTree.d.ts +1 -1
  500. package/dist/apps/shared/mail/listSnapshots.d.ts +2 -2
  501. package/dist/apps/shared/mail/messageReadState.d.ts +4 -3
  502. package/dist/apps/shared/mail/messageReadState.js +5 -5
  503. package/dist/apps/shared/mail/newMailNotifications.d.ts +1 -1
  504. package/dist/apps/shared/mail/newMailNotifications.js +1 -1
  505. package/dist/apps/shared/mail/outbox/composeBridge.d.ts +2 -2
  506. package/dist/apps/shared/mail/outbox/outboxState.d.ts +1 -1
  507. package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +2 -2
  508. package/dist/apps/shared/mail/outbox/sendDecision.d.ts +2 -2
  509. package/dist/apps/shared/mail/outbox/sendDecision.js +1 -1
  510. package/dist/apps/shared/mail/outbox/sendJob.d.ts +10 -6
  511. package/dist/apps/shared/mail/outbox/sendJob.js +39 -35
  512. package/dist/apps/shared/mail/outbox/sendOutcomes.d.ts +6 -3
  513. package/dist/apps/shared/mail/outbox/sendOutcomes.js +19 -15
  514. package/dist/apps/shared/mail/outbox/useOutboxStatus.js +5 -3
  515. package/dist/apps/shared/mail/permanentDelete.d.ts +4 -3
  516. package/dist/apps/shared/mail/permanentDelete.js +8 -8
  517. package/dist/apps/shared/mail/primaryMailbox.d.ts +1 -1
  518. package/dist/apps/shared/mail/primaryMailbox.js +1 -1
  519. package/dist/apps/shared/mail/reportNotices.d.ts +1 -1
  520. package/dist/apps/shared/mail/senderBlocking.d.ts +5 -4
  521. package/dist/apps/shared/mail/senderBlocking.js +19 -16
  522. package/dist/apps/shared/mail/useMailConnection.d.ts +1 -1
  523. package/dist/apps/shared/mail/useMailConnection.js +12 -10
  524. package/dist/apps/shared/mail/useMailLiveUpdates.d.ts +2 -2
  525. package/dist/apps/shared/mail/useMailLiveUpdates.js +2 -2
  526. package/dist/apps/shared/mail/useMailboxUpdateAccess.d.ts +3 -2
  527. package/dist/apps/shared/mail/useMailboxUpdateAccess.js +31 -10
  528. package/dist/apps/shared/mail/useMarkMessageRead.d.ts +1 -1
  529. package/dist/apps/shared/mail/useMarkMessageRead.js +5 -3
  530. package/dist/apps/shared/mail/useNewMailNotifications.d.ts +1 -1
  531. package/dist/apps/shared/mail/usePermanentDelete.d.ts +1 -1
  532. package/dist/apps/shared/mail/usePermanentDelete.js +4 -2
  533. package/dist/apps/shared/navigation/pageTitle.d.ts +1 -1
  534. package/dist/apps/shared/notifications/NotificationCenter.js +1 -1
  535. package/dist/apps/shared/notifications/NotificationHistoryDialog.js +2 -2
  536. package/dist/apps/shared/notifications/apiErrors.js +2 -2
  537. package/dist/apps/shared/notifications/pushStatus.js +1 -1
  538. package/dist/apps/shared/notifications/systemErrors.js +1 -1
  539. package/dist/apps/shared/search/LocalIndexLifecycle.d.ts +2 -2
  540. package/dist/apps/shared/search/LocalIndexLifecycle.js +15 -10
  541. package/dist/apps/shared/search/crossMailboxSearch.d.ts +1 -1
  542. package/dist/apps/shared/search/crossMailboxSearch.js +2 -2
  543. package/dist/apps/shared/search/localIndexBuilder.d.ts +4 -3
  544. package/dist/apps/shared/search/localIndexBuilder.js +15 -12
  545. package/dist/apps/shared/search/localIndexKey.js +1 -1
  546. package/dist/apps/shared/search/localIndexRpcClient.d.ts +43 -31
  547. package/dist/apps/shared/search/localIndexRpcClient.js +113 -20
  548. package/dist/apps/shared/search/localIndexTransport.d.ts +77 -0
  549. package/dist/apps/shared/search/localIndexTransport.js +1 -0
  550. package/dist/apps/shared/search/localIndexWorker.d.ts +1 -1
  551. package/dist/apps/shared/search/searchTier2.d.ts +3 -3
  552. package/dist/apps/shared/signing/enrollmentTracker.d.ts +1 -1
  553. package/dist/apps/shared/signing/enrollmentTracker.js +3 -3
  554. package/dist/apps/shared/signing/enrollmentView.d.ts +1 -1
  555. package/dist/apps/shared/signing/signingInfo.d.ts +1 -1
  556. package/dist/apps/shared/signing/signingInfo.js +1 -1
  557. package/dist/apps/shared/signing/useSigningEnrollmentWatcher.d.ts +1 -1
  558. package/dist/apps/shared/signing/useSigningEnrollmentWatcher.js +5 -3
  559. package/dist/apps/shared/styles/app.css +14 -23
  560. package/dist/apps/www/_layout.d.ts +1 -1
  561. package/dist/apps/www/_layout.js +1 -1
  562. package/dist/apps/www/calendar/index.d.ts +1 -1
  563. package/dist/apps/www/calendar/index.js +20 -18
  564. package/dist/apps/www/contacts/[uid].d.ts +1 -1
  565. package/dist/apps/www/contacts/[uid].js +8 -6
  566. package/dist/apps/www/contacts/index.d.ts +1 -1
  567. package/dist/apps/www/contacts/index.js +19 -17
  568. package/dist/apps/www/index.d.ts +1 -1
  569. package/dist/apps/www/index.js +64 -50
  570. package/dist/apps/www/messages/[uid].d.ts +1 -1
  571. package/dist/apps/www/messages/[uid].js +11 -9
  572. package/dist/apps/www/settings/appearance/index.d.ts +1 -1
  573. package/dist/apps/www/settings/auto-reply/index.d.ts +1 -1
  574. package/dist/apps/www/settings/auto-reply/index.js +6 -4
  575. package/dist/apps/www/settings/blocked-senders/index.d.ts +1 -1
  576. package/dist/apps/www/settings/blocked-senders/index.js +6 -4
  577. package/dist/apps/www/settings/encryption/index.d.ts +1 -1
  578. package/dist/apps/www/settings/encryption/index.js +31 -29
  579. package/dist/apps/www/settings/filters/[uid].d.ts +1 -1
  580. package/dist/apps/www/settings/filters/[uid].js +11 -9
  581. package/dist/apps/www/settings/filters/_mailFilterRuleConfig.d.ts +2 -2
  582. package/dist/apps/www/settings/filters/index.d.ts +1 -1
  583. package/dist/apps/www/settings/filters/index.js +4 -4
  584. package/dist/apps/www/settings/filters/new/index.d.ts +1 -1
  585. package/dist/apps/www/settings/filters/new/index.js +10 -8
  586. package/dist/apps/www/settings/labels/index.d.ts +1 -1
  587. package/dist/apps/www/settings/labels/index.js +12 -10
  588. package/dist/apps/www/settings/privacy/index.d.ts +1 -1
  589. package/dist/apps/www/settings/privacy/index.js +18 -14
  590. package/dist/apps/www/settings/profile/index.d.ts +1 -1
  591. package/dist/apps/www/settings/profile/index.js +7 -5
  592. package/dist/apps/www/settings/read-receipts/index.d.ts +1 -1
  593. package/dist/apps/www/settings/read-receipts/index.js +5 -3
  594. package/dist/apps/www/settings/sharing/index.d.ts +1 -1
  595. package/dist/apps/www/settings/sharing/index.js +6 -6
  596. package/dist/apps/www/settings/signatures/[uid].d.ts +1 -1
  597. package/dist/apps/www/settings/signatures/[uid].js +5 -5
  598. package/dist/apps/www/settings/signatures/index.d.ts +1 -1
  599. package/dist/apps/www/settings/signatures/index.js +4 -4
  600. package/dist/apps/www/settings/signatures/new/index.d.ts +1 -1
  601. package/dist/apps/www/settings/signatures/new/index.js +4 -4
  602. package/dist/apps/www/settings/signatures/signatureDefaults.d.ts +1 -1
  603. package/dist/apps/www/settings/signatures/signatureDefaults.js +1 -1
  604. package/dist/apps/www/tasks/index.d.ts +1 -1
  605. package/dist/apps/www/tasks/index.js +17 -15
  606. package/dist/lib/admin/auditLogApi.d.ts +32 -0
  607. package/dist/lib/admin/auditLogApi.js +27 -0
  608. package/dist/lib/admin/distributionListsApi.d.ts +47 -0
  609. package/dist/lib/admin/distributionListsApi.js +34 -0
  610. package/dist/lib/admin/domainsApi.d.ts +75 -0
  611. package/dist/lib/admin/domainsApi.js +44 -0
  612. package/dist/lib/admin/escrowAccessRequestsApi.d.ts +79 -0
  613. package/dist/lib/admin/escrowAccessRequestsApi.js +46 -0
  614. package/dist/lib/admin/escrowAuditLogApi.d.ts +66 -0
  615. package/dist/lib/admin/escrowAuditLogApi.js +31 -0
  616. package/dist/lib/admin/escrowScopesApi.d.ts +78 -0
  617. package/dist/lib/admin/escrowScopesApi.js +50 -0
  618. package/dist/lib/admin/leftoverMailboxApi.d.ts +73 -0
  619. package/dist/lib/admin/leftoverMailboxApi.js +67 -0
  620. package/dist/lib/admin/mailboxPolicyApi.d.ts +27 -0
  621. package/dist/lib/admin/mailboxPolicyApi.js +21 -0
  622. package/dist/lib/admin/matterExportApi.d.ts +40 -0
  623. package/dist/lib/admin/matterExportApi.js +39 -0
  624. package/dist/lib/admin/matterSearchApi.d.ts +20 -0
  625. package/dist/lib/admin/matterSearchApi.js +27 -0
  626. package/dist/lib/admin/mattersApi.d.ts +56 -0
  627. package/dist/lib/admin/mattersApi.js +40 -0
  628. package/dist/lib/admin/pluginsApi.d.ts +265 -0
  629. package/dist/lib/admin/pluginsApi.js +102 -0
  630. package/dist/lib/admin/retentionPolicyApi.d.ts +32 -0
  631. package/dist/lib/admin/retentionPolicyApi.js +29 -0
  632. package/dist/lib/admin/setupApi.d.ts +23 -0
  633. package/dist/lib/admin/setupApi.js +26 -0
  634. package/dist/lib/admin/transportRulesApi.d.ts +66 -0
  635. package/dist/lib/admin/transportRulesApi.js +43 -0
  636. package/dist/lib/appearance/preferencesApi.d.ts +128 -0
  637. package/dist/lib/appearance/preferencesApi.js +257 -0
  638. package/dist/lib/auth/profileApi.d.ts +33 -0
  639. package/dist/lib/auth/profileApi.js +52 -0
  640. package/dist/lib/auth/session.d.ts +70 -0
  641. package/dist/lib/auth/session.js +210 -0
  642. package/dist/lib/branding/brandingApi.d.ts +47 -0
  643. package/dist/lib/branding/brandingApi.js +61 -0
  644. package/dist/lib/branding/useBranding.d.ts +23 -0
  645. package/dist/lib/branding/useBranding.js +65 -0
  646. package/dist/lib/calendar/calendarApi.d.ts +230 -0
  647. package/dist/lib/calendar/calendarApi.js +106 -0
  648. package/dist/lib/calendar/calendarColors.d.ts +18 -0
  649. package/dist/lib/calendar/calendarColors.js +39 -0
  650. package/dist/lib/calendar/calendarDragIds.d.ts +42 -0
  651. package/dist/lib/calendar/calendarDragIds.js +92 -0
  652. package/dist/lib/calendar/calendarMutations.d.ts +68 -0
  653. package/dist/lib/calendar/calendarMutations.js +190 -0
  654. package/dist/lib/calendar/eventDescription.d.ts +43 -0
  655. package/dist/lib/calendar/eventDescription.js +195 -0
  656. package/dist/lib/calendar/freeBusyApi.d.ts +100 -0
  657. package/dist/lib/calendar/freeBusyApi.js +119 -0
  658. package/dist/lib/calendar/inviteApi.d.ts +121 -0
  659. package/dist/lib/calendar/inviteApi.js +54 -0
  660. package/dist/lib/calendar/recurrence.d.ts +60 -0
  661. package/dist/lib/calendar/recurrence.js +225 -0
  662. package/dist/lib/components/avatar/ContactAvatar.d.ts +8 -0
  663. package/dist/lib/components/avatar/ContactAvatar.js +26 -0
  664. package/dist/lib/components/buttons/Button.d.ts +9 -0
  665. package/dist/lib/components/buttons/Button.js +14 -0
  666. package/dist/lib/components/buttons/CopyButton.d.ts +18 -0
  667. package/dist/lib/components/buttons/CopyButton.js +14 -0
  668. package/dist/lib/components/feedback/Alert.d.ts +4 -0
  669. package/dist/lib/components/feedback/Alert.js +4 -0
  670. package/dist/lib/components/feedback/Skeleton.d.ts +21 -0
  671. package/dist/lib/components/feedback/Skeleton.js +14 -0
  672. package/dist/lib/components/forms/FormField.d.ts +8 -0
  673. package/dist/lib/components/forms/FormField.js +5 -0
  674. package/dist/lib/components/navigation/BottomTabBar.d.ts +27 -0
  675. package/dist/lib/components/navigation/BottomTabBar.js +32 -0
  676. package/dist/lib/components/overlays/Drawer.d.ts +20 -0
  677. package/dist/lib/components/overlays/Drawer.js +27 -0
  678. package/dist/lib/components/overlays/Modal.d.ts +17 -0
  679. package/dist/lib/components/overlays/Modal.js +25 -0
  680. package/dist/lib/components/overlays/PopoverPortal.d.ts +23 -0
  681. package/dist/lib/components/overlays/PopoverPortal.js +53 -0
  682. package/dist/lib/components/overlays/overlayStack.d.ts +31 -0
  683. package/dist/lib/components/overlays/overlayStack.js +143 -0
  684. package/dist/lib/components/pickers/MiniDatePicker.d.ts +13 -0
  685. package/dist/lib/components/pickers/MiniDatePicker.js +42 -0
  686. package/dist/lib/contacts/contactsApi.d.ts +174 -0
  687. package/dist/lib/contacts/contactsApi.js +139 -0
  688. package/dist/lib/contacts/vcard.d.ts +23 -0
  689. package/dist/lib/contacts/vcard.js +179 -0
  690. package/dist/lib/crypto/composeSecurity.d.ts +67 -0
  691. package/dist/lib/crypto/composeSecurity.js +93 -0
  692. package/dist/lib/crypto/encoding.d.ts +9 -0
  693. package/dist/lib/crypto/encoding.js +32 -0
  694. package/dist/lib/crypto/escrowKeys.d.ts +25 -0
  695. package/dist/lib/crypto/escrowKeys.js +59 -0
  696. package/dist/lib/crypto/idleTimeout.d.ts +16 -0
  697. package/dist/lib/crypto/idleTimeout.js +47 -0
  698. package/dist/lib/crypto/keySession.d.ts +159 -0
  699. package/dist/lib/crypto/keySession.js +367 -0
  700. package/dist/lib/crypto/keys.d.ts +50 -0
  701. package/dist/lib/crypto/keys.js +89 -0
  702. package/dist/lib/crypto/keyvaultApi.d.ts +394 -0
  703. package/dist/lib/crypto/keyvaultApi.js +350 -0
  704. package/dist/lib/crypto/masterKey.d.ts +59 -0
  705. package/dist/lib/crypto/masterKey.js +104 -0
  706. package/dist/lib/crypto/masterKeyWraps.d.ts +108 -0
  707. package/dist/lib/crypto/masterKeyWraps.js +228 -0
  708. package/dist/lib/crypto/messageSecurity.d.ts +248 -0
  709. package/dist/lib/crypto/messageSecurity.js +367 -0
  710. package/dist/lib/crypto/mime.d.ts +143 -0
  711. package/dist/lib/crypto/mime.js +504 -0
  712. package/dist/lib/crypto/passkeyUnlock.d.ts +20 -0
  713. package/dist/lib/crypto/passkeyUnlock.js +79 -0
  714. package/dist/lib/crypto/passwordUnlock.d.ts +39 -0
  715. package/dist/lib/crypto/passwordUnlock.js +73 -0
  716. package/dist/lib/crypto/recoveryCode.d.ts +28 -0
  717. package/dist/lib/crypto/recoveryCode.js +86 -0
  718. package/dist/lib/crypto/signingProviderApi.d.ts +95 -0
  719. package/dist/lib/crypto/signingProviderApi.js +60 -0
  720. package/dist/lib/crypto/smime.d.ts +128 -0
  721. package/dist/lib/crypto/smime.js +402 -0
  722. package/dist/lib/crypto/smimeMessage.d.ts +132 -0
  723. package/dist/lib/crypto/smimeMessage.js +341 -0
  724. package/dist/lib/crypto/useIdleKeyTimeout.d.ts +10 -0
  725. package/dist/lib/crypto/useIdleKeyTimeout.js +163 -0
  726. package/dist/lib/crypto/verificationSeal.d.ts +56 -0
  727. package/dist/lib/crypto/verificationSeal.js +220 -0
  728. package/dist/lib/mail/compose/composeQuoting.d.ts +88 -0
  729. package/dist/lib/mail/compose/composeQuoting.js +204 -0
  730. package/dist/lib/mail/compose/emojiData.d.ts +9 -0
  731. package/dist/lib/mail/compose/emojiData.js +18 -0
  732. package/dist/lib/mail/compose/giphyApi.d.ts +17 -0
  733. package/dist/lib/mail/compose/giphyApi.js +20 -0
  734. package/dist/lib/mail/conversationsApi.d.ts +80 -0
  735. package/dist/lib/mail/conversationsApi.js +44 -0
  736. package/dist/lib/mail/dataExportApi.d.ts +50 -0
  737. package/dist/lib/mail/dataExportApi.js +40 -0
  738. package/dist/lib/mail/directoryApi.d.ts +49 -0
  739. package/dist/lib/mail/directoryApi.js +101 -0
  740. package/dist/lib/mail/erasureRequestApi.d.ts +45 -0
  741. package/dist/lib/mail/erasureRequestApi.js +43 -0
  742. package/dist/lib/mail/flaggedMessages.d.ts +22 -0
  743. package/dist/lib/mail/flaggedMessages.js +73 -0
  744. package/dist/lib/mail/focusedInboxOverridesApi.d.ts +37 -0
  745. package/dist/lib/mail/focusedInboxOverridesApi.js +34 -0
  746. package/dist/lib/mail/labelsApi.d.ts +47 -0
  747. package/dist/lib/mail/labelsApi.js +38 -0
  748. package/dist/lib/mail/mailAddress.d.ts +27 -0
  749. package/dist/lib/mail/mailAddress.js +54 -0
  750. package/dist/lib/mail/mailApi.d.ts +850 -0
  751. package/dist/lib/mail/mailApi.js +602 -0
  752. package/dist/lib/mail/mailDetailHooks.d.ts +10 -0
  753. package/dist/lib/mail/mailDetailHooks.js +53 -0
  754. package/dist/lib/mail/mailFilterRulesApi.d.ts +76 -0
  755. package/dist/lib/mail/mailFilterRulesApi.js +45 -0
  756. package/dist/lib/mail/mailSignaturesApi.d.ts +49 -0
  757. package/dist/lib/mail/mailSignaturesApi.js +42 -0
  758. package/dist/lib/mail/mailboxAccessApi.d.ts +74 -0
  759. package/dist/lib/mail/mailboxAccessApi.js +56 -0
  760. package/dist/lib/mail/mailboxImportApi.d.ts +53 -0
  761. package/dist/lib/mail/mailboxImportApi.js +51 -0
  762. package/dist/lib/mail/messageBodySanitizer.d.ts +16 -0
  763. package/dist/lib/mail/messageBodySanitizer.js +118 -0
  764. package/dist/lib/mail/pushClient.d.ts +106 -0
  765. package/dist/lib/mail/pushClient.js +317 -0
  766. package/dist/lib/mail/sendEvents.d.ts +33 -0
  767. package/dist/lib/mail/sendEvents.js +44 -0
  768. package/dist/lib/mail/sendFailure.d.ts +16 -0
  769. package/dist/lib/mail/sendFailure.js +86 -0
  770. package/dist/lib/mail/senderListsApi.d.ts +69 -0
  771. package/dist/lib/mail/senderListsApi.js +126 -0
  772. package/dist/lib/search/queryGrammar.d.ts +51 -0
  773. package/dist/lib/search/queryGrammar.js +111 -0
  774. package/dist/lib/search/searchApi.d.ts +100 -0
  775. package/dist/lib/search/searchApi.js +107 -0
  776. package/dist/lib/search/searchScoring.d.ts +34 -0
  777. package/dist/lib/search/searchScoring.js +44 -0
  778. package/dist/lib/search/searchTier3.d.ts +64 -0
  779. package/dist/lib/search/searchTier3.js +335 -0
  780. package/dist/lib/tasks/tasksApi.d.ts +85 -0
  781. package/dist/lib/tasks/tasksApi.js +55 -0
  782. package/dist/lib/util/api.d.ts +160 -0
  783. package/dist/lib/util/api.js +251 -0
  784. package/dist/lib/util/apiClientContext.d.ts +7 -0
  785. package/dist/lib/util/apiClientContext.js +32 -0
  786. package/dist/lib/util/apiQuery.d.ts +32 -0
  787. package/dist/lib/util/apiQuery.js +42 -0
  788. package/dist/lib/util/clipboard.d.ts +7 -0
  789. package/dist/lib/util/clipboard.js +56 -0
  790. package/dist/lib/util/dateInput.d.ts +6 -0
  791. package/dist/lib/util/dateInput.js +14 -0
  792. package/dist/lib/util/timeZone.d.ts +12 -0
  793. package/dist/lib/util/timeZone.js +32 -0
  794. package/dist/lib/util/useCopyToClipboard.d.ts +12 -0
  795. package/dist/lib/util/useCopyToClipboard.js +34 -0
  796. package/dist/lib/util/useIsMobile.d.ts +10 -0
  797. package/dist/lib/util/useIsMobile.js +29 -0
  798. package/dist/lib/videoconf/videoMeetingsApi.d.ts +116 -0
  799. package/dist/lib/videoconf/videoMeetingsApi.js +49 -0
  800. package/lib/admin/auditLogApi.ts +48 -0
  801. package/lib/admin/distributionListsApi.ts +77 -0
  802. package/lib/admin/domainsApi.ts +113 -0
  803. package/lib/admin/escrowAccessRequestsApi.ts +110 -0
  804. package/lib/admin/escrowAuditLogApi.ts +101 -0
  805. package/lib/admin/escrowScopesApi.ts +112 -0
  806. package/lib/admin/leftoverMailboxApi.ts +120 -0
  807. package/lib/admin/mailboxPolicyApi.ts +38 -0
  808. package/lib/admin/matterExportApi.ts +62 -0
  809. package/lib/admin/matterSearchApi.ts +35 -0
  810. package/lib/admin/mattersApi.ts +86 -0
  811. package/lib/admin/pluginsApi.ts +339 -0
  812. package/lib/admin/retentionPolicyApi.ts +46 -0
  813. package/lib/admin/setupApi.ts +40 -0
  814. package/lib/admin/transportRulesApi.ts +106 -0
  815. package/lib/appearance/preferencesApi.ts +335 -0
  816. package/lib/auth/profileApi.ts +77 -0
  817. package/lib/auth/session.ts +238 -0
  818. package/lib/branding/brandingApi.ts +97 -0
  819. package/lib/branding/useBranding.ts +81 -0
  820. package/lib/calendar/calendarApi.ts +309 -0
  821. package/lib/calendar/calendarColors.ts +45 -0
  822. package/lib/calendar/calendarDragIds.ts +112 -0
  823. package/lib/calendar/calendarMutations.ts +236 -0
  824. package/lib/calendar/eventDescription.ts +211 -0
  825. package/lib/calendar/freeBusyApi.ts +197 -0
  826. package/lib/calendar/inviteApi.ts +154 -0
  827. package/lib/calendar/recurrence.ts +285 -0
  828. package/lib/components/avatar/ContactAvatar.tsx +47 -0
  829. package/lib/components/buttons/Button.tsx +40 -0
  830. package/lib/components/buttons/CopyButton.tsx +45 -0
  831. package/lib/components/feedback/Alert.tsx +13 -0
  832. package/lib/components/feedback/Skeleton.tsx +38 -0
  833. package/lib/components/forms/FormField.tsx +23 -0
  834. package/lib/components/navigation/BottomTabBar.tsx +66 -0
  835. package/lib/components/overlays/Drawer.tsx +72 -0
  836. package/lib/components/overlays/Modal.tsx +64 -0
  837. package/lib/components/overlays/PopoverPortal.tsx +74 -0
  838. package/lib/components/overlays/overlayStack.ts +165 -0
  839. package/lib/components/pickers/MiniDatePicker.tsx +90 -0
  840. package/lib/contacts/contactsApi.ts +289 -0
  841. package/lib/contacts/vcard.ts +197 -0
  842. package/lib/crypto/composeSecurity.ts +140 -0
  843. package/lib/crypto/encoding.ts +36 -0
  844. package/lib/crypto/escrowKeys.ts +74 -0
  845. package/lib/crypto/idleTimeout.ts +49 -0
  846. package/lib/crypto/keySession.ts +483 -0
  847. package/lib/crypto/keys.ts +105 -0
  848. package/lib/crypto/keyvaultApi.ts +674 -0
  849. package/lib/crypto/masterKey.ts +134 -0
  850. package/lib/crypto/masterKeyWraps.ts +269 -0
  851. package/lib/crypto/messageSecurity.ts +600 -0
  852. package/lib/crypto/mime.ts +568 -0
  853. package/lib/crypto/passkeyUnlock.ts +103 -0
  854. package/lib/crypto/passwordUnlock.ts +98 -0
  855. package/lib/crypto/recoveryCode.ts +93 -0
  856. package/lib/crypto/signingProviderApi.ts +135 -0
  857. package/lib/crypto/smime.ts +459 -0
  858. package/lib/crypto/smimeMessage.ts +491 -0
  859. package/lib/crypto/useIdleKeyTimeout.ts +176 -0
  860. package/lib/crypto/verificationSeal.ts +288 -0
  861. package/lib/mail/compose/composeQuoting.ts +243 -0
  862. package/lib/mail/compose/emojiData.ts +34 -0
  863. package/lib/mail/compose/giphyApi.ts +31 -0
  864. package/lib/mail/conversationsApi.ts +123 -0
  865. package/lib/mail/dataExportApi.ts +73 -0
  866. package/lib/mail/directoryApi.ts +161 -0
  867. package/lib/mail/erasureRequestApi.ts +71 -0
  868. package/lib/mail/flaggedMessages.ts +80 -0
  869. package/lib/mail/focusedInboxOverridesApi.ts +64 -0
  870. package/lib/mail/labelsApi.ts +71 -0
  871. package/lib/mail/mailAddress.ts +76 -0
  872. package/lib/mail/mailApi.ts +1286 -0
  873. package/lib/mail/mailDetailHooks.ts +57 -0
  874. package/lib/mail/mailFilterRulesApi.ts +116 -0
  875. package/lib/mail/mailSignaturesApi.ts +84 -0
  876. package/lib/mail/mailboxAccessApi.ts +106 -0
  877. package/lib/mail/mailboxImportApi.ts +87 -0
  878. package/lib/mail/messageBodySanitizer.ts +129 -0
  879. package/lib/mail/pushClient.ts +375 -0
  880. package/lib/mail/sendEvents.ts +72 -0
  881. package/lib/mail/sendFailure.ts +98 -0
  882. package/lib/mail/senderListsApi.ts +161 -0
  883. package/lib/search/queryGrammar.ts +179 -0
  884. package/lib/search/searchApi.ts +199 -0
  885. package/lib/search/searchScoring.ts +46 -0
  886. package/lib/search/searchTier3.ts +406 -0
  887. package/lib/tasks/tasksApi.ts +128 -0
  888. package/lib/util/api.ts +318 -0
  889. package/lib/util/apiClientContext.ts +35 -0
  890. package/lib/util/apiQuery.ts +61 -0
  891. package/lib/util/clipboard.ts +55 -0
  892. package/lib/util/dateInput.ts +15 -0
  893. package/lib/util/timeZone.ts +33 -0
  894. package/lib/util/useCopyToClipboard.ts +48 -0
  895. package/lib/util/useIsMobile.ts +34 -0
  896. package/lib/videoconf/videoMeetingsApi.ts +144 -0
  897. package/package.json +10 -4
@@ -0,0 +1,504 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * A small, dependency-free MIME (RFC 5322 / RFC 2045-2047) parser used by `smimeMessage.ts` and
7
+ * `messageSecurity.ts` to read *received* messages - which, unlike this package's own output, can come
8
+ * from any foreign MUA/MTA. It deliberately covers exactly what S/MIME evaluation needs and nothing more:
9
+ *
10
+ * header unfolding (RFC 5322 §2.2.3) and CRLF-or-bare-LF line endings; case-insensitive RFC 2045
11
+ * `type/subtype; name=value` parameters, quoted or unquoted; RFC 2046 multipart splitting with
12
+ * preamble/epilogue, transport padding after the delimiter, and delimiters only recognized at the start
13
+ * of a line; `Content-Transfer-Encoding` decoding (base64, quoted-printable; 7bit/8bit/binary pass
14
+ * through) plus `charset` decoding via `TextDecoder`; and picking the displayable body (text/html
15
+ * preferred, text/plain otherwise) out of a nested multipart.
16
+ *
17
+ * **Binary strings.** Received message source is handled as a "binary string": one UTF-16 code unit per
18
+ * byte (0x00-0xFF), which is what `mailApi.ts`'s `getMessageRawContent()` returns (it reads the response
19
+ * as bytes and decodes them as Latin-1) and what decrypted CMS content is converted to. That keeps an
20
+ * 8bit body's bytes intact until its own `charset` is known, and keeps signed bytes verifiable exactly.
21
+ * A string containing any code unit above 0xFF can't be a binary string, so it is treated as already
22
+ * decoded text and UTF-8 encoded wherever bytes are needed (the pre-round-4 convention) - see
23
+ * `binaryStringToBytes()`.
24
+ *
25
+ * Not supported (documented, not silently wrong): RFC 2231 parameter continuations/charset-encoded
26
+ * parameters - not needed to classify, decrypt, or verify a message, and left verbatim. RFC 2047
27
+ * encoded-words are decoded only where text is shown to a user (`decodeHeaderText()`); raw header values
28
+ * (`MimeEntity.headers`) stay verbatim so header comparisons remain exact.
29
+ */
30
+ /** Maximum multipart nesting `extractDisplayBody()` descends into - a hostile message can nest
31
+ * arbitrarily deep, and nothing legitimate needs more than a handful of levels. */
32
+ const MAX_MULTIPART_DEPTH = 8;
33
+ /** Splits a MIME entity into its header fields and body. Never throws. */
34
+ export function parseMimeEntity(entity) {
35
+ let rawHeaderBlock;
36
+ let body;
37
+ const leading = /^\r?\n/.exec(entity);
38
+ if (leading) {
39
+ // An entity whose very first line is blank has no headers at all (RFC 2046 §5.1.1 - a body part
40
+ // with no header fields defaults to text/plain; charset=us-ascii).
41
+ rawHeaderBlock = "";
42
+ body = entity.slice(leading[0].length);
43
+ }
44
+ else {
45
+ const separator = /\r?\n\r?\n/.exec(entity);
46
+ rawHeaderBlock = separator ? entity.slice(0, separator.index) : entity;
47
+ body = separator ? entity.slice(separator.index + separator[0].length) : "";
48
+ }
49
+ const fields = [];
50
+ const headers = {};
51
+ const unfolded = rawHeaderBlock.replace(/\r?\n(?=[ \t])/g, "");
52
+ for (const line of unfolded.split(/\r?\n/)) {
53
+ const colonIndex = line.indexOf(":");
54
+ if (colonIndex <= 0) {
55
+ continue;
56
+ }
57
+ const name = line.slice(0, colonIndex).trim();
58
+ const value = line.slice(colonIndex + 1).trim();
59
+ fields.push({ name, value });
60
+ const key = name.toLowerCase();
61
+ if (!(key in headers)) {
62
+ headers[key] = value;
63
+ }
64
+ }
65
+ return { fields, headers, rawHeaderBlock, body };
66
+ }
67
+ /** Parses an RFC 2045 parameterized header value (`Content-Type`, `Content-Disposition`). */
68
+ export function parseParameterizedHeader(headerValue) {
69
+ const segments = [];
70
+ let current = "";
71
+ let inQuotes = false;
72
+ const input = headerValue ?? "";
73
+ for (let i = 0; i < input.length; i++) {
74
+ const ch = input[i];
75
+ if (inQuotes && ch === "\\" && i + 1 < input.length) {
76
+ current += input[++i];
77
+ }
78
+ else if (ch === '"') {
79
+ inQuotes = !inQuotes;
80
+ }
81
+ else if (ch === ";" && !inQuotes) {
82
+ segments.push(current);
83
+ current = "";
84
+ }
85
+ else {
86
+ current += ch;
87
+ }
88
+ }
89
+ segments.push(current);
90
+ const [main, ...rest] = segments;
91
+ const params = {};
92
+ for (const segment of rest) {
93
+ const eq = segment.indexOf("=");
94
+ const name = segment.slice(0, Math.max(eq, 0)).trim().toLowerCase();
95
+ if (name && !(name in params)) {
96
+ params[name] = segment.slice(eq + 1).trim();
97
+ }
98
+ }
99
+ return { value: main.trim().toLowerCase(), params };
100
+ }
101
+ function escapeRegExp(value) {
102
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
103
+ }
104
+ /**
105
+ * Splits a multipart body on `boundary` per RFC 2046 §5.1.1: a delimiter is `--boundary` at the start of
106
+ * a line (optionally followed by transport-padding whitespace), the CRLF preceding it belongs to the
107
+ * delimiter (not the previous part), text before the first delimiter is preamble and text after the close
108
+ * delimiter (`--boundary--`) is epilogue - both discarded. Each returned part is the exact text between
109
+ * delimiter lines, which is what a `multipart/signed` signature covers.
110
+ */
111
+ export function splitMultipart(body, boundary) {
112
+ const delimiter = new RegExp(`(?:^|\\r?\\n)--${escapeRegExp(boundary)}(--)?[ \\t]*(?=\\r?\\n|$)`, "g");
113
+ const parts = [];
114
+ let partStart = -1;
115
+ let match;
116
+ while ((match = delimiter.exec(body)) !== null) {
117
+ if (partStart !== -1) {
118
+ parts.push(body.slice(partStart, Math.max(partStart, match.index)));
119
+ }
120
+ if (match[1]) {
121
+ return parts;
122
+ }
123
+ const end = match.index + match[0].length;
124
+ partStart = end + (body.startsWith("\r\n", end) ? 2 : body.startsWith("\n", end) ? 1 : 0);
125
+ }
126
+ // No close delimiter (a truncated message): whatever follows the last delimiter is still a part.
127
+ if (partStart !== -1) {
128
+ parts.push(body.slice(partStart));
129
+ }
130
+ return parts;
131
+ }
132
+ /** Returns the lowercased, trimmed `Content-Transfer-Encoding` mechanism, or `undefined`. */
133
+ function transferEncodingOf(entity) {
134
+ return entity.headers["content-transfer-encoding"]?.trim().toLowerCase();
135
+ }
136
+ /** Decodes a base64 body into bytes, ignoring whitespace/line breaks. Returns `undefined` for invalid
137
+ * base64 rather than throwing. */
138
+ export function decodeBase64Text(text) {
139
+ try {
140
+ const binary = atob(text.replace(/\s+/g, ""));
141
+ const bytes = new Uint8Array(binary.length);
142
+ for (let i = 0; i < binary.length; i++) {
143
+ bytes[i] = binary.charCodeAt(i);
144
+ }
145
+ return bytes;
146
+ }
147
+ catch {
148
+ return undefined;
149
+ }
150
+ }
151
+ /** `true` when every code unit of `value` is at most 0xFF - i.e. it can be a binary string (see this
152
+ * module's doc comment). */
153
+ export function isBinaryString(value) {
154
+ for (let i = 0; i < value.length; i++) {
155
+ if (value.charCodeAt(i) > 0xff) {
156
+ return false;
157
+ }
158
+ }
159
+ return true;
160
+ }
161
+ /** Converts a binary string to its bytes, or - for a string that can't be one (a code unit above 0xFF) -
162
+ * to its UTF-8 encoding. */
163
+ export function binaryStringToBytes(value) {
164
+ if (!isBinaryString(value)) {
165
+ return new TextEncoder().encode(value);
166
+ }
167
+ const bytes = new Uint8Array(value.length);
168
+ for (let i = 0; i < value.length; i++) {
169
+ bytes[i] = value.charCodeAt(i);
170
+ }
171
+ return bytes;
172
+ }
173
+ /** Converts bytes to a binary string (one code unit per byte), in chunks so a large message never exceeds
174
+ * the engine's argument-count limit. */
175
+ export function bytesToBinaryString(bytes) {
176
+ const CHUNK = 0x8000;
177
+ const pieces = [];
178
+ for (let i = 0; i < bytes.length; i += CHUNK) {
179
+ pieces.push(String.fromCharCode(...bytes.subarray(i, i + CHUNK)));
180
+ }
181
+ return pieces.join("");
182
+ }
183
+ function hexValue(code) {
184
+ if (code >= 0x30 && code <= 0x39)
185
+ return code - 0x30;
186
+ if (code >= 0x41 && code <= 0x46)
187
+ return code - 0x37;
188
+ if (code >= 0x61 && code <= 0x66)
189
+ return code - 0x57;
190
+ return -1;
191
+ }
192
+ /** Decodes a quoted-printable body (RFC 2045 §6.7) into bytes, in one linear pass into a preallocated
193
+ * buffer. Literal text between escapes (which can't legally be non-ASCII in QP, but is after an
194
+ * 8-bit-unsafe gateway) is written run by run, decided once for the whole input: as the runs' own bytes
195
+ * when the input is a binary string, else as their UTF-8 encoding (so an already-decoded `é` next to an
196
+ * emoji isn't written as a lone 0xE9 byte). A run always ends at an ASCII `=`, so a surrogate pair is never
197
+ * split. */
198
+ export function decodeQuotedPrintable(text) {
199
+ const input = text.replace(/=[ \t]*\r?\n/g, "");
200
+ const binary = isBinaryString(input);
201
+ // At most 3 UTF-8 bytes per UTF-16 code unit, which only a non-binary string can need.
202
+ const out = new Uint8Array(binary ? input.length : input.length * 3);
203
+ const encoder = new TextEncoder();
204
+ let length = 0;
205
+ let runStart = 0;
206
+ const flushRun = (end) => {
207
+ if (binary) {
208
+ for (let j = runStart; j < end; j++) {
209
+ out[length++] = input.charCodeAt(j);
210
+ }
211
+ }
212
+ else {
213
+ length += encoder.encodeInto(input.slice(runStart, end), out.subarray(length)).written;
214
+ }
215
+ };
216
+ for (let i = 0; i + 2 < input.length; i++) {
217
+ if (input.charCodeAt(i) !== 0x3d) {
218
+ continue;
219
+ }
220
+ const high = hexValue(input.charCodeAt(i + 1));
221
+ const low = hexValue(input.charCodeAt(i + 2));
222
+ if (high < 0 || low < 0) {
223
+ continue;
224
+ }
225
+ flushRun(i);
226
+ out[length++] = (high << 4) | low;
227
+ i += 2;
228
+ runStart = i + 1;
229
+ }
230
+ flushRun(input.length);
231
+ return out.slice(0, length);
232
+ }
233
+ /** Decodes `bytes` in `charset` (UTF-8 when absent or unknown). With `fallbackText`, a decode that hits
234
+ * invalid input returns `fallbackText` instead of replacement characters. */
235
+ function decodeCharset(bytes, charset, fallbackText) {
236
+ const options = { fatal: fallbackText !== undefined };
237
+ let decoder;
238
+ try {
239
+ decoder = new TextDecoder(charset || "utf-8", options);
240
+ }
241
+ catch {
242
+ // An unknown/unsupported charset label - UTF-8 is the least-bad fallback (a superset of ASCII).
243
+ decoder = new TextDecoder("utf-8", options);
244
+ }
245
+ try {
246
+ return decoder.decode(bytes);
247
+ }
248
+ catch {
249
+ return fallbackText;
250
+ }
251
+ }
252
+ /** Decodes an entity's body into bytes per its `Content-Transfer-Encoding`. 7bit/8bit/binary (or no
253
+ * header) return the body's own bytes (see `binaryStringToBytes()`). Returns `undefined` only for invalid
254
+ * base64. */
255
+ export function decodeBodyBytes(entity) {
256
+ const cte = transferEncodingOf(entity);
257
+ if (cte === "base64") {
258
+ return decodeBase64Text(entity.body);
259
+ }
260
+ if (cte === "quoted-printable") {
261
+ return decodeQuotedPrintable(entity.body);
262
+ }
263
+ return binaryStringToBytes(entity.body);
264
+ }
265
+ /** Decodes an entity's body to text: transfer encoding first, then its `charset` parameter (UTF-8 when
266
+ * absent). A 7bit/8bit/binary body that isn't a binary string was already decoded by whoever produced the
267
+ * string and passes through unchanged; so does a binary-string body whose bytes are invalid in its charset
268
+ * (e.g. legacy already-decoded Latin-1 text under a UTF-8 charset). */
269
+ export function decodeBodyText(entity) {
270
+ const cte = transferEncodingOf(entity);
271
+ const charset = parseParameterizedHeader(entity.headers["content-type"]).params["charset"];
272
+ if (cte !== "base64" && cte !== "quoted-printable") {
273
+ return isBinaryString(entity.body) ? decodeCharset(binaryStringToBytes(entity.body), charset, entity.body) : entity.body;
274
+ }
275
+ return decodeCharset(decodeBodyBytes(entity) ?? new Uint8Array(), charset);
276
+ }
277
+ const ENCODED_WORD = /=\?([^?\s]+)\?([bBqQ])\?([^?\s]*)\?=/g;
278
+ const WHITESPACE_BETWEEN_ENCODED_WORDS = /(=\?[^?\s]+\?[bBqQ]\?[^?\s]*\?=)\s+(?==\?[^?\s]+\?[bBqQ]\?[^?\s]*\?=)/g;
279
+ /**
280
+ * Turns a raw header value into display text: a binary string holding valid UTF-8 (a raw 8-bit header,
281
+ * RFC 6532) is decoded as UTF-8, then RFC 2047 encoded-words (`=?charset?B|Q?text?=`) are decoded, with
282
+ * whitespace between adjacent encoded-words dropped (RFC 2047 §6.2). An encoded-word with an unknown
283
+ * charset or undecodable content is left verbatim.
284
+ */
285
+ export function decodeHeaderText(value) {
286
+ let text = value;
287
+ if (isBinaryString(text) && /[\x80-\xff]/.test(text)) {
288
+ text = decodeCharset(binaryStringToBytes(text), "utf-8", text);
289
+ }
290
+ return text.replace(WHITESPACE_BETWEEN_ENCODED_WORDS, "$1").replace(ENCODED_WORD, (word, charset, encoding, encoded) => {
291
+ const bytes = encoding.toUpperCase() === "B"
292
+ ? decodeBase64Text(encoded)
293
+ : binaryStringToBytes(encoded.replace(/_/g, " ").replace(/=([0-9A-Fa-f]{2})/g, (_match, hex) => String.fromCharCode(parseInt(hex, 16))));
294
+ if (!bytes) {
295
+ return word;
296
+ }
297
+ try {
298
+ // RFC 2231 §5 allows a language suffix on the charset: `charset*lang`.
299
+ return new TextDecoder(charset.split("*")[0], { fatal: true }).decode(bytes);
300
+ }
301
+ catch {
302
+ return word;
303
+ }
304
+ });
305
+ }
306
+ /** Anything outside printable ASCII (space through `~`) and tab - such header text needs RFC 2047 encoding. */
307
+ const NEEDS_ENCODING = /[^\x20-\x7e\t]/;
308
+ /** Characters that must never reach a serialized header value: CR/LF (header injection) and NUL. */
309
+ const HEADER_BREAKING = /[\r\n\0]+/g;
310
+ /** Encodes `text` as RFC 2047 `B` encoded-words (UTF-8), each at most 75 characters, never splitting a
311
+ * multi-byte character between words, joined by folding whitespace. */
312
+ function encodeWords(text) {
313
+ // "=?UTF-8?B?" + "?=" is 12 characters, leaving 63 for base64 - i.e. at most 45 source bytes.
314
+ const MAX_BYTES_PER_WORD = 45;
315
+ const encoder = new TextEncoder();
316
+ const words = [];
317
+ let current = "";
318
+ let currentBytes = 0;
319
+ for (const ch of text) {
320
+ const size = encoder.encode(ch).length;
321
+ if (currentBytes + size > MAX_BYTES_PER_WORD && current) {
322
+ words.push(current);
323
+ current = "";
324
+ currentBytes = 0;
325
+ }
326
+ current += ch;
327
+ currentBytes += size;
328
+ }
329
+ words.push(current);
330
+ return words.map((word) => `=?UTF-8?B?${btoa(bytesToBinaryString(encoder.encode(word)))}?=`).join("\r\n ");
331
+ }
332
+ /** Makes an unstructured header value (e.g. `Subject`) safe to serialize: CR/LF/NUL become a space
333
+ * (never a header break), and a value containing non-ASCII is RFC 2047-encoded. */
334
+ export function encodeUnstructuredHeaderValue(value) {
335
+ const flattened = value.replace(HEADER_BREAKING, " ");
336
+ return NEEDS_ENCODING.test(flattened) ? encodeWords(flattened) : flattened;
337
+ }
338
+ /** Encodes one mailbox (`Name <addr>` or a bare addr-spec) - see `encodeAddressListHeaderValue()`. */
339
+ function encodeMailbox(mailbox) {
340
+ const angle = mailbox.lastIndexOf("<");
341
+ if (angle === -1) {
342
+ // A bare addr-spec (possibly internationalized) stays verbatim; stray non-ASCII text that
343
+ // isn't an address at all is encoded rather than written raw.
344
+ const bare = mailbox.trim();
345
+ return bare.includes("@") || !NEEDS_ENCODING.test(bare) ? bare : encodeWords(bare);
346
+ }
347
+ const rawName = mailbox.slice(0, angle).trim();
348
+ const address = mailbox.slice(angle).trim();
349
+ const name = encodePhrase(rawName);
350
+ return name ? `${name} ${address}` : address;
351
+ }
352
+ /** Encodes a display-name phrase (a mailbox's name or a group's label): unquoted and RFC 2047-encoded when
353
+ * it holds non-ASCII, else kept exactly as written. */
354
+ function encodePhrase(rawPhrase) {
355
+ const phrase = rawPhrase.trim();
356
+ const unquoted = /^".*"$/.test(phrase) ? phrase.slice(1, -1).replace(/\\(.)/g, "$1") : phrase;
357
+ return NEEDS_ENCODING.test(unquoted) ? encodeWords(unquoted) : phrase;
358
+ }
359
+ /**
360
+ * Makes an address-list header value (`From`/`To`/`Cc`) safe to serialize: CR/LF/NUL become a space, and
361
+ * each mailbox's non-ASCII display name (`Zoë <z@example.com>`, quoted or not) is RFC 2047-encoded while
362
+ * its addr-spec is kept verbatim (an internationalized address is left to SMTPUTF8, never encoded -
363
+ * RFC 2047 §5 forbids encoded-words in an addr-spec). RFC 5322 group syntax (`Équipe: Zoë <z@x>, b@x;`)
364
+ * keeps its `:` and `;`, with the group label encoded as a phrase of its own. A top-level `:` only opens
365
+ * a group when a `;` follows it, so a stray colon in an unquoted display name isn't mistaken for one.
366
+ */
367
+ export function encodeAddressListHeaderValue(value) {
368
+ const flattened = value.replace(HEADER_BREAKING, " ");
369
+ if (!NEEDS_ENCODING.test(flattened)) {
370
+ return flattened;
371
+ }
372
+ let out = "";
373
+ let current = "";
374
+ let inQuotes = false;
375
+ let inAngle = false;
376
+ let inGroup = false;
377
+ const emit = (encoded, delimiter) => {
378
+ out += (encoded && /[,:;]$/.test(out) ? " " : "") + encoded + delimiter;
379
+ current = "";
380
+ };
381
+ for (let i = 0; i < flattened.length; i++) {
382
+ const ch = flattened[i];
383
+ if (inQuotes && ch === "\\" && i + 1 < flattened.length) {
384
+ current += ch + flattened[++i];
385
+ continue;
386
+ }
387
+ if (ch === '"') {
388
+ inQuotes = !inQuotes;
389
+ }
390
+ else if (!inQuotes && ch === "<") {
391
+ inAngle = true;
392
+ }
393
+ else if (!inQuotes && ch === ">") {
394
+ inAngle = false;
395
+ }
396
+ else if (!inQuotes && !inAngle) {
397
+ if (ch === ",") {
398
+ emit(encodeMailbox(current), ",");
399
+ continue;
400
+ }
401
+ if (ch === ":" && !inGroup && flattened.includes(";", i)) {
402
+ emit(encodePhrase(current), ":");
403
+ inGroup = true;
404
+ continue;
405
+ }
406
+ if (ch === ";" && inGroup) {
407
+ emit(encodeMailbox(current), ";");
408
+ inGroup = false;
409
+ continue;
410
+ }
411
+ }
412
+ current += ch;
413
+ }
414
+ emit(encodeMailbox(current), "");
415
+ return out;
416
+ }
417
+ function isAttachment(entity) {
418
+ return parseParameterizedHeader(entity.headers["content-disposition"]).value === "attachment";
419
+ }
420
+ /** Picks the displayable body out of an entity: a `text/html` part is preferred over `text/plain`, and a
421
+ * multipart entity is searched (non-attachment children only, bounded depth). Entities with no
422
+ * Content-Type default to text/plain per RFC 2045 §5.2. */
423
+ export function extractDisplayBody(entity, depth = 0) {
424
+ const contentType = parseParameterizedHeader(entity.headers["content-type"] ?? "text/plain");
425
+ if (contentType.value === "text/html") {
426
+ return { html: decodeBodyText(entity) };
427
+ }
428
+ if (contentType.value === "text/plain") {
429
+ return { text: decodeBodyText(entity) };
430
+ }
431
+ const boundary = contentType.params["boundary"];
432
+ if (!contentType.value.startsWith("multipart/") || !boundary || depth >= MAX_MULTIPART_DEPTH) {
433
+ return {};
434
+ }
435
+ let text;
436
+ for (const part of splitMultipart(entity.body, boundary)) {
437
+ const child = parseMimeEntity(part);
438
+ if (isAttachment(child)) {
439
+ continue;
440
+ }
441
+ const found = extractDisplayBody(child, depth + 1);
442
+ if (found.html !== undefined) {
443
+ return { html: found.html };
444
+ }
445
+ text ?? (text = found.text);
446
+ }
447
+ return text === undefined ? {} : { text };
448
+ }
449
+ /**
450
+ * Lists the attachments inside `entity` (descending into multipart children, bounded depth): every leaf part
451
+ * with `Content-Disposition: attachment`, a filename, or a non-text type. The `text/plain`/`text/html` parts a
452
+ * reader would display (no disposition, no filename) are not attachments. Nested `message/rfc822` content is
453
+ * reported as one attachment, never expanded.
454
+ */
455
+ export function extractAttachments(entity, depth = 0) {
456
+ const contentType = parseParameterizedHeader(entity.headers["content-type"] ?? "text/plain");
457
+ const disposition = parseParameterizedHeader(entity.headers["content-disposition"]);
458
+ const boundary = contentType.params["boundary"];
459
+ if (contentType.value.startsWith("multipart/")) {
460
+ if (!boundary || depth >= MAX_MULTIPART_DEPTH) {
461
+ return [];
462
+ }
463
+ return splitMultipart(entity.body, boundary).flatMap((part) => extractAttachments(parseMimeEntity(part), depth + 1));
464
+ }
465
+ const rawFilename = disposition.params["filename"] ?? contentType.params["name"];
466
+ const isAttachmentDisposition = disposition.value === "attachment";
467
+ if (!isAttachmentDisposition && rawFilename === undefined && contentType.value.startsWith("text/")) {
468
+ return [];
469
+ }
470
+ const contentId = entity.headers["content-id"]?.trim().replace(/^<(.*)>$/, "$1");
471
+ return [
472
+ {
473
+ ...(rawFilename !== undefined ? { filename: decodeHeaderText(rawFilename) } : {}),
474
+ contentType: contentType.value,
475
+ disposition: isAttachmentDisposition ? "attachment" : "inline",
476
+ ...(contentId ? { contentId } : {}),
477
+ decode: () => decodeBodyBytes(entity),
478
+ },
479
+ ];
480
+ }
481
+ /** HTML-escapes plain text and wraps it in a whitespace-preserving `<pre>`, so a `text/plain` body can be
482
+ * rendered through the same HTML path without ever being interpreted as markup. */
483
+ export function plainTextToHtml(text) {
484
+ const escaped = text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
485
+ return `<pre style="white-space: pre-wrap; word-wrap: break-word; font-family: inherit">${escaped}</pre>`;
486
+ }
487
+ /** Extracts the bare, lowercased addr-specs from an address-list header value (`"Name" <a@b>, c@d`).
488
+ * Handles quoted display names containing commas/angle brackets and RFC 5322 comments. */
489
+ export function extractAddresses(headerValue) {
490
+ if (!headerValue) {
491
+ return [];
492
+ }
493
+ const withoutQuoted = headerValue.replace(/"(?:[^"\\]|\\.)*"/g, '""').replace(/\((?:[^()\\]|\\.)*\)/g, "");
494
+ const addresses = [];
495
+ for (const item of withoutQuoted.split(",")) {
496
+ const angle = /<([^>]*)>/.exec(item);
497
+ // A bare addr-spec may carry RFC 5322 group syntax around it (`Team: a@b, c@d;`).
498
+ const address = (angle ? angle[1] : item.replace(/^[^:]*:/, "").replace(/;\s*$/, "")).trim().toLowerCase();
499
+ if (address.includes("@")) {
500
+ addresses.push(address);
501
+ }
502
+ }
503
+ return addresses;
504
+ }
@@ -0,0 +1,20 @@
1
+ export interface PasskeyRegistration {
2
+ /** Base64url-encoded credential ID — stored as `MasterKeyWrap.methodId`. */
3
+ credentialId: string;
4
+ /** Whether this authenticator reported PRF support at registration time. A `false`/absent value here
5
+ * does not necessarily mean PRF evaluation will fail later on some platforms (some only report
6
+ * support upon first `get()`), but MUST be treated as "unknown/unlikely," not "yes." */
7
+ prfSupported: boolean;
8
+ }
9
+ /**
10
+ * Registers a new platform/roaming passkey for use purely as a local unlock method (see this module's
11
+ * doc comment for why no server round-trip is involved). `rpId` MUST be this deployment's own domain.
12
+ */
13
+ export declare function registerPasskeyForUnlock(rpId: string, userId: Uint8Array, userName: string): Promise<PasskeyRegistration>;
14
+ /**
15
+ * Evaluates the PRF extension for an already-registered passkey and HKDF-derives a wrapping key from the
16
+ * result. Throws if the authenticator doesn't return a PRF output (e.g. it doesn't support the
17
+ * extension) — callers MUST treat that as "this unlock method is unavailable here," not silently fall
18
+ * back to a weaker derivation.
19
+ */
20
+ export declare function deriveFromPasskey(rpId: string, credentialId: string, salt: Uint8Array): Promise<Uint8Array>;
@@ -0,0 +1,79 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * The "passkey" unlock method from `specs/end-to-end_encryption.md`'s "Master Key Wrapping": uses the
7
+ * WebAuthn **PRF extension** to obtain a stable per-credential secret, then HKDF-derives a wrapping key
8
+ * from it — `wrap_passkey_N = AEAD(HKDF(WebAuthn-PRF(credential_N, salt)), MK)`. The credential's own
9
+ * private key is non-extractable and never used directly; only the PRF extension's derived secret is.
10
+ *
11
+ * This deliberately talks to the raw `navigator.credentials` WebAuthn API rather than
12
+ * `@simplewebauthn/browser` — that library's `startRegistration`/`startAuthentication` helpers expect a
13
+ * server-generated `optionsJSON` (from `@simplewebauthn/server`'s `generateRegistrationOptions()`/
14
+ * `generateAuthenticationOptions()`), which assumes a full relying-party ceremony with server-side
15
+ * challenge issuance and assertion verification. There is no such flow here — this passkey is never used
16
+ * to authenticate to `@rapidmx/restapi` or auth-server, only as a local, hardware-backed KDF input. A
17
+ * locally-generated challenge is fine because nothing server-side ever verifies this credential's
18
+ * attestation/assertion signature; only the PRF extension output is consumed. Identity/session auth
19
+ * remains entirely `auth-server`'s job (see `.claude/NOTES.md` in `server`).
20
+ *
21
+ * **Needs real hardware/browser verification.** PRF extension behavior (in particular, whether a
22
+ * browser returns `prf.results` on the *registration* ceremony itself vs. only on a subsequent
23
+ * `navigator.credentials.get()`) is not exercisable in this test environment (no real authenticator) —
24
+ * this module's tests mock `navigator.credentials` and cover this module's own request-building/
25
+ * response-parsing logic, not real authenticator behavior end to end. Verify against real hardware
26
+ * before shipping, the same honesty standard `@rapidmx/restapi` holds its own hard-to-verify pieces to
27
+ * (e.g. that repo's `sameIssuingCa()` doc comment).
28
+ */
29
+ import { fromBase64Url, toBase64Url } from "./encoding.js";
30
+ import { hkdfDerive } from "./masterKey.js";
31
+ const PRF_HKDF_INFO = "wrap";
32
+ const CHALLENGE_LENGTH_BYTES = 32;
33
+ /**
34
+ * Registers a new platform/roaming passkey for use purely as a local unlock method (see this module's
35
+ * doc comment for why no server round-trip is involved). `rpId` MUST be this deployment's own domain.
36
+ */
37
+ export async function registerPasskeyForUnlock(rpId, userId, userName) {
38
+ const challenge = crypto.getRandomValues(new Uint8Array(CHALLENGE_LENGTH_BYTES));
39
+ const credential = (await navigator.credentials.create({
40
+ publicKey: {
41
+ rp: { id: rpId, name: rpId },
42
+ user: { id: userId, name: userName, displayName: userName },
43
+ challenge: challenge,
44
+ // ES256 - matches this system's P-256 default elsewhere (see crypto/keys.ts).
45
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
46
+ authenticatorSelection: { residentKey: "preferred", userVerification: "required" },
47
+ extensions: { prf: {} },
48
+ },
49
+ }));
50
+ const results = credential.getClientExtensionResults();
51
+ return {
52
+ credentialId: toBase64Url(new Uint8Array(credential.rawId)),
53
+ prfSupported: !!results.prf?.enabled,
54
+ };
55
+ }
56
+ /**
57
+ * Evaluates the PRF extension for an already-registered passkey and HKDF-derives a wrapping key from the
58
+ * result. Throws if the authenticator doesn't return a PRF output (e.g. it doesn't support the
59
+ * extension) — callers MUST treat that as "this unlock method is unavailable here," not silently fall
60
+ * back to a weaker derivation.
61
+ */
62
+ export async function deriveFromPasskey(rpId, credentialId, salt) {
63
+ const challenge = crypto.getRandomValues(new Uint8Array(CHALLENGE_LENGTH_BYTES));
64
+ const assertion = (await navigator.credentials.get({
65
+ publicKey: {
66
+ rpId,
67
+ challenge: challenge,
68
+ allowCredentials: [{ id: fromBase64Url(credentialId), type: "public-key" }],
69
+ userVerification: "required",
70
+ extensions: { prf: { eval: { first: salt } } },
71
+ },
72
+ }));
73
+ const results = assertion.getClientExtensionResults();
74
+ const prfOutput = results.prf?.results?.first;
75
+ if (!prfOutput) {
76
+ throw new Error("This passkey did not return a PRF result - it may not support the PRF extension.");
77
+ }
78
+ return hkdfDerive(new Uint8Array(prfOutput), salt, PRF_HKDF_INFO);
79
+ }
@@ -0,0 +1,39 @@
1
+ export interface Argon2idParams {
2
+ /** Memory cost, in KiB. */
3
+ memorySize: number;
4
+ iterations: number;
5
+ parallelism: number;
6
+ }
7
+ /** Matches the `kdf` string format `MasterKeyWrap.kdf` documents (`argon2id:m=65536,t=3,p=4`) — OWASP's
8
+ * current recommended minimum for Argon2id (m=19MiB is the OWASP floor; this is deliberately higher,
9
+ * matching the doc comment on `EncryptionCertificateAuthority`'s own conservative defaults elsewhere in
10
+ * this system). */
11
+ export declare const DEFAULT_ARGON2ID_PARAMS: Argon2idParams;
12
+ /** Builds the `kdf` string stored alongside a password-method `MasterKeyWrap`, so parameters can be
13
+ * upgraded over time without breaking existing accounts (each wrap records the parameters it was
14
+ * actually created with). */
15
+ export declare function argon2idKdfLabel(params: Argon2idParams): string;
16
+ /** Inverse of `argon2idKdfLabel()` — reads back the exact parameters a `MasterKeyWrap.kdf` string was
17
+ * created with, so unlocking always re-derives with the *original* parameters even if
18
+ * `DEFAULT_ARGON2ID_PARAMS` has since changed (the spec's own "KDF parameters ... MUST be stored
19
+ * alongside each wrap, so costs can be raised over time without breaking existing accounts"). Returns
20
+ * `undefined` for anything that isn't a well-formed `argon2id:m=...,t=...,p=...` label — including a
21
+ * different KDF entirely (e.g. recovery codes' own `"hkdf-sha256"` label), which callers must not
22
+ * attempt to unlock as if it were password-derived.
23
+ */
24
+ export declare function parseArgon2idKdfLabel(label: string): Argon2idParams | undefined;
25
+ /** A fresh random salt for a new password enrollment. 16 bytes is Argon2id's own recommended minimum. */
26
+ export declare function generateSalt(lengthBytes?: number): Uint8Array;
27
+ export interface PasswordDerivation {
28
+ /** Base64-encoded. See this module's own doc comment — not yet sent anywhere, reserved for a future
29
+ * server-side verification endpoint. */
30
+ authProof: string;
31
+ /** Never leaves the device. Passed directly to `masterKey.ts`'s `sealWithKey`/`openWithKey`. */
32
+ wrappingKey: Uint8Array;
33
+ }
34
+ /**
35
+ * Runs Argon2id once against `password`/`salt`, then HKDF-splits the result into `authProof` and
36
+ * `wrappingKey` (see this module's doc comment for why two independent values, not one reused for both
37
+ * purposes). The plaintext password itself never leaves this function.
38
+ */
39
+ export declare function deriveFromPassword(password: string, salt: Uint8Array, params?: Argon2idParams): Promise<PasswordDerivation>;