@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.
- package/README.md +48 -14
- package/apps/admin/_layout.tsx +2 -2
- package/apps/admin/audit-log/index.tsx +4 -4
- package/apps/admin/branding/index.tsx +3 -3
- package/apps/admin/data-requests/index.tsx +8 -8
- package/apps/admin/distribution-lists/[uid].tsx +3 -3
- package/apps/admin/distribution-lists/index.tsx +4 -4
- package/apps/admin/distribution-lists/new/index.tsx +5 -5
- package/apps/admin/domains/[uid].tsx +6 -6
- package/apps/admin/domains/index.tsx +4 -4
- package/apps/admin/domains/new/index.tsx +5 -5
- package/apps/admin/encryption-policy/index.tsx +1 -1
- package/apps/admin/escrow-scopes/[uid].tsx +7 -7
- package/apps/admin/escrow-scopes/index.tsx +4 -4
- package/apps/admin/escrow-scopes/new/index.tsx +5 -5
- package/apps/admin/index.tsx +6 -6
- package/apps/admin/ingest-queue/index.tsx +4 -4
- package/apps/admin/mailbox-policy/index.tsx +1 -1
- package/apps/admin/mailboxes/[uid].tsx +5 -5
- package/apps/admin/quarantine/index.tsx +5 -5
- package/apps/admin/retention-policy/index.tsx +3 -3
- package/apps/admin/signing-certificates/index.tsx +5 -5
- package/apps/admin/transport-rules/[uid].tsx +5 -5
- package/apps/admin/transport-rules/_transportRuleConfig.tsx +3 -3
- package/apps/admin/transport-rules/index.tsx +4 -4
- package/apps/admin/transport-rules/new/index.tsx +5 -5
- package/apps/escrow/_layout.tsx +1 -1
- package/apps/escrow/audit-log/index.tsx +4 -4
- package/apps/escrow/index.tsx +4 -4
- package/apps/escrow/matters/[uid].tsx +10 -10
- package/apps/escrow/matters/new/index.tsx +6 -6
- package/apps/shared/appearance/AppearanceForm.tsx +3 -3
- package/apps/shared/appearance/AppearanceHead.tsx +1 -1
- package/apps/shared/appearance/AppearanceProvider.tsx +3 -3
- package/apps/shared/appearance/appearanceCache.ts +1 -1
- package/apps/shared/appearance/appearanceContext.ts +1 -1
- package/apps/shared/appearance/theme.ts +1 -1
- package/apps/shared/auth/adminAccess.ts +1 -1
- package/apps/shared/calendar/bookingPlugin.ts +1 -1
- package/apps/shared/calendar/calendarLiveUpdates.ts +1 -1
- package/apps/shared/calendar/calendarReminders.ts +1 -1
- package/apps/shared/calendar/useCalendarReminders.ts +1 -1
- package/apps/shared/components/admin/diagnostics/DiagnosticsManager.tsx +1 -1
- package/apps/shared/components/admin/diagnostics/InstalledPlugins.tsx +2 -2
- package/apps/shared/components/admin/diagnostics/LogsPanel.tsx +2 -2
- package/apps/shared/components/admin/diagnostics/PackagesTable.tsx +1 -1
- package/apps/shared/components/admin/diagnostics/RuntimePanel.tsx +1 -1
- package/apps/shared/components/admin/diagnostics/SystemPanel.tsx +2 -2
- package/apps/shared/components/admin/diagnostics/VersionsPanel.tsx +1 -1
- package/apps/shared/components/admin/diagnostics/diagnosticsApi.ts +1 -1
- package/apps/shared/components/admin/diagnostics/format.ts +1 -1
- package/apps/shared/components/admin/diagnostics/logClient.ts +1 -1
- package/apps/shared/components/admin/distributionLists/MemberListCard.tsx +4 -4
- package/apps/shared/components/admin/elevation.ts +1 -1
- package/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.tsx +3 -3
- package/apps/shared/components/admin/layout/AdminShell.tsx +8 -8
- package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +6 -6
- package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +10 -8
- package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +4 -4
- package/apps/shared/components/admin/mailboxes/MailboxTable.tsx +1 -1
- package/apps/shared/components/admin/mailboxes/ResourceSettingsCard.tsx +19 -14
- package/apps/shared/components/admin/mailboxes/ShareAccessCard.tsx +5 -5
- package/apps/shared/components/admin/settings/BrandingForm.tsx +5 -5
- package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +5 -5
- package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +4 -4
- package/apps/shared/components/admin/settings/LoadedSettingsForm.tsx +2 -2
- package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +32 -27
- package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +4 -4
- package/apps/shared/components/admin/settings/PluginsManager.tsx +5 -5
- package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +5 -5
- package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +7 -7
- package/apps/shared/components/admin/setup/SetupWizard.tsx +28 -24
- package/apps/shared/components/admin/signOut.ts +1 -1
- package/apps/shared/components/admin/usePagedList.tsx +2 -2
- package/apps/shared/components/calendar/AppointmentQuickForm.tsx +3 -3
- package/apps/shared/components/calendar/CalendarListSidebar.tsx +3 -3
- package/apps/shared/components/calendar/DescriptionEditor.tsx +1 -1
- package/apps/shared/components/calendar/EventDescriptionView.tsx +1 -1
- package/apps/shared/components/calendar/EventDetails.tsx +16 -14
- package/apps/shared/components/calendar/EventEditor.tsx +54 -39
- package/apps/shared/components/calendar/EventExpandedForm.tsx +3 -3
- package/apps/shared/components/calendar/EventFormParts.tsx +2 -2
- package/apps/shared/components/calendar/EventModal.tsx +5 -5
- package/apps/shared/components/calendar/EventQuickForm.tsx +3 -3
- package/apps/shared/components/calendar/EventShell.tsx +1 -1
- package/apps/shared/components/calendar/FindATime.tsx +6 -4
- package/apps/shared/components/calendar/GuestInput.tsx +2 -2
- package/apps/shared/components/calendar/MonthView.tsx +2 -2
- package/apps/shared/components/calendar/QuickCreateFaces.tsx +1 -1
- package/apps/shared/components/calendar/QuickFaceFrame.tsx +1 -1
- package/apps/shared/components/calendar/RecurrenceEditor.tsx +2 -2
- package/apps/shared/components/calendar/RequestChangeForm.tsx +8 -6
- package/apps/shared/components/calendar/ResourcePicker.tsx +7 -5
- package/apps/shared/components/calendar/SplitDayView.tsx +1 -1
- package/apps/shared/components/calendar/TaskQuickForm.tsx +23 -18
- package/apps/shared/components/calendar/TimeGridView.tsx +5 -3
- package/apps/shared/components/calendar/allDay.ts +2 -2
- package/apps/shared/components/calendar/eventDialogFields.ts +3 -3
- package/apps/shared/components/calendar/eventForm.ts +3 -3
- package/apps/shared/components/calendar/eventFormat.ts +3 -3
- package/apps/shared/components/calendar/findTimeGrid.ts +2 -2
- package/apps/shared/components/calendar/layout/CalendarShell.tsx +11 -9
- package/apps/shared/components/contacts/ContactDetailPane.tsx +4 -4
- package/apps/shared/components/contacts/ContactForm.tsx +27 -17
- package/apps/shared/components/contacts/ContactsSidebar.tsx +7 -5
- package/apps/shared/components/contacts/KeyChangeReview.tsx +5 -5
- package/apps/shared/components/contacts/contactKeys.ts +3 -3
- package/apps/shared/components/contacts/layout/ContactsShell.tsx +9 -7
- package/apps/shared/components/escrow/layout/EscrowShell.tsx +6 -6
- package/apps/shared/components/forms/StringListField.tsx +1 -1
- package/apps/shared/components/layout/AppShell.tsx +12 -10
- package/apps/shared/components/layout/BrandingChrome.tsx +1 -1
- package/apps/shared/components/layout/KeyEnrollmentGate.tsx +9 -9
- package/apps/shared/components/layout/MailboxProvisioning.tsx +8 -6
- package/apps/shared/components/layout/RecoveryCodeUnlock.tsx +9 -9
- package/apps/shared/components/layout/ThemeSwitch.tsx +1 -1
- package/apps/shared/components/layout/UnlockPromptProvider.tsx +6 -6
- package/apps/shared/components/layout/UserMenu.tsx +6 -4
- package/apps/shared/components/mail/ConversationList.tsx +25 -10
- package/apps/shared/components/mail/ConversationThreadPane.tsx +33 -17
- package/apps/shared/components/mail/InviteCard.tsx +11 -9
- package/apps/shared/components/mail/LazyReadingPane.tsx +2 -2
- package/apps/shared/components/mail/MailAddress.tsx +1 -1
- package/apps/shared/components/mail/MailListToolbar.tsx +2 -2
- package/apps/shared/components/mail/MailSelectionBar.tsx +2 -2
- package/apps/shared/components/mail/MenuButton.tsx +1 -1
- package/apps/shared/components/mail/MessageDetailPane.tsx +69 -48
- package/apps/shared/components/mail/MoveToFolderDialog.tsx +8 -6
- package/apps/shared/components/mail/OutboxRowStatus.tsx +1 -1
- package/apps/shared/components/mail/PermanentDeleteDialog.tsx +2 -2
- package/apps/shared/components/mail/compose/ComposeContext.tsx +14 -3
- package/apps/shared/components/mail/compose/ComposeWindow.tsx +34 -30
- package/apps/shared/components/mail/compose/ComposeWindowPlaceholder.tsx +4 -4
- package/apps/shared/components/mail/compose/EmojiPicker.tsx +2 -2
- package/apps/shared/components/mail/compose/GifPicker.tsx +3 -3
- package/apps/shared/components/mail/compose/RecipientInput.tsx +1 -1
- package/apps/shared/components/mail/compose/ScheduleSendPicker.tsx +1 -1
- package/apps/shared/components/mail/compose/encryptionRequirement.ts +2 -2
- package/apps/shared/components/mail/compose/quotedBody.ts +5 -5
- package/apps/shared/components/mail/compose/recipients.ts +1 -1
- package/apps/shared/components/mail/invite/InviteRowChip.tsx +10 -14
- package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +11 -9
- package/apps/shared/components/mail/invite/InviteTimeline.tsx +1 -1
- package/apps/shared/components/mail/invite/ProposeTimeForm.tsx +2 -2
- package/apps/shared/components/mail/invite/inviteFormat.ts +2 -2
- package/apps/shared/components/mail/invite/inviteStore.ts +14 -6
- package/apps/shared/components/mail/labelMenu.tsx +9 -7
- package/apps/shared/components/mail/layout/MailShell.tsx +4 -4
- package/apps/shared/components/mail/listPreferences.ts +2 -2
- package/apps/shared/components/mail/pinnedSigners.ts +45 -19
- package/apps/shared/components/mail/reading/EncryptedBody.tsx +2 -2
- package/apps/shared/components/mail/reading/MessageBody.tsx +6 -6
- package/apps/shared/components/mail/reading/MessageCard.tsx +3 -3
- package/apps/shared/components/mail/reading/MessageSourceDialog.tsx +3 -3
- package/apps/shared/components/mail/reading/PendingMessageCard.tsx +1 -1
- package/apps/shared/components/mail/reading/bodyContent.ts +3 -3
- package/apps/shared/components/mail/reading/bodyHtml.ts +1 -1
- package/apps/shared/components/mail/reading/conversationPrint.ts +76 -0
- package/apps/shared/components/mail/reading/messageExport.ts +1 -1
- package/apps/shared/components/mail/reading/printMessage.ts +46 -9
- package/apps/shared/components/mail/reading/useMessageActions.ts +28 -21
- package/apps/shared/components/mail/unreadStyle.tsx +1 -1
- package/apps/shared/components/mail/verificationSeals.ts +16 -12
- package/apps/shared/components/mail/writableMailboxes.ts +14 -7
- package/apps/shared/components/rules/RuleBuilder.tsx +1 -1
- package/apps/shared/components/settings/SigningCertificateCard.tsx +4 -4
- package/apps/shared/components/settings/layout/SettingsShell.tsx +8 -6
- package/apps/shared/components/sharing/PrincipalListField.tsx +1 -1
- package/apps/shared/components/sharing/PrincipalPicker.tsx +1 -1
- package/apps/shared/components/sharing/PrincipalResolver.tsx +4 -4
- package/apps/shared/components/tasks/TasksSidebar.tsx +7 -5
- package/apps/shared/components/tasks/layout/TasksShell.tsx +9 -7
- package/apps/shared/keyboard/ShortcutsDialog.tsx +1 -1
- package/apps/shared/keyboard/keymap.ts +1 -0
- package/apps/shared/mail/decryptedMessages.ts +116 -0
- package/apps/shared/mail/findWellKnownFolderUid.ts +6 -4
- package/apps/shared/mail/folderCounts.ts +8 -4
- package/apps/shared/mail/folderOfType.ts +5 -3
- package/apps/shared/mail/folderTree.ts +1 -1
- package/apps/shared/mail/listSnapshots.ts +2 -2
- package/apps/shared/mail/messageReadState.ts +6 -5
- package/apps/shared/mail/newMailNotifications.ts +2 -2
- package/apps/shared/mail/outbox/composeBridge.ts +2 -2
- package/apps/shared/mail/outbox/outboxState.ts +1 -1
- package/apps/shared/mail/outbox/outgoingReplies.ts +2 -2
- package/apps/shared/mail/outbox/sendDecision.ts +2 -2
- package/apps/shared/mail/outbox/sendJob.ts +40 -35
- package/apps/shared/mail/outbox/sendOutcomes.ts +20 -15
- package/apps/shared/mail/outbox/useOutboxStatus.ts +5 -3
- package/apps/shared/mail/permanentDelete.ts +8 -7
- package/apps/shared/mail/primaryMailbox.ts +1 -1
- package/apps/shared/mail/reportNotices.ts +1 -1
- package/apps/shared/mail/senderBlocking.ts +36 -20
- package/apps/shared/mail/useMailConnection.ts +12 -10
- package/apps/shared/mail/useMailLiveUpdates.ts +3 -3
- package/apps/shared/mail/useMailboxUpdateAccess.ts +35 -11
- package/apps/shared/mail/useMarkMessageRead.ts +14 -7
- package/apps/shared/mail/useNewMailNotifications.ts +1 -1
- package/apps/shared/mail/usePermanentDelete.tsx +5 -3
- package/apps/shared/navigation/pageTitle.ts +1 -1
- package/apps/shared/notifications/NotificationCenter.tsx +1 -1
- package/apps/shared/notifications/NotificationHistoryDialog.tsx +2 -2
- package/apps/shared/notifications/apiErrors.ts +2 -2
- package/apps/shared/notifications/pushStatus.ts +1 -1
- package/apps/shared/notifications/systemErrors.ts +1 -1
- package/apps/shared/search/LocalIndexLifecycle.tsx +18 -12
- package/apps/shared/search/crossMailboxSearch.ts +3 -3
- package/apps/shared/search/localIndexBuilder.ts +24 -12
- package/apps/shared/search/localIndexKey.ts +1 -1
- package/apps/shared/search/localIndexRpcClient.ts +150 -30
- package/apps/shared/search/localIndexTransport.ts +84 -0
- package/apps/shared/search/localIndexWorker.ts +1 -1
- package/apps/shared/search/searchTier2.ts +3 -3
- package/apps/shared/signing/enrollmentTracker.ts +3 -3
- package/apps/shared/signing/enrollmentView.ts +1 -1
- package/apps/shared/signing/signingInfo.ts +1 -1
- package/apps/shared/signing/useSigningEnrollmentWatcher.ts +6 -4
- package/apps/shared/styles/app.css +14 -23
- package/apps/www/_layout.tsx +2 -2
- package/apps/www/calendar/index.tsx +20 -18
- package/apps/www/contacts/[uid].tsx +8 -6
- package/apps/www/contacts/index.tsx +19 -17
- package/apps/www/index.tsx +68 -48
- package/apps/www/messages/[uid].tsx +11 -9
- package/apps/www/settings/auto-reply/index.tsx +6 -4
- package/apps/www/settings/blocked-senders/index.tsx +9 -7
- package/apps/www/settings/encryption/index.tsx +38 -32
- package/apps/www/settings/filters/[uid].tsx +19 -14
- package/apps/www/settings/filters/_mailFilterRuleConfig.tsx +2 -2
- package/apps/www/settings/filters/index.tsx +4 -4
- package/apps/www/settings/filters/new/index.tsx +10 -8
- package/apps/www/settings/labels/index.tsx +12 -10
- package/apps/www/settings/privacy/index.tsx +18 -14
- package/apps/www/settings/profile/index.tsx +16 -11
- package/apps/www/settings/read-receipts/index.tsx +17 -12
- package/apps/www/settings/sharing/index.tsx +6 -6
- package/apps/www/settings/signatures/[uid].tsx +5 -5
- package/apps/www/settings/signatures/index.tsx +4 -4
- package/apps/www/settings/signatures/new/index.tsx +4 -4
- package/apps/www/settings/signatures/signatureDefaults.ts +1 -1
- package/apps/www/tasks/index.tsx +28 -23
- package/dist/apps/admin/_layout.d.ts +1 -1
- package/dist/apps/admin/_layout.js +1 -1
- package/dist/apps/admin/audit-log/index.d.ts +1 -1
- package/dist/apps/admin/audit-log/index.js +4 -4
- package/dist/apps/admin/branding/index.js +3 -3
- package/dist/apps/admin/data-requests/index.js +8 -8
- package/dist/apps/admin/distribution-lists/[uid].js +3 -3
- package/dist/apps/admin/distribution-lists/index.js +4 -4
- package/dist/apps/admin/distribution-lists/new/index.js +5 -5
- package/dist/apps/admin/domains/[uid].js +6 -6
- package/dist/apps/admin/domains/index.js +4 -4
- package/dist/apps/admin/domains/new/index.js +5 -5
- package/dist/apps/admin/encryption-policy/index.js +1 -1
- package/dist/apps/admin/escrow-scopes/[uid].d.ts +1 -1
- package/dist/apps/admin/escrow-scopes/[uid].js +7 -7
- package/dist/apps/admin/escrow-scopes/index.js +4 -4
- package/dist/apps/admin/escrow-scopes/new/index.js +5 -5
- package/dist/apps/admin/index.js +6 -6
- package/dist/apps/admin/ingest-queue/index.js +4 -4
- package/dist/apps/admin/mailbox-policy/index.js +1 -1
- package/dist/apps/admin/mailboxes/[uid].js +5 -5
- package/dist/apps/admin/quarantine/index.js +5 -5
- package/dist/apps/admin/retention-policy/index.js +3 -3
- package/dist/apps/admin/signing-certificates/index.js +5 -5
- package/dist/apps/admin/transport-rules/[uid].js +5 -5
- package/dist/apps/admin/transport-rules/_transportRuleConfig.d.ts +1 -1
- package/dist/apps/admin/transport-rules/_transportRuleConfig.js +2 -2
- package/dist/apps/admin/transport-rules/index.js +4 -4
- package/dist/apps/admin/transport-rules/new/index.js +5 -5
- package/dist/apps/escrow/_layout.d.ts +1 -1
- package/dist/apps/escrow/audit-log/index.d.ts +1 -1
- package/dist/apps/escrow/audit-log/index.js +4 -4
- package/dist/apps/escrow/index.js +4 -4
- package/dist/apps/escrow/matters/[uid].js +10 -10
- package/dist/apps/escrow/matters/new/index.js +6 -6
- package/dist/apps/shared/appearance/AppearanceForm.js +3 -3
- package/dist/apps/shared/appearance/AppearanceHead.js +1 -1
- package/dist/apps/shared/appearance/AppearanceProvider.d.ts +1 -1
- package/dist/apps/shared/appearance/AppearanceProvider.js +3 -3
- package/dist/apps/shared/appearance/appearanceCache.d.ts +1 -1
- package/dist/apps/shared/appearance/appearanceCache.js +1 -1
- package/dist/apps/shared/appearance/appearanceContext.d.ts +1 -1
- package/dist/apps/shared/appearance/theme.d.ts +1 -1
- package/dist/apps/shared/auth/adminAccess.js +1 -1
- package/dist/apps/shared/calendar/bookingPlugin.js +1 -1
- package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +1 -1
- package/dist/apps/shared/calendar/calendarReminders.d.ts +1 -1
- package/dist/apps/shared/calendar/useCalendarReminders.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/DiagnosticsManager.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.d.ts +1 -1
- package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.js +2 -2
- package/dist/apps/shared/components/admin/diagnostics/LogsPanel.js +2 -2
- package/dist/apps/shared/components/admin/diagnostics/PackagesTable.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/RuntimePanel.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/SystemPanel.js +2 -2
- package/dist/apps/shared/components/admin/diagnostics/VersionsPanel.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/diagnosticsApi.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/format.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/logClient.js +1 -1
- package/dist/apps/shared/components/admin/distributionLists/MemberListCard.d.ts +1 -1
- package/dist/apps/shared/components/admin/distributionLists/MemberListCard.js +4 -4
- package/dist/apps/shared/components/admin/elevation.js +1 -1
- package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js +3 -3
- package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
- package/dist/apps/shared/components/admin/layout/AdminShell.js +7 -7
- package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +1 -1
- package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +6 -6
- package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.d.ts +1 -1
- package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.js +10 -8
- package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +4 -4
- package/dist/apps/shared/components/admin/mailboxes/MailboxTable.d.ts +1 -1
- package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.d.ts +1 -1
- package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.js +7 -5
- package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.js +5 -5
- package/dist/apps/shared/components/admin/settings/BrandingForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/BrandingForm.js +5 -5
- package/dist/apps/shared/components/admin/settings/DomainDnsSetup.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +5 -5
- package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +4 -4
- package/dist/apps/shared/components/admin/settings/LoadedSettingsForm.js +2 -2
- package/dist/apps/shared/components/admin/settings/MailboxCreateForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +14 -12
- package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.js +4 -4
- package/dist/apps/shared/components/admin/settings/PluginsManager.js +5 -5
- package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.js +5 -5
- package/dist/apps/shared/components/admin/setup/EscrowSetupStep.js +7 -7
- package/dist/apps/shared/components/admin/setup/SetupWizard.d.ts +4 -4
- package/dist/apps/shared/components/admin/setup/SetupWizard.js +27 -23
- package/dist/apps/shared/components/admin/signOut.js +1 -1
- package/dist/apps/shared/components/admin/usePagedList.js +2 -2
- package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +3 -3
- package/dist/apps/shared/components/calendar/CalendarListSidebar.d.ts +1 -1
- package/dist/apps/shared/components/calendar/CalendarListSidebar.js +2 -2
- package/dist/apps/shared/components/calendar/DescriptionEditor.js +1 -1
- package/dist/apps/shared/components/calendar/EventDescriptionView.js +1 -1
- package/dist/apps/shared/components/calendar/EventDetails.d.ts +2 -2
- package/dist/apps/shared/components/calendar/EventDetails.js +16 -14
- package/dist/apps/shared/components/calendar/EventEditor.d.ts +2 -2
- package/dist/apps/shared/components/calendar/EventEditor.js +22 -20
- package/dist/apps/shared/components/calendar/EventExpandedForm.js +2 -2
- package/dist/apps/shared/components/calendar/EventFormParts.d.ts +1 -1
- package/dist/apps/shared/components/calendar/EventFormParts.js +1 -1
- package/dist/apps/shared/components/calendar/EventModal.d.ts +2 -2
- package/dist/apps/shared/components/calendar/EventModal.js +3 -3
- package/dist/apps/shared/components/calendar/EventQuickForm.js +3 -3
- package/dist/apps/shared/components/calendar/EventShell.js +1 -1
- package/dist/apps/shared/components/calendar/FindATime.js +6 -4
- package/dist/apps/shared/components/calendar/GuestInput.d.ts +2 -2
- package/dist/apps/shared/components/calendar/MonthView.d.ts +1 -1
- package/dist/apps/shared/components/calendar/MonthView.js +1 -1
- package/dist/apps/shared/components/calendar/QuickCreateFaces.js +1 -1
- package/dist/apps/shared/components/calendar/QuickFaceFrame.js +1 -1
- package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +1 -1
- package/dist/apps/shared/components/calendar/RecurrenceEditor.js +1 -1
- package/dist/apps/shared/components/calendar/RequestChangeForm.js +8 -6
- package/dist/apps/shared/components/calendar/ResourcePicker.d.ts +1 -1
- package/dist/apps/shared/components/calendar/ResourcePicker.js +7 -5
- package/dist/apps/shared/components/calendar/SplitDayView.d.ts +1 -1
- package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +1 -1
- package/dist/apps/shared/components/calendar/TaskQuickForm.js +9 -7
- package/dist/apps/shared/components/calendar/TimeGridView.d.ts +1 -1
- package/dist/apps/shared/components/calendar/TimeGridView.js +2 -2
- package/dist/apps/shared/components/calendar/allDay.d.ts +2 -2
- package/dist/apps/shared/components/calendar/allDay.js +1 -1
- package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +2 -2
- package/dist/apps/shared/components/calendar/eventDialogFields.js +2 -2
- package/dist/apps/shared/components/calendar/eventForm.d.ts +3 -3
- package/dist/apps/shared/components/calendar/eventFormat.d.ts +1 -1
- package/dist/apps/shared/components/calendar/eventFormat.js +2 -2
- package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +1 -1
- package/dist/apps/shared/components/calendar/findTimeGrid.js +1 -1
- package/dist/apps/shared/components/calendar/layout/CalendarShell.d.ts +1 -1
- package/dist/apps/shared/components/calendar/layout/CalendarShell.js +11 -9
- package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +1 -1
- package/dist/apps/shared/components/contacts/ContactDetailPane.js +2 -2
- package/dist/apps/shared/components/contacts/ContactForm.d.ts +2 -2
- package/dist/apps/shared/components/contacts/ContactForm.js +12 -8
- package/dist/apps/shared/components/contacts/ContactsSidebar.d.ts +1 -1
- package/dist/apps/shared/components/contacts/ContactsSidebar.js +7 -5
- package/dist/apps/shared/components/contacts/KeyChangeReview.d.ts +1 -1
- package/dist/apps/shared/components/contacts/KeyChangeReview.js +5 -5
- package/dist/apps/shared/components/contacts/contactKeys.d.ts +2 -2
- package/dist/apps/shared/components/contacts/contactKeys.js +2 -2
- package/dist/apps/shared/components/contacts/layout/ContactsShell.d.ts +1 -1
- package/dist/apps/shared/components/contacts/layout/ContactsShell.js +9 -7
- package/dist/apps/shared/components/escrow/layout/EscrowShell.js +6 -6
- package/dist/apps/shared/components/forms/StringListField.js +1 -1
- package/dist/apps/shared/components/layout/AppShell.d.ts +2 -2
- package/dist/apps/shared/components/layout/AppShell.js +11 -9
- package/dist/apps/shared/components/layout/BrandingChrome.d.ts +1 -1
- package/dist/apps/shared/components/layout/KeyEnrollmentGate.d.ts +1 -1
- package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +9 -9
- package/dist/apps/shared/components/layout/MailboxProvisioning.js +8 -6
- package/dist/apps/shared/components/layout/RecoveryCodeUnlock.d.ts +1 -1
- package/dist/apps/shared/components/layout/RecoveryCodeUnlock.js +9 -9
- package/dist/apps/shared/components/layout/UnlockPromptProvider.d.ts +2 -2
- package/dist/apps/shared/components/layout/UnlockPromptProvider.js +5 -5
- package/dist/apps/shared/components/layout/UserMenu.js +6 -4
- package/dist/apps/shared/components/mail/ConversationList.d.ts +2 -2
- package/dist/apps/shared/components/mail/ConversationList.js +23 -8
- package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +3 -3
- package/dist/apps/shared/components/mail/ConversationThreadPane.js +19 -13
- package/dist/apps/shared/components/mail/InviteCard.js +10 -8
- package/dist/apps/shared/components/mail/LazyReadingPane.js +2 -2
- package/dist/apps/shared/components/mail/MailAddress.d.ts +1 -1
- package/dist/apps/shared/components/mail/MailAddress.js +1 -1
- package/dist/apps/shared/components/mail/MailListToolbar.d.ts +2 -2
- package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +2 -2
- package/dist/apps/shared/components/mail/MenuButton.js +1 -1
- package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +3 -3
- package/dist/apps/shared/components/mail/MessageDetailPane.js +61 -46
- package/dist/apps/shared/components/mail/MoveToFolderDialog.d.ts +1 -1
- package/dist/apps/shared/components/mail/MoveToFolderDialog.js +8 -6
- package/dist/apps/shared/components/mail/OutboxRowStatus.d.ts +1 -1
- package/dist/apps/shared/components/mail/PermanentDeleteDialog.js +2 -2
- package/dist/apps/shared/components/mail/compose/ComposeContext.d.ts +10 -1
- package/dist/apps/shared/components/mail/compose/ComposeContext.js +4 -2
- package/dist/apps/shared/components/mail/compose/ComposeWindow.js +34 -30
- package/dist/apps/shared/components/mail/compose/ComposeWindowPlaceholder.js +4 -4
- package/dist/apps/shared/components/mail/compose/EmojiPicker.js +2 -2
- package/dist/apps/shared/components/mail/compose/GifPicker.js +3 -3
- package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +1 -1
- package/dist/apps/shared/components/mail/compose/RecipientInput.js +1 -1
- package/dist/apps/shared/components/mail/compose/ScheduleSendPicker.js +1 -1
- package/dist/apps/shared/components/mail/compose/encryptionRequirement.d.ts +2 -2
- package/dist/apps/shared/components/mail/compose/encryptionRequirement.js +1 -1
- package/dist/apps/shared/components/mail/compose/quotedBody.d.ts +3 -3
- package/dist/apps/shared/components/mail/compose/quotedBody.js +3 -3
- package/dist/apps/shared/components/mail/compose/recipients.d.ts +1 -1
- package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +3 -3
- package/dist/apps/shared/components/mail/invite/InviteRowChip.js +7 -9
- package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +2 -2
- package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +11 -9
- package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +1 -1
- package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +1 -1
- package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +1 -1
- package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +2 -2
- package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +9 -3
- package/dist/apps/shared/components/mail/invite/inviteStore.js +13 -6
- package/dist/apps/shared/components/mail/labelMenu.d.ts +1 -1
- package/dist/apps/shared/components/mail/labelMenu.js +9 -7
- package/dist/apps/shared/components/mail/layout/MailShell.d.ts +1 -1
- package/dist/apps/shared/components/mail/layout/MailShell.js +3 -3
- package/dist/apps/shared/components/mail/listPreferences.d.ts +2 -2
- package/dist/apps/shared/components/mail/listPreferences.js +1 -1
- package/dist/apps/shared/components/mail/pinnedSigners.d.ts +12 -5
- package/dist/apps/shared/components/mail/pinnedSigners.js +37 -18
- package/dist/apps/shared/components/mail/reading/EncryptedBody.js +2 -2
- package/dist/apps/shared/components/mail/reading/MessageBody.d.ts +2 -2
- package/dist/apps/shared/components/mail/reading/MessageBody.js +4 -4
- package/dist/apps/shared/components/mail/reading/MessageCard.d.ts +1 -1
- package/dist/apps/shared/components/mail/reading/MessageCard.js +2 -2
- package/dist/apps/shared/components/mail/reading/MessageSourceDialog.js +3 -3
- package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +1 -1
- package/dist/apps/shared/components/mail/reading/bodyContent.d.ts +2 -2
- package/dist/apps/shared/components/mail/reading/bodyContent.js +2 -2
- package/dist/apps/shared/components/mail/reading/bodyHtml.js +1 -1
- package/dist/apps/shared/components/mail/reading/conversationPrint.d.ts +15 -0
- package/dist/apps/shared/components/mail/reading/conversationPrint.js +69 -0
- package/dist/apps/shared/components/mail/reading/messageExport.js +1 -1
- package/dist/apps/shared/components/mail/reading/printMessage.d.ts +9 -3
- package/dist/apps/shared/components/mail/reading/printMessage.js +33 -6
- package/dist/apps/shared/components/mail/reading/useMessageActions.d.ts +1 -1
- package/dist/apps/shared/components/mail/reading/useMessageActions.js +18 -16
- package/dist/apps/shared/components/mail/unreadStyle.d.ts +1 -1
- package/dist/apps/shared/components/mail/verificationSeals.d.ts +27 -6
- package/dist/apps/shared/components/mail/verificationSeals.js +15 -11
- package/dist/apps/shared/components/mail/writableMailboxes.d.ts +8 -3
- package/dist/apps/shared/components/mail/writableMailboxes.js +12 -6
- package/dist/apps/shared/components/rules/RuleBuilder.js +1 -1
- package/dist/apps/shared/components/settings/SigningCertificateCard.d.ts +1 -1
- package/dist/apps/shared/components/settings/SigningCertificateCard.js +3 -3
- package/dist/apps/shared/components/settings/layout/SettingsShell.d.ts +1 -1
- package/dist/apps/shared/components/settings/layout/SettingsShell.js +8 -6
- package/dist/apps/shared/components/sharing/PrincipalListField.d.ts +1 -1
- package/dist/apps/shared/components/sharing/PrincipalPicker.d.ts +1 -1
- package/dist/apps/shared/components/sharing/PrincipalPicker.js +1 -1
- package/dist/apps/shared/components/sharing/PrincipalResolver.d.ts +1 -1
- package/dist/apps/shared/components/sharing/PrincipalResolver.js +3 -3
- package/dist/apps/shared/components/tasks/TasksSidebar.d.ts +1 -1
- package/dist/apps/shared/components/tasks/TasksSidebar.js +7 -5
- package/dist/apps/shared/components/tasks/layout/TasksShell.d.ts +1 -1
- package/dist/apps/shared/components/tasks/layout/TasksShell.js +9 -7
- package/dist/apps/shared/keyboard/ShortcutsDialog.js +1 -1
- package/dist/apps/shared/keyboard/keymap.d.ts +6 -0
- package/dist/apps/shared/keyboard/keymap.js +1 -0
- package/dist/apps/shared/mail/decryptedMessages.d.ts +27 -0
- package/dist/apps/shared/mail/decryptedMessages.js +97 -0
- package/dist/apps/shared/mail/findWellKnownFolderUid.d.ts +5 -3
- package/dist/apps/shared/mail/findWellKnownFolderUid.js +5 -4
- package/dist/apps/shared/mail/folderCounts.d.ts +1 -1
- package/dist/apps/shared/mail/folderCounts.js +6 -4
- package/dist/apps/shared/mail/folderOfType.d.ts +3 -2
- package/dist/apps/shared/mail/folderOfType.js +4 -4
- package/dist/apps/shared/mail/folderTree.d.ts +1 -1
- package/dist/apps/shared/mail/listSnapshots.d.ts +2 -2
- package/dist/apps/shared/mail/messageReadState.d.ts +4 -3
- package/dist/apps/shared/mail/messageReadState.js +5 -5
- package/dist/apps/shared/mail/newMailNotifications.d.ts +1 -1
- package/dist/apps/shared/mail/newMailNotifications.js +1 -1
- package/dist/apps/shared/mail/outbox/composeBridge.d.ts +2 -2
- package/dist/apps/shared/mail/outbox/outboxState.d.ts +1 -1
- package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +2 -2
- package/dist/apps/shared/mail/outbox/sendDecision.d.ts +2 -2
- package/dist/apps/shared/mail/outbox/sendDecision.js +1 -1
- package/dist/apps/shared/mail/outbox/sendJob.d.ts +10 -6
- package/dist/apps/shared/mail/outbox/sendJob.js +39 -35
- package/dist/apps/shared/mail/outbox/sendOutcomes.d.ts +6 -3
- package/dist/apps/shared/mail/outbox/sendOutcomes.js +19 -15
- package/dist/apps/shared/mail/outbox/useOutboxStatus.js +5 -3
- package/dist/apps/shared/mail/permanentDelete.d.ts +4 -3
- package/dist/apps/shared/mail/permanentDelete.js +8 -8
- package/dist/apps/shared/mail/primaryMailbox.d.ts +1 -1
- package/dist/apps/shared/mail/primaryMailbox.js +1 -1
- package/dist/apps/shared/mail/reportNotices.d.ts +1 -1
- package/dist/apps/shared/mail/senderBlocking.d.ts +5 -4
- package/dist/apps/shared/mail/senderBlocking.js +19 -16
- package/dist/apps/shared/mail/useMailConnection.d.ts +1 -1
- package/dist/apps/shared/mail/useMailConnection.js +12 -10
- package/dist/apps/shared/mail/useMailLiveUpdates.d.ts +2 -2
- package/dist/apps/shared/mail/useMailLiveUpdates.js +2 -2
- package/dist/apps/shared/mail/useMailboxUpdateAccess.d.ts +3 -2
- package/dist/apps/shared/mail/useMailboxUpdateAccess.js +31 -10
- package/dist/apps/shared/mail/useMarkMessageRead.d.ts +1 -1
- package/dist/apps/shared/mail/useMarkMessageRead.js +5 -3
- package/dist/apps/shared/mail/useNewMailNotifications.d.ts +1 -1
- package/dist/apps/shared/mail/usePermanentDelete.d.ts +1 -1
- package/dist/apps/shared/mail/usePermanentDelete.js +4 -2
- package/dist/apps/shared/navigation/pageTitle.d.ts +1 -1
- package/dist/apps/shared/notifications/NotificationCenter.js +1 -1
- package/dist/apps/shared/notifications/NotificationHistoryDialog.js +2 -2
- package/dist/apps/shared/notifications/apiErrors.js +2 -2
- package/dist/apps/shared/notifications/pushStatus.js +1 -1
- package/dist/apps/shared/notifications/systemErrors.js +1 -1
- package/dist/apps/shared/search/LocalIndexLifecycle.d.ts +2 -2
- package/dist/apps/shared/search/LocalIndexLifecycle.js +15 -10
- package/dist/apps/shared/search/crossMailboxSearch.d.ts +1 -1
- package/dist/apps/shared/search/crossMailboxSearch.js +2 -2
- package/dist/apps/shared/search/localIndexBuilder.d.ts +4 -3
- package/dist/apps/shared/search/localIndexBuilder.js +15 -12
- package/dist/apps/shared/search/localIndexKey.js +1 -1
- package/dist/apps/shared/search/localIndexRpcClient.d.ts +43 -31
- package/dist/apps/shared/search/localIndexRpcClient.js +113 -20
- package/dist/apps/shared/search/localIndexTransport.d.ts +77 -0
- package/dist/apps/shared/search/localIndexTransport.js +1 -0
- package/dist/apps/shared/search/localIndexWorker.d.ts +1 -1
- package/dist/apps/shared/search/searchTier2.d.ts +3 -3
- package/dist/apps/shared/signing/enrollmentTracker.d.ts +1 -1
- package/dist/apps/shared/signing/enrollmentTracker.js +3 -3
- package/dist/apps/shared/signing/enrollmentView.d.ts +1 -1
- package/dist/apps/shared/signing/signingInfo.d.ts +1 -1
- package/dist/apps/shared/signing/signingInfo.js +1 -1
- package/dist/apps/shared/signing/useSigningEnrollmentWatcher.d.ts +1 -1
- package/dist/apps/shared/signing/useSigningEnrollmentWatcher.js +5 -3
- package/dist/apps/shared/styles/app.css +14 -23
- package/dist/apps/www/_layout.d.ts +1 -1
- package/dist/apps/www/_layout.js +1 -1
- package/dist/apps/www/calendar/index.d.ts +1 -1
- package/dist/apps/www/calendar/index.js +20 -18
- package/dist/apps/www/contacts/[uid].d.ts +1 -1
- package/dist/apps/www/contacts/[uid].js +8 -6
- package/dist/apps/www/contacts/index.d.ts +1 -1
- package/dist/apps/www/contacts/index.js +19 -17
- package/dist/apps/www/index.d.ts +1 -1
- package/dist/apps/www/index.js +64 -50
- package/dist/apps/www/messages/[uid].d.ts +1 -1
- package/dist/apps/www/messages/[uid].js +11 -9
- package/dist/apps/www/settings/appearance/index.d.ts +1 -1
- package/dist/apps/www/settings/auto-reply/index.d.ts +1 -1
- package/dist/apps/www/settings/auto-reply/index.js +6 -4
- package/dist/apps/www/settings/blocked-senders/index.d.ts +1 -1
- package/dist/apps/www/settings/blocked-senders/index.js +6 -4
- package/dist/apps/www/settings/encryption/index.d.ts +1 -1
- package/dist/apps/www/settings/encryption/index.js +31 -29
- package/dist/apps/www/settings/filters/[uid].d.ts +1 -1
- package/dist/apps/www/settings/filters/[uid].js +11 -9
- package/dist/apps/www/settings/filters/_mailFilterRuleConfig.d.ts +2 -2
- package/dist/apps/www/settings/filters/index.d.ts +1 -1
- package/dist/apps/www/settings/filters/index.js +4 -4
- package/dist/apps/www/settings/filters/new/index.d.ts +1 -1
- package/dist/apps/www/settings/filters/new/index.js +10 -8
- package/dist/apps/www/settings/labels/index.d.ts +1 -1
- package/dist/apps/www/settings/labels/index.js +12 -10
- package/dist/apps/www/settings/privacy/index.d.ts +1 -1
- package/dist/apps/www/settings/privacy/index.js +18 -14
- package/dist/apps/www/settings/profile/index.d.ts +1 -1
- package/dist/apps/www/settings/profile/index.js +7 -5
- package/dist/apps/www/settings/read-receipts/index.d.ts +1 -1
- package/dist/apps/www/settings/read-receipts/index.js +5 -3
- package/dist/apps/www/settings/sharing/index.d.ts +1 -1
- package/dist/apps/www/settings/sharing/index.js +6 -6
- package/dist/apps/www/settings/signatures/[uid].d.ts +1 -1
- package/dist/apps/www/settings/signatures/[uid].js +5 -5
- package/dist/apps/www/settings/signatures/index.d.ts +1 -1
- package/dist/apps/www/settings/signatures/index.js +4 -4
- package/dist/apps/www/settings/signatures/new/index.d.ts +1 -1
- package/dist/apps/www/settings/signatures/new/index.js +4 -4
- package/dist/apps/www/settings/signatures/signatureDefaults.d.ts +1 -1
- package/dist/apps/www/settings/signatures/signatureDefaults.js +1 -1
- package/dist/apps/www/tasks/index.d.ts +1 -1
- package/dist/apps/www/tasks/index.js +17 -15
- package/dist/lib/admin/auditLogApi.d.ts +32 -0
- package/dist/lib/admin/auditLogApi.js +27 -0
- package/dist/lib/admin/distributionListsApi.d.ts +47 -0
- package/dist/lib/admin/distributionListsApi.js +34 -0
- package/dist/lib/admin/domainsApi.d.ts +75 -0
- package/dist/lib/admin/domainsApi.js +44 -0
- package/dist/lib/admin/escrowAccessRequestsApi.d.ts +79 -0
- package/dist/lib/admin/escrowAccessRequestsApi.js +46 -0
- package/dist/lib/admin/escrowAuditLogApi.d.ts +66 -0
- package/dist/lib/admin/escrowAuditLogApi.js +31 -0
- package/dist/lib/admin/escrowScopesApi.d.ts +78 -0
- package/dist/lib/admin/escrowScopesApi.js +50 -0
- package/dist/lib/admin/leftoverMailboxApi.d.ts +73 -0
- package/dist/lib/admin/leftoverMailboxApi.js +67 -0
- package/dist/lib/admin/mailboxPolicyApi.d.ts +27 -0
- package/dist/lib/admin/mailboxPolicyApi.js +21 -0
- package/dist/lib/admin/matterExportApi.d.ts +40 -0
- package/dist/lib/admin/matterExportApi.js +39 -0
- package/dist/lib/admin/matterSearchApi.d.ts +20 -0
- package/dist/lib/admin/matterSearchApi.js +27 -0
- package/dist/lib/admin/mattersApi.d.ts +56 -0
- package/dist/lib/admin/mattersApi.js +40 -0
- package/dist/lib/admin/pluginsApi.d.ts +265 -0
- package/dist/lib/admin/pluginsApi.js +102 -0
- package/dist/lib/admin/retentionPolicyApi.d.ts +32 -0
- package/dist/lib/admin/retentionPolicyApi.js +29 -0
- package/dist/lib/admin/setupApi.d.ts +23 -0
- package/dist/lib/admin/setupApi.js +26 -0
- package/dist/lib/admin/transportRulesApi.d.ts +66 -0
- package/dist/lib/admin/transportRulesApi.js +43 -0
- package/dist/lib/appearance/preferencesApi.d.ts +128 -0
- package/dist/lib/appearance/preferencesApi.js +257 -0
- package/dist/lib/auth/profileApi.d.ts +33 -0
- package/dist/lib/auth/profileApi.js +52 -0
- package/dist/lib/auth/session.d.ts +70 -0
- package/dist/lib/auth/session.js +210 -0
- package/dist/lib/branding/brandingApi.d.ts +47 -0
- package/dist/lib/branding/brandingApi.js +61 -0
- package/dist/lib/branding/useBranding.d.ts +23 -0
- package/dist/lib/branding/useBranding.js +65 -0
- package/dist/lib/calendar/calendarApi.d.ts +230 -0
- package/dist/lib/calendar/calendarApi.js +106 -0
- package/dist/lib/calendar/calendarColors.d.ts +18 -0
- package/dist/lib/calendar/calendarColors.js +39 -0
- package/dist/lib/calendar/calendarDragIds.d.ts +42 -0
- package/dist/lib/calendar/calendarDragIds.js +92 -0
- package/dist/lib/calendar/calendarMutations.d.ts +68 -0
- package/dist/lib/calendar/calendarMutations.js +190 -0
- package/dist/lib/calendar/eventDescription.d.ts +43 -0
- package/dist/lib/calendar/eventDescription.js +195 -0
- package/dist/lib/calendar/freeBusyApi.d.ts +100 -0
- package/dist/lib/calendar/freeBusyApi.js +119 -0
- package/dist/lib/calendar/inviteApi.d.ts +121 -0
- package/dist/lib/calendar/inviteApi.js +54 -0
- package/dist/lib/calendar/recurrence.d.ts +60 -0
- package/dist/lib/calendar/recurrence.js +225 -0
- package/dist/lib/components/avatar/ContactAvatar.d.ts +8 -0
- package/dist/lib/components/avatar/ContactAvatar.js +26 -0
- package/dist/lib/components/buttons/Button.d.ts +9 -0
- package/dist/lib/components/buttons/Button.js +14 -0
- package/dist/lib/components/buttons/CopyButton.d.ts +18 -0
- package/dist/lib/components/buttons/CopyButton.js +14 -0
- package/dist/lib/components/feedback/Alert.d.ts +4 -0
- package/dist/lib/components/feedback/Alert.js +4 -0
- package/dist/lib/components/feedback/Skeleton.d.ts +21 -0
- package/dist/lib/components/feedback/Skeleton.js +14 -0
- package/dist/lib/components/forms/FormField.d.ts +8 -0
- package/dist/lib/components/forms/FormField.js +5 -0
- package/dist/lib/components/navigation/BottomTabBar.d.ts +27 -0
- package/dist/lib/components/navigation/BottomTabBar.js +32 -0
- package/dist/lib/components/overlays/Drawer.d.ts +20 -0
- package/dist/lib/components/overlays/Drawer.js +27 -0
- package/dist/lib/components/overlays/Modal.d.ts +17 -0
- package/dist/lib/components/overlays/Modal.js +25 -0
- package/dist/lib/components/overlays/PopoverPortal.d.ts +23 -0
- package/dist/lib/components/overlays/PopoverPortal.js +53 -0
- package/dist/lib/components/overlays/overlayStack.d.ts +31 -0
- package/dist/lib/components/overlays/overlayStack.js +143 -0
- package/dist/lib/components/pickers/MiniDatePicker.d.ts +13 -0
- package/dist/lib/components/pickers/MiniDatePicker.js +42 -0
- package/dist/lib/contacts/contactsApi.d.ts +174 -0
- package/dist/lib/contacts/contactsApi.js +139 -0
- package/dist/lib/contacts/vcard.d.ts +23 -0
- package/dist/lib/contacts/vcard.js +179 -0
- package/dist/lib/crypto/composeSecurity.d.ts +67 -0
- package/dist/lib/crypto/composeSecurity.js +93 -0
- package/dist/lib/crypto/encoding.d.ts +9 -0
- package/dist/lib/crypto/encoding.js +32 -0
- package/dist/lib/crypto/escrowKeys.d.ts +25 -0
- package/dist/lib/crypto/escrowKeys.js +59 -0
- package/dist/lib/crypto/idleTimeout.d.ts +16 -0
- package/dist/lib/crypto/idleTimeout.js +47 -0
- package/dist/lib/crypto/keySession.d.ts +159 -0
- package/dist/lib/crypto/keySession.js +367 -0
- package/dist/lib/crypto/keys.d.ts +50 -0
- package/dist/lib/crypto/keys.js +89 -0
- package/dist/lib/crypto/keyvaultApi.d.ts +394 -0
- package/dist/lib/crypto/keyvaultApi.js +350 -0
- package/dist/lib/crypto/masterKey.d.ts +59 -0
- package/dist/lib/crypto/masterKey.js +104 -0
- package/dist/lib/crypto/masterKeyWraps.d.ts +108 -0
- package/dist/lib/crypto/masterKeyWraps.js +228 -0
- package/dist/lib/crypto/messageSecurity.d.ts +248 -0
- package/dist/lib/crypto/messageSecurity.js +367 -0
- package/dist/lib/crypto/mime.d.ts +143 -0
- package/dist/lib/crypto/mime.js +504 -0
- package/dist/lib/crypto/passkeyUnlock.d.ts +20 -0
- package/dist/lib/crypto/passkeyUnlock.js +79 -0
- package/dist/lib/crypto/passwordUnlock.d.ts +39 -0
- package/dist/lib/crypto/passwordUnlock.js +73 -0
- package/dist/lib/crypto/recoveryCode.d.ts +28 -0
- package/dist/lib/crypto/recoveryCode.js +86 -0
- package/dist/lib/crypto/signingProviderApi.d.ts +95 -0
- package/dist/lib/crypto/signingProviderApi.js +60 -0
- package/dist/lib/crypto/smime.d.ts +128 -0
- package/dist/lib/crypto/smime.js +402 -0
- package/dist/lib/crypto/smimeMessage.d.ts +132 -0
- package/dist/lib/crypto/smimeMessage.js +341 -0
- package/dist/lib/crypto/useIdleKeyTimeout.d.ts +10 -0
- package/dist/lib/crypto/useIdleKeyTimeout.js +163 -0
- package/dist/lib/crypto/verificationSeal.d.ts +56 -0
- package/dist/lib/crypto/verificationSeal.js +220 -0
- package/dist/lib/mail/compose/composeQuoting.d.ts +88 -0
- package/dist/lib/mail/compose/composeQuoting.js +204 -0
- package/dist/lib/mail/compose/emojiData.d.ts +9 -0
- package/dist/lib/mail/compose/emojiData.js +18 -0
- package/dist/lib/mail/compose/giphyApi.d.ts +17 -0
- package/dist/lib/mail/compose/giphyApi.js +20 -0
- package/dist/lib/mail/conversationsApi.d.ts +80 -0
- package/dist/lib/mail/conversationsApi.js +44 -0
- package/dist/lib/mail/dataExportApi.d.ts +50 -0
- package/dist/lib/mail/dataExportApi.js +40 -0
- package/dist/lib/mail/directoryApi.d.ts +49 -0
- package/dist/lib/mail/directoryApi.js +101 -0
- package/dist/lib/mail/erasureRequestApi.d.ts +45 -0
- package/dist/lib/mail/erasureRequestApi.js +43 -0
- package/dist/lib/mail/flaggedMessages.d.ts +22 -0
- package/dist/lib/mail/flaggedMessages.js +73 -0
- package/dist/lib/mail/focusedInboxOverridesApi.d.ts +37 -0
- package/dist/lib/mail/focusedInboxOverridesApi.js +34 -0
- package/dist/lib/mail/labelsApi.d.ts +47 -0
- package/dist/lib/mail/labelsApi.js +38 -0
- package/dist/lib/mail/mailAddress.d.ts +27 -0
- package/dist/lib/mail/mailAddress.js +54 -0
- package/dist/lib/mail/mailApi.d.ts +850 -0
- package/dist/lib/mail/mailApi.js +602 -0
- package/dist/lib/mail/mailDetailHooks.d.ts +10 -0
- package/dist/lib/mail/mailDetailHooks.js +53 -0
- package/dist/lib/mail/mailFilterRulesApi.d.ts +76 -0
- package/dist/lib/mail/mailFilterRulesApi.js +45 -0
- package/dist/lib/mail/mailSignaturesApi.d.ts +49 -0
- package/dist/lib/mail/mailSignaturesApi.js +42 -0
- package/dist/lib/mail/mailboxAccessApi.d.ts +74 -0
- package/dist/lib/mail/mailboxAccessApi.js +56 -0
- package/dist/lib/mail/mailboxImportApi.d.ts +53 -0
- package/dist/lib/mail/mailboxImportApi.js +51 -0
- package/dist/lib/mail/messageBodySanitizer.d.ts +16 -0
- package/dist/lib/mail/messageBodySanitizer.js +118 -0
- package/dist/lib/mail/pushClient.d.ts +106 -0
- package/dist/lib/mail/pushClient.js +317 -0
- package/dist/lib/mail/sendEvents.d.ts +33 -0
- package/dist/lib/mail/sendEvents.js +44 -0
- package/dist/lib/mail/sendFailure.d.ts +16 -0
- package/dist/lib/mail/sendFailure.js +86 -0
- package/dist/lib/mail/senderListsApi.d.ts +69 -0
- package/dist/lib/mail/senderListsApi.js +126 -0
- package/dist/lib/search/queryGrammar.d.ts +51 -0
- package/dist/lib/search/queryGrammar.js +111 -0
- package/dist/lib/search/searchApi.d.ts +100 -0
- package/dist/lib/search/searchApi.js +107 -0
- package/dist/lib/search/searchScoring.d.ts +34 -0
- package/dist/lib/search/searchScoring.js +44 -0
- package/dist/lib/search/searchTier3.d.ts +64 -0
- package/dist/lib/search/searchTier3.js +335 -0
- package/dist/lib/tasks/tasksApi.d.ts +85 -0
- package/dist/lib/tasks/tasksApi.js +55 -0
- package/dist/lib/util/api.d.ts +160 -0
- package/dist/lib/util/api.js +251 -0
- package/dist/lib/util/apiClientContext.d.ts +7 -0
- package/dist/lib/util/apiClientContext.js +32 -0
- package/dist/lib/util/apiQuery.d.ts +32 -0
- package/dist/lib/util/apiQuery.js +42 -0
- package/dist/lib/util/clipboard.d.ts +7 -0
- package/dist/lib/util/clipboard.js +56 -0
- package/dist/lib/util/dateInput.d.ts +6 -0
- package/dist/lib/util/dateInput.js +14 -0
- package/dist/lib/util/timeZone.d.ts +12 -0
- package/dist/lib/util/timeZone.js +32 -0
- package/dist/lib/util/useCopyToClipboard.d.ts +12 -0
- package/dist/lib/util/useCopyToClipboard.js +34 -0
- package/dist/lib/util/useIsMobile.d.ts +10 -0
- package/dist/lib/util/useIsMobile.js +29 -0
- package/dist/lib/videoconf/videoMeetingsApi.d.ts +116 -0
- package/dist/lib/videoconf/videoMeetingsApi.js +49 -0
- package/lib/admin/auditLogApi.ts +48 -0
- package/lib/admin/distributionListsApi.ts +77 -0
- package/lib/admin/domainsApi.ts +113 -0
- package/lib/admin/escrowAccessRequestsApi.ts +110 -0
- package/lib/admin/escrowAuditLogApi.ts +101 -0
- package/lib/admin/escrowScopesApi.ts +112 -0
- package/lib/admin/leftoverMailboxApi.ts +120 -0
- package/lib/admin/mailboxPolicyApi.ts +38 -0
- package/lib/admin/matterExportApi.ts +62 -0
- package/lib/admin/matterSearchApi.ts +35 -0
- package/lib/admin/mattersApi.ts +86 -0
- package/lib/admin/pluginsApi.ts +339 -0
- package/lib/admin/retentionPolicyApi.ts +46 -0
- package/lib/admin/setupApi.ts +40 -0
- package/lib/admin/transportRulesApi.ts +106 -0
- package/lib/appearance/preferencesApi.ts +335 -0
- package/lib/auth/profileApi.ts +77 -0
- package/lib/auth/session.ts +238 -0
- package/lib/branding/brandingApi.ts +97 -0
- package/lib/branding/useBranding.ts +81 -0
- package/lib/calendar/calendarApi.ts +309 -0
- package/lib/calendar/calendarColors.ts +45 -0
- package/lib/calendar/calendarDragIds.ts +112 -0
- package/lib/calendar/calendarMutations.ts +236 -0
- package/lib/calendar/eventDescription.ts +211 -0
- package/lib/calendar/freeBusyApi.ts +197 -0
- package/lib/calendar/inviteApi.ts +154 -0
- package/lib/calendar/recurrence.ts +285 -0
- package/lib/components/avatar/ContactAvatar.tsx +47 -0
- package/lib/components/buttons/Button.tsx +40 -0
- package/lib/components/buttons/CopyButton.tsx +45 -0
- package/lib/components/feedback/Alert.tsx +13 -0
- package/lib/components/feedback/Skeleton.tsx +38 -0
- package/lib/components/forms/FormField.tsx +23 -0
- package/lib/components/navigation/BottomTabBar.tsx +66 -0
- package/lib/components/overlays/Drawer.tsx +72 -0
- package/lib/components/overlays/Modal.tsx +64 -0
- package/lib/components/overlays/PopoverPortal.tsx +74 -0
- package/lib/components/overlays/overlayStack.ts +165 -0
- package/lib/components/pickers/MiniDatePicker.tsx +90 -0
- package/lib/contacts/contactsApi.ts +289 -0
- package/lib/contacts/vcard.ts +197 -0
- package/lib/crypto/composeSecurity.ts +140 -0
- package/lib/crypto/encoding.ts +36 -0
- package/lib/crypto/escrowKeys.ts +74 -0
- package/lib/crypto/idleTimeout.ts +49 -0
- package/lib/crypto/keySession.ts +483 -0
- package/lib/crypto/keys.ts +105 -0
- package/lib/crypto/keyvaultApi.ts +674 -0
- package/lib/crypto/masterKey.ts +134 -0
- package/lib/crypto/masterKeyWraps.ts +269 -0
- package/lib/crypto/messageSecurity.ts +600 -0
- package/lib/crypto/mime.ts +568 -0
- package/lib/crypto/passkeyUnlock.ts +103 -0
- package/lib/crypto/passwordUnlock.ts +98 -0
- package/lib/crypto/recoveryCode.ts +93 -0
- package/lib/crypto/signingProviderApi.ts +135 -0
- package/lib/crypto/smime.ts +459 -0
- package/lib/crypto/smimeMessage.ts +491 -0
- package/lib/crypto/useIdleKeyTimeout.ts +176 -0
- package/lib/crypto/verificationSeal.ts +288 -0
- package/lib/mail/compose/composeQuoting.ts +243 -0
- package/lib/mail/compose/emojiData.ts +34 -0
- package/lib/mail/compose/giphyApi.ts +31 -0
- package/lib/mail/conversationsApi.ts +123 -0
- package/lib/mail/dataExportApi.ts +73 -0
- package/lib/mail/directoryApi.ts +161 -0
- package/lib/mail/erasureRequestApi.ts +71 -0
- package/lib/mail/flaggedMessages.ts +80 -0
- package/lib/mail/focusedInboxOverridesApi.ts +64 -0
- package/lib/mail/labelsApi.ts +71 -0
- package/lib/mail/mailAddress.ts +76 -0
- package/lib/mail/mailApi.ts +1286 -0
- package/lib/mail/mailDetailHooks.ts +57 -0
- package/lib/mail/mailFilterRulesApi.ts +116 -0
- package/lib/mail/mailSignaturesApi.ts +84 -0
- package/lib/mail/mailboxAccessApi.ts +106 -0
- package/lib/mail/mailboxImportApi.ts +87 -0
- package/lib/mail/messageBodySanitizer.ts +129 -0
- package/lib/mail/pushClient.ts +375 -0
- package/lib/mail/sendEvents.ts +72 -0
- package/lib/mail/sendFailure.ts +98 -0
- package/lib/mail/senderListsApi.ts +161 -0
- package/lib/search/queryGrammar.ts +179 -0
- package/lib/search/searchApi.ts +199 -0
- package/lib/search/searchScoring.ts +46 -0
- package/lib/search/searchTier3.ts +406 -0
- package/lib/tasks/tasksApi.ts +128 -0
- package/lib/util/api.ts +318 -0
- package/lib/util/apiClientContext.ts +35 -0
- package/lib/util/apiQuery.ts +61 -0
- package/lib/util/clipboard.ts +55 -0
- package/lib/util/dateInput.ts +15 -0
- package/lib/util/timeZone.ts +33 -0
- package/lib/util/useCopyToClipboard.ts +48 -0
- package/lib/util/useIsMobile.ts +34 -0
- package/lib/videoconf/videoMeetingsApi.ts +144 -0
- package/package.json +10 -4
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
/**
|
|
6
|
+
* Typed wrappers over `@rapidmx/restapi`'s E2E encryption endpoints (`BaseKeyVaultRoute`,
|
|
7
|
+
* `BaseKeyLookupRoute`, `BaseEncryptionPolicyRoute` — mounted in `server` at `mail/mailboxes` and
|
|
8
|
+
* `system/encryption-policy`, see `src/{mongo,sql}/routes/{KeyVaultRoute,KeyLookupRoute,
|
|
9
|
+
* EncryptionPolicyRoute}.ts`). These calls carry only wrapped/ciphertext key material and public
|
|
10
|
+
* certificates — the server never sees an unwrapped private key or master key; see `crypto/masterKey.ts`
|
|
11
|
+
* and `crypto/keys.ts` for the client-side cryptography that produces the values passed here.
|
|
12
|
+
*/
|
|
13
|
+
import { ApiClient, ApiRequestError, withClient } from "../util/api.js";
|
|
14
|
+
|
|
15
|
+
/** A cryptographic public key used to sign or encrypt messages — safe to expose publicly. Mirrors
|
|
16
|
+
* `@rapidmx/restapi`'s `PublicKey` type exactly. */
|
|
17
|
+
export interface PublicKey {
|
|
18
|
+
/** Base64-encoded DER X.509 certificate. */
|
|
19
|
+
publicKey: string;
|
|
20
|
+
/** The key's type/format (e.g. `x509`). */
|
|
21
|
+
type: string;
|
|
22
|
+
useType: "sign" | "encrypt";
|
|
23
|
+
/** SHA-256 fingerprint of the certificate, hex encoded. */
|
|
24
|
+
fingerprint: string;
|
|
25
|
+
/** UTC timestamp (epoch ms) at which this key becomes valid. */
|
|
26
|
+
notBefore: number;
|
|
27
|
+
/** UTC timestamp (epoch ms) at which this key expires. */
|
|
28
|
+
notAfter: number;
|
|
29
|
+
/** UTC timestamp (epoch ms) at which this key was revoked, if applicable. */
|
|
30
|
+
revokedAt?: number;
|
|
31
|
+
/** Why the key was revoked, alongside `revokedAt`: `"superseded"` for a routine rotation (the key is only retired,
|
|
32
|
+
* so mail it signed stays verifiable), `"compromised"` for a key that must not be trusted. A revoked key with no
|
|
33
|
+
* reason (legacy data) is treated as compromised - see `isTrustedForVerification()`. */
|
|
34
|
+
revocationReason?: "superseded" | "compromised";
|
|
35
|
+
/** Base64-encoded DER X.509 certificate of this key's direct issuer, when known. restapi uses it to recognize a
|
|
36
|
+
* same-CA renewal (see `PreviousKey.replacement`); a UI can show it in a key-changed comparison. */
|
|
37
|
+
issuerCertificate?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** A private key encrypted under the mailbox's master key (MK). Mirrors `@rapidmx/restapi`'s
|
|
41
|
+
* `WrappedPrivateKey` exactly. */
|
|
42
|
+
export interface WrappedPrivateKey {
|
|
43
|
+
/** Base64-encoded AEAD ciphertext of the private key. */
|
|
44
|
+
ciphertext: string;
|
|
45
|
+
/** Base64-encoded AEAD nonce. */
|
|
46
|
+
nonce: string;
|
|
47
|
+
/** AEAD algorithm identifier (e.g. `AES-256-GCM`). */
|
|
48
|
+
algorithm: string;
|
|
49
|
+
fingerprint: string;
|
|
50
|
+
useType: "sign" | "encrypt";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** One wrapped copy of the mailbox master key (MK), per unlock method. Mirrors `@rapidmx/restapi`'s
|
|
54
|
+
* `MasterKeyWrap` exactly. */
|
|
55
|
+
export interface MasterKeyWrap {
|
|
56
|
+
method: "password" | "passkey" | "recovery" | "escrow";
|
|
57
|
+
/** Opaque identifier for the method instance (e.g. a WebAuthn credential ID). */
|
|
58
|
+
methodId?: string;
|
|
59
|
+
escrowScopeId?: string;
|
|
60
|
+
/** Base64-encoded AEAD ciphertext of the master key. */
|
|
61
|
+
ciphertext: string;
|
|
62
|
+
/** Base64-encoded AEAD nonce. */
|
|
63
|
+
nonce: string;
|
|
64
|
+
/** Base64-encoded KDF salt. */
|
|
65
|
+
salt: string;
|
|
66
|
+
/** KDF identifier and parameters (e.g. `argon2id:m=65536,t=3,p=4`). */
|
|
67
|
+
kdf: string;
|
|
68
|
+
schemeVersion: number;
|
|
69
|
+
createdAt: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface EncryptionPreference {
|
|
73
|
+
lastSeen?: number;
|
|
74
|
+
preferEncrypt: "mutual" | "nopreference";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** A newly observed key that differs from a contact's pinned key of the same `useType` - restapi records it instead of
|
|
78
|
+
* silently replacing the pin (the spec's Key Conflict Handling) until the user resolves it with `resolveKeyConflict()`.
|
|
79
|
+
* A contact holds at most one per `useType`. Mirrors `@rapidmx/restapi`'s `KeyConflict`. */
|
|
80
|
+
export interface KeyConflict {
|
|
81
|
+
useType: "sign" | "encrypt";
|
|
82
|
+
/** The key that was observed, in full, so a UI can compare it with the pinned one. */
|
|
83
|
+
observedKey: PublicKey;
|
|
84
|
+
/** UTC timestamp (epoch ms) at which the key was observed. */
|
|
85
|
+
observedAt: number;
|
|
86
|
+
/** Where it was observed: an incoming message's key header, or server-side Discovery. */
|
|
87
|
+
source: "header" | "discovery";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** A contact key that used to be pinned and was replaced - newest first, at most 5 per `useType` on a contact.
|
|
91
|
+
* `replacement` says how: `"automatic"` when restapi replaced an expired or revoked pinned key with one from the same
|
|
92
|
+
* CA issuer, `"user"` when the user accepted a key conflict. Mirrors `@rapidmx/restapi`'s `PreviousKey`. */
|
|
93
|
+
export interface PreviousKey extends PublicKey {
|
|
94
|
+
/** UTC timestamp (epoch ms) at which this key stopped being the pinned one. */
|
|
95
|
+
replacedAt: number;
|
|
96
|
+
replacement: "automatic" | "user";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** A key the user rejected when resolving a conflict, remembered so the same key isn't raised again. Mirrors an entry
|
|
100
|
+
* of `@rapidmx/restapi`'s `Contact.rejectedKeys`. */
|
|
101
|
+
export interface RejectedKey {
|
|
102
|
+
useType: "sign" | "encrypt";
|
|
103
|
+
fingerprint: string;
|
|
104
|
+
/** UTC timestamp (epoch ms) at which the key was rejected. */
|
|
105
|
+
rejectedAt: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** The wire shape `GET`/`POST`/`PUT`/`DELETE` `/mail/mailboxes/:id/keyvault*` return. */
|
|
109
|
+
export interface KeyVault {
|
|
110
|
+
wrappedKeys: WrappedPrivateKey[];
|
|
111
|
+
masterKeyWraps: MasterKeyWrap[];
|
|
112
|
+
/** How many times the vault's master key has been rotated (`0` for never, and for no vault yet). Send it back as
|
|
113
|
+
* `expectedMasterKeyGeneration` on a write whose key material was sealed under the master key read with this vault
|
|
114
|
+
* (`enrollKey()`, `startSignEnrollment()`, `addMasterKeyWrap()`, `rekey()`), so restapi refuses it with `409` if
|
|
115
|
+
* another device rotated the master key meanwhile. Absent from servers that don't track it yet. */
|
|
116
|
+
masterKeyGeneration?: number;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** The optional optimistic check restapi applies to vault writes carrying key material sealed under the master key. */
|
|
120
|
+
export interface ExpectedMasterKeyGeneration {
|
|
121
|
+
/** The `KeyVault.masterKeyGeneration` read alongside the master key this request's material is sealed under. When
|
|
122
|
+
* given and the vault's generation has moved on, restapi answers `409` instead of installing material nobody can
|
|
123
|
+
* open with the current master key. Omitted, the write is accepted as before. */
|
|
124
|
+
expectedMasterKeyGeneration?: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** `client`, given by every function below that calls the network, is an explicit `ApiClient` from `createApiClient()`
|
|
128
|
+
* (e.g. one account of a multi-account app) to call instead of the default global `apiFetch()` - see `withClient()`'s
|
|
129
|
+
* own doc comment in `util/api.ts`. Omitted (the default), every function here behaves exactly as before. */
|
|
130
|
+
export function getKeyVault(mailboxUid: string, client?: ApiClient): Promise<KeyVault> {
|
|
131
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** The most recently issued, currently-valid (non-revoked, non-expired) published key of the given use
|
|
135
|
+
* type — the one that should actually be used to sign/encrypt going forward. A mailbox or contact may
|
|
136
|
+
* have several of the same `useType` on file after a rotation; older ones are kept for decrypting old
|
|
137
|
+
* mail, never removed, per the spec's own key-lifecycle rules. Every revoked key is skipped, whatever its
|
|
138
|
+
* `revocationReason` - a superseded key may still verify old mail (`isTrustedForVerification()`) but is never used for
|
|
139
|
+
* new mail. Shared by `crypto/keySession.ts` (the
|
|
140
|
+
* mailbox's own keys) and `crypto/composeSecurity.ts` (a recipient's discovered keys). */
|
|
141
|
+
export function findActivePublicKey(keys: PublicKey[], useType: "sign" | "encrypt"): PublicKey | undefined {
|
|
142
|
+
const now = Date.now();
|
|
143
|
+
return keys
|
|
144
|
+
.filter((k) => k.useType === useType && !k.revokedAt && k.notAfter > now)
|
|
145
|
+
.sort((a, b) => b.notBefore - a.notBefore)[0];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Whether `key` may still be trusted to *verify* existing signatures - never whether to sign or encrypt with it (that is
|
|
150
|
+
* `findActivePublicKey()`, which skips every revoked key). Expired keys are trusted: mail signed while a key was valid
|
|
151
|
+
* stays verifiable after it expires. A key revoked with `revocationReason: "superseded"` (a routine rotation) is trusted
|
|
152
|
+
* for the same reason. A key revoked as `"compromised"`, or revoked with no reason (legacy data, treated as
|
|
153
|
+
* compromised), is never trusted, because a message's claimed signing time can't show it was signed before the
|
|
154
|
+
* compromise.
|
|
155
|
+
*/
|
|
156
|
+
export function isTrustedForVerification(key: PublicKey): boolean {
|
|
157
|
+
return !key.revokedAt || key.revocationReason === "superseded";
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The fingerprints (lowercased, de-duplicated) of every signing key in `keys` and `previousKeys` that is still trusted
|
|
162
|
+
* for verification (`isTrustedForVerification()`) - the trusted pins to pass to `messageSecurity.ts`'s
|
|
163
|
+
* `evaluateMessageSecurity()` for a `Contact` (its TOFU-pinned `keys` plus its `previousKeys`, which only key
|
|
164
|
+
* discovery, "trust this signer" and conflict resolution write) or a `Mailbox` (its own `keys`, so the user's own mail
|
|
165
|
+
* signed before their rotation still verifies).
|
|
166
|
+
*
|
|
167
|
+
* Key rotation continuity: a `PreviousKey` was pinned before it was replaced - by the user accepting a conflict
|
|
168
|
+
* (`replacement: "user"`) or by restapi's same-issuer renewal of an expired or revoked key (`"automatic"`, which moves
|
|
169
|
+
* the superseded key here with `revocationReason: "superseded"`) - so it is trusted for verification exactly like a
|
|
170
|
+
* current pin, and mail it signed before the rotation still verifies. Both replacement kinds are trusted alike, and the
|
|
171
|
+
* revocation rule is the same for current and previous keys: expired and superseded keys are trusted, compromised and
|
|
172
|
+
* reasonless revoked keys are not.
|
|
173
|
+
*/
|
|
174
|
+
export function signingKeyFingerprints(keys: PublicKey[] | undefined, previousKeys?: PreviousKey[]): string[] {
|
|
175
|
+
const fingerprints = [...(keys ?? []), ...(previousKeys ?? [])]
|
|
176
|
+
.filter((key) => key.useType === "sign" && isTrustedForVerification(key))
|
|
177
|
+
.map((key) => key.fingerprint.toLowerCase());
|
|
178
|
+
return [...new Set(fingerprints)];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface EnrollKeyInput extends ExpectedMasterKeyGeneration {
|
|
182
|
+
useType: "sign" | "encrypt";
|
|
183
|
+
/** PEM-encoded PKCS#10 CSR — required (and only meaningful) for `useType: "encrypt"`; the server
|
|
184
|
+
* calls its own internal CA against this CSR. */
|
|
185
|
+
csr?: string;
|
|
186
|
+
/** An already-issued PEM certificate — required (and only meaningful) for `useType: "sign"`. */
|
|
187
|
+
certificate?: string;
|
|
188
|
+
wrappedKey: Omit<WrappedPrivateKey, "fingerprint" | "useType">;
|
|
189
|
+
/** Only meaningful the very first time a mailbox enrolls a key at all (bootstraps its master key). */
|
|
190
|
+
masterKeyWraps?: MasterKeyWrap[];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Thrown by `enrollKey()` when `masterKeyWraps` were supplied (a first-time vault setup) but the mailbox's vault
|
|
195
|
+
* already has master-key wraps - e.g. another device or tab finished setting it up first. restapi answers `409`;
|
|
196
|
+
* this subclass (still an `ApiRequestError` with `status` 409) is only used once a re-read of the vault confirms it
|
|
197
|
+
* really has wraps, so an unrelated `409` (a lost optimistic-lock race) isn't mistaken for it. A caller should
|
|
198
|
+
* unlock the existing vault instead of enrolling a new master key.
|
|
199
|
+
*/
|
|
200
|
+
export class VaultAlreadyInitializedError extends ApiRequestError {
|
|
201
|
+
constructor(message: string, code?: string) {
|
|
202
|
+
super(message, 409, code);
|
|
203
|
+
this.name = "VaultAlreadyInitializedError";
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Enrolls a new signing or encryption key. See `EnrollKeyInput`'s own doc comments for which fields
|
|
208
|
+
* matter for which `useType`. Rejects with `VaultAlreadyInitializedError` when `masterKeyWraps` were supplied
|
|
209
|
+
* but the vault is already set up (see that class). */
|
|
210
|
+
export async function enrollKey(mailboxUid: string, input: EnrollKeyInput, client?: ApiClient): Promise<KeyVault> {
|
|
211
|
+
try {
|
|
212
|
+
return await withClient<KeyVault>(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault/keys`, {
|
|
213
|
+
method: "POST",
|
|
214
|
+
body: JSON.stringify(input),
|
|
215
|
+
});
|
|
216
|
+
} catch (err) {
|
|
217
|
+
if (err instanceof ApiRequestError && err.status === 409 && input.masterKeyWraps?.length) {
|
|
218
|
+
const vault = await getKeyVault(mailboxUid, client).catch(() => undefined);
|
|
219
|
+
if (vault && vault.masterKeyWraps.length > 0) {
|
|
220
|
+
throw new VaultAlreadyInitializedError(err.message, err.code);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
throw err;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface SignEnrollmentRequest extends ExpectedMasterKeyGeneration {
|
|
228
|
+
/** A PEM-encoded PKCS#10 CSR for the signing key pair to enroll. */
|
|
229
|
+
csr: string;
|
|
230
|
+
wrappedKey: Omit<WrappedPrivateKey, "fingerprint" | "useType">;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Where an automated enrollment is, in the order it normally goes. */
|
|
234
|
+
export type SignEnrollmentStage =
|
|
235
|
+
| "submitted"
|
|
236
|
+
| "awaiting-challenge"
|
|
237
|
+
| "challenge-answered"
|
|
238
|
+
| "validating"
|
|
239
|
+
| "issuing"
|
|
240
|
+
| "issued"
|
|
241
|
+
| "failed";
|
|
242
|
+
|
|
243
|
+
const SIGN_ENROLLMENT_STAGES: readonly string[] = [
|
|
244
|
+
"submitted",
|
|
245
|
+
"awaiting-challenge",
|
|
246
|
+
"challenge-answered",
|
|
247
|
+
"validating",
|
|
248
|
+
"issuing",
|
|
249
|
+
"issued",
|
|
250
|
+
"failed",
|
|
251
|
+
];
|
|
252
|
+
|
|
253
|
+
/** One step of the enrollment's progress, for a stepper: the server names the steps and says which one is under way. */
|
|
254
|
+
export interface SignEnrollmentStep {
|
|
255
|
+
id: string;
|
|
256
|
+
label: string;
|
|
257
|
+
state: "done" | "active" | "pending" | "failed";
|
|
258
|
+
/** When the step finished (or started), an ISO date. */
|
|
259
|
+
at?: string;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** The status of a started automated (RFC 8823 ACME) signing-certificate enrollment. Mirrors
|
|
263
|
+
* `@rapidmx/restapi`'s `EnrollmentResult`; every field after `error` is optional because an older server sends only
|
|
264
|
+
* `status`, `certificate` and `error` - callers must degrade to those. Everything the server sends is checked by
|
|
265
|
+
* `normalizeEnrollmentResult()` before it gets here. */
|
|
266
|
+
export interface EnrollmentResult {
|
|
267
|
+
status: "pending" | "issued" | "failed";
|
|
268
|
+
/** The issued certificate, PEM-encoded — present only once `status` is `"issued"`. Not needed
|
|
269
|
+
* client-side: once issued, restapi's own `AcmeEnrollmentDriverJob` auto-installs it into this
|
|
270
|
+
* mailbox's `KeyVault` server-side, using the `wrappedKey` already submitted in
|
|
271
|
+
* `startSignEnrollment()` — no further client action installs it. */
|
|
272
|
+
certificate?: string;
|
|
273
|
+
/** A human-readable reason — present only once `status` is `"failed"`. */
|
|
274
|
+
error?: string;
|
|
275
|
+
/** How this deployment issues the certificate: `rfc8823` is automatic (a public CA and an e-mail round trip), `manual` means an administrator uploads it. */
|
|
276
|
+
provider?: "manual" | "rfc8823";
|
|
277
|
+
/** The step the enrollment is at. */
|
|
278
|
+
stage?: SignEnrollmentStage;
|
|
279
|
+
/** All the steps, in order, each with its own state and time. */
|
|
280
|
+
stages?: SignEnrollmentStep[];
|
|
281
|
+
/** 0-100. */
|
|
282
|
+
progress?: number;
|
|
283
|
+
/** ISO dates: when the request was made, when the server last changed it, when the CA was last asked, and when it will next be. */
|
|
284
|
+
requestedAt?: string;
|
|
285
|
+
updatedAt?: string;
|
|
286
|
+
lastCheckedAt?: string;
|
|
287
|
+
nextCheckAt?: string;
|
|
288
|
+
/** A short note from the server about what it is doing or waiting for. */
|
|
289
|
+
note?: string;
|
|
290
|
+
/** A machine-readable reason for a failure, and whether asking for a new certificate is worth trying (a CA that could not be reached is `ca-unreachable`, `retryable`, and still `pending`). */
|
|
291
|
+
errorCode?: string;
|
|
292
|
+
retryable?: boolean;
|
|
293
|
+
/** Once issued. `installedAt` comes later: a job puts the certificate into the mailbox's key vault a few minutes after it is issued, so an
|
|
294
|
+
* enrollment can be `issued` and not yet installed (no `installedAt`, and the mailbox does not list the new key). */
|
|
295
|
+
issuedAt?: string;
|
|
296
|
+
installedAt?: string;
|
|
297
|
+
notAfter?: string;
|
|
298
|
+
serialNumber?: string;
|
|
299
|
+
issuer?: string;
|
|
300
|
+
subject?: string;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** The mailbox's current (most recent) enrollment: an `EnrollmentResult` that also says which one it is. */
|
|
304
|
+
export interface CurrentSignEnrollment extends EnrollmentResult {
|
|
305
|
+
enrollmentId: string;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const ENROLLMENT_STATUSES = new Set(["pending", "issued", "failed"]);
|
|
309
|
+
const STEP_STATES = new Set(["done", "active", "pending", "failed"]);
|
|
310
|
+
const ENROLLMENT_TEXT_FIELDS = [
|
|
311
|
+
"certificate",
|
|
312
|
+
"error",
|
|
313
|
+
"requestedAt",
|
|
314
|
+
"updatedAt",
|
|
315
|
+
"lastCheckedAt",
|
|
316
|
+
"nextCheckAt",
|
|
317
|
+
"errorCode",
|
|
318
|
+
"note",
|
|
319
|
+
"issuedAt",
|
|
320
|
+
"installedAt",
|
|
321
|
+
"notAfter",
|
|
322
|
+
"serialNumber",
|
|
323
|
+
"issuer",
|
|
324
|
+
"subject",
|
|
325
|
+
] as const;
|
|
326
|
+
|
|
327
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
328
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Reads an enrollment status from the network: keeps `status` (an unknown value counts as still `pending`, the safe reading) and
|
|
333
|
+
* whichever optional fields have the right type, drops the rest - an older server's answer comes through as it always did, and a
|
|
334
|
+
* newer one's malformed field cannot break the page. `progress` is clamped to 0-100; a step needs an id, a label and a known state.
|
|
335
|
+
*/
|
|
336
|
+
export function normalizeEnrollmentResult(raw: unknown): EnrollmentResult {
|
|
337
|
+
const source = isRecord(raw) ? raw : {};
|
|
338
|
+
const result: EnrollmentResult = {
|
|
339
|
+
status: ENROLLMENT_STATUSES.has(source.status as string) ? (source.status as EnrollmentResult["status"]) : "pending",
|
|
340
|
+
};
|
|
341
|
+
for (const field of ENROLLMENT_TEXT_FIELDS) {
|
|
342
|
+
if (typeof source[field] === "string") {
|
|
343
|
+
result[field] = source[field];
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (source.provider === "manual" || source.provider === "rfc8823") {
|
|
347
|
+
result.provider = source.provider;
|
|
348
|
+
}
|
|
349
|
+
if (typeof source.stage === "string" && SIGN_ENROLLMENT_STAGES.includes(source.stage)) {
|
|
350
|
+
result.stage = source.stage as SignEnrollmentStage;
|
|
351
|
+
}
|
|
352
|
+
if (Array.isArray(source.stages)) {
|
|
353
|
+
result.stages = source.stages
|
|
354
|
+
.filter((step) => isRecord(step) && typeof step.id === "string" && typeof step.label === "string" && STEP_STATES.has(step.state as string))
|
|
355
|
+
.map((step: Record<string, unknown>) => ({
|
|
356
|
+
id: step.id as string,
|
|
357
|
+
label: step.label as string,
|
|
358
|
+
state: step.state as SignEnrollmentStep["state"],
|
|
359
|
+
...(typeof step.at === "string" ? { at: step.at } : {}),
|
|
360
|
+
}));
|
|
361
|
+
}
|
|
362
|
+
if (typeof source.progress === "number" && Number.isFinite(source.progress)) {
|
|
363
|
+
result.progress = Math.min(100, Math.max(0, source.progress));
|
|
364
|
+
}
|
|
365
|
+
if (typeof source.retryable === "boolean") {
|
|
366
|
+
result.retryable = source.retryable;
|
|
367
|
+
}
|
|
368
|
+
return result;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/** Starts an automated (RFC 8823 email-reply-00 ACME) public-CA signing-certificate enrollment —
|
|
372
|
+
* only meaningful when the deployment has `mail:pki:signing_enrollment:backend` set to `"rfc8823"`
|
|
373
|
+
* (a `"manual"`-backend deployment's `SigningCertificateEnrollment` throws instead). Genuinely
|
|
374
|
+
* asynchronous — the CA issues the certificate via a real email round-trip, likely minutes away, not
|
|
375
|
+
* synchronous the way `enrollKey()`'s encryption-key path is — poll `checkSignEnrollmentStatus()`
|
|
376
|
+
* rather than expecting an immediate result. `wrappedKey` is submitted upfront (this server never sees
|
|
377
|
+
* an unwrapped private key) so the eventual install needs no further client action at all. */
|
|
378
|
+
export function startSignEnrollment(
|
|
379
|
+
mailboxUid: string,
|
|
380
|
+
input: SignEnrollmentRequest,
|
|
381
|
+
client?: ApiClient,
|
|
382
|
+
): Promise<{ enrollmentId: string }> {
|
|
383
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault/keys/sign-enrollment`, {
|
|
384
|
+
method: "POST",
|
|
385
|
+
body: JSON.stringify(input),
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/** Reports the current status of a previously started automated enrollment — see
|
|
390
|
+
* `startSignEnrollment()`. Answers from what the server already knows; `checkSignEnrollmentNow()` asks the CA. */
|
|
391
|
+
export async function checkSignEnrollmentStatus(mailboxUid: string, enrollmentId: string, client?: ApiClient): Promise<EnrollmentResult> {
|
|
392
|
+
return normalizeEnrollmentResult(
|
|
393
|
+
await withClient<unknown>(
|
|
394
|
+
client,
|
|
395
|
+
`/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault/keys/sign-enrollment/${encodeURIComponent(enrollmentId)}`,
|
|
396
|
+
),
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/** The mailbox's current (most recent) signing-certificate enrollment, or `null` when it has never had one - so a second device or
|
|
401
|
+
* a fresh page learns of one started elsewhere. Needs no stored enrollment id. */
|
|
402
|
+
export async function getCurrentSignEnrollment(mailboxUid: string, client?: ApiClient): Promise<CurrentSignEnrollment | null> {
|
|
403
|
+
let raw: unknown;
|
|
404
|
+
try {
|
|
405
|
+
raw = await withClient<unknown>(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault/keys/sign-enrollment`);
|
|
406
|
+
} catch (err) {
|
|
407
|
+
if (err instanceof ApiRequestError && err.status === 404) {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
throw err;
|
|
411
|
+
}
|
|
412
|
+
const enrollmentId = isRecord(raw) && typeof raw.enrollmentId === "string" ? raw.enrollmentId : undefined;
|
|
413
|
+
return enrollmentId ? { ...normalizeEnrollmentResult(raw), enrollmentId } : null;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/** How long a "check now" is refused for after a `429`, when the server doesn't say (it answers `Retry-After`, which `apiFetch()` does not surface). */
|
|
417
|
+
export const CHECK_NOW_DEFAULT_RETRY_SECONDS = 10;
|
|
418
|
+
|
|
419
|
+
/** How many seconds to wait before asking again after `checkSignEnrollmentNow()` was refused with `429`: the body's `retryAfter` (seconds)
|
|
420
|
+
* when the server put one there, else `CHECK_NOW_DEFAULT_RETRY_SECONDS`. `undefined` for any other error. */
|
|
421
|
+
export function checkNowRetryAfterSeconds(err: unknown): number | undefined {
|
|
422
|
+
if (!(err instanceof ApiRequestError) || err.status !== 429) {
|
|
423
|
+
return undefined;
|
|
424
|
+
}
|
|
425
|
+
const retryAfter = isRecord(err.details) ? err.details.retryAfter : undefined;
|
|
426
|
+
return typeof retryAfter === "number" && Number.isFinite(retryAfter) && retryAfter > 0
|
|
427
|
+
? Math.ceil(retryAfter)
|
|
428
|
+
: CHECK_NOW_DEFAULT_RETRY_SECONDS;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** Forces an immediate re-check of an enrollment with the CA (instead of waiting for the server's own schedule) and returns its
|
|
432
|
+
* status. The server refuses with `429` when asked again within about ten seconds - see `checkNowRetryAfterSeconds()`. */
|
|
433
|
+
export async function checkSignEnrollmentNow(mailboxUid: string, enrollmentId: string, client?: ApiClient): Promise<EnrollmentResult> {
|
|
434
|
+
return normalizeEnrollmentResult(
|
|
435
|
+
await withClient<unknown>(
|
|
436
|
+
client,
|
|
437
|
+
`/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault/keys/sign-enrollment/${encodeURIComponent(enrollmentId)}/check`,
|
|
438
|
+
{ method: "POST" },
|
|
439
|
+
),
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/** Cancels a pending automated enrollment of this mailbox, so no key is installed from it afterwards, and returns its
|
|
444
|
+
* resulting status. Owner-only. `rekey()` is refused (409) while an enrollment holding a wrapped key is in flight, so
|
|
445
|
+
* this is how an owner with an enrollment stuck at the CA gets to rotate their keys. */
|
|
446
|
+
export function cancelSignEnrollment(mailboxUid: string, enrollmentId: string, client?: ApiClient): Promise<EnrollmentResult> {
|
|
447
|
+
return withClient(
|
|
448
|
+
client,
|
|
449
|
+
`/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault/keys/sign-enrollment/${encodeURIComponent(enrollmentId)}`,
|
|
450
|
+
{ method: "DELETE" },
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/** An escrow scope's public key, exposed only via `getEscrowInfo()` below. Mirrors `@rapidmx/restapi`'s
|
|
455
|
+
* `EscrowScopePublicKey` exactly - the same shape as `PublicKey` minus `useType` (an escrow scope's key
|
|
456
|
+
* is only ever used for encryption, never signing). */
|
|
457
|
+
export interface EscrowScopePublicKey {
|
|
458
|
+
/** Base64-encoded DER X.509 certificate. */
|
|
459
|
+
publicKey: string;
|
|
460
|
+
type: string;
|
|
461
|
+
fingerprint: string;
|
|
462
|
+
notBefore: number;
|
|
463
|
+
notAfter: number;
|
|
464
|
+
revokedAt?: number;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/** The wire shape `GET /mail/mailboxes/:id/escrow-info` returns - see that route's own doc comment
|
|
468
|
+
* (`server`'s `BaseEscrowInfoRoute`) for why this exists as a `server`-only proxy rather than a restapi
|
|
469
|
+
* route: `@rapidmx/restapi`'s own `GET /escrow-scopes/:id` is trusted-admin-only, with no lighter
|
|
470
|
+
* alternative a mailbox owner could use to read the one scope their own mailbox is assigned to. */
|
|
471
|
+
export interface EscrowInfo {
|
|
472
|
+
escrowScopeId: string;
|
|
473
|
+
publicKey: EscrowScopePublicKey;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/** Fetches `{escrowScopeId, publicKey}` for the `EscrowScope` this mailbox is currently assigned to
|
|
477
|
+
* (`Mailbox.escrowScopeId`, an admin-only assignment - see `EscrowInfo`'s own doc comment). 404s if the
|
|
478
|
+
* mailbox has no escrow scope assigned, the scope no longer exists, or the caller can't access this
|
|
479
|
+
* mailbox. Used by `crypto/masterKeyWraps.ts`'s `buildEscrowWrap()` to get the certificate MK is wrapped
|
|
480
|
+
* against. */
|
|
481
|
+
export function getEscrowInfo(mailboxUid: string, client?: ApiClient): Promise<EscrowInfo> {
|
|
482
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/escrow-info`);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/** Adds a wrapped copy of the master key for a new unlock method (e.g. registering a new passkey),
|
|
486
|
+
* independent of key enrollment. Requires an already-initialized vault. `expectedMasterKeyGeneration`, when given, is
|
|
487
|
+
* sent alongside the wrap (see `ExpectedMasterKeyGeneration`): a `409` then means the master key was rotated since. */
|
|
488
|
+
export function addMasterKeyWrap(
|
|
489
|
+
mailboxUid: string,
|
|
490
|
+
wrap: MasterKeyWrap,
|
|
491
|
+
expectedMasterKeyGeneration?: number,
|
|
492
|
+
client?: ApiClient,
|
|
493
|
+
): Promise<KeyVault> {
|
|
494
|
+
const body = expectedMasterKeyGeneration === undefined ? wrap : { ...wrap, expectedMasterKeyGeneration };
|
|
495
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault/wraps`, {
|
|
496
|
+
method: "POST",
|
|
497
|
+
body: JSON.stringify(body),
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/** Removes a wrapped copy of the master key for one unlock method. `methodId` is required whenever more
|
|
502
|
+
* than one wrap could share the same `method` (e.g. multiple passkeys). This alone does NOT revoke
|
|
503
|
+
* access for anyone who already captured the wrapped blob — see `rekey()`. */
|
|
504
|
+
export function removeMasterKeyWrap(mailboxUid: string, method: string, methodId?: string, client?: ApiClient): Promise<KeyVault> {
|
|
505
|
+
const query = methodId ? `?methodId=${encodeURIComponent(methodId)}` : "";
|
|
506
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault/wraps/${encodeURIComponent(method)}${query}`, {
|
|
507
|
+
method: "DELETE",
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
export interface RekeyInput extends ExpectedMasterKeyGeneration {
|
|
512
|
+
wrappedKeys: WrappedPrivateKey[];
|
|
513
|
+
/** Every wrap of the new master key. For a mailbox assigned an escrow scope, this must include a fresh escrow wrap
|
|
514
|
+
* for that scope (`buildEscrowWrap()`): `rekey()` drops the old escrow wraps and refuses (409) an escrowed
|
|
515
|
+
* mailbox's rekey without a replacement. */
|
|
516
|
+
masterKeyWraps: MasterKeyWrap[];
|
|
517
|
+
keys: PublicKey[];
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/** Full, atomic replacement of the mailbox's key-vault contents — the only real revocation mechanism
|
|
521
|
+
* for a captured wrap. Restricted server-side to the mailbox's actual owner. Refused (409) while a signing enrollment
|
|
522
|
+
* holding a wrapped key is in flight (see `cancelSignEnrollment()`), or when an escrowed mailbox's request carries no
|
|
523
|
+
* replacement escrow wrap. */
|
|
524
|
+
export function rekey(mailboxUid: string, input: RekeyInput, client?: ApiClient): Promise<KeyVault> {
|
|
525
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keyvault/rekey`, {
|
|
526
|
+
method: "PUT",
|
|
527
|
+
body: JSON.stringify(input),
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/** The wire shape `GET /mail/mailboxes/:id/keys/lookup`, `POST .../keys/trust` and `POST .../keys/resolve` return: the
|
|
532
|
+
* contact's resulting key state. */
|
|
533
|
+
export interface KeyLookupResult {
|
|
534
|
+
keys: PublicKey[];
|
|
535
|
+
encryptPreference?: EncryptionPreference;
|
|
536
|
+
/** Unresolved key conflicts, at most one per `useType` - see `resolveKeyConflict()`. */
|
|
537
|
+
keyConflicts?: KeyConflict[];
|
|
538
|
+
/** Keys that were pinned before, newest first - see `PreviousKey`. */
|
|
539
|
+
previousKeys?: PreviousKey[];
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/** Server-side Discovery: the server itself performs the `_rapidmx` DNS lookup and remote key-endpoint
|
|
543
|
+
* fetch (browsers can't do DNS TXT lookups, and a direct cross-origin fetch would hit CORS), persisting
|
|
544
|
+
* the result onto a `Contact` in the caller's own address book. MUST be called lazily at compose time,
|
|
545
|
+
* never on message receipt (see `specs/end-to-end_encryption.md`'s "Discovery is Server-Side"). */
|
|
546
|
+
export function lookupKeys(mailboxUid: string, addr: string, client?: ApiClient): Promise<KeyLookupResult> {
|
|
547
|
+
const query = new URLSearchParams({ addr });
|
|
548
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keys/lookup?${query.toString()}`);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/** What `trustSigner()` pins: the sender's address and the certificate that signed their message. */
|
|
552
|
+
export interface TrustSignerInput {
|
|
553
|
+
address: string;
|
|
554
|
+
/** Base64 DER of the signer certificate - `MessageSecurityResult.signerCertificate`. */
|
|
555
|
+
certificate: string;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Thrown by `trustSigner()` when restapi answers `409`: a different signing key is already pinned for that address, so
|
|
560
|
+
* trusting this one would silently replace it. Still an `ApiRequestError` (`status` 409). A UI should show this as a
|
|
561
|
+
* key conflict for the user to resolve deliberately, not retry.
|
|
562
|
+
*/
|
|
563
|
+
export class SignerKeyConflictError extends ApiRequestError {
|
|
564
|
+
constructor(message: string, code?: string) {
|
|
565
|
+
super(message, 409, code);
|
|
566
|
+
this.name = "SignerKeyConflictError";
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* "Trust this signer": pins `certificate` as `address`'s signing key on the caller's contact for that address
|
|
572
|
+
* (`POST /mail/mailboxes/:id/keys/trust`), after which `evaluateMessageSecurity()` given that contact's pins reports
|
|
573
|
+
* the sender's signed mail as verified. Resolves with the contact's resulting key state, the same shape as
|
|
574
|
+
* `lookupKeys()`. Rejects with `SignerKeyConflictError` on `409` (a different signing key is already pinned), and a
|
|
575
|
+
* plain `ApiRequestError` for `400` (an invalid certificate, or one that doesn't name `address`) and `403`/`404`.
|
|
576
|
+
*/
|
|
577
|
+
export async function trustSigner(mailboxUid: string, input: TrustSignerInput, client?: ApiClient): Promise<KeyLookupResult> {
|
|
578
|
+
try {
|
|
579
|
+
return await withClient<KeyLookupResult>(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keys/trust`, {
|
|
580
|
+
method: "POST",
|
|
581
|
+
body: JSON.stringify({ address: input.address, certificate: input.certificate }),
|
|
582
|
+
});
|
|
583
|
+
} catch (err) {
|
|
584
|
+
if (err instanceof ApiRequestError && err.status === 409) {
|
|
585
|
+
throw new SignerKeyConflictError(err.message, err.code);
|
|
586
|
+
}
|
|
587
|
+
throw err;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/** What `resolveKeyConflict()` sends to `POST /mail/mailboxes/:id/keys/resolve`. */
|
|
592
|
+
export interface ResolveKeyConflictInput {
|
|
593
|
+
/** The contact's email address. */
|
|
594
|
+
address: string;
|
|
595
|
+
/** Which pinned key's conflict to resolve. */
|
|
596
|
+
useType: "sign" | "encrypt";
|
|
597
|
+
/** `"accept"` pins the new key and moves the old one into `previousKeys` (`replacement: "user"`); `"reject"` keeps
|
|
598
|
+
* the pinned key and remembers the rejected fingerprint in `Contact.rejectedKeys`. */
|
|
599
|
+
action: "accept" | "reject";
|
|
600
|
+
/** The fingerprint of the pinned key the user was shown. restapi refuses with `409` (`PinnedKeyChangedError`) when
|
|
601
|
+
* the pinned key is no longer this one, so a decision made against a stale comparison is never applied. */
|
|
602
|
+
expectedPinnedFingerprint: string;
|
|
603
|
+
/** For `"accept"`: base64 DER of the certificate to pin (e.g. `MessageSecurityResult.signerCertificate` of a
|
|
604
|
+
* `signer_key_changed` result). Omitted, restapi pins the recorded conflict's `observedKey`. */
|
|
605
|
+
certificate?: string;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/** The contact's resulting key state after `resolveKeyConflict()`. */
|
|
609
|
+
export type ResolveKeyConflictResult = KeyLookupResult;
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Thrown by `resolveKeyConflict()` when restapi answers `409`: the contact's pinned key is no longer
|
|
613
|
+
* `expectedPinnedFingerprint` (another device or an automatic renewal changed it meanwhile). Still an `ApiRequestError`
|
|
614
|
+
* (`status` 409). A UI should reload the key state and ask again rather than retry.
|
|
615
|
+
*/
|
|
616
|
+
export class PinnedKeyChangedError extends ApiRequestError {
|
|
617
|
+
constructor(message: string, code?: string) {
|
|
618
|
+
super(message, 409, code);
|
|
619
|
+
this.name = "PinnedKeyChangedError";
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Resolves a contact's key conflict (`POST /mail/mailboxes/:id/keys/resolve`) - see `ResolveKeyConflictInput` for what
|
|
625
|
+
* each action does. Resolves with the contact's resulting key state. Rejects with `PinnedKeyChangedError` on `409`, and
|
|
626
|
+
* a plain `ApiRequestError` for `400` (an invalid body or certificate), `403` (no rights) and `404` (no such contact, no
|
|
627
|
+
* pinned key, or no recorded conflict when one is needed).
|
|
628
|
+
*/
|
|
629
|
+
export async function resolveKeyConflict(
|
|
630
|
+
mailboxUid: string,
|
|
631
|
+
input: ResolveKeyConflictInput,
|
|
632
|
+
client?: ApiClient,
|
|
633
|
+
): Promise<ResolveKeyConflictResult> {
|
|
634
|
+
const body = {
|
|
635
|
+
address: input.address,
|
|
636
|
+
useType: input.useType,
|
|
637
|
+
action: input.action,
|
|
638
|
+
expectedPinnedFingerprint: input.expectedPinnedFingerprint,
|
|
639
|
+
...(input.certificate !== undefined ? { certificate: input.certificate } : {}),
|
|
640
|
+
};
|
|
641
|
+
try {
|
|
642
|
+
return await withClient<ResolveKeyConflictResult>(client, `/mail/mailboxes/${encodeURIComponent(mailboxUid)}/keys/resolve`, {
|
|
643
|
+
method: "POST",
|
|
644
|
+
body: JSON.stringify(body),
|
|
645
|
+
});
|
|
646
|
+
} catch (err) {
|
|
647
|
+
if (err instanceof ApiRequestError && err.status === 409) {
|
|
648
|
+
throw new PinnedKeyChangedError(err.message, err.code);
|
|
649
|
+
}
|
|
650
|
+
throw err;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
export type PolicyState ="automatic" | "optional" | "prohibited";
|
|
655
|
+
|
|
656
|
+
export interface EncryptionPolicy {
|
|
657
|
+
encryptSameOrg: PolicyState;
|
|
658
|
+
encryptFederated: PolicyState;
|
|
659
|
+
encryptExternal: PolicyState;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/** The system-wide encryption policy (readable by any authenticated user, used to decide what encryption
|
|
663
|
+
* controls a compose UI should offer). */
|
|
664
|
+
export function getEncryptionPolicy(client?: ApiClient): Promise<EncryptionPolicy> {
|
|
665
|
+
return withClient(client, `/system/encryption-policy`);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/** Admin-only (`RequiresTrustedRole`) — updates the system-wide encryption policy. */
|
|
669
|
+
export function updateEncryptionPolicy(patch: Partial<EncryptionPolicy>, client?: ApiClient): Promise<EncryptionPolicy> {
|
|
670
|
+
return withClient(client, `/system/encryption-policy`, {
|
|
671
|
+
method: "PUT",
|
|
672
|
+
body: JSON.stringify(patch),
|
|
673
|
+
});
|
|
674
|
+
}
|