إنتقل إلى المحتوى الرئيسي

حوكمة النظام البيئي

شام باص ليس تطبيقاً واحداً، بل نظاماً بيئياً كاملاً يشمل:

  • بوابة العملاء
  • لوحة الشركات
  • لوحة الإدارة
  • تطبيق العميل للموبايل
  • تطبيق السائق
  • الحزم المشتركة
  • قاعدة البيانات والترحيلات والدوال
  • التوثيق الداخلي والعام
  • CI/CD والنشر والمراقبة

الهدف من هذه الصفحة هو تقليل الازدواجية وتوضيح المكان الصحيح لأي تغيير جديد.

الحدود الافتراضية للمسؤوليات

المجالالمصدر المعتمدملاحظات
إنشاء عملاء Supabase وإدارة الجلسات والكوكيزpackages/databaseالأغلفة داخل التطبيقات يجب أن تبقى خفيفة ومخصصة للتهيئة فقط.
أدوات المصادقة و CSRF والصلاحيات المشتركةpackages/authسياسات كل تطبيق قد تغلف هذه الأدوات لكنها لا تنسخها.
الأنواع المشتركة و Zod schemas وعقود الطلب/الاستجابةpackages/typesلا تكرر الأنواع نفسها داخل عدة تطبيقات.
التحقق المشترك والتنسيق والتطبيعpackages/utilsتطبيع أرقام الهواتف وقواعد التحقق العامة يجب أن تكون مركزية.
مكونات UI المشتركة للويبpackages/uiالمكونات المحلية داخل التطبيق تبقى للتجميع أو السلوك الخاص بالمنتج.
الثوابت والتوكنات المشتركة بين الويب والموبايلpackages/shared و packages/configأي قيمة يفترض أن تتطابق بين المنصات يجب أن تبدأ هنا.
الخدمات المشتركة مثل الإشعارات و rate limiting ومزودي الدفعpackages/servicesيجب فصلها عن imports المحلية من نوع @/lib/*.
التحقق من طلبات HTTP وتحويل أخطاء Zod إلى responses موحدةpackages/services/utils/validateتستخدمه مسارات Next كطبقة موحدة فوق packages/types.
منطق السياسات الخاصة بكل تطبيق ومسارات APIداخل التطبيق نفسهطبقات BFF تبقى في التطبيقات لكنها تعتمد على الخدمات المشتركة.
مخطط البيانات و RLS و RPCs و triggersinfrastructure/supabase/migrationsهذا هو المصدر المعتمد لسلوك قاعدة البيانات.
الدوال الطرفية Edge Functionsinfrastructure/supabase/functionsيجب توثيق العلاقة بينها وبين كود التطبيقات بوضوح.
التوثيق الداخلي والتشغيليapps/docs/docs/internalيجب تحديثه بعد أي تغيير معماري أو تشغيلي مهم.
CI/CD والنشر والفحوص الأمنية.github/workflowsيجب أن تعكس المسارات والأوامر الحالية في المستودع.

قواعد العمل

  • إذا كان السلوك مشتركاً بين تطبيقين أو أكثر، ابدأ من الحزم المشتركة.
  • إنشاء عملاء Supabase على الخادم، جلسات SSR، إعادة كتابة عناوين Docker، وقراءة التوكن من Authorization أو الكوكيز المخصصة يجب أن يتم من خلال packages/database.
  • تطبيع أرقام الهواتف، تنسيقها، وتوحيد قواعد كود الحجز يجب أن يتم من خلال packages/utils مع استخدام packages/types كطبقة العقود والتحقق وقت التشغيل.
  • لا تضف منطقاً جديداً مكرراً داخل apps/*/src/lib إذا كان له مكان واضح داخل packages/*.
  • أي route handler جديد يحتاج قراءة body أو query params يجب أن يبدأ من validateBody أو validateQuery بدلاً من تكرار request.json() و safeParse() يدوياً.
  • حافظ على عقود API الحالية للمستهلكين، خصوصاً تطبيقات Flutter، أثناء نقل المنطق إلى الحزم المشتركة.
  • اعتبر الترحيلات المصدر الأول للحقيقة عند توثيق مخطط البيانات أو سلوك القاعدة.
  • لا تترك فحوص CI الأساسية في وضع fail-open: pnpm audit و Semgrep و Patrol/Playwright يجب أن تفشل عند وجود مشكلة حقيقية، لا أن تمر عبر continue-on-error أو || true.
  • أي تغيير مهم في المعمارية أو الإعداد أو التشغيل يجب أن يصاحبه تحديث توثيقي.

ما الذي أصبح مركزياً الآن؟

  • إنشاء عملاء Supabase على الخادم والكوكيز متعددة التطبيقات يبدأ من packages/database.
  • تطبيع الهاتف وتوليد/تطبيع كود الحجز يبدأ من packages/utils.
  • عقود الحجز المشتركة مثل createRoundTripBookingSchema و bulkBookingActionSchema و bookingPaginationQuerySchema تبدأ من packages/types.
  • توجد الآن عقود نظام بيئي صريحة داخل packages/types/src/ecosystem.ts لحالات مثل تفاصيل الحجز، المسارات الشائعة، قائمة الانتظار، وضع الصيانة، وإعدادات الشركة، ويجب أن تبقى هذه العقود هي المرجع عند تعديل المسارات أو مستهلكي Flutter/Next.
  • توسعت هذه العقود لتشمل أيضاً طبقة "ثقة الرحلة" المعيارية عبر TripStatusSnapshot و BookingTicketState و JourneyUpdate و SupportTicketState، إضافة إلى سجل 2FA للإدارة عبر AdminTwoFactorState.
  • إدارة أعلام الميزات داخل لوحة الإدارة يجب أن تمر الآن عبر مسارات app/api/feature-flags/* فقط، بما في ذلك التبديل والتعديل والاستثناءات، حتى تبقى الصلاحيات و CSRF و سجل التدقيق موحدة ولا تنتقل الكتابة المباشرة إلى Supabase من المتصفح.
  • مسارات الويب التي تحتاج parsing و validation للطلبات تبدأ من packages/services/utils/validate ثم تمرر البيانات النظيفة إلى الخدمات المحلية أو المشتركة.
  • routes.service و drivers.service و check-permission أصبحت تعمل كطبقات مشتركة قابلة للحقن من داخل الحزم، بينما تبقى الملفات داخل apps/*/src/lib/... مجرد adapters خفيفة لربط createClient أو createAdminClient المحليين.
  • يوجد الآن فحص تكاملي في tests/integration/system/shared-package-boundaries.test.ts يمنع إضافة imports جديدة من نوع @/lib/* أو @/types/* داخل الحزم المشتركة خارج الاستثناءات المؤقتة الموثقة.

متى يبقى التغيير محلياً داخل التطبيق؟

التغيير يبقى داخل التطبيق عندما يكون:

  • متعلقاً بسياسة وصول أو صلاحيات خاصة بذلك التطبيق
  • متعلقاً بتجميع واجهة أو UX محلي
  • متعلقاً بتشكيل response خاص بمستهلك محدد
  • غلافاً صغيراً فوق طبقة مشتركة لأغراض التهيئة فقط

مسار التنفيذ الموصى به

  1. عدل المصدر المعتمد أولاً.
  2. اجعل الطبقات المحلية مجرد adapters أو wrappers خفيفة.
  3. حدث الاختبارات الأقرب للسلوك المتغير.
  4. حدث التوثيق المرتبط بالمعمارية أو التشغيل أو قاعدة البيانات.
  5. اجعل الـ commits مقسمة حسب النظام الفرعي لتسهيل المراجعة.