خطة مقترحة لتحويل المشروع إلى منتج يتنصّب على أي استضافة (زي ووردبريس) — مع تحديثات تلقائية تحافظ على بيانات العميل وتاخد الكود والـ migrations الجديدة.
حالة المستند: مسودة للمراجعة — مفيش تنفيذ لسه · الهدف: نتفق على القرارات قبل ما نبدأ أي حاجة.
الفكرة في سطر: نفصل الكود (اللي بيتغيّر مع كل تحديث) عن الداتا (اللي بتفضل للعميل للأبد).
التحديث بيستبدل الكود + يشغّل migrations آمنة، ومش بيلمس قاعدة البيانات ولا الملفات ولا الـ APP_KEY أبداً.
1. الهدف والنموذج (The WordPress model)
زي ووردبريس بالظبط:
تنزيل نسخة = حزمة (package) واحدة فيها كل اللي محتاجه المشروع يشتغل.
تركيب على أي هوست = معالج تنصيب (Installer wizard) يسأل عن قاعدة البيانات ويجهّز كل حاجة.
عند إصدار تحديث = النسخة المركّبة عند العميل تعرف إن فيه تحديث، تنزّله، تعمل backup، تركّبه، وتشغّل الـ migrations — والداتا زي ما هي.
كل عميل عنده نسخته الخاصة + قاعدة بياناته الخاصة (مش SaaS مشترك). ده بيدّي العميل تحكّم وخصوصية، وبيخلّينا نبيع المنتج «منتَج» مش «خدمة».
2. المبدأ الأساسي: فصل الكود عن الداتا
🔁 كود (يُستبدَل في كل تحديث)
Modules/, app/, config/, routes/
database/migrations/ (تعريف التغييرات)
vendor/ (الحزم — متجمّعة جاهزة)
artisan, composer.json/lock
الواجهة Angular مبنية جاهزة (app/*.js/.css)
🔒 داتا (تُحفَظ للأبد — ممنوع المساس)
قاعدة البيانات MySQL (migrations فقط)
.env — وبالذات APP_KEY
storage/app/ (مرفقات / ملفات مرفوعة)
public/uploads/ (صور / ملفات)
أي إعدادات أو ضبط خاص بالعميل
⚠️ قاعدة حياة أو موت — APP_KEY: الـ APP_KEY بيتولّد مرة واحدة وقت التنصيب ومايتغيّرش أبداً.
لو اتغيّر، كل الأعمدة المشفّرة في قاعدة البيانات بتبوظ (The MAC is invalid — اللي حصل معانا فعلاً في صفحة الـ AI settings).
المُحدِّث ممنوع منعاً باتاً يلمس .env.
3. الواقع اللي بيحكم كل القرارات: استضافة cPanel
دي مش تفصيلة — دي اللي بتحدّد التصميم كله. على cPanel/الاستضافة المشتركة:
القيد
النتيجة على التصميم
مفيش root ولا Docker ولا SSH مضمون
المُحدِّث لازم يشتغل من المتصفّح بـ PHP (زي شاشة Updates في ووردبريس)، مش بأوامر طرفية.
composer install غالباً مش متاح/بطيء
نشحن vendor/جاهز داخل الحزمة (vendored). على الهوست بنعمل dump-autoload بس (من غير إنترنت).
أحياناً exec() / mysqldump مقفولين
نعمل backup للداتا بـ PHP خالص (fallback) بدل ما نعتمد على أوامر النظام.
ملفات بملكية root بتعمل 500
كل عمليات الملفات والـ artisan تشتغل بمستخدم الويب (اللي بيشغّل PHP-FPM).
الواجهة Angular محتاجة build (Node)
نشحن النسخة المبنية جاهزة في الحزمة — العميل مش هيعمل ng build أبداً.
mod_proxy مش متاح في .htaccess
كل حاجة PHP-native (ZipArchive للفك، cURL للتنزيل).
الخلاصة: مُحدِّث ويب بـ PHP + حزمة self-contained (vendor مدمج + FE مبني) هو الطريق الوحيد العملي هنا.
4. المكوّنات اللي هنبنيها
① خط بناء الحزمة عندنا
سكربت بناء يطلّع حزمة مُوقّعة بإصدار محدّد: BE + vendor + FE مبني + manifest. بيستبعد .env وبيانات storage.
② سيرفر التحديث والترخيص عندنا
سيرفر مركزي: يستضيف الحِزَم + manifest بالإصدارات + يتحقّق من الترخيص + سجل النسخ المركّبة (phone-home).
③ المُنصِّب (Installer) داخل الحزمة
معالج أول تشغيل: فحص البيئة ← إعداد قاعدة البيانات ← توليد .env+APP_KEY ← migrate+seed ← إنشاء أول أدمن/شركة.
④ المُحدِّث داخل التطبيق داخل الحزمة
شاشة «التحديثات» + محرّك: يفحص ← ينزّل ← يتحقّق ← backup ← يركّب ← migrate ← reseed ← يمسح الكاش ← يبدّل الـ FE ← rollback لو فشل.
5. مسار التحديث خطوة بخطوة (قلب النظام)
فحص (Check): النسخة تكلّم السيرفر بـ {license_key, current_version, php_version} ← يرجّع آخر إصدار + سجل التغييرات + المتطلبات + رابط التنزيل + sha256 + التوقيع (حسب صلاحية الترخيص).
فحص مسبق (Pre-flight): توافق نسخة PHP والإضافات + مساحة قرص كافية + صلاحيات كتابة. لو حاجة ناقصة → نوقف قبل ما نبدأ.
وضع الصيانة (Maintenance):artisan down — صفحة «جاري التحديث» للمستخدمين.
نسخة احتياطية (Backup): dump لقاعدة البيانات + ضغط الكود الحالي + storage. تتخزّن في storage/updates/backups/<version>/. دي شبكة الأمان.
تنزيل + تحقّق: ننزّل الحزمة، نتأكد من sha256 + التوقيع (ضد التلاعب وللتأكد إنها مننا).
تجهيز + تركيب (Stage & Apply): نفك في مجلد staging، نبدّل ملفات الكود — مع الحفاظ على .env وstorage/ وpublic/uploads/. الـ vendor/ بييجي جاهز من الحزمة.
إعادة بناء:dump-autoload -o (من غير إنترنت) + optimize:clear + كاش config/route.
تبديل الواجهة (FE): نمسح ملفات app/ القديمة الأول (gotcha معروفة عندنا) وننسخ الـ dist الجديد.
رجوع للخدمة:artisan up + فحص صحة (health endpoint).
تقرير: نبلّغ السيرفر «اتحدّثنا لـ vX». عند أي فشل في أي خطوة → Rollback (نرجّع الداتا + الكود من الـ backup ونرجّع للخدمة).
6. القواعد المؤسِّسة (اللي لازم نلتزم بيها للأبد)
1
ثبات الـ APP_KEY. يُولَّد مرة واحدة وقت التنصيب، ومايتغيّرش. كل التشفير معتمد عليه. التحديث ممنوع يلمس .env.
2
فصل الكود عن الداتا عبر «بيان مسارات» (manifest). ملف يحدّد المسارات اللي «داتا» وممنوع تتكتب فوقها: .env, storage/app/**, public/uploads/**.
3
انضباط الـ Migrations. كل migration إضافي وآمن للداتا. الحذف (drop column/table) يتم على إصدارين فقط (إضافة الجديد ← ترحيل الداتا ← في إصدار لاحق نحذف القديم). ممنوع تعديل migration اتشحن قبل كده — دايماً نضيف جديد. والقفزات بين عدة إصدارات لازم تشتغل (Laravel بيشغّل كل المعلّق بالترتيب).
4
Seeders idempotent. البيانات المرجعية (صلاحيات، تعريفات إعدادات، أنواع القيود) تُزرَع بـ firstOrCreate في كل تحديث — من غير truncate أبداً. (عندنا النمط ده فعلاً في RolePermissionSeeder.)
5
حزم مُجمّعة (vendored). نشحن vendor/ جاهز — مفيش composer install على الهوست. الإصدارات مثبّتة، والبناء يحصل عندنا بس.
6
Backup قبل أي تحديث — إجباري وأوتوماتيك، مع زر استرجاع بضغطة.
بوّابة توافق. كل إصدار يعلن حد أدنى لـ PHP/الإضافات/الإصدار السابق. لو مش متحقّق → نرفض التركيب.
9
التنفيذ بمستخدم الويب. كل عمليات الملفات والـ artisan بمستخدم PHP (تفادياً لـ 500 من كاش بملكية root).
10
ذرّي وقابل للرجوع (Atomic & reversible). stage ثم swap؛ rollback عند أي فشل. ملاحظة MySQL: الـ DDL مش transactional — عشان كده الـ backup-أولاً هو الضمان الحقيقي.
11
لا افتراض لوجود طرفية (shell). المُحدِّث الويب هو الأساسي؛ الـ CLI اختياري للهوستات اللي فيها SSH.
12
تتبّع الإصدار في قاعدة البيانات. نسجّل app_version + schema_version؛ المُحدِّث يفرض ترتيباً صحيحاً بلا تخطّي.
vendor مدمج + ZipArchive بـ PHP + backup قاعدة بيانات PHP خالص.
تحديث اتقطع في النص
وضع صيانة + backup + rollback أوتوماتيك.
ضياع/تغيّر APP_KEY
المُنصِّب يخزّنه، المُحدِّث مايلمسوش، وتنبيه واضح «اعمل backup لـ .env».
فشل migration في النص (DDL مش transactional)
backup-أولاً إجباري + migrations قابلة لإعادة التشغيل ومحميّة (guarded).
مساحة قرص للـ backup
فحص مساحة مسبق قبل البدء.
صلاحيات الملفات
التشغيل بمستخدم الويب + فحص كتابة مسبق.
العميل عدّل في الـ core
سياسة «ممنوع تعديل core» + التخصيص عبر إعدادات/موديولات.
10. خطة البناء على مراحل
Phase 0
الأساسات: توثيق القواعد (manifest الداتا، انضباط الـ migrations، ثبات APP_KEY، مراجعة الـ seeders idempotent) + إضافة تتبّع app_version/schema_version. مخاطرة قليلة
Phase 1
خط بناء الحزمة: سكربت يطلّع حزمة موقّعة بإصدار (BE+vendor+FE dist+manifest).
Phase 2
المُنصِّب: معالج ويب (فحص بيئة ← قاعدة بيانات ← .env/APP_KEY ← migrate+seed ← أدمن/شركة).
Phase 3
سيرفر التحديث: API الـ manifest + استضافة الحِزَم الموقّعة + ترخيص/استحقاق + سجل النسخ.
Phase 4
المُحدِّث داخل التطبيق: محرّك فحص/تنزيل/تحقّق/backup/تركيب/migrate/rollback + شاشة «التحديثات».
Phase 5
تقوية الـ Backup/Restore + الـ Rollback.
Phase 6
واجهة الترخيص/التفعيل + فرض الاستحقاق.
Phase 7
تجربة Pilot: تنصيب ← تحديث ← rollback كامل على حساب cPanel نظيف (dry-run حقيقي).
نقطة قوة عندنا بالفعل: النمط الأساسي موجود — Laravel migrations مرتّبة، seeders idempotent (RolePermissionSeeder)،
واجهة مبنية static، وvendor/ موجود. يعني Phase 0–1 أغلبه تنظيم وتوثيق، مش بناء من الصفر.
11. الخطوة الجاية
راجع القسم 8 (القرارات المفتوحة) وقول لي اختياراتك — وبعد ما نتفق عليها، أبدأ بـ Phase 0 (الأساسات والقواعد) لأنه أقل مخاطرة وبيمهّد لكل اللي بعده.
ممكن كمان أعمل إثبات مفهوم (PoC) صغير لمسار تحديث واحد على نسخة تجريبية قبل ما نلتزم بالبناء الكامل.