تخطَّ إلى المحتوى
kazma.
EN نجمة 6 ابدأ الآن

سلسلة التوريد — التحقق من إصدار كاظمه

سلسلة التوريد — التحقق من إصدار كاظمه

Section titled “سلسلة التوريد — التحقق من إصدار كاظمه”

كاظمه ذاتية الاستضافة. تشغّلها على جهازك أنت، غالبًا مقابل خزنتك الخاصة، ومسموح لها لمس ملفاتك وصدفتك ومستودعك. والإصدار الذي لا تستطيع التحقق منه إصدار تأخذه على الثقة، و«ثق بي» هو الشيء الوحيد الذي ليس هذا المشروع مستعدًا لطلبه.

لذلك كل قطعة إصدار موقَّعة، وتحمل إثبات منشأ البناء (build provenance)، وتُشحن معها SBOM. هذه الصفحة هي كيف تتحقق من الثلاثة. ولا شيء من ذلك يتطلب حسابًا ولا مورّدًا ولا خدمة مدفوعة.


الملفما هو
kazma-<version>-py3-none-any.whlحزمة wheel
kazma-<version>.tar.gzالتوزيعة المصدرية
kazma-<version>.cdx.jsonSBOM بصيغة CycloneDX 1.6 لمجموعة التبعيات المثبّتة
SHA256SUMSبصمات تحقق (checksums) للملفات الثلاثة أعلاه
*.sigstore.jsonحزمة Sigstore لكل قطعة — التوقيع

شهادات إثبات المنشأ ليست ملفات في الإصدار؛ GitHub يخزنها ويجلبها لك gh attestation verify.


تُوزَّع كاظمه عبر إصدارات Mubder/kazma على GitHub وعبر المستودع نفسه، ولا شيء غيرهما. وعلى PyPI يحجز المشروع kazma وkazma-core والأسماء التي حولها بحزم محجوزة: الإصدار 0.0.1 من كل منها، بلا شيفرة، وفيها صفحة فقط تحيل القارئ إلى إصدارات GitHub. فتثبيت إحداها لا يثبّت شيئًا، ولا يستطيع أحد غير المشروع أن ينشر تحت الاسم. لا تثبّت أبدًا kazma (أو kazma[...]) بالاسم من PyPI لتحصل على كاظمه. ثبّت الإضافة من مجلد كاظمه لديك (pip install -e ".[web]"، أو الإعدادات ← الحزم) وحدّث باستخدام kazma update.

في التثبيت المأخوذ من حزمة wheel لإصدار، يقرأ kazma update أحدث إصدار من واجهة GitHub البرمجية، وينزّل حزمة wheel الخاصة به من ذلك الإصدار، ولا يثبّتها إلا إذا طابقت بصمةُ SHA-256 للملف ملفَّ SHA256SUMS في الإصدار، وبصمةَ GitHub نفسه للملف حين يذكرها؛ وإلا توقف وذكر صفحة الإصدار. ولا يتحقق هو نفسه من توقيع Sigstore: شغّل gh attestation verify (أدناه) حين تريد هذا الإثبات. ويقرأ فحص التحديثات في الإعدادات الإصدار نفسه. حتى 2026-09-30 كان كلاهما يسأل PyPI، ثم كان kazma update يطلب من pip ترقية kazma بالاسم.

الأسماء هي kazma وkazma-cli وkazma-core وkazma-gateway وkazma-memory (المتقاعد) وkazma-skills وkazma-tui وkazma-ui (يبني الحزم المحجوزة scripts/pypi_reserve.py). ونُشرت الثمانية كلها في 2026-10-01: الإصدار 0.0.1 من كلٍّ منها، بحزمة wheel وأرشيف مصدر. ورفعها سير العمل .github/workflows/pypi-reserve.yml عبر النشر الموثوق (Trusted Publishing) في PyPI، فلا يوجد أي توكن لـPyPI في أي مكان. ولا يعمل إلا يدويًا (Actions ← Reserve PyPI names)، ودون خانة «publish» يكتفي ببناء الحزم وفحصها.

ولا يقبل PyPI أول رفع لاسم إلا من ناشر مسجَّل له، ثم يبقى الناشر مع المشروع. ولحجز اسم آخر، أضفه إلى قائمة السكربت (يُبقي الفحص في tests/test_no_pypi_kazma.py تلك القائمة مطابقة لأسماء حزم كاظمه)، ثم سجّله في pypi.org، من Account ← Publishing ← Add a new pending publisher ← GitHub، بما يلي:

الحقلالقيمة
PyPI Project Nameالاسم (kazma، ثم kazma-cli، …)
OwnerMubder
Repository namekazma
Workflow namepypi-reserve.yml
Environment namepypi- والاسم (pypi-kazma، ثم pypi-kazma-cli، …)

ولكل اسم بيئته الخاصة لأن PyPI لا يُبقي الإعداد الواحد منتظرًا إلا لمشروع جديد واحد في الوقت نفسه. فإن تشاركت الأسماء البيئة نفسها قبل الأول ورفض الباقي: “A pending trusted publisher matching this configuration has already been registered for a different project name”.

ثم شغّل سير العمل مع تحديد «publish» وكتابة الاسم الجديد في خانة «names». يُرفع كل اسم في مهمة خاصة به، تحت بيئته الخاصة، فإن غاب ناشر اسمٍ ما أو لم يطابق فشل وحده (“invalid-publisher”)، ويمكن إعادة التشغيل لذلك الاسم وحده. ولا يحتفظ الحساب بأكثر من ثلاثة ناشرين منتظرين في وقت واحد، ولهذا رُفعت الأسماء الثمانية الأولى على أربع دفعات.


1. إثبات المنشأ — هل بُني هذا من هذا المستودع؟

Section titled “1. إثبات المنشأ — هل بُني هذا من هذا المستودع؟”

هذا هو الفحص الأهم، وهو أمر واحد:

Terminal window
gh attestation verify kazma-0.11.0-py3-none-any.whl --repo Mubder/kazma

والنجاح يعني أن سجلّ شفافية GitHub يقرّ بأن الملف أنتجه سير عمل Release في Mubder/kazma، من إيداع محدد، في تشغيلة يمكنك الذهاب إليها وقراءتها. والملف الذي أعاد أحدهم بناءه أو رقّعه أو أدخله يفشل هنا — فلا يمكن إعادة الشهادة له دون صلاحية كتابة على هذا المستودع.


2. التوقيع — Sigstore بلا مفاتيح

Section titled “2. التوقيع — Sigstore بلا مفاتيح”

التوقيع بلا مفاتيح (keyless): لا مفتاح خاص يحتفظ به المشرف، فلا مفتاح يتسرب أو يُدار أو يُفقد. والهوية المشهَد لها هي سير عمل GitHub Actions نفسه، والشهادة مدوَّنة في سجلّ شفافية Sigstore العام.

Terminal window
pip install sigstore
python -m sigstore verify github \
--repository Mubder/kazma \
--bundle kazma-0.11.0-py3-none-any.whl.sigstore.json \
kazma-0.11.0-py3-none-any.whl

والصيغة الصريحة، إن أردت تثبيت الهوية الدقيقة بدل ترك الأمر الفرعي github يبنيها:

Terminal window
python -m sigstore verify identity \
--cert-identity "https://github.com/Mubder/kazma/.github/workflows/release.yml@refs/tags/v0.11.0" \
--cert-oidc-issuer "https://token.actions.githubusercontent.com" \
--bundle kazma-0.11.0-py3-none-any.whl.sigstore.json \
kazma-0.11.0-py3-none-any.whl

اللاحقة @refs/... هي مرجع git الذي بُني منه الإصدار. راجع التشغيلة إن لم تكن متأكدًا أيها ينطبق.


Terminal window
sha256sum -c SHA256SUMS

أضعف الثلاثة وهي وحدها — إذ يمكن استبدال ملف البصمات مع القطع. ويستحق التشغيل لأن SHA256SUMS موقَّع أيضًا، فالتحقق من حزمة Sigstore الخاصة به أولًا يجعل البصمات ذات معنى.


‏kazma-<version>.cdx.json بصيغة CycloneDX 1.6، مولَّد من uv.lock لا من بيئة آلة البناء. وهذا التمييز مهم: فهو يصف المجموعة المثبّتة الدقيقة التي يثبّتها لك uv sync، لا ما صادف أن حلّه مشغّل CI في ذلك اليوم.

أطعمه لما تستخدمه مؤسستك أصلًا. ولنظرة سريعة:

Terminal window
# Component count and licences
python - <<'PY'
import json
d = json.load(open("kazma-0.11.0.cdx.json", encoding="utf-8"))
comps = d.get("components") or []
print(f"{len(comps)} components, CycloneDX {d['specVersion']}")
PY
# Known vulnerabilities, via any CycloneDX-aware scanner
grype sbom:kazma-0.11.0.cdx.json
trivy sbom kazma-0.11.0.cdx.json

إعادة بناء الأصول المضمَّنة

Section titled “إعادة بناء الأصول المضمَّنة”

أصلان من طرف ثالث مُدرجان في المستودع بدل جلبهما، لأن الواجهة يجب أن تُصيَّر على جهاز لا طريق له إلى الإنترنت:

  • CodeMirror 5 ‏(MIT) — kazma-ui/kazma_ui/static/vendor/codemirror/. أعِد البناء بـ python scripts/vendor_codemirror.py؛ والنسخة المثبّتة تعيش في ذلك السكربت وفي ملف VERSION بجوار الحزمة.
  • IBM Plex Sans Arabic ‏(OFL) — kazma-ui/kazma_ui/static/fonts/.

يفشل tests/test_editor_assets_offline.py البناء إن بدأ أي قالب بتحميل سكربت أو أوراق أنماط بعيدة مجددًا.


يستحق القول بصراحة، لأن صفحة سلسلة توريد تبالغ في الوعود أسوأ من عدم وجودها أصلًا.

  • ليست بناءات قابلة لإعادة الإنتاج. إثبات المنشأ يثبت من بنى القطعة ومن أي إيداع. وهو لا يمكّنك من إعادة بنائها باستقلال والحصول على نتيجة متطابقة بايتًا-ببايت. ذلك عمل أكبر ولا يُدَّعى.
  • إثبات المنشأ ليس مراجعة كود. يثبت أن القطعة جاءت من هذا المستودع. ولا يقول شيئًا عن إن كان الكود في ذلك المستودع جيدًا أو آمنًا أو خاليًا من العلل. اقرأه؛ فلهذا هو مفتوح.
  • الـ SBOM يسرد التبعيات، لا الثغرات. هو مدخل لماسح، لا شهادة سلامة.
  • سجلّ Sigstore عام. التحقق لا يسرّب شيئًا، لكن كون إصدارًا موجودًا معلومة عامة بالتصميم.