السلام عليكم ورحمة الله وبركاته،
سعدت بالمشاركة في مهمتين ضمن حملة كود يخدم القرآن في مشروع Itqan CMS، وكانت المساهمة موزعة بين تحسين تتبع استخدام التطبيقات عبر API Keys، ووضع مواصفة موحدة لتعريف أصول Itqan وتثبيت إصداراتها.
فيما يلي توضيح للمشكلتين والحلول التي تم اعتمادها:
المهمة1: ربط هوية التطبيق بتتبع الاستخدام Issue #411
رابط المهمة:
https://github.com/Itqan-community/cms-backend/issues/411
المشكلة
كان نظام تتبع الاستخدام يعتمد على بيانات التتبع الموجودة، كما كان يحتوي على مسار قائم للتعامل مع هوية تطبيقات OAuth2. لكن عند استخدام API Key لم تكن هوية المفتاح نفسه تصل إلى طبقة تتبع الاستخدام.
كان ذلك يجعل التمييز بين استخدام مفاتيح API مختلفة أكثر صعوبة، خصوصًا عندما تكون هذه المفاتيح مملوكة للمستخدم نفسه، رغم أنها قد تمثل تطبيقات مختلفة.
طريقة الحل التي اتبعتها
- الاستفادة من كائن "APIKey" الذي يتم حله أصلًا داخل طبقة المصادقة، بدل إعادة قراءة المفتاح أو تنفيذ عملية حله مرة أخرى.
- الإبقاء على مالك المفتاح داخل "request.user" حتى يستمر سلوك الصلاحيات وفحوصات الوصول كما هو.
- إعادة كائن "APIKey" نفسه من طبقة المصادقة، ليصبح متاحًا من خلال "request.auth".
- استخدام "request.auth.prefix" بوصفه "application_id" غير سري داخل بيانات تتبع الاستخدام.
- الحفاظ على مسار OAuth2 الحالي وأولويته عند وجود هوية تطبيق OAuth2.
- تجنب إعادة قراءة أو إعادة حل قيمة الترويسة "X-API-Key".
- عدم إضافة استعلامات أو تخزين جديد في مسار التتبع، والإبقاء على إسناد هوية التطبيق في Mixpanel فقط.
تم اختيار "prefix" بدل قيمة المفتاح الكاملة حتى يمكن تمييز التطبيقات دون كشف قيمة API Key السرية أو تخزينها.
الاختبارات والتحقق
تمت إضافة اختبارات للتحقق من الحالات الأساسية، من بينها:
- تسجيل "application_id" باستخدام "APIKey.prefix".
- التمييز بين مفاتيح API مختلفة مملوكة للمستخدم نفسه.
- الحفاظ على أولوية هوية OAuth2 عند توفرها.
- التأكد من بقاء "application_name" بقيمة "None" عند استخدام API Key.
- التأكد من استمرار عمل التتبع في الطلبات العامة.
كما تم تشغيل اختبارات التتبع والتكامل، بالإضافة إلى فحوصات Ruff والتحقق من نظافة التغييرات باستخدام "git diff --check".
النتيجة
أصبح نظام تتبع الاستخدام قادرًا على ربط الطلب بهوية التطبيق عند استخدام API Key، مع الحفاظ على مالك المفتاح في "request.user" واستمرار سلوك الصلاحيات وOAuth2 كما هو.
PR:
https://github.com/Itqan-community/cms-backend/pull/453
المهمة 2: تعريف صيغة ملف الأصول وتثبيت الإصدارات Issue #416
رابط المهمة:
https://github.com/Itqan-community/cms-backend/issues/416
المشكلة
كانت الأصول تُستخدم وتُضمّن في التطبيقات دون وجود صيغة موحدة توضّح الأصول المطلوبة والإصدارات المقبولة منها، وبالتالي لم يكن هناك فصل واضح بين الإصدار الذي يسمح به المشروع والإصدار الذي تم اختياره فعليًا.
هذا يجعل إعادة البناء والتحديث المنضبط أكثر صعوبة، خصوصًا مع التخطيط مستقبلًا لأداة تثبيت ومدير تحديثات شبيه بـ Dependabot.
طريقة الحل التي اتبعتها
- اعتماد "itqan-assets.yaml" كملف Manifest يحدد الأصول ونطاقات الإصدارات المقبولة.
- اعتماد "itqan-assets.lock" كـ Lockfile يسجل الإصدار المحدد الذي تم اختياره فعليًا.
- استخدام "Asset.slug" كمعرّف للأصل في الإصدار الأول V1.
- توثيق قواعد SemVer، بما في ذلك التعامل مع الإصدارات ذات مكوّنين مثل "1.2".
- تحديد آلية حتمية لاختيار أعلى إصدار صالح ومطابق للقيد من توزيعات "PACKAGE".
- توضيح التعامل مع الإصدارات التجريبية وحالات توفر التحديث.
- اعتماد حل ذري للاعتماديات، بحيث لا يتم إنشاء Lockfile جزئي عند فشل حل أحد الأصول.
- توثيق قواعد التحقق والتسلسل لضمان نتائج قابلة لإعادة الإنتاج بين الأدوات المختلفة.
النتيجة
أصبح لدى المشروع مواصفة V1 واضحة وموحدة لتعريف أصول Itqan وإصداراتها، وتفصل بين نطاق الإصدارات المطلوب والإصدار الفعلي المثبت.
وهذا يوفر أساسًا واضحًا يمكن البناء عليه لاحقًا لتطوير Registry API وCLI Installer وآلية تحديث شبيهة بـ Dependabot، دون اختلاف في تفسير صيغة الإصدارات أو طريقة حلها.
تم توثيق المواصفة في: "docs/ASSET_MANIFEST.md"
وتم دمجها عبر PR #455: https://github.com/Itqan-community/cms-backend/pull/455
سعدت بهذه المساهمة، وأتمنى أن تكون هذه التغييرات مفيدة لباقي المطورين، وأن تساهم في بناء أدوات ومشاريع تقنية تخدم القرآن الكريم بصورة أفضل وأكثر استدامة.