تخطَّ إلى المحتوى

أمان أداة بناء Backport وعملياتها

هذه أدوات بناء، وليست اعتمادية وقت تشغيل. توضّح هذه الصفحة كيفية تشغيل مسار البناء والوثوق به. أما الوضع الأمني لمحرّك تنسيق المستندات المحمولة (⁨PDF⁩) نفسه فموثَّق مع المحرّك، لا هنا.

تحوّل أداة البناء شيفرة مصدرية لم تؤلّفها، وتُصدر توزيعة لا يجري التطوير اعتمادًا عليها. ومن هذا الحدّ ينبثق نموذجها الأمني. يبدأ حدّ الثقة عند سحب الشيفرة المصدرية وسلسلة الأدوات. أما المُخرَج الناتج فهو للقراءة فقط ومُنتَج آليًّا. كما أن الفصل في الترخيص بين الحزمة العامة وحزمة ⁨Pro⁩ مثبَّت في الشيفرة.

تتعامل أداة البناء مع مستودعات المصدر وسلسلة الأدوات المثبَّتة كمدخلات، وتُنتج مُخرَجًا مشتقًّا. وتتحقق من ذلك ثلاث خصائص:

  • التوزيعة المُولَّدة للقراءة فقط ومُنتَجة آليًّا. تُنشَر كوسوم إصدار، لا كفروع في هذا المستودع. وجّه التطوير وتقارير الأخطاء وطلبات الميزات إلى مستودعات المصدر الأصلية nextpdf/*، لا إلى الشجرة المُولَّدة أبدًا. مُتحقَّق منه مقابل كتلة التنبيه في ملف المشروع README.md وملف .github/workflows/build.yml (يودِع الإصدار الشجرة المُولَّدة ويضع وسمها من الصفر).
  • نطاق رمز الإصدار ضيّق. يصرّح secrets.BACKPORT_TRIGGER_TOKEN باستنساخ مستودعات المصدر عند وسم الإصدار. ولا يُشار إليه إلا في خطوات سحب الشيفرة المصدرية. مُتحقَّق منه مقابل build.yml (استخدام GH_TOKEN).
  • فصل مُشغِّلات التكامل المستمر (⁨CI⁩) متعمَّد. تعمل الأحداث الموثوقة على مُشغِّلات ⁨PHP⁩ ذاتية الاستضافة، بينما تُجبَر طلبات السحب من النسخ المتفرّعة وعمليات ⁨Dependabot⁩ على مُشغِّلات مُستضافة على ⁨GitHub.⁩ ولا تُنفَّذ الشيفرة غير الموثوقة على مجمَّع المُشغِّلات الموثوقة أبدًا. مُتحقَّق منه مقابل .github/workflows/0-ci.yml (شرط runs-on).
  • سلسلة الأدوات مُقيَّدة في composer.json. تستخدم ⁨Rector⁩ ^2.0، و⁨PHPStan⁩ ^2.1، و⁨PHPUnit⁩ ^13.0، ومجموعة symfony/polyfill-*. ولا تعتمد أداة البناء في وقت التشغيل على ⁨NextPDF⁩، لذلك لا تستطيع حزمة وقت تشغيل ⁨NextPDF⁩ مُخترَقة الوصول إلى أداة البناء. مُتحقَّق منه مقابل composer.json.
  • تحديثات الاعتماديات مدفوعة بروبوت ومُقيَّدة ببوابة. يتوفّر إعداد ⁨Dependabot⁩ وسير عمل للدمج التلقائي. عمليات ⁨Dependabot⁩ مثبَّتة على مُشغِّلات مُستضافة على ⁨GitHub⁩، لكنها مع ذلك تمر عبر بوابة ⁨CI⁩ الكاملة (⁨PHPStan⁩، الاختبارات، التشغيل التجريبي) قبل الدمج. مُتحقَّق منه مقابل .github/dependabot.yml و.github/workflows/0-ci.yml و9-dependabot-auto-merge.yml.
  • يستبعد المُخرَج حالة البناء. يُضغَط أرشيف الإصدار مع استبعاد vendor/ و.git/. ويحمل المُخرَج المنشور الشيفرة المصدرية والبيان المُولَّد، لا شجرة اعتماديات أداة البناء نفسها. مُتحقَّق منه مقابل build.yml (zip ... -x '*/vendor/*' '*/.git/*').
  • يُخضِع التحليل الساكن شيفرة البناء لبوابة. يشغّل composer analyse أداة ⁨PHPStan⁩ عند المستوى 10 على rector/rules وscripts عند كل دفع وكل طلب سحب إلى أيٍّ من الفرعين الدائمين. ويُنفَّذ قبل أي تشغيل تجريبي. مُتحقَّق منه مقابل composer.json و0-ci.yml.

بوابة التحقق من بناء الجملة

قسم بعنوان «بوابة التحقق من بناء الجملة»

لا يفحص سكربت البناء بناء جملة المُخرَج محليًّا، لأن مضيف البناء يشغّل إصدار ⁨PHP⁩ أحدث من الهدف. والبوابة المرجعية موجودة في سير عمل الإصدار. بعد البناء، يتحوّل المُشغِّل إلى إصدار ⁨PHP⁩ الهدف ويشغّل php -l عبر output/src، فيُفشِل الإصدار عند أي خطأ تحليل أو خطأ فادح. ثم يُثبَّت المُخرَج ويُختبَر عبر مصفوفة التحقق — من ⁨PHP 8.1⁩ إلى 8.4 لمسار ⁨PHP 8.1⁩، و⁨PHP 7.4⁩ و8.0 لمسار ⁨PHP 7.4.⁩ ولا تصل إلى الإصدار أي توزيعة يرفضها وقت تشغيل هدف. مُتحقَّق منه مقابل scripts/build.php (validateOutput()) و.github/workflows/build.yml (مهمتا فحص بناء الجملة وvalidate-*).

هذا ضمان قائم على السلوك المُلاحَظ ومحصور في أوقات التشغيل التي يختبرها المسار. وهو ليس شهادة مطابقة، ولا يؤكّد صحة البرنامج المُحوَّل بما يتجاوز قبول بناء الجملة ومجموعة اختبارات المشروع نفسها.

تحمل الحزمتان المُنتَجتان تراخيص مختلفة، وهي مثبَّتة في scripts/adjust-composer.php:

الحزمةحقل الترخيصيُضبَط بواسطة
nextpdf/backportApache-2.0generatePublicComposer()
nextpdf/backport-proproprietarygenerateProComposer()

يخضع مستودع أداة البناء نفسه لـ ⁨Apache-2.0⁩ (composer.jsonlicense). ويسجّل ملف CHANGELOG.md الخاص به إعادة ترخيص سابقة من ⁨LGPL-3.0-or-later⁩ إلى ⁨Apache-2.0.⁩ تبقى الإصدارات المنشورة قبل ذلك التغيير خاضعة للترخيص الأقدم وتظل قابلة للاسترجاع، بينما يخضع كل إصدار جديد لـ ⁨Apache-2.0.⁩ توزيعة ⁨Pro⁩ خاصة المِلكية، وتُنتَج فقط لهدف ⁨PHP 8.1⁩، وتتطلّب phpseclib/phpseclib ^3.0. مُتحقَّق منه مقابل CHANGELOG.md وcomposer.json وscripts/adjust-composer.php.

الضمانات التشغيلية وحدودها

قسم بعنوان «الضمانات التشغيلية وحدودها»

ما يضمنه المسار، ضمن الحدود التي تفرضها الشيفرة:

  • التوقّف عند أول فشل. يُجهَض البناء عند أول مرحلة فاشلة مع خطأ مُسمّى. ولا تُصدَر توزيعة جزئية أبدًا، لأن مهام الإصدار تعتمد على نجاح البناء والتحقق. مُتحقَّق منه مقابل scripts/build.php (step()) وbuild.yml عبر needs في المهمة.
  • عمليات بناء متسلسلة. تمنع مجموعة التزامن backport-build المضبوطة بـ cancel-in-progress: false تسابُق إصدارَي مصدر على وسم الإصدار نفسه. مُتحقَّق منه مقابل build.yml.
  • مدخلات قابلة لإعادة الإنتاج. يستنسخ المسار كل مستودع مصدر عند وسم الإصدار المحدّد بدقة قبل البناء. مُتحقَّق منه مقابل build.yml (--branch "${TAG}").

ما لا يدّعيه:

  • لا يصدّق على مطابقة المعايير، ولا على التوافق الكامل مع إصدارات ⁨PHP⁩، ولا على صحة البرنامج المُحوَّل بما يتجاوز قبول بناء الجملة ومجموعة الاختبارات.
  • يزيل خفض الإصدار عدم القابلية للتغيير المفروضة في وقت التشغيل (إزالة readonly). والشيفرة التي اعتمدت على وقت التشغيل لرفض الكتابة إلى خاصية للقراءة فقط تفقد ذلك الدفاع في المُخرَج المخفَّض الإصدار. هذه مقايضة موثَّقة ومتعمَّدة مقابل أمان ⁨clone-with⁩ — راجع /⁨integrations/backport/troubleshooting/.⁩

تتبع المشكلات الأمنية في أداة البناء ملف SECURITY.md الخاص بالمستودع: أبلِغ عنها عبر استشارة أمنية في ⁨GitHub⁩ أو عبر جهة الاتصال الأمنية، لا من خلال مشكلة عامة. قدّم مشكلات الشيفرة المُولَّدة في مستودعات المصدر الأصلية، لأن الشجرة المُولَّدة مُنتَجة آليًّا ولا يجري التطوير اعتمادًا عليها. مُتحقَّق منه مقابل SECURITY.md وملف المشروع README.md.

  • /⁨integrations/backport/overview/⁩ — ما هي أداة البناء وماذا تُنتج.
  • /⁨integrations/backport/production-usage/⁩ — كيفية تشغيل مسار الإصدار.