Refactor event integration service collection extensions into their own extension
đ Objective
As the event integration services grew, they were simply being added to the large ServiceCollectionExtensions in SharedWeb. This PR refactors them into their own self-contained extension. This gives us the advantage of not having so much done in one file, but also added an easy place to add extensive tests for all of these (where there previously had been no tests).
This is primarily simply a migration. However there are 2 functional changes:
- We were previously calling
AddDistributedCacheinside of the event integration functions. This is not possible when moving outside of SharedWeb. Instead, we are now callingAddDistributedCachein the Startup.cs in Events and EventsProcessor (which follows the pattern in other apps - Api, Billing, etc). This has been documented as a requirement in the XMLDoc for these methods - In writing tests I realized that we supported launching listeners for both Azure Service Bus and RabbitMQ if you had both of them configured. This is likely a misconfiguration and is out of step with how we handle precedence on the write side. I've updated the logic to explicitly prefer ASB and register only ASB if they are both configured (as well as adding a test to exercise this scenario explicitly).
â° Reminders before review
- Contributor guidelines followed
- All formatters and local linters executed and passed
- Written new unit and / or integration tests where applicable
- Protected functional changes with optionality (feature flags)
- Used internationalization (i18n) for all UI strings
- CI builds passed
- Communicated to DevOps any deployment requirements
- Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team
đĻŽ Reviewer guidelines
- đ (
:+1:) or similar for great changes - đ (
:memo:) or âšī¸ (:information_source:) for notes or general info - â (
:question:) for questions - đ¤ (
:thinking:) or đ (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion - đ¨ (
:art:) for suggestions / improvements - â (
:x:) or â ī¸ (:warning:) for more significant problems or concerns needing attention - đą (
:seedling:) or âģī¸ (:recycle:) for future improvements or indications of technical debt - â (
:pick:) for minor or nitpick changes
Claude finished @brant-livefront's task in 1m 34s ââ View job
Code Review Complete â
I've reviewed this refactoring PR and it looks solid overall. The changes successfully extract event integration service registration into a dedicated, well-tested extension file. Here are my findings:
Strengths đ
-
Excellent Test Coverage: The new test file has 667 lines of comprehensive tests covering:
- Service registration and idempotency
- Configuration precedence (Azure Service Bus over RabbitMQ)
- All configuration permutations
- Service lifetimes and scoping
-
Clear Documentation: XML docs thoroughly explain each method's purpose, prerequisites, and behavior
-
Improved Organization: Moving ~300 lines from SharedWeb into a focused extension improves maintainability
-
Proper Dependency Injection Patterns: Uses
TryAddmethods following ADR-0026 -
Sensible Precedence Logic: Azure Service Bus over RabbitMQ is well-documented and tested (lines 644-669 in tests)
Areas of Concern â ī¸
-
Distributed Cache Prerequisite (EventIntegrationsServiceCollectionExtensions.cs:130, 171, 274)
- The XML docs state callers "must ensure AddDistributedCache has been called"
- However, there's no runtime validation to enforce this requirement
- If a caller forgets, they'll get a cryptic DI resolution error at runtime
- Suggestion: Consider adding a guard check or making the dependency explicit
-
Bot Builder Dependencies in Core.csproj (line 43-45)
- Microsoft.Bot.Builder packages are now required in Core, which increases the footprint
- These are only needed when Teams integration is configured
- The PR reviewer @jrmccannon already confirmed this is for Teams integration
- Note: This is acceptable but worth documenting as a tradeoff
-
Test Coverage Gap
- While tests verify service registration, there are no integration tests verifying the startup flows in Events/EventsProcessor actually work correctly with the new prerequisite
- The 77% patch coverage reported by Codecov suggests some code paths aren't tested
Security & Architecture â
- No security concerns identified
- Follows zero-knowledge principles (no vault data handling)
- Consistent with Bitwarden architectural patterns
- No breaking changes beyond documented behavior fixes
Minor Observations đ
- The functional change to prevent dual ASB+RabbitMQ registration is correct and well-tested
- The Startup.cs changes correctly add
AddDistributedCachecalls before listener registration - The precedence logic matches between write services and listener services
Recommendation
This is a well-executed refactoring with excellent test coverage. The code quality is high and follows project conventions. My only suggestion would be to add runtime validation for the distributed cache prerequisite to prevent configuration errors.
Approval: â Ready to merge once CI passes
Quality Gate passed
Issues
2 New issues
0 Accepted issues
Measures
0 Security Hotspots
0.0% Coverage on New Code
2.7% Duplication on New Code
Checkmarx One â Scan Summary & Details â 08622646-d1a0-4500-85f8-9523cc7015d9
New Issues (2)
Checkmarx found the following issues in this Pull Request
| Severity | Issue | Source File / Package | Checkmarx Insight |
|---|---|---|---|
![]() |
CSRF | /src/Api/Vault/Controllers/CiphersController.cs: 1519 | detailsMethod at line 1519 of /src/Api/Vault/Controllers/CiphersController.cs gets a parameter from a user request from id. This parameter value flows ...ID: dMGF5qNfAN72zlvQcA1MgbhHv%2Fc%3D |
![]() |
CSRF | /src/Api/Vault/Controllers/CiphersController.cs: 1395 | detailsMethod at line 1395 of /src/Api/Vault/Controllers/CiphersController.cs gets a parameter from a user request from id. This parameter value flows ...ID: iOCFr11iI9znjDnv46yLfiS4aDY%3D |
Codecov Report
:x: Patch coverage is 77.25322% with 53 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 54.10%. Comparing base (72c8967) to head (2fe2ceb).
:warning: Report is 4 commits behind head on main.
| Files with missing lines | Patch % | Lines |
|---|---|---|
| ...ns/EventIntegrationsServiceCollectionExtensions.cs | 77.48% | 52 Missing :warning: |
| src/EventsProcessor/Startup.cs | 0.00% | 1 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## main #6714 +/- ##
==========================================
+ Coverage 53.90% 54.10% +0.19%
==========================================
Files 1922 1922
Lines 85214 85215 +1
Branches 7621 7621
==========================================
+ Hits 45937 46106 +169
+ Misses 37511 37352 -159
+ Partials 1766 1757 -9
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
- :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
@jrmccannon @withinfocus This is ready for a re-approval after being re-targeted to main (should be no new changes)
