Architecture¶
Tenants is a Layer 3 host on the Base Template layering (template layering and reuse). Layer suffixes are described in solution structure.
Service contracts¶
Code-first contracts in ConnectSoft.Saas.Tenants.ServiceModel (namespace ConnectSoft.Saas.Tenants.servicemodel/2025/tenants/):
| Contract | gRPC adapter |
|---|---|
ITenantManagementService |
GrpcTenantManagementService |
ITenantQueryService |
GrpcTenantQueryService |
Tenants-specific gRPC interceptor: TenantGrpcServerInterceptor.
REST surface (TenantsController, api/tenants)¶
| HTTP | Route | Operation |
|---|---|---|
| POST | /draft |
CreateDraftAsync |
| PUT | /activate |
ActivateAsync |
| PUT | /suspend |
SuspendAsync |
| PUT | /decommission |
DecommissionAsync |
| PUT | /residency |
ChangeResidencyAsync |
| POST | /queries/by-partition |
GetTenantForTenantAsync |
| POST | /queries/by-id |
GetTenantByIdAsync |
| POST | /queries/by-tenant-key |
GetTenantByTenantKeyAsync |
DTOs: TenantDto, TenantResponse, request types (CreateTenantDraftRequest, etc.).
Messaging¶
Publishes the five tenants.domain.v1.* lifecycle events; consumes only its own TenantCreatedEvent via TenantLifecycleSaga. No IConsumer<T> classes - the saga is the only handler.
Persistence¶
NHibernate + Fluent mapping TenantEntityMap -> table Tenants in schema ConnectSoft.Saas.Tenants. Single-table aggregate with unique constraints UQ_Tenants_TenantId and UQ_Tenants_TenantKey (globally unique tenant id and key - distinct from other contexts where uniqueness is only filter-scoped). FluentMigrator MicroserviceMigration + SampleTenantSeed. Shipped dialect: SQL Server.
Multitenancy uses the shared SaasTenantFilter row filter on TenantId; appsettings Multitenancy defaults to SharedDb.
Concurrency¶
TenantLifecycleGrain (keyed by tenant partition id) serializes writes per partition.