@rapidmx/web-client 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +27 -23
- 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 +2 -2
- 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 +7 -5
- package/apps/shared/components/mail/ConversationThreadPane.tsx +26 -15
- 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 +32 -30
- 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 +2 -2
- package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +9 -7
- 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/messageExport.ts +1 -1
- package/apps/shared/components/mail/reading/printMessage.ts +2 -2
- 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/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 +57 -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.js +26 -22
- 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 +1 -1
- 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 +6 -4
- package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +3 -3
- package/dist/apps/shared/components/mail/ConversationThreadPane.js +13 -11
- 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 +30 -28
- 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 +1 -1
- package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +1 -1
- package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +9 -7
- 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/messageExport.js +1 -1
- package/dist/apps/shared/components/mail/reading/printMessage.d.ts +2 -2
- 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/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 +54 -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,504 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
/**
|
|
6
|
+
* A small, dependency-free MIME (RFC 5322 / RFC 2045-2047) parser used by `smimeMessage.ts` and
|
|
7
|
+
* `messageSecurity.ts` to read *received* messages - which, unlike this package's own output, can come
|
|
8
|
+
* from any foreign MUA/MTA. It deliberately covers exactly what S/MIME evaluation needs and nothing more:
|
|
9
|
+
*
|
|
10
|
+
* header unfolding (RFC 5322 §2.2.3) and CRLF-or-bare-LF line endings; case-insensitive RFC 2045
|
|
11
|
+
* `type/subtype; name=value` parameters, quoted or unquoted; RFC 2046 multipart splitting with
|
|
12
|
+
* preamble/epilogue, transport padding after the delimiter, and delimiters only recognized at the start
|
|
13
|
+
* of a line; `Content-Transfer-Encoding` decoding (base64, quoted-printable; 7bit/8bit/binary pass
|
|
14
|
+
* through) plus `charset` decoding via `TextDecoder`; and picking the displayable body (text/html
|
|
15
|
+
* preferred, text/plain otherwise) out of a nested multipart.
|
|
16
|
+
*
|
|
17
|
+
* **Binary strings.** Received message source is handled as a "binary string": one UTF-16 code unit per
|
|
18
|
+
* byte (0x00-0xFF), which is what `mailApi.ts`'s `getMessageRawContent()` returns (it reads the response
|
|
19
|
+
* as bytes and decodes them as Latin-1) and what decrypted CMS content is converted to. That keeps an
|
|
20
|
+
* 8bit body's bytes intact until its own `charset` is known, and keeps signed bytes verifiable exactly.
|
|
21
|
+
* A string containing any code unit above 0xFF can't be a binary string, so it is treated as already
|
|
22
|
+
* decoded text and UTF-8 encoded wherever bytes are needed (the pre-round-4 convention) - see
|
|
23
|
+
* `binaryStringToBytes()`.
|
|
24
|
+
*
|
|
25
|
+
* Not supported (documented, not silently wrong): RFC 2231 parameter continuations/charset-encoded
|
|
26
|
+
* parameters - not needed to classify, decrypt, or verify a message, and left verbatim. RFC 2047
|
|
27
|
+
* encoded-words are decoded only where text is shown to a user (`decodeHeaderText()`); raw header values
|
|
28
|
+
* (`MimeEntity.headers`) stay verbatim so header comparisons remain exact.
|
|
29
|
+
*/
|
|
30
|
+
/** Maximum multipart nesting `extractDisplayBody()` descends into - a hostile message can nest
|
|
31
|
+
* arbitrarily deep, and nothing legitimate needs more than a handful of levels. */
|
|
32
|
+
const MAX_MULTIPART_DEPTH = 8;
|
|
33
|
+
/** Splits a MIME entity into its header fields and body. Never throws. */
|
|
34
|
+
export function parseMimeEntity(entity) {
|
|
35
|
+
let rawHeaderBlock;
|
|
36
|
+
let body;
|
|
37
|
+
const leading = /^\r?\n/.exec(entity);
|
|
38
|
+
if (leading) {
|
|
39
|
+
// An entity whose very first line is blank has no headers at all (RFC 2046 §5.1.1 - a body part
|
|
40
|
+
// with no header fields defaults to text/plain; charset=us-ascii).
|
|
41
|
+
rawHeaderBlock = "";
|
|
42
|
+
body = entity.slice(leading[0].length);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const separator = /\r?\n\r?\n/.exec(entity);
|
|
46
|
+
rawHeaderBlock = separator ? entity.slice(0, separator.index) : entity;
|
|
47
|
+
body = separator ? entity.slice(separator.index + separator[0].length) : "";
|
|
48
|
+
}
|
|
49
|
+
const fields = [];
|
|
50
|
+
const headers = {};
|
|
51
|
+
const unfolded = rawHeaderBlock.replace(/\r?\n(?=[ \t])/g, "");
|
|
52
|
+
for (const line of unfolded.split(/\r?\n/)) {
|
|
53
|
+
const colonIndex = line.indexOf(":");
|
|
54
|
+
if (colonIndex <= 0) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const name = line.slice(0, colonIndex).trim();
|
|
58
|
+
const value = line.slice(colonIndex + 1).trim();
|
|
59
|
+
fields.push({ name, value });
|
|
60
|
+
const key = name.toLowerCase();
|
|
61
|
+
if (!(key in headers)) {
|
|
62
|
+
headers[key] = value;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { fields, headers, rawHeaderBlock, body };
|
|
66
|
+
}
|
|
67
|
+
/** Parses an RFC 2045 parameterized header value (`Content-Type`, `Content-Disposition`). */
|
|
68
|
+
export function parseParameterizedHeader(headerValue) {
|
|
69
|
+
const segments = [];
|
|
70
|
+
let current = "";
|
|
71
|
+
let inQuotes = false;
|
|
72
|
+
const input = headerValue ?? "";
|
|
73
|
+
for (let i = 0; i < input.length; i++) {
|
|
74
|
+
const ch = input[i];
|
|
75
|
+
if (inQuotes && ch === "\\" && i + 1 < input.length) {
|
|
76
|
+
current += input[++i];
|
|
77
|
+
}
|
|
78
|
+
else if (ch === '"') {
|
|
79
|
+
inQuotes = !inQuotes;
|
|
80
|
+
}
|
|
81
|
+
else if (ch === ";" && !inQuotes) {
|
|
82
|
+
segments.push(current);
|
|
83
|
+
current = "";
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
current += ch;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
segments.push(current);
|
|
90
|
+
const [main, ...rest] = segments;
|
|
91
|
+
const params = {};
|
|
92
|
+
for (const segment of rest) {
|
|
93
|
+
const eq = segment.indexOf("=");
|
|
94
|
+
const name = segment.slice(0, Math.max(eq, 0)).trim().toLowerCase();
|
|
95
|
+
if (name && !(name in params)) {
|
|
96
|
+
params[name] = segment.slice(eq + 1).trim();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return { value: main.trim().toLowerCase(), params };
|
|
100
|
+
}
|
|
101
|
+
function escapeRegExp(value) {
|
|
102
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Splits a multipart body on `boundary` per RFC 2046 §5.1.1: a delimiter is `--boundary` at the start of
|
|
106
|
+
* a line (optionally followed by transport-padding whitespace), the CRLF preceding it belongs to the
|
|
107
|
+
* delimiter (not the previous part), text before the first delimiter is preamble and text after the close
|
|
108
|
+
* delimiter (`--boundary--`) is epilogue - both discarded. Each returned part is the exact text between
|
|
109
|
+
* delimiter lines, which is what a `multipart/signed` signature covers.
|
|
110
|
+
*/
|
|
111
|
+
export function splitMultipart(body, boundary) {
|
|
112
|
+
const delimiter = new RegExp(`(?:^|\\r?\\n)--${escapeRegExp(boundary)}(--)?[ \\t]*(?=\\r?\\n|$)`, "g");
|
|
113
|
+
const parts = [];
|
|
114
|
+
let partStart = -1;
|
|
115
|
+
let match;
|
|
116
|
+
while ((match = delimiter.exec(body)) !== null) {
|
|
117
|
+
if (partStart !== -1) {
|
|
118
|
+
parts.push(body.slice(partStart, Math.max(partStart, match.index)));
|
|
119
|
+
}
|
|
120
|
+
if (match[1]) {
|
|
121
|
+
return parts;
|
|
122
|
+
}
|
|
123
|
+
const end = match.index + match[0].length;
|
|
124
|
+
partStart = end + (body.startsWith("\r\n", end) ? 2 : body.startsWith("\n", end) ? 1 : 0);
|
|
125
|
+
}
|
|
126
|
+
// No close delimiter (a truncated message): whatever follows the last delimiter is still a part.
|
|
127
|
+
if (partStart !== -1) {
|
|
128
|
+
parts.push(body.slice(partStart));
|
|
129
|
+
}
|
|
130
|
+
return parts;
|
|
131
|
+
}
|
|
132
|
+
/** Returns the lowercased, trimmed `Content-Transfer-Encoding` mechanism, or `undefined`. */
|
|
133
|
+
function transferEncodingOf(entity) {
|
|
134
|
+
return entity.headers["content-transfer-encoding"]?.trim().toLowerCase();
|
|
135
|
+
}
|
|
136
|
+
/** Decodes a base64 body into bytes, ignoring whitespace/line breaks. Returns `undefined` for invalid
|
|
137
|
+
* base64 rather than throwing. */
|
|
138
|
+
export function decodeBase64Text(text) {
|
|
139
|
+
try {
|
|
140
|
+
const binary = atob(text.replace(/\s+/g, ""));
|
|
141
|
+
const bytes = new Uint8Array(binary.length);
|
|
142
|
+
for (let i = 0; i < binary.length; i++) {
|
|
143
|
+
bytes[i] = binary.charCodeAt(i);
|
|
144
|
+
}
|
|
145
|
+
return bytes;
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/** `true` when every code unit of `value` is at most 0xFF - i.e. it can be a binary string (see this
|
|
152
|
+
* module's doc comment). */
|
|
153
|
+
export function isBinaryString(value) {
|
|
154
|
+
for (let i = 0; i < value.length; i++) {
|
|
155
|
+
if (value.charCodeAt(i) > 0xff) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
/** Converts a binary string to its bytes, or - for a string that can't be one (a code unit above 0xFF) -
|
|
162
|
+
* to its UTF-8 encoding. */
|
|
163
|
+
export function binaryStringToBytes(value) {
|
|
164
|
+
if (!isBinaryString(value)) {
|
|
165
|
+
return new TextEncoder().encode(value);
|
|
166
|
+
}
|
|
167
|
+
const bytes = new Uint8Array(value.length);
|
|
168
|
+
for (let i = 0; i < value.length; i++) {
|
|
169
|
+
bytes[i] = value.charCodeAt(i);
|
|
170
|
+
}
|
|
171
|
+
return bytes;
|
|
172
|
+
}
|
|
173
|
+
/** Converts bytes to a binary string (one code unit per byte), in chunks so a large message never exceeds
|
|
174
|
+
* the engine's argument-count limit. */
|
|
175
|
+
export function bytesToBinaryString(bytes) {
|
|
176
|
+
const CHUNK = 0x8000;
|
|
177
|
+
const pieces = [];
|
|
178
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
179
|
+
pieces.push(String.fromCharCode(...bytes.subarray(i, i + CHUNK)));
|
|
180
|
+
}
|
|
181
|
+
return pieces.join("");
|
|
182
|
+
}
|
|
183
|
+
function hexValue(code) {
|
|
184
|
+
if (code >= 0x30 && code <= 0x39)
|
|
185
|
+
return code - 0x30;
|
|
186
|
+
if (code >= 0x41 && code <= 0x46)
|
|
187
|
+
return code - 0x37;
|
|
188
|
+
if (code >= 0x61 && code <= 0x66)
|
|
189
|
+
return code - 0x57;
|
|
190
|
+
return -1;
|
|
191
|
+
}
|
|
192
|
+
/** Decodes a quoted-printable body (RFC 2045 §6.7) into bytes, in one linear pass into a preallocated
|
|
193
|
+
* buffer. Literal text between escapes (which can't legally be non-ASCII in QP, but is after an
|
|
194
|
+
* 8-bit-unsafe gateway) is written run by run, decided once for the whole input: as the runs' own bytes
|
|
195
|
+
* when the input is a binary string, else as their UTF-8 encoding (so an already-decoded `é` next to an
|
|
196
|
+
* emoji isn't written as a lone 0xE9 byte). A run always ends at an ASCII `=`, so a surrogate pair is never
|
|
197
|
+
* split. */
|
|
198
|
+
export function decodeQuotedPrintable(text) {
|
|
199
|
+
const input = text.replace(/=[ \t]*\r?\n/g, "");
|
|
200
|
+
const binary = isBinaryString(input);
|
|
201
|
+
// At most 3 UTF-8 bytes per UTF-16 code unit, which only a non-binary string can need.
|
|
202
|
+
const out = new Uint8Array(binary ? input.length : input.length * 3);
|
|
203
|
+
const encoder = new TextEncoder();
|
|
204
|
+
let length = 0;
|
|
205
|
+
let runStart = 0;
|
|
206
|
+
const flushRun = (end) => {
|
|
207
|
+
if (binary) {
|
|
208
|
+
for (let j = runStart; j < end; j++) {
|
|
209
|
+
out[length++] = input.charCodeAt(j);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
length += encoder.encodeInto(input.slice(runStart, end), out.subarray(length)).written;
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
for (let i = 0; i + 2 < input.length; i++) {
|
|
217
|
+
if (input.charCodeAt(i) !== 0x3d) {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
const high = hexValue(input.charCodeAt(i + 1));
|
|
221
|
+
const low = hexValue(input.charCodeAt(i + 2));
|
|
222
|
+
if (high < 0 || low < 0) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
flushRun(i);
|
|
226
|
+
out[length++] = (high << 4) | low;
|
|
227
|
+
i += 2;
|
|
228
|
+
runStart = i + 1;
|
|
229
|
+
}
|
|
230
|
+
flushRun(input.length);
|
|
231
|
+
return out.slice(0, length);
|
|
232
|
+
}
|
|
233
|
+
/** Decodes `bytes` in `charset` (UTF-8 when absent or unknown). With `fallbackText`, a decode that hits
|
|
234
|
+
* invalid input returns `fallbackText` instead of replacement characters. */
|
|
235
|
+
function decodeCharset(bytes, charset, fallbackText) {
|
|
236
|
+
const options = { fatal: fallbackText !== undefined };
|
|
237
|
+
let decoder;
|
|
238
|
+
try {
|
|
239
|
+
decoder = new TextDecoder(charset || "utf-8", options);
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
// An unknown/unsupported charset label - UTF-8 is the least-bad fallback (a superset of ASCII).
|
|
243
|
+
decoder = new TextDecoder("utf-8", options);
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
return decoder.decode(bytes);
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return fallbackText;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/** Decodes an entity's body into bytes per its `Content-Transfer-Encoding`. 7bit/8bit/binary (or no
|
|
253
|
+
* header) return the body's own bytes (see `binaryStringToBytes()`). Returns `undefined` only for invalid
|
|
254
|
+
* base64. */
|
|
255
|
+
export function decodeBodyBytes(entity) {
|
|
256
|
+
const cte = transferEncodingOf(entity);
|
|
257
|
+
if (cte === "base64") {
|
|
258
|
+
return decodeBase64Text(entity.body);
|
|
259
|
+
}
|
|
260
|
+
if (cte === "quoted-printable") {
|
|
261
|
+
return decodeQuotedPrintable(entity.body);
|
|
262
|
+
}
|
|
263
|
+
return binaryStringToBytes(entity.body);
|
|
264
|
+
}
|
|
265
|
+
/** Decodes an entity's body to text: transfer encoding first, then its `charset` parameter (UTF-8 when
|
|
266
|
+
* absent). A 7bit/8bit/binary body that isn't a binary string was already decoded by whoever produced the
|
|
267
|
+
* string and passes through unchanged; so does a binary-string body whose bytes are invalid in its charset
|
|
268
|
+
* (e.g. legacy already-decoded Latin-1 text under a UTF-8 charset). */
|
|
269
|
+
export function decodeBodyText(entity) {
|
|
270
|
+
const cte = transferEncodingOf(entity);
|
|
271
|
+
const charset = parseParameterizedHeader(entity.headers["content-type"]).params["charset"];
|
|
272
|
+
if (cte !== "base64" && cte !== "quoted-printable") {
|
|
273
|
+
return isBinaryString(entity.body) ? decodeCharset(binaryStringToBytes(entity.body), charset, entity.body) : entity.body;
|
|
274
|
+
}
|
|
275
|
+
return decodeCharset(decodeBodyBytes(entity) ?? new Uint8Array(), charset);
|
|
276
|
+
}
|
|
277
|
+
const ENCODED_WORD = /=\?([^?\s]+)\?([bBqQ])\?([^?\s]*)\?=/g;
|
|
278
|
+
const WHITESPACE_BETWEEN_ENCODED_WORDS = /(=\?[^?\s]+\?[bBqQ]\?[^?\s]*\?=)\s+(?==\?[^?\s]+\?[bBqQ]\?[^?\s]*\?=)/g;
|
|
279
|
+
/**
|
|
280
|
+
* Turns a raw header value into display text: a binary string holding valid UTF-8 (a raw 8-bit header,
|
|
281
|
+
* RFC 6532) is decoded as UTF-8, then RFC 2047 encoded-words (`=?charset?B|Q?text?=`) are decoded, with
|
|
282
|
+
* whitespace between adjacent encoded-words dropped (RFC 2047 §6.2). An encoded-word with an unknown
|
|
283
|
+
* charset or undecodable content is left verbatim.
|
|
284
|
+
*/
|
|
285
|
+
export function decodeHeaderText(value) {
|
|
286
|
+
let text = value;
|
|
287
|
+
if (isBinaryString(text) && /[\x80-\xff]/.test(text)) {
|
|
288
|
+
text = decodeCharset(binaryStringToBytes(text), "utf-8", text);
|
|
289
|
+
}
|
|
290
|
+
return text.replace(WHITESPACE_BETWEEN_ENCODED_WORDS, "$1").replace(ENCODED_WORD, (word, charset, encoding, encoded) => {
|
|
291
|
+
const bytes = encoding.toUpperCase() === "B"
|
|
292
|
+
? decodeBase64Text(encoded)
|
|
293
|
+
: binaryStringToBytes(encoded.replace(/_/g, " ").replace(/=([0-9A-Fa-f]{2})/g, (_match, hex) => String.fromCharCode(parseInt(hex, 16))));
|
|
294
|
+
if (!bytes) {
|
|
295
|
+
return word;
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
// RFC 2231 §5 allows a language suffix on the charset: `charset*lang`.
|
|
299
|
+
return new TextDecoder(charset.split("*")[0], { fatal: true }).decode(bytes);
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return word;
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
/** Anything outside printable ASCII (space through `~`) and tab - such header text needs RFC 2047 encoding. */
|
|
307
|
+
const NEEDS_ENCODING = /[^\x20-\x7e\t]/;
|
|
308
|
+
/** Characters that must never reach a serialized header value: CR/LF (header injection) and NUL. */
|
|
309
|
+
const HEADER_BREAKING = /[\r\n\0]+/g;
|
|
310
|
+
/** Encodes `text` as RFC 2047 `B` encoded-words (UTF-8), each at most 75 characters, never splitting a
|
|
311
|
+
* multi-byte character between words, joined by folding whitespace. */
|
|
312
|
+
function encodeWords(text) {
|
|
313
|
+
// "=?UTF-8?B?" + "?=" is 12 characters, leaving 63 for base64 - i.e. at most 45 source bytes.
|
|
314
|
+
const MAX_BYTES_PER_WORD = 45;
|
|
315
|
+
const encoder = new TextEncoder();
|
|
316
|
+
const words = [];
|
|
317
|
+
let current = "";
|
|
318
|
+
let currentBytes = 0;
|
|
319
|
+
for (const ch of text) {
|
|
320
|
+
const size = encoder.encode(ch).length;
|
|
321
|
+
if (currentBytes + size > MAX_BYTES_PER_WORD && current) {
|
|
322
|
+
words.push(current);
|
|
323
|
+
current = "";
|
|
324
|
+
currentBytes = 0;
|
|
325
|
+
}
|
|
326
|
+
current += ch;
|
|
327
|
+
currentBytes += size;
|
|
328
|
+
}
|
|
329
|
+
words.push(current);
|
|
330
|
+
return words.map((word) => `=?UTF-8?B?${btoa(bytesToBinaryString(encoder.encode(word)))}?=`).join("\r\n ");
|
|
331
|
+
}
|
|
332
|
+
/** Makes an unstructured header value (e.g. `Subject`) safe to serialize: CR/LF/NUL become a space
|
|
333
|
+
* (never a header break), and a value containing non-ASCII is RFC 2047-encoded. */
|
|
334
|
+
export function encodeUnstructuredHeaderValue(value) {
|
|
335
|
+
const flattened = value.replace(HEADER_BREAKING, " ");
|
|
336
|
+
return NEEDS_ENCODING.test(flattened) ? encodeWords(flattened) : flattened;
|
|
337
|
+
}
|
|
338
|
+
/** Encodes one mailbox (`Name <addr>` or a bare addr-spec) - see `encodeAddressListHeaderValue()`. */
|
|
339
|
+
function encodeMailbox(mailbox) {
|
|
340
|
+
const angle = mailbox.lastIndexOf("<");
|
|
341
|
+
if (angle === -1) {
|
|
342
|
+
// A bare addr-spec (possibly internationalized) stays verbatim; stray non-ASCII text that
|
|
343
|
+
// isn't an address at all is encoded rather than written raw.
|
|
344
|
+
const bare = mailbox.trim();
|
|
345
|
+
return bare.includes("@") || !NEEDS_ENCODING.test(bare) ? bare : encodeWords(bare);
|
|
346
|
+
}
|
|
347
|
+
const rawName = mailbox.slice(0, angle).trim();
|
|
348
|
+
const address = mailbox.slice(angle).trim();
|
|
349
|
+
const name = encodePhrase(rawName);
|
|
350
|
+
return name ? `${name} ${address}` : address;
|
|
351
|
+
}
|
|
352
|
+
/** Encodes a display-name phrase (a mailbox's name or a group's label): unquoted and RFC 2047-encoded when
|
|
353
|
+
* it holds non-ASCII, else kept exactly as written. */
|
|
354
|
+
function encodePhrase(rawPhrase) {
|
|
355
|
+
const phrase = rawPhrase.trim();
|
|
356
|
+
const unquoted = /^".*"$/.test(phrase) ? phrase.slice(1, -1).replace(/\\(.)/g, "$1") : phrase;
|
|
357
|
+
return NEEDS_ENCODING.test(unquoted) ? encodeWords(unquoted) : phrase;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Makes an address-list header value (`From`/`To`/`Cc`) safe to serialize: CR/LF/NUL become a space, and
|
|
361
|
+
* each mailbox's non-ASCII display name (`Zoë <z@example.com>`, quoted or not) is RFC 2047-encoded while
|
|
362
|
+
* its addr-spec is kept verbatim (an internationalized address is left to SMTPUTF8, never encoded -
|
|
363
|
+
* RFC 2047 §5 forbids encoded-words in an addr-spec). RFC 5322 group syntax (`Équipe: Zoë <z@x>, b@x;`)
|
|
364
|
+
* keeps its `:` and `;`, with the group label encoded as a phrase of its own. A top-level `:` only opens
|
|
365
|
+
* a group when a `;` follows it, so a stray colon in an unquoted display name isn't mistaken for one.
|
|
366
|
+
*/
|
|
367
|
+
export function encodeAddressListHeaderValue(value) {
|
|
368
|
+
const flattened = value.replace(HEADER_BREAKING, " ");
|
|
369
|
+
if (!NEEDS_ENCODING.test(flattened)) {
|
|
370
|
+
return flattened;
|
|
371
|
+
}
|
|
372
|
+
let out = "";
|
|
373
|
+
let current = "";
|
|
374
|
+
let inQuotes = false;
|
|
375
|
+
let inAngle = false;
|
|
376
|
+
let inGroup = false;
|
|
377
|
+
const emit = (encoded, delimiter) => {
|
|
378
|
+
out += (encoded && /[,:;]$/.test(out) ? " " : "") + encoded + delimiter;
|
|
379
|
+
current = "";
|
|
380
|
+
};
|
|
381
|
+
for (let i = 0; i < flattened.length; i++) {
|
|
382
|
+
const ch = flattened[i];
|
|
383
|
+
if (inQuotes && ch === "\\" && i + 1 < flattened.length) {
|
|
384
|
+
current += ch + flattened[++i];
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (ch === '"') {
|
|
388
|
+
inQuotes = !inQuotes;
|
|
389
|
+
}
|
|
390
|
+
else if (!inQuotes && ch === "<") {
|
|
391
|
+
inAngle = true;
|
|
392
|
+
}
|
|
393
|
+
else if (!inQuotes && ch === ">") {
|
|
394
|
+
inAngle = false;
|
|
395
|
+
}
|
|
396
|
+
else if (!inQuotes && !inAngle) {
|
|
397
|
+
if (ch === ",") {
|
|
398
|
+
emit(encodeMailbox(current), ",");
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
if (ch === ":" && !inGroup && flattened.includes(";", i)) {
|
|
402
|
+
emit(encodePhrase(current), ":");
|
|
403
|
+
inGroup = true;
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
if (ch === ";" && inGroup) {
|
|
407
|
+
emit(encodeMailbox(current), ";");
|
|
408
|
+
inGroup = false;
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
current += ch;
|
|
413
|
+
}
|
|
414
|
+
emit(encodeMailbox(current), "");
|
|
415
|
+
return out;
|
|
416
|
+
}
|
|
417
|
+
function isAttachment(entity) {
|
|
418
|
+
return parseParameterizedHeader(entity.headers["content-disposition"]).value === "attachment";
|
|
419
|
+
}
|
|
420
|
+
/** Picks the displayable body out of an entity: a `text/html` part is preferred over `text/plain`, and a
|
|
421
|
+
* multipart entity is searched (non-attachment children only, bounded depth). Entities with no
|
|
422
|
+
* Content-Type default to text/plain per RFC 2045 §5.2. */
|
|
423
|
+
export function extractDisplayBody(entity, depth = 0) {
|
|
424
|
+
const contentType = parseParameterizedHeader(entity.headers["content-type"] ?? "text/plain");
|
|
425
|
+
if (contentType.value === "text/html") {
|
|
426
|
+
return { html: decodeBodyText(entity) };
|
|
427
|
+
}
|
|
428
|
+
if (contentType.value === "text/plain") {
|
|
429
|
+
return { text: decodeBodyText(entity) };
|
|
430
|
+
}
|
|
431
|
+
const boundary = contentType.params["boundary"];
|
|
432
|
+
if (!contentType.value.startsWith("multipart/") || !boundary || depth >= MAX_MULTIPART_DEPTH) {
|
|
433
|
+
return {};
|
|
434
|
+
}
|
|
435
|
+
let text;
|
|
436
|
+
for (const part of splitMultipart(entity.body, boundary)) {
|
|
437
|
+
const child = parseMimeEntity(part);
|
|
438
|
+
if (isAttachment(child)) {
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
const found = extractDisplayBody(child, depth + 1);
|
|
442
|
+
if (found.html !== undefined) {
|
|
443
|
+
return { html: found.html };
|
|
444
|
+
}
|
|
445
|
+
text ?? (text = found.text);
|
|
446
|
+
}
|
|
447
|
+
return text === undefined ? {} : { text };
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Lists the attachments inside `entity` (descending into multipart children, bounded depth): every leaf part
|
|
451
|
+
* with `Content-Disposition: attachment`, a filename, or a non-text type. The `text/plain`/`text/html` parts a
|
|
452
|
+
* reader would display (no disposition, no filename) are not attachments. Nested `message/rfc822` content is
|
|
453
|
+
* reported as one attachment, never expanded.
|
|
454
|
+
*/
|
|
455
|
+
export function extractAttachments(entity, depth = 0) {
|
|
456
|
+
const contentType = parseParameterizedHeader(entity.headers["content-type"] ?? "text/plain");
|
|
457
|
+
const disposition = parseParameterizedHeader(entity.headers["content-disposition"]);
|
|
458
|
+
const boundary = contentType.params["boundary"];
|
|
459
|
+
if (contentType.value.startsWith("multipart/")) {
|
|
460
|
+
if (!boundary || depth >= MAX_MULTIPART_DEPTH) {
|
|
461
|
+
return [];
|
|
462
|
+
}
|
|
463
|
+
return splitMultipart(entity.body, boundary).flatMap((part) => extractAttachments(parseMimeEntity(part), depth + 1));
|
|
464
|
+
}
|
|
465
|
+
const rawFilename = disposition.params["filename"] ?? contentType.params["name"];
|
|
466
|
+
const isAttachmentDisposition = disposition.value === "attachment";
|
|
467
|
+
if (!isAttachmentDisposition && rawFilename === undefined && contentType.value.startsWith("text/")) {
|
|
468
|
+
return [];
|
|
469
|
+
}
|
|
470
|
+
const contentId = entity.headers["content-id"]?.trim().replace(/^<(.*)>$/, "$1");
|
|
471
|
+
return [
|
|
472
|
+
{
|
|
473
|
+
...(rawFilename !== undefined ? { filename: decodeHeaderText(rawFilename) } : {}),
|
|
474
|
+
contentType: contentType.value,
|
|
475
|
+
disposition: isAttachmentDisposition ? "attachment" : "inline",
|
|
476
|
+
...(contentId ? { contentId } : {}),
|
|
477
|
+
decode: () => decodeBodyBytes(entity),
|
|
478
|
+
},
|
|
479
|
+
];
|
|
480
|
+
}
|
|
481
|
+
/** HTML-escapes plain text and wraps it in a whitespace-preserving `<pre>`, so a `text/plain` body can be
|
|
482
|
+
* rendered through the same HTML path without ever being interpreted as markup. */
|
|
483
|
+
export function plainTextToHtml(text) {
|
|
484
|
+
const escaped = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
485
|
+
return `<pre style="white-space: pre-wrap; word-wrap: break-word; font-family: inherit">${escaped}</pre>`;
|
|
486
|
+
}
|
|
487
|
+
/** Extracts the bare, lowercased addr-specs from an address-list header value (`"Name" <a@b>, c@d`).
|
|
488
|
+
* Handles quoted display names containing commas/angle brackets and RFC 5322 comments. */
|
|
489
|
+
export function extractAddresses(headerValue) {
|
|
490
|
+
if (!headerValue) {
|
|
491
|
+
return [];
|
|
492
|
+
}
|
|
493
|
+
const withoutQuoted = headerValue.replace(/"(?:[^"\\]|\\.)*"/g, '""').replace(/\((?:[^()\\]|\\.)*\)/g, "");
|
|
494
|
+
const addresses = [];
|
|
495
|
+
for (const item of withoutQuoted.split(",")) {
|
|
496
|
+
const angle = /<([^>]*)>/.exec(item);
|
|
497
|
+
// A bare addr-spec may carry RFC 5322 group syntax around it (`Team: a@b, c@d;`).
|
|
498
|
+
const address = (angle ? angle[1] : item.replace(/^[^:]*:/, "").replace(/;\s*$/, "")).trim().toLowerCase();
|
|
499
|
+
if (address.includes("@")) {
|
|
500
|
+
addresses.push(address);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return addresses;
|
|
504
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface PasskeyRegistration {
|
|
2
|
+
/** Base64url-encoded credential ID — stored as `MasterKeyWrap.methodId`. */
|
|
3
|
+
credentialId: string;
|
|
4
|
+
/** Whether this authenticator reported PRF support at registration time. A `false`/absent value here
|
|
5
|
+
* does not necessarily mean PRF evaluation will fail later on some platforms (some only report
|
|
6
|
+
* support upon first `get()`), but MUST be treated as "unknown/unlikely," not "yes." */
|
|
7
|
+
prfSupported: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Registers a new platform/roaming passkey for use purely as a local unlock method (see this module's
|
|
11
|
+
* doc comment for why no server round-trip is involved). `rpId` MUST be this deployment's own domain.
|
|
12
|
+
*/
|
|
13
|
+
export declare function registerPasskeyForUnlock(rpId: string, userId: Uint8Array, userName: string): Promise<PasskeyRegistration>;
|
|
14
|
+
/**
|
|
15
|
+
* Evaluates the PRF extension for an already-registered passkey and HKDF-derives a wrapping key from the
|
|
16
|
+
* result. Throws if the authenticator doesn't return a PRF output (e.g. it doesn't support the
|
|
17
|
+
* extension) — callers MUST treat that as "this unlock method is unavailable here," not silently fall
|
|
18
|
+
* back to a weaker derivation.
|
|
19
|
+
*/
|
|
20
|
+
export declare function deriveFromPasskey(rpId: string, credentialId: string, salt: Uint8Array): Promise<Uint8Array>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
/**
|
|
6
|
+
* The "passkey" unlock method from `specs/end-to-end_encryption.md`'s "Master Key Wrapping": uses the
|
|
7
|
+
* WebAuthn **PRF extension** to obtain a stable per-credential secret, then HKDF-derives a wrapping key
|
|
8
|
+
* from it — `wrap_passkey_N = AEAD(HKDF(WebAuthn-PRF(credential_N, salt)), MK)`. The credential's own
|
|
9
|
+
* private key is non-extractable and never used directly; only the PRF extension's derived secret is.
|
|
10
|
+
*
|
|
11
|
+
* This deliberately talks to the raw `navigator.credentials` WebAuthn API rather than
|
|
12
|
+
* `@simplewebauthn/browser` — that library's `startRegistration`/`startAuthentication` helpers expect a
|
|
13
|
+
* server-generated `optionsJSON` (from `@simplewebauthn/server`'s `generateRegistrationOptions()`/
|
|
14
|
+
* `generateAuthenticationOptions()`), which assumes a full relying-party ceremony with server-side
|
|
15
|
+
* challenge issuance and assertion verification. There is no such flow here — this passkey is never used
|
|
16
|
+
* to authenticate to `@rapidmx/restapi` or auth-server, only as a local, hardware-backed KDF input. A
|
|
17
|
+
* locally-generated challenge is fine because nothing server-side ever verifies this credential's
|
|
18
|
+
* attestation/assertion signature; only the PRF extension output is consumed. Identity/session auth
|
|
19
|
+
* remains entirely `auth-server`'s job (see `.claude/NOTES.md` in `server`).
|
|
20
|
+
*
|
|
21
|
+
* **Needs real hardware/browser verification.** PRF extension behavior (in particular, whether a
|
|
22
|
+
* browser returns `prf.results` on the *registration* ceremony itself vs. only on a subsequent
|
|
23
|
+
* `navigator.credentials.get()`) is not exercisable in this test environment (no real authenticator) —
|
|
24
|
+
* this module's tests mock `navigator.credentials` and cover this module's own request-building/
|
|
25
|
+
* response-parsing logic, not real authenticator behavior end to end. Verify against real hardware
|
|
26
|
+
* before shipping, the same honesty standard `@rapidmx/restapi` holds its own hard-to-verify pieces to
|
|
27
|
+
* (e.g. that repo's `sameIssuingCa()` doc comment).
|
|
28
|
+
*/
|
|
29
|
+
import { fromBase64Url, toBase64Url } from "./encoding.js";
|
|
30
|
+
import { hkdfDerive } from "./masterKey.js";
|
|
31
|
+
const PRF_HKDF_INFO = "wrap";
|
|
32
|
+
const CHALLENGE_LENGTH_BYTES = 32;
|
|
33
|
+
/**
|
|
34
|
+
* Registers a new platform/roaming passkey for use purely as a local unlock method (see this module's
|
|
35
|
+
* doc comment for why no server round-trip is involved). `rpId` MUST be this deployment's own domain.
|
|
36
|
+
*/
|
|
37
|
+
export async function registerPasskeyForUnlock(rpId, userId, userName) {
|
|
38
|
+
const challenge = crypto.getRandomValues(new Uint8Array(CHALLENGE_LENGTH_BYTES));
|
|
39
|
+
const credential = (await navigator.credentials.create({
|
|
40
|
+
publicKey: {
|
|
41
|
+
rp: { id: rpId, name: rpId },
|
|
42
|
+
user: { id: userId, name: userName, displayName: userName },
|
|
43
|
+
challenge: challenge,
|
|
44
|
+
// ES256 - matches this system's P-256 default elsewhere (see crypto/keys.ts).
|
|
45
|
+
pubKeyCredParams: [{ type: "public-key", alg: -7 }],
|
|
46
|
+
authenticatorSelection: { residentKey: "preferred", userVerification: "required" },
|
|
47
|
+
extensions: { prf: {} },
|
|
48
|
+
},
|
|
49
|
+
}));
|
|
50
|
+
const results = credential.getClientExtensionResults();
|
|
51
|
+
return {
|
|
52
|
+
credentialId: toBase64Url(new Uint8Array(credential.rawId)),
|
|
53
|
+
prfSupported: !!results.prf?.enabled,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Evaluates the PRF extension for an already-registered passkey and HKDF-derives a wrapping key from the
|
|
58
|
+
* result. Throws if the authenticator doesn't return a PRF output (e.g. it doesn't support the
|
|
59
|
+
* extension) — callers MUST treat that as "this unlock method is unavailable here," not silently fall
|
|
60
|
+
* back to a weaker derivation.
|
|
61
|
+
*/
|
|
62
|
+
export async function deriveFromPasskey(rpId, credentialId, salt) {
|
|
63
|
+
const challenge = crypto.getRandomValues(new Uint8Array(CHALLENGE_LENGTH_BYTES));
|
|
64
|
+
const assertion = (await navigator.credentials.get({
|
|
65
|
+
publicKey: {
|
|
66
|
+
rpId,
|
|
67
|
+
challenge: challenge,
|
|
68
|
+
allowCredentials: [{ id: fromBase64Url(credentialId), type: "public-key" }],
|
|
69
|
+
userVerification: "required",
|
|
70
|
+
extensions: { prf: { eval: { first: salt } } },
|
|
71
|
+
},
|
|
72
|
+
}));
|
|
73
|
+
const results = assertion.getClientExtensionResults();
|
|
74
|
+
const prfOutput = results.prf?.results?.first;
|
|
75
|
+
if (!prfOutput) {
|
|
76
|
+
throw new Error("This passkey did not return a PRF result - it may not support the PRF extension.");
|
|
77
|
+
}
|
|
78
|
+
return hkdfDerive(new Uint8Array(prfOutput), salt, PRF_HKDF_INFO);
|
|
79
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface Argon2idParams {
|
|
2
|
+
/** Memory cost, in KiB. */
|
|
3
|
+
memorySize: number;
|
|
4
|
+
iterations: number;
|
|
5
|
+
parallelism: number;
|
|
6
|
+
}
|
|
7
|
+
/** Matches the `kdf` string format `MasterKeyWrap.kdf` documents (`argon2id:m=65536,t=3,p=4`) — OWASP's
|
|
8
|
+
* current recommended minimum for Argon2id (m=19MiB is the OWASP floor; this is deliberately higher,
|
|
9
|
+
* matching the doc comment on `EncryptionCertificateAuthority`'s own conservative defaults elsewhere in
|
|
10
|
+
* this system). */
|
|
11
|
+
export declare const DEFAULT_ARGON2ID_PARAMS: Argon2idParams;
|
|
12
|
+
/** Builds the `kdf` string stored alongside a password-method `MasterKeyWrap`, so parameters can be
|
|
13
|
+
* upgraded over time without breaking existing accounts (each wrap records the parameters it was
|
|
14
|
+
* actually created with). */
|
|
15
|
+
export declare function argon2idKdfLabel(params: Argon2idParams): string;
|
|
16
|
+
/** Inverse of `argon2idKdfLabel()` — reads back the exact parameters a `MasterKeyWrap.kdf` string was
|
|
17
|
+
* created with, so unlocking always re-derives with the *original* parameters even if
|
|
18
|
+
* `DEFAULT_ARGON2ID_PARAMS` has since changed (the spec's own "KDF parameters ... MUST be stored
|
|
19
|
+
* alongside each wrap, so costs can be raised over time without breaking existing accounts"). Returns
|
|
20
|
+
* `undefined` for anything that isn't a well-formed `argon2id:m=...,t=...,p=...` label — including a
|
|
21
|
+
* different KDF entirely (e.g. recovery codes' own `"hkdf-sha256"` label), which callers must not
|
|
22
|
+
* attempt to unlock as if it were password-derived.
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseArgon2idKdfLabel(label: string): Argon2idParams | undefined;
|
|
25
|
+
/** A fresh random salt for a new password enrollment. 16 bytes is Argon2id's own recommended minimum. */
|
|
26
|
+
export declare function generateSalt(lengthBytes?: number): Uint8Array;
|
|
27
|
+
export interface PasswordDerivation {
|
|
28
|
+
/** Base64-encoded. See this module's own doc comment — not yet sent anywhere, reserved for a future
|
|
29
|
+
* server-side verification endpoint. */
|
|
30
|
+
authProof: string;
|
|
31
|
+
/** Never leaves the device. Passed directly to `masterKey.ts`'s `sealWithKey`/`openWithKey`. */
|
|
32
|
+
wrappingKey: Uint8Array;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Runs Argon2id once against `password`/`salt`, then HKDF-splits the result into `authProof` and
|
|
36
|
+
* `wrappingKey` (see this module's doc comment for why two independent values, not one reused for both
|
|
37
|
+
* purposes). The plaintext password itself never leaves this function.
|
|
38
|
+
*/
|
|
39
|
+
export declare function deriveFromPassword(password: string, salt: Uint8Array, params?: Argon2idParams): Promise<PasswordDerivation>;
|