Multi-Tenant: X-Tenant-Id Header
Tenant izolasyonu nasıl çalışır, RLS güvenlik mantığı, header zorunluluğu.
Tenant nedir?
Qando çok kiracılı (multi-tenant) bir platformdur. Her workspace bir tenant'tır. Veriler tenant bazında izole edilir — bir tenant'ın verisi başka tenant'a sızmaz.
Header zorunluluğu
Her korunan API isteğine X-Tenant-Id header'ı eklenmelidir:
GET /api/products
Authorization: Bearer <token>
X-Tenant-Id: <tenantId>
Bu header eklenmezse:
{ "error": "X-Tenant-Id header zorunlu" }
400 Bad Request döner.
Tenant ID nereden alınır?
Login yanıtındaki user.tenants[] dizisinden:
{
"user": {
"tenants": [
{ "tenantId": "abc-123", "name": "Ana Mağaza", "role": "OWNER" },
{ "tenantId": "def-456", "name": "Şube", "role": "STAFF" }
]
}
}
Kullanıcı birden fazla tenant'ın üyesi olabilir; her API isteğinde hangisi için olduğunu belirtin.
Erişim kontrolü
Backend her isteği şu şekilde kontrol eder:
- Token geçerli mi? (JWT validasyonu)
- Token sahibi bu tenant'a üye mi? (
membershipstablosu kontrolü) - Tenant statüsü erişime izin veriyor mu? (SUSPENDED ise sadece-okuma)
- Geçerse istek işlenir; tenant context'i set edilir.
Row Level Security (RLS)
Veri tabanı seviyesinde PostgreSQL Row Level Security ile ek güvenlik katmanı:
- Her korunan tabloda
tenant_idkolonu vardır - PostgreSQL RLS policy'si
app.current_tenant_idsession değişkeniyle filtreleme yapar - Backend kodunda her sorgu öncesi
SET LOCAL app.current_tenant_idyazılır
Bu sayede:
- Backend kodda bir bug olsa bile DB seviyesi tenant izolasyonu bypass edilemez
- Cross-tenant veri sızıntısı engellenir
Tenant değiştirme
UI'da workspace selector ile tenant değiştirildiğinde:
- Kullanıcı arabirimde aktif tenant değişir
- Bir sonraki API isteğinde yeni tenant ID gönderilir
- Backend yeni context'le çalışır
API consumer olarak siz de:
- Hangi tenant için istek atacağınızı kararlaştırın
- Header'ı doğru tenantId ile doldurun
Yanlış tenant durumu
Eğer kullanıcı üye olmadığı bir tenant ID gönderirse:
HTTP 403 Forbidden
{
"error": "Bu workspace'e erişiminiz yok"
}
Sistem context'i
Cron job'lar ve sistem servisleri kullanıcı context'inde değil sistem context'inde çalışır:
- Tüm tenant'ların verisini görebilir (cross-tenant okuma)
app.bypass_rls=onsession değişkeniyle RLS bypass edilir- Tipik kullanım: pazaryeri sipariş sync (her tenant'ın bağlantısı için sync çalışır)
Bu mekanizma sadece sunucu içinden kullanılır; API consumer olarak siz buna erişemezsiniz.
Yaygın sorunlar
- 403 Forbidden → tenantId yanlış veya üye değilsiniz
- 400 Bad Request → header tamamen eksik
- Veri görünmüyor → tenantId doğru ama tenant statüsü SUSPENDED olabilir