Files
tripz-llc/docs/06-tenant-model.md
T
HamzaandClaude Opus 4.8 95fea546f5 first commit: منصة Tripz — خطط كاملة + سكافولد باك إند NestJS/Docker
- docs/00-15: دراسة، بنية، محرك تعرفة، تسعير، نموذج استئجار، تكاملات، بيانات، realtime، خطة، devops، لاندنج، مخاطر، اصطلاحات سيرفر، تدفق نشر
- backend/: NestJS 11 على Docker (health + tenants + عزل tenant_id + بادئة tripz_ + Redis DB 3)
- apps/rider, apps/driver, dashboards/admin-web, dashboards/superadmin-web (هياكل)
- sync-to-server.sh + .gitignore

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 15:22:06 +03:00

60 lines
3.2 KiB
Markdown

# 06 — نموذج الاستئجار متعدد المستأجرين
## وضعان
### 1. القياسي (Shared) — الافتراضي
- نشرة واحدة مشتركة، قاعدة واحدة، عمود **`tenant_id`** في كل جدول.
- نطاق إلزامي على مستوى الـ Repository (نفس نمط انطلق الحالي).
- الأرخص تشغيلاً والأسرع تحديثاً. يخدم باقات انطلاقة/علامة/أسطول+.
### 2. السيادة (Sovereign / Enterprise)
- نسخة معزولة كاملة (Docker Compose / K8s namespace) داخل بلد المستأجر أو على خوادمه.
- **نفس الكود، متغيرات بيئة مختلفة** — لا فرع كود منفصل.
- المنتج المضاد لثغرة Onde السيادية. يخدم باقة سيادة.
## فرض العزل (الأهم أمنياً)
- **كل استعلام يُنطَّق بـ `tenant_id`** — لا استثناء.
- يُفرض عبر أحد نمطين (يُحسم في P0):
- **Repository scoped:** مستودع مخصّص يحقن الشرط تلقائياً.
- **TypeORM subscriber/query filter:** فلتر عام يُضاف لكل استعلام.
- `TenantGuard` يستخرج `tenant_id` من الـ subdomain/header/JWT ويحقنه في سياق الطلب (AsyncLocalStorage).
- **اختبار اختراق العزل** ضمن CI: طلب من مستأجر A لا يرى بيانات B أبداً.
## حزمة الدولة (Country Pack)
ملف إعداد لكل دولة يجمع كل ما يختلف بين الأسواق:
```yaml
country: JO
currency: JOD
rounding: { increment: 0.05 }
locale: ar
direction: rtl
phone: { length: 9, prefix: "+962" }
otp: { length: 4, ttl_sec: 300 }
payments: [cash, cliq, zaincash]
sms_provider: local_jo
maps_scope: "amman,zarqa,irbid"
default_tariff_mode: time_or_distance # العداد المنظّم
regulator: ltrc # هيئة تنظيم النقل البري
legal_docs: { terms: jo/terms.md, privacy: jo/privacy.md }
```
**المستأجر الجديد = country pack + هوية بصرية. لا كود جديد.**
## التطبيقات: كود واحد، نكهة لكل مستأجر
```
كود موحّد (راكب+سائق)
→ flavor لكل مستأجر (bundle id, أيقونة, ألوان, مفاتيح FCM)
→ إعداد تشغيلي من GET /tenant/config عند الإقلاع
→ fastlane + CI ينشران كل النكهات بأمر واحد
```
- ديناميكي (من API، بلا إصدار متجر): النصوص، الميزات، طرق الدفع، التعرفة، الألوان.
- بالبناء فقط (flavor): اسم الحزمة، الأيقونة، مفاتيح FCM.
- **الهدف الصلب: مستأجر جديد في يوم عمل واحد.** إن احتاج أكثر — النموذج لا يتوسع.
## جدول tenants (مبسّط)
```
tenants: id, name, slug, country_pack, plan, mode (shared|sovereign),
branding (jsonb), features (jsonb), status, created_at
```
راجع [08-data-model](08-data-model.md) للتفصيل.
← السابق: [05-pricing-billing](05-pricing-billing.md) · التالي: [07-integrations](07-integrations.md)