From ffbe368dafbc3993f0719c93062ad5986f8b73dc Mon Sep 17 00:00:00 2001 From: Justin Baur <19896123+justindbaur@users.noreply.github.com> Date: Tue, 26 Aug 2025 14:36:03 -0400 Subject: [PATCH] Add Push READMEs --- src/Core/Platform/Push/README.md | 92 ++++++++++++++++++++ src/Core/Platform/PushRegistration/README.md | 46 ++++++++++ 2 files changed, 138 insertions(+) create mode 100644 src/Core/Platform/Push/README.md create mode 100644 src/Core/Platform/PushRegistration/README.md diff --git a/src/Core/Platform/Push/README.md b/src/Core/Platform/Push/README.md new file mode 100644 index 0000000000..eaaf37db59 --- /dev/null +++ b/src/Core/Platform/Push/README.md @@ -0,0 +1,92 @@ +# Push + +## About + +Push is a feature for sending packets of information to end user devices. This can be useful for +telling the device that there is new information that it should request or that the request they +created was just accepted. + +## Usage + +The general usage will be to call `Bit.Core.Platform.Push.IPushNotificationService.PushAsync`. That +method takes a `PushNotification`. + +```c# +// This would send a notification to all the devices of the given `userId`. +await pushNotificationService.PushAsync(new PushNotification +{ + Type = PushType.MyNotificationType, + Target = NotificationTarget.User, + TargetId = userId, + Payload = new MyPayload + { + Message = "Request accepted", + }, + ExcludeCurrentContext = false, +}); +``` + +## Extending + +If you want to extend this framework for sending your own notification type you do so by adding a +new enum member the [`PushType`](./PushType.cs) enum. Assign a number to it that is 1 above the next +highest value. You must then annotate that enum member with a +[`[NotificationInfo]`](./NotificationInfoAttribute.cs) attribute to inform others who the owning +team and expected payload type are. Then you may inject +[`IPushNotificationService`](./IPushNotificationService.cs) into your own service and call its +`PushAsync` method. + +You should NOT add tests for your specific notification type in any of the `IPushEngine` +implementations. They do currently have tests for many of the notification types but those will +eventually be deleted and no new ones need to be added. + +Since notifications are relayed through our cloud instance for self hosted users (whom opt-in) it's +important to try and keep the information in the notification payload minimal. It's generally best +to send a notification with various ID's that mean nothing to our cloud but can then be used to get +more detailed information once the notification is received on the device. + +## Implementations + +The implementation of push notifications scatters push notification requests to all `IPushEngine`'s +that have been registered in DI for the current application. In release builds, this service does +NOT await the underlying engines to make sure that the notification has gotten to its destination +before its returned task completes. + +### Azure Notification Hub + +Used when the application is hosted by Bitwarden in the cloud. This sends the notification to the +configured Azure Notification Hub which we currently rely on it for sending the notification to our +mobile clients and any clients configured to use Web Push (currently Chrome Extension). + +This implementation is always assumed to have available configuration when running in the cloud. + +### Azure Queue + +Used when the application is hosted by Bitwarden in the cloud. This sends notifications to a Azure +Queue, that queue is then consumed in our Notifications service and the notifications are then sent +to a SignalR hub so that our clients connected through a persistent web socket to our notifications +service get the notification. + +This implementation is registered in DI when `GlobalSettings:Notifications:ConnectionString` is set +to a value. + +### Relay + +Used when the application is being self-hosted. This relays a notification from the self-hosted +instance to a cloud instance. The notification is recieved by our cloud and then relayed to +Azure Notification Hub. This is because self-hosted instance aren't able to directly send +notifications to mobile devices. + +This instance is registered in DI when `GlobalSettings:PushRelayBaseUri` and +`GlobalSettings:Installation:Key` are available. + +### Notifications API + +Used when the application is being self-hosted. This sends a API request to the self-hosted instance +of the Notifications service. The notifications service receives the request and then sends the +notification through the SignalR hub. This is very similar to cloud using an Azure Queue but it +doesn't require the self-hosted infrastructure to run their own queuing infrastructure. + +This instance is registered when `GlobalSettings:InternalIdentityKey` and +`GlobalSettings:BaseServiceUri:InternalNotifications` are set. Both of these settings are usually +set automatically in supported Bitwarden setups. diff --git a/src/Core/Platform/PushRegistration/README.md b/src/Core/Platform/PushRegistration/README.md new file mode 100644 index 0000000000..e7f4d162e3 --- /dev/null +++ b/src/Core/Platform/PushRegistration/README.md @@ -0,0 +1,46 @@ +# Push Registration + +## About + +Push Registration is a feature for managing devices that should receive push notifications. The main +entrypoint for this feature is `IPushRegistrationService`. + +## Usage + +This feature is largely used internally to Platform owned endpoints or in concert with another team. + +If your feature changes the status of any of the following pieces of data please contact Platform +so that we can keep push registration working correctly. + +- The creation/deletion of a new `Device`. +- The addition of removal of an organization a `User` is a part of. + +## Implementation + +### Azure Notification Hub + +Used when the application is hosted by Bitwarden in the cloud. This registers the device and +associated metadata with Azure Notification Hub. This is necessary so that when a notification +is sent ANH will be able to get the notification to that device. + +Since Azure Notification Hubs has a limit on the amount of devices per hub we have begun to shard +devices across multiple hubs. Multiple hubs can be configured through configuration and each one can +have a `RegistrationStartDate` and `RegistrationEndDate`. If the start date is `null` no devices +will be registered against that given hub. A `null` end date is treated as no known expiry. The +creation of a device is pulled out of the devices ID and that date is used to find a hub that spans +during it's creation date. + +When we register a device with Azure Notificaiton Hub we include tags, which are data that can later +be used to specifically target that device with a notification. We send the ID of the user this +device belongs to, the type of the client (Web, Desktop, Mobile, etc), all the organization id's of +organizations the user is a confirmed member of, the ID of the self-hosted installation if this +device was relayed to us, and the device identifier which is a random guid generated on the device. +Most of this data is considered immutable after the creation of a device except for the +organization memberships of a user. If a user is added/removed from an organization it's important +that `CreateOrUpdateRegistrationAsync` is called with the new memberships. + +### Relay + +Used when the application is self-hosted. This sends a API request to the configured cloud instance +and which will then use [Azure Notification Hub](#azure-notification-hub) but will associate the +installation as the self-hosted installation id instead of using the cloud one.