organization_id ile sağlanır. DB-per-tenant veya schema-per-tenant yoktur.
Tenant kimliği nereden gelir
Tenant, JWT claim’inden okunur. İki eşdeğer claim kabul edilir:tenant_id(birincil)organization_id(Keycloak Protocol Mapper uyumluluğu; dev provisioning bunu kurar)
HttpContextCurrentTenant (SeedWork/Security/HttpContextCurrentTenant.cs) fallback uygular:
ICurrentTenant Program.cs → RBAC bölümünde kaydedilir:
Domain arayüzleri
Tenant’a ait varlıklar SharedKernel’deki marker arayüzlerini implement eder:IMayHaveTenant global (tenant-agnostic) kayıtlara da izin verir; ITenant ise zorunlu tenant
bağı ifade eder.
Pipeline-level izolasyon
Command/query bir tenant kaynağına eriştiğindeIRequireTenantAccess implement eder; bunu
AuthorizationPipelineBehavior (Application/SeedWork/PipelineBehaviors/) handler çalışmadan
önce doğrular:
TenantId ile istek atarsa 403 alır.
Bu kontrol controller attribute’undan bağımsızdır; use-case seviyesinde garanti verir.
Neden DB-per-tenant değil
Soft-tenant tercih edildi çünkü:- Tek migration, tek bağlantı havuzu — N tenant için N veritabanı yönetmek operasyonel yük.
- Müşteri on-prem ortamı — mevcut tek Postgres instance’ı paylaşılır; dinamik veritabanı oluşturma yetkisi her zaman olmayabilir.
- Cross-tenant raporlama tek sorguda mümkün (yetki dahilinde).
organization_id
filtresini taşımalı ve mutasyonlar IRequireTenantAccess ile korunmalıdır.
İlgili
Authorization
Permission ve pipeline behavior.
Realm Yapısı
organization_id Protocol Mapper.
Tasarım Kararları
Soft-tenant tercihi ve gerekçeleri.
DbContext
Query filter ve şema yapısı.