bitwarden/server
Events
Active contributors: Dirt (Data Insights & Reporting) team.
Purpose
src/Events/ is a tiny ASP.NET Core service that accepts batches of audit events from authenticated clients and pushes them onto an Azure Storage queue (or Azure Service Bus / RabbitMQ in dev) for later persistence by EventsProcessor. The split exists so that the chatty event-write path doesn't load the same connection pool as the API.
Directory layout
src/Events/
├── Program.cs / Startup.cs
├── Controllers/
│ ├── CollectController.cs # POST /collect, accepts EventModel[]
│ └── InfoController.cs # /alive, /version
├── Models/ # Request DTOs
├── appsettings.{Development,Production,QA,SelfHosted}.json
└── Dockerfile / build.sh / entrypoint.shKey abstractions
| Type | Path | Description |
|---|---|---|
Startup |
src/Events/Startup.cs |
Configures MVC + Bearer JWT auth scoped to Policies.Application, plus the queue / Service Bus event writer. |
CollectController |
src/Events/Controllers/CollectController.cs |
POSTs from clients land here; they must include a JWT with the api scope. The controller reads ICurrentContext to attribute the events. |
IEventWriteService (resolved at runtime) |
src/Core/Services/Implementations/AzureQueueEventWriteService.cs, RepositoryEventWriteService.cs, RabbitMqEventWriteService.cs, ... |
Each implementation persists to a different sink. The Events host typically resolves to the queue writer; EventsProcessor resolves to the repository writer. |
How it works
sequenceDiagram
participant Client
participant Events
participant Queue as Azure Queue / Service Bus / RabbitMQ
participant EP as EventsProcessor
participant DB
Client->>Events: POST /collect (Bearer JWT, [{type, cipherId, date,...}])
Events->>Events: AuthZ Policies.Application
Events->>Queue: IEventWriteService.CreateManyAsync
Events-->>Client: 200 Accepted
EP->>Queue: Dequeue batch
EP->>DB: Insert into Event table / Cosmos / Azure Table StorageIntegration points
- Identity — Bearer JWT validation. Only legitimate clients can post events.
- Queue / Bus —
globalSettings.Events.ConnectionStringselects which writer is used. Self-hosted defaults to the local repository writer (single-process write to SQL). - EventsProcessor — the consumer side (see events-processor).
- Audit logs — surfaced in the Admin Console UI via
LogsControllerand thePublic/EventsControllerorg public API.
Why split the write path?
- Clients post events frequently (every successful sync logs a
User_LoggedInand similar). Putting that on the same hot path as cipher CRUD made the API slow under load. - The queue allows replay if
EventsProcessorfalls behind. - It also lets self-host write straight to SQL while cloud uses an event-streaming pipeline.
Entry points for modification
- New event type → add to
EventType(src/Core/Enums/EventType.cs) and useIEventService.LogXxxEventAsyncfrom API code. The Events host doesn't need changes. - New ingest sink → implement
IEventWriteServiceand register it conditionally inStartup.ConfigureServices. - Different auth policy for the collect endpoint → adjust the
Policies.Applicationreference inCollectController(rare).
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.