Sistem Haritası
6 bağımsız uygulama, tek backend. Gateway yalnızca frontend seçer + tenant context enjekte eder. İki realm: merkezî Control DB ↔ firma-başına Tenant DB.
Belge Haritası
2 düzlem, multi-DB engine, abonelik/modül/entitlement, gateway, auth, güvenlik (§20), benchmark sonuçları.
Base→sub entity'ler, value object'ler, aggregate'ler, Product STI, IModule plug-in kontratı, ER + UML diyagramları.
DB-per-tenant topolojisinin yük testi: kapasite, sınırlar, sizing yasası, provisioning/migration ölçümleri.
Tasarımı koda dökmek için fazlandırma: Faz 0–6, her fazın hedefi/çıktısı/bağımlılığı + dikey-dilim-önce stratejisi.
Kilitli Kararlar
Tüm mimari kararlar kilitli; açık-soru yok. Sıradaki adım kodlama.
Sözlük
Mimari & Kapsam
Bu fazda tasarlanan: bir tenant'ın lisans/modül/tema satın alıp, kendi DB'sini bağlayıp, admin panelinden yöneterek sitesinin canlıya çıkması için gereken tüm kontrol-düzlemi makinesi. İş mantığı / org-schema / approval-engine sonraki faz.
Teklifteki Prisma yerine bilinçli sapma — gerekçe: dinamik multi-DB / BYODB + karmaşık SQL + transaction + AI-fidelity tip sistemi. Mongo elendi (ERP → ağır transaction + ilişki).
1 firma = 1 Postgres DB; birçok DB az sayıda paylaşımlı cluster'da; BYODB kendi sunucusunda. Canlı routing, sync yok. BYODB sadece PostgreSQL.
3 izolasyon seviyesi
Premises (onaylandı)
Multi-DB Motoru
Control DB tek bir Drizzle instance'ı; her tenant DB'si istek başına registry'den çözülen ayrı Drizzle instance'ı. İzolasyonun bel kemiği: servise vermeden önce çözülen descriptor'ın tenant_id'si CLS'teki tenant_id ile eşleşmek zorunda.
Connection registry + yaşam döngüsü
max_server_conns tavanı + app-tarafı küçük pool'lar), tenant sayısının fonksiyonu DEĞİL. Sabit backend tavanı (150–300) → ~1–3GB. Naif yol bu tavanı kaldırdığı için patlar.cls.run({tenantId}, fn) ile sarılır.Repository / ORM katmanı — R1–R8
Modül & Entitlement
Sadeleştirici prensip: Module = tek kavram, beş hizalı görünüm. Yeni modül eklemek = tek paket + tek ürün; gating / aktivasyon / UI / migration hepsi türetilir.
Katmanlar — oturmuş patternler
Satıştan aktivasyona, her katman bir sonrakini besler.
Tek modelden türeyen gereksinimler
Provisioning & "Site Canlıya Çıkar"
Aktivasyon türetilir, elle bağlanmaz: bir modül "aktif" iff entitlement set feature_key'i içerir ve deps karşılanmış ve (şema gerekiyorsa) migration'ları tenant DB'ye uygulanmış.
Control plane + worker/outbox sürer; admin panel canlı yansıtır; her adım resumable.
Runtime canlı yolu
Migration stratejisi — iki set (control + tenant)
Auth & Gateway Güven Sınırı
Gateway → backend imzalı tenant context (spoof'lanabilir düz X-Public-Key yerine). İzolasyonun güvenlik bel kemiği budur.
Caching / Redis — paylaşımlı (process-local LRU yerine)
Güvenlik — Kapatma Maddeleri (§20)
Tasarım-seviyesi adversarial güvenlik review'ı (8 lens, kod yok). Posture: fiziksel izolasyon omurgası güçlü; bu maddeler veri-yapıları / kodlama fazından ÖNCE tasarıma girer.
Benchmark — Topoloji Feasibility
Ortam: OrbStack/Mac, Postgres 16, max_connections=200, shared_buffers=256MB, PgBouncer transaction-pool. Lokal koşum şekil/knee verir; mutlak tavan prod-donanım gerektirir.
Temel Hiyerarşi
C#/OOP mentalitesi: base/derived entity, value object, aggregate, interface. Tablo sayısı hedef değil; temiz entity modeli hedef.
Capability interface'ler
God-base değil, ihtiyaç kadar opt-in. Ölü kolon yok.
Value Object'ler
Immutable, self-validating, structural equality, kimliksiz. Kural: sorgulanan çok-alanlı VO → düz sibling kolonlar; bütün-okunan VO → typed jsonb. Mapper kurar; entity sadece doğrulanmış nesneyi görür.
Polimorfik Entity'ler — STI
Drizzle native STI yok → tek tablo + kind + explicit per-kind check() + Mapper.fromRow + per-kind zod parse. Union domain-only.
Theme / BundleItem ayrı child tablo — kendi kimlik/ilişkileri var (STI değil, aggregate-child).
Aggregate Sınırları
Kök üzerinden tek tx'te yüklenir/yazılır (R6). Cross-aggregate tutarlılık outbox + saga ile EVENTUAL — distributed tx YOK.
IModule Kontratı
SKU (satış) + NestJS modülü (kod) + Drizzle şema dilimi (veri) + manifest (deps/UI) + featureKey (entitlement). Pluggable = deploy-zamanı statik kod + per-tenant entitlement aktivasyonu; runtime hot-plug DEĞİL.
Dış Proje Entegrasyonu
"Any big project can come in" → EVET (clean + generic). Tek kontrat (IModule), 5 hizalı görünüm. Dış projenin veri nesneleri sadece extends TenantEntity → izolasyon / RLS / soft-delete / audit / optlock bedava — modülde sıfır izolasyon kodu.
4 örnek — hepsi aynı 5 görünüm, branch yok
Schema-less + sandboxed + metered bir modül de aynı şekilde absorbe edilir.
ER Diyagramı — Control DB (26 tablo)
~30 domain entity sınıfı + ~15 value object = ~45 veri nesnesi. entity ≠ tablo: Product ailesi 5 sınıf → 1 tablo; VO'lar gömülü. Tenant-DB tabloları (company + modül lic_/prd_/stk_) ayrı; cross-DB FK yok.
UML Class Diyagramı
△ inheritance <|-- · ◆ composition *-- · ○ realize ..|>
Kod & Klasör Yapısı
Hedef yapı (backend/ greenfield). Domain katmanı Nest'ten bağımsız POJO; her modül ports/ + adapters/pg/ ile izole.
Repository spine + boot
Out-of-Process Modül ABI
Karar: out-of-process out-of-process bugün desteklenmiyor; ancak genişleme noktası baştan hazır — type-level + tek forRoot dalı. İleride eklemek = sadece bir transport adapter yazmak.
assert(manifest.isolation === hostBinding.kind) · in-process → imports.push(module) · out-of-process → bugün throw NotImplemented. Başka hiçbir şey değişmez.Frontend Dinamik Kayıt
In-process LRU memory derdi YOK. Build-time statik registry + Redis ui-manifest.
Eng-Review Revizyonları
Mimari korunarak düzeltilen P0/P1 noktalar — doğruluk, güvenlik ve mapping.
Genel Bakış
C#/OOP mentalitesi: base/derived entity, value object, aggregate, interface. Tablo sayısı hedef değil; temiz entity modeli hedef.
Karar Bekleyen Noktalar
§8'in açtığı sorular; çoğu §9 fork kararlarında çözüldü.
Topoloji ucuz, migration hızlı.
Tek Postgres 16 düğümü (max_connections=200, shared_buffers=256MB) + PgBouncer (transaction pool). Lokal ortam, tek makine. Sayılar eğilim/şekil içindir; mutlak rakamlar prod donanımında tekrar ölçülmeli.
Kapasite
Sınırlar
Provisioning & Migration
Spine-first, sonra tek dikey dilim.
Önce çekirdek omurga, sonra bir tenant'ı gerçekten canlıya çıkaran uçtan-uca ince dilim; sonra ilk gerçek modül; sonra sertleştirme. Güvenlik must-close'ları (§20) ait oldukları fazda yapılır, ertelenmez.