Files
tripz-llc/docs/06-tenant-model.md
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

3.2 KiB

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)

ملف إعداد لكل دولة يجمع كل ما يختلف بين الأسواق:

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 للتفصيل.

← السابق: 05-pricing-billing · التالي: 07-integrations