Notification Tenant Isolation
Summary
The Notification Service is a cross-tenant consumer. NotificationDbContext applies no global tenant query filter by design; tenant scoping is applied explicitly on each query. The tenant identifier flows from the consumed event header and is nullable.
Scoping model
Per-query scoping (verified)
- Templates resolve a tenant-specific active row first, then fall back to the global default where
TenantIdis null. - Recipients are keyed and upserted by
(TenantId, RecipientType, ExternalRef). - Preferences are evaluated with the tenant, recipient and channel in the predicate.
- Inbox reads filter by the supplied
tenantIdandrecipientRef. - Idempotency and audit rows carry the tenant for traceability.
Deliberate cross-tenant posture
Because the service observes every tenant’s events, the DbContext comment documents the absence of a global filter as intentional. This places responsibility for correct tenant scoping on each query rather than on a context-wide guard.
Isolation risks (verified)
Endpoints accept tenantId as a caller-supplied parameter with no authenticated tenant claim. A query that omits tenantId (or supplies another tenant’s value) is not blocked by a context-level filter, so isolation depends on callers passing the correct value and on upstream enforcement.
Requires Confirmation
Whether upstream components guarantee the correct tenantId on every notification request, and whether a defense-in-depth tenant guard is planned, require confirmation.
Source References
microservices/src/notification-service/Infrastructure/NotificationDbContext.csmicroservices/src/notification-service/Application/NotificationDispatcher.csmicroservices/src/notification-service/Application/TemplateEngine.csmicroservices/src/notification-service/Api/NotificationEndpoints.cs
Related Articles
See Also
Keywords
Tenant isolation, multi-tenancy, query scoping, global default, cross-tenant.
Revision Information
- Status: Draft
- Last reviewed: 2026-07-21
- Next review: 2026-10-21