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
122 lines
4.1 KiB
Markdown
122 lines
4.1 KiB
Markdown
# 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:
|
|
```csharp
|
|
// 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 `tenantId` filter
|
|
- Document IDs use `{tenantId}:{resourceId}` composite pattern for RLS
|
|
- Correlation key lookup scoped to tenant
|
|
- Soft delete support with `deletedAt` field
|
|
|
|
### 3. MongoDB Indexes (tenant-scoped)
|
|
|
|
Added in `EnsureNotifyIndexesMigration.cs`:
|
|
```javascript
|
|
// 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 `TenantId` property (NotifyRule, NotifyChannel, NotifyTemplate, etc.)
|
|
- Repository interfaces take `tenantId` as parameter
|
|
- Endpoints extract tenant from `X-StellaOps-Tenant` header
|
|
- MongoDB document IDs use tenant-prefixed composite keys
|
|
|
|
## Configuration
|
|
|
|
```json
|
|
{
|
|
"Notifier": {
|
|
"Tenant": {
|
|
"TenantIdHeader": "X-StellaOps-Tenant",
|
|
"ActorHeader": "X-StellaOps-Actor",
|
|
"RequireTenant": true,
|
|
"DefaultActor": "system",
|
|
"ExcludedPaths": ["/health", "/ready", "/metrics", "/openapi"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### HTTP API
|
|
```http
|
|
GET /api/v2/rules HTTP/1.1
|
|
X-StellaOps-Tenant: tenant-123
|
|
X-StellaOps-Actor: user@example.com
|
|
```
|
|
|
|
### Worker Processing
|
|
```csharp
|
|
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.cs`
|
|
- `src/Notifier/StellaOps.Notifier.Worker/Tenancy/TenantServiceExtensions.cs`
|
|
- `src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/Repositories/INotifyIncidentRepository.cs`
|
|
- `src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/Repositories/NotifyIncidentRepository.cs`
|
|
- `src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/Serialization/NotifyIncidentDocumentMapper.cs`
|
|
- `src/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)
|