Domain & DDD
Aggregate
Aggregate
Tutarlılık sınırı oluşturan, birlikte kaydedilip yüklenen domain nesneleri kümesi. Dışarıdan yalnızca aggregate root üzerinden değiştirilir. Örnek:
User aggregate’ı UserSession, UserOtpChallenge, UserIdentityProvider, UserRole çocuk entity’lerini kapsar.Aggregate Root
Aggregate Root
Aggregate’e tek giriş noktası olan entity;
IAggregateRoot marker’ı taşır. İş kuralları ve invariant’lar burada korunur, domain event’ler buradan (AddDomainEvent) yayılır. Repository’ler yalnızca root tipiyle çalışır.Entity
Entity
Kimliği (
Id) ile eşitlenen, yaşam döngüsü boyunca değişebilen nesne. Bu şablonda EntityBase<TId> / Entity : EntityBase<Guid> tabanından türer; CreatedAt, UpdatedAt, soft-delete alanlarını miras alır.Value Object
Value Object
Kimliği olmayan, değeriyle eşitlenen, immutable nesne.
ValueObject tabanı GetAtomicValues() ile eşitlik üretir. Örnek: Phone, Email, FullName, OtpCode, TCKimlikNo.Domain Event
Domain Event
Aggregate içinde gerçekleşen önemli bir olayın aynı process içindeki temsili.
DomainEvent : INotification tabanından türer; AddDomainEvent ile biriker, SaveEntitiesAsync sonrası MediatR ile dispatch edilir. Örnek: UserOtpGeneratedDomainEvent.Specification
Specification
Sorgu mantığını (where/orderby/include/paging) yeniden kullanılabilir bir nesnede kapsülleyen desen (Ardalis.Specification). Cache ve tag’leme spec üzerinden (
EnableCache, WithTags) açılır. Örnek: UserByPhoneNumberSpecification, PublicFaqsPagedSpecification.Repository
Repository
Aggregate’lere koleksiyon-benzeri erişim soyutlaması.
EFRepository<T> : RepositoryBase<T>, IRepository<T> yazma için; CachedRepository<T> : IReadRepository<T> HybridCache decorator’ı okuma için. EFRepository.SaveChangesAsync bilerek exception fırlatır — kayıt IUnitOfWork ile yapılır.Unit of Work
Unit of Work
Bir işlemdeki tüm değişiklikleri tek transaction’da kaydeden soyutlama.
IUnitOfWork.SaveEntitiesAsync SaveChanges’i çağırır ve ardından domain event’leri dispatch eder (MediatorExtension.DispatchDomainEventsAsync).BuildingBlock
BuildingBlock
Domain’den bağımsız, yeniden kullanılabilir altyapı paketi (
src/BuildingBlocks/*). Caching, Jwt, Keycloak, OAuth, Specification, DeviceDetector gibi 20 paket içerir.CQRS & Application
Command
Command
Sistemin state’ini değiştirme niyeti (yazma).
IRequest<IResponseWrapper<T>> implement eder; bir CommandHandler işler. Örnek: SignUpUserCommand, VerifyOtpCommand.Query
Query
State değiştirmeden veri okuma. Command ile aynı MediatR altyapısını kullanır ama yan etkisizdir; çoğu zaman cache’li okuma yapar. Örnek:
GetAdminMeQuery.Handler
Handler
Bir command/query/notification’ı işleyen sınıf (
IRequestHandler<,> / INotificationHandler<>). İnce kalır: aggregate metodunu çağırır ve SaveEntitiesAsync ile kaydeder.Pipeline Behavior
Pipeline Behavior
Her MediatR isteğinin etrafını saran ara katman. Bu şablondaki sıra: Exception → Authorization → Validation → Permission. Validation FluentValidation ile çalışır; başarısızlık
422’ye dönüşür.Identity & Yetki
Realm (Keycloak)
Realm (Keycloak)
Bağımsız kullanıcı havuzu + ayarları. Bu proje çift realm kullanır: vatandaş (
diyanet-vatandas-*-realm) ve yönetim/personel (diyanet-yonetim-*-realm).Client (Keycloak)
Client (Keycloak)
Bir realm içindeki uygulama tanımı. Örnek:
diyanet-website (public + PKCE) ve diyanet-admin (token 5 dk).Claim
Claim
Token içindeki anahtar-değer bilgisi. Bu projede önemli claim’ler:
permissions (multivalued), organization_id / tenant_id, accountStatus.Scope
Scope
Bir client’ın isteyebileceği yetki/veri kümesini tanımlayan OAuth/OIDC kavramı; token’a hangi claim’lerin gireceğini etkiler.
Permission
Permission
İnce taneli işlem yetkisi (örn. “FAQ yönet”). Lokal DB’de rol → permission eşlemesinden gelir ve
permissions claim’ine yazılır; otorizasyon kararı her zaman lokaldir.Tenant
Tenant
Çok-kiracılı kurulumda bir kuruluşu/şubeyi temsil eden izolasyon birimi.
IMayHaveTenant / ITenant ile modellenir; organization_id claim’i taşır.TOTP
TOTP
Time-based One-Time Password (RFC 6238). Authenticator uygulamasının ürettiği 6 haneli, zamana bağlı kod.
AuthenticationTotpService (OtpNet) doğrular; pencere ±1 adım.OTP
OTP
One-Time Password. Bu projede sunucu üretimi 4 haneli kod (
OtpCode, 1000–9999), SMS (NetGSM) veya e-posta ile gönderilir. SMS challenge 1 dk geçerlidir.PKCE
PKCE
Proof Key for Code Exchange. Public client’larda (SPA) Authorization Code akışını koruyan ek doğrulama (S256 verifier/challenge). Keycloak akışlarında ve OAuth client’larda kullanılır.
Provisioning
Provisioning
Dış kimlikle (Keycloak) giren kullanıcıyı lokal DB’ye eşleme süreci. Personel realm davet bazlıdır — eşleşme yoksa
403 not_invited. ProvisionKeycloakUserCommandHandler yürütür.Veri & Cache
HybridCache (L1/L2)
HybridCache (L1/L2)
.NET’in iki kademeli cache altyapısı. L1 in-memory (TTL ~1 dk), L2 Redis (TTL ~5 dk). Kayıt sırası:
AddRedisCache → AddCache → AddHybridCache. IHybridRequestCache ile erişilir.Tag Invalidation
Tag Invalidation
Cache girdilerini bir tag’le işaretleyip toplu silme.
WithTags(tag) ile spec’te işaretlenir; RemoveByTagAsync(tag) ile düşürülür. Örnek tag: faqs.Soft Delete
Soft Delete
Kaydı fiziksel silmek yerine
DeletedAt/DeletedBy set etmek. AuditInterceptor Deleted durumunu Modified’a çevirir; her ISoftDeletable için DeletedAt == null global query filter uygulanır.Audit
Audit
CreatedAt/By, UpdatedAt/By (ve soft-delete) alanlarının otomatik doldurulması. Tek AuditInterceptor : SaveChangesInterceptor ile.Migration
Migration
EF Core şema değişikliği dosyası.
dotnet ef migrations add <Ad> -p Infrastructure.EFCore -s API ile üretilir.Snake_case
Snake_case
PostgreSQL’de tablo/kolon isimlendirme kuralı (
EFCore.NamingConventions). DbContext snake_case kullanır; kod PascalCase kalır.Event-Driven
Integration Event
Integration Event
Process/servis-arası olay.
IntegrationEvent tabanından türer, IEventBus.PublishAsync ile Outbox’a yazılır, RabbitMQ üzerinden teslim edilir. Örnek: CacheInvalidationIntegrationEvent.Outbox
Outbox
Olayı, onu doğuran DB değişikliğiyle aynı transaction içinde
messaging.outbox_message tablosuna yazma deseni. MassTransit relay tabloyu okuyup RabbitMQ’ya yayar — “kaydedildi ama yayınlanmadı” tutarsızlığını önler.Inbox
Inbox
Gelen mesajların tekrar işlenmesini önleyen idempotency deseni (consumer tarafı). At-least-once teslimatta aynı mesaj iki kez gelirse ikincisi yutulur.
DLX (Dead Letter Exchange)
DLX (Dead Letter Exchange)
Tekrarlı denemelere rağmen işlenemeyen mesajların yönlendirildiği exchange/kuyruk. Retry stratejisi: in-process 3×2 sn + gecikmeli yeniden teslim
[0.16, 1, 5] dk + DLX.Operasyon
Seq
Seq
Yapılandırılmış log toplama/sorgulama aracı (Serilog sink). Dev’de ingest
5341, UI 5342 portunda.İlgili
Sık Sorulan Sorular
Kavramsal ve operasyonel kısa cevaplar.
Mimari Genel Bakış
Katmanlar ve bağımlılık akışı.