الوثائق

تعدّد المستأجرين الصارم

كيف تعزل betool بياناتك وأسرارك وعمليات التنفيذ الخاصة بك عن المؤسسات الأخرى.

تعدّد المستأجرين الصارم

يُعدّ العزل بين المؤسسات الثابت التأسيسي في betool. وفيما يلي كيفية فرضه، طبقةً تلو الأخرى.

على مستوى قاعدة البيانات

تحمل جداول الأعمال عمود org_id الذي يربط كل صفّ بمؤسسته (وهو في الغالب مقيّد بمفتاح أجنبي إلى organisation(id)).

تمرّ جميع الاستعلامات على جانب الخادم عبر دوال المخزن (store methods) التي تُرشّح بشكل منهجي حسب org_id للجلسة الحالية. لا مسار برمجي يكشف استعلامًا اعتباطيًا؛ ولا يستطيع أي عميل فرض org_id مختلف.

بالنسبة للعدد القليل من الموارد التي يمكن مشاركتها عبر المؤسسات (عادةً حسابات LLM المشتركة على مستوى المنصّة)، يتيح عمود is_shared BOOLEAN NOT NULL DEFAULT FALSE موافقةً صريحة (opt-in). القواعد:

  • تُصرَّح أي قراءة بـ WHERE org_id = %s OR is_shared = TRUE.
  • يتطلّب أي تعديل لصفٍّ قيمته is_shared = TRUE دور hyperadmin (مُشغّل المنصّة).
  • يُبطِل أي تعديل التخزين المؤقّت عالميًا — لا تباين لكل مؤسسة.

على مستوى تخزين الملفّات

تُحفَظ الملفّات في تخزين كائنات (قرص محلّي أو bucket سحابي بحسب النشر)، ضمن مساحة خاصة بكل مؤسسة:

orgs/
└── <org_id>/
    ├── files/<canal>/<exchange_id>/<fichier>   ← الملفات المستلَمة عبر القنوات
    └── fixtures/                               ← البيانات التجريبية للمعايير

تُبنى المفاتيح على جانب الخادم (اسم ملف مُنقّى، حماية من path-traversal). وتمرّ كل قراءة لملف باسم مستخدم أو أداة أو وكيل عبر تحقّق يرفض أي مفتاح خارج المساحة orgs/<org_id>/files/ للمؤسسة الحالية.

على مستوى التخزين المؤقّت

طبقات التخزين المؤقّت للتطبيق (مثلًا حلّ مزوّدي LLM) مفهرسة حسب المؤسسة. وعند تعديل مورد قيمته is_shared = TRUE، يُبطَل التخزين المؤقّت عالميًا — فلا توجد نافذة زمنية قد ترى فيها مؤسسة قيمة قديمة.

على مستوى الأسرار

تُخزَّن بيانات الاعتماد (مفاتيح LLM، ورموز مصادقة المُشغّل، وأسرار webhook) على جانب الخادم، مرتبطةً بكل مؤسسة. ولا تُعاد أبدًا بنصٍّ صريح عبر API: لا تُشير مسارات GET إلا إلى وجودها (مثلًا has_api_key: bool).

على مستوى التنفيذ

عند تشغيل خط معالجة (pipeline):

  • لا تصل المُشغّلات (operators) إلّا إلى الحسابات الخارجية المُصرّح بها في المؤسسة.
  • تُحَلّ نماذج LLM المستخدَمة بالترتيب own > shared (fallback auto) — دائمًا.
  • لا تكون الملفّات المرفقة قابلة للقراءة إلّا في مساحة التخزين الخاصة بالمؤسسة الحالية.

إذا حاول مُشغّل الوصول إلى مورد خارج نطاقه، يُرفَض الوصول بخطأ صريح — لا مهلة زمنية صامتة.

قائمة تحقّق عملية

كلما أُضيف مورد مشترك جديد، يُجيب الفريق عن هذه الأسئلة الأربعة:

  1. إذا ظهرت مؤسسة backoffice ثانية، هل يتصرّف الكود لديّ بشكل صحيح؟
  2. إذا عدّلتُ صفًّا مشتركًا، هل تُبطَل جميع طبقات التخزين المؤقّت لكل مؤسسة؟
  3. هل تبقى أسراري على جانب الخادم حصريًا؟
  4. هل يسمح GET لدَيّ لمُنتقيات المؤسسات الأخرى بسرد المورد دون كشف السرّ؟

إذا كانت أي إجابة «لا»، فلا يُشحَن المورد.