Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
4.1 KiB
4.1 KiB
Notifier Tenancy Prep — PREP-NOTIFY-TEN-48-001
Status: Implemented (2025-11-27) Owners: Notifications Service Guild Scope: Tenancy model and DAL/routes for tenant context in Notifier WebService.
Overview
Tenant scoping for the Notifier module ensures that rules, templates, incidents, and channels are isolated per tenant with proper row-level security (RLS) in MongoDB storage.
Implementation Summary
1. Tenant Context Service (src/Notifier/StellaOps.Notifier.Worker/Tenancy/)
- TenantContext.cs: AsyncLocal-based context propagation for tenant ID and actor
- TenantServiceExtensions.cs: DI registration and configuration options
- ITenantAccessor: Interface for accessing tenant from HTTP context
Key pattern:
// Set tenant context for async scope
using var scope = tenantContext.SetContext(tenantId, actor);
await ProcessEventAsync();
// Or with extension method
await tenantContext.WithTenantAsync(tenantId, actor, async () =>
{
await ProcessNotificationAsync();
});
2. Incident Repository (src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/)
New files:
- Repositories/INotifyIncidentRepository.cs: Repository interface for incident persistence
- Repositories/NotifyIncidentRepository.cs: MongoDB implementation with tenant filtering
- Serialization/NotifyIncidentDocumentMapper.cs: BSON serialization for incidents
Key features:
- All queries include mandatory
tenantIdfilter - Document IDs use
{tenantId}:{resourceId}composite pattern for RLS - Correlation key lookup scoped to tenant
- Soft delete support with
deletedAtfield
3. MongoDB Indexes (tenant-scoped)
Added in EnsureNotifyIndexesMigration.cs:
// incidents collection
{ tenantId: 1, status: 1, lastOccurrence: -1 } // Status filtering
{ tenantId: 1, correlationKey: 1, status: 1 } // Correlation lookup
4. Existing Tenancy Infrastructure
The following was already in place:
- All models have
TenantIdproperty (NotifyRule, NotifyChannel, NotifyTemplate, etc.) - Repository interfaces take
tenantIdas parameter - Endpoints extract tenant from
X-StellaOps-Tenantheader - MongoDB document IDs use tenant-prefixed composite keys
Configuration
{
"Notifier": {
"Tenant": {
"TenantIdHeader": "X-StellaOps-Tenant",
"ActorHeader": "X-StellaOps-Actor",
"RequireTenant": true,
"DefaultActor": "system",
"ExcludedPaths": ["/health", "/ready", "/metrics", "/openapi"]
}
}
}
Usage Examples
HTTP API
GET /api/v2/rules HTTP/1.1
X-StellaOps-Tenant: tenant-123
X-StellaOps-Actor: user@example.com
Worker Processing
public class NotificationProcessor
{
private readonly ITenantContext _tenantContext;
public async Task ProcessAsync(NotifyEvent @event)
{
using var scope = _tenantContext.SetContext(@event.TenantId, "worker");
// All subsequent operations are scoped to tenant
var rules = await _rules.ListAsync(@event.TenantId);
// ...
}
}
Handoff Notes
- Incident storage moved from in-memory to MongoDB with full tenant isolation
- Worker should use
ITenantContext.SetContext()before processing events - All new repositories MUST include tenant filtering in queries
- Test tenant isolation with multi-tenant integration tests
Related Files
src/Notifier/StellaOps.Notifier.Worker/Tenancy/TenantContext.cssrc/Notifier/StellaOps.Notifier.Worker/Tenancy/TenantServiceExtensions.cssrc/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/Repositories/INotifyIncidentRepository.cssrc/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/Repositories/NotifyIncidentRepository.cssrc/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/Serialization/NotifyIncidentDocumentMapper.cssrc/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/Options/NotifyMongoOptions.cs(added IncidentsCollection)src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/Migrations/EnsureNotifyIndexesMigration.cs(added incident indexes)src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/ServiceCollectionExtensions.cs(added INotifyIncidentRepository registration)