Skip to content

المفاهيم الأساسية

نموذج بيانات Patchwire يتكوّن من خمس كيانات. فهم حدود كل منها هو الفرق بين استخدام Patchwire بشكل صحيح ومحاربته.

المنظمة (org)

المستأجر على المستوى الأعلى. كل شيء آخر ينتمي إلى منظمة واحدة فقط. كل صف في قاعدة البيانات يحمل عمود org_id، وكل استعلام يُرشِّح به، وكل JWT يحمل الـslug الذي صدر له.

الخصائص:

  • slug — معرّف مناسب للروابط، فريد عبر كامل التثبيت، وغير قابل للتغيير بعد الإنشاء.
  • name — التسمية الظاهرة.
  • statusactive للاستخدام الطبيعي؛ حالات الأرشفة والتعليق محجوزة لميزات إدارة مستقبلية.

لا شيء يعبر حدود المنظمة. المستخدم في المنظمة A لا يستطيع — حرفياً — رؤية مشروع في المنظمة B؛ الـSQL لا يجمع بينهما أصلاً.

المستخدم

شخص يستطيع تسجيل الدخول. ينتمي إلى منظمة واحدة.

  • email — فريد داخل المنظمة.
  • roleadmin أو member. أوّل مستخدم (المُنشَأ عبر /register) يكون دائماً admin.
  • statusactive أو suspended أو deleted.

لاحظ أن قائمة الأدوار قصيرة عمداً. Patchwire اليوم لا يملك أدواراً دقيقة؛ الافتراض هو فِرق صغيرة الجميع فيها موثوق به.

المشروع

مستودع مُسجَّل للفحص. ينتمي إلى منظمة واحدة.

  • slug — فريد داخل المنظمة. يصبح جزءاً من كل رابط ومن مطابقة <owner>/<project> التي تستخدمها الـwebhooks.
  • name, description — بيانات تعريفية للقارئ البشري.
  • repo_url — رابط HTTPS للنسخ. يُعبّئ نموذج الفحص تلقائياً.
  • default_branch — الفرع الذي يُفحص عند عدم تحديد أي شيء (الافتراضي main).
  • access_token_enc — رمز PAT مشفَّر للمستودعات الخاصة. لا يُعاد عبر الـAPI أبداً؛ الاستجابة تحمل has_access_token: bool بدلاً منه.
  • access_token_user — اسم المستخدم في URL الموقَّع (x-access-token لـGitHub، oauth2 لـGitLab، اسم مستخدمك لـBitbucket).

الفحص (Scan)

تنفيذ واحد لخط أنابيب الماسحات على مشروع واحد عند فرع واحد.

  • id — UUID. الجزء الذي يظهر في الروابط.
  • project_id, org_id — مرجع المستأجر مكرَّر.
  • scanner_type — مصدر الفحص: webhook-all (كل الماسحات تشتغل، مُطلَقة من حدث دفع)، manual-all (يدوياً عبر الزر).
  • target_ref — هاش الـcommit من الـwebhook، أو اسم الفرع للفحوصات اليدوية.
  • statuspendingrunningcompleted (أو failed إذا فشل أحد الماسحات).
  • summary — كائن JSON يحتوي عدد النتائج حسب الخطورة: {critical, high, medium, low, info, total}.
  • started_at, finished_at — أوقات.

الفحوصات غير قابلة للتعديل بعد الوصول إلى completed أو failed. إعادة التشغيل تُنشئ صف فحص جديد.

النتيجة (Finding)

ثغرة واحدة رصدها أحد الماسحات، مرتبطة بفحص واحد.

  • external_id — معرّف الماسح الخاص للنتيجة. الزوج (scan_id, external_id) فريد — هكذا تعمل عملية إزالة التكرار.
  • title, description — ما تقوله القاعدة.
  • severitycritical أو high أو medium أو low أو info. مُحوَّلة من حقل الخطورة الأصلي عند الماسح.
  • scannersemgrep أو gitleaks.
  • location_path, location_line, location_column — مكان النتيجة في المستودع.
  • metadata — كائن JSON لتفاصيل خاصة بالماسح.

كيف تترابط

المنظمة
  ├── المستخدمون  (1:N)
  └── المشاريع     (1:N)
        └── الفحوصات   (1:N)
              └── النتائج  (1:N)

كل نتيجة يمكن الوصول إليها من منظمتها عبر قفزتي مفتاح أجنبي. هذا أساسي لنموذج المصادقة — الـAPI لا يثق أبداً بـorg_id المخزَّن في النتيجة وحدها؛ يتحقّق دائماً عبر منظمة المشروع الأم.

ماذا عن الـwebhooks؟

الـwebhooks ليست كياناً في قاعدة البيانات. تُضبط على جانب الـSCM — الحالة الوحيدة التي يحتفظ بها Patchwire هي مفتاح HMAC المشترك في PATCHWIRE_WEBHOOK_SECRET (مفتاح واحد للتثبيت كله، يخدم المزودين الأربعة).

عند وصول webhook، Patchwire:

  1. يتحقّق من توقيع HMAC مقابل بايتات الجسم.
  2. يحلّل full_name للمستودع (owner/name) لإيجاد slug المنظمة + slug المشروع.
  3. يبحث عن المشروع؛ إذا لم يكن موجوداً يعيد 200 مع "status":"ignored" كي تتوقف إعادة المحاولة.
  4. يُنشئ صف فحص، يُطلق خط الأنابيب في الخلفية، ويعيد 200 خلال مهلة المزوِّد.

راجع Webhooks لشرح الإعداد.