سجل الأعمال¶
2026-07-27 — سجلٌّ للعمل الذي أُقيمت به منصّة الوثائق هذه، وغُيِّر فيه نموذج ملكية إعدادات الحافّة، وسُدَّت نقاط الضعف التشغيلية، وتُرجمت به الوثائق كلّها إلى سبع لغات.
الغاية من هذه الصفحة ليست تدوين ما فُعل، بل لماذا اتُّخذ القرار على هذا النحو. فالتعليل هو المعلومة الأبطأ تقادمًا: قد تتغيّر الشيفرة، ويبقى سندُ القرار.
نطاق التغطية
التفاصيل التشغيلية — عناوين المضيفات والمسارات وقيم الإعداد السرّية — ليست في هذا الموقع العام؛ بل توجد في دليل تشغيل مغلق داخل المستودع المعني.
خمسة مسارات¶
| # | العمل | النتيجة |
|---|---|---|
| 1 | إقامة منصّة الوثائق | بدأ docs.gerege.mn بالعمل |
| 2 | تفكيك ملكية إعدادات الحافّة | انتقل كل نطاق إلى مستودعه الخاص |
| 3 | سدّ نقاط الضعف التشغيلية | أُزيل الحذف العرضي ومناطق العمى الرقابية |
| 4 | ترجمة الوثائق إلى سبع لغات | المنغولية + اللغات الرسمية الست للأمم المتحدة، تغطية كاملة |
| 5 | تسجيل الانتقال إلى Nexus | نموذج المنظومة الجديد موثَّق بسبع لغات |
1. منصّة الوثائق¶
ما أُنجز¶
بوّابة بـ MkDocs Material تجمع في موضع واحد وثائقَ منظومة Gerege على مستوى المنظومة: 25 صفحة، والمنغولية افتراضيًا، ومخطّطات Mermaid، وCSS للعلامة التجارية. ثم وُسِّعت التغطية اللغوية لاحقًا إلى سبع لغات — راجع القسم 4.
جُمع المحتوى من ملفّات README ومجلّدات docs/ ووثائق البنية في مستودعات
المنظومة، ونُظِّم في أربعة أبواب: الطبقات · المنصّات · المعايير · التشغيل.
القرارات الجوهرية¶
تقديم الموقع الساكن من حاوية مستقلّة. فإضافة نقطة ربط جديدة إلى حاوية edge nginx تستلزم إعادة إنشائها، وعندها تسقط جميع النطاقات لبرهة. أمّا التقديم من حاوية صغيرة خاصة فيكفي معه أن تُضاف سطورٌ في إعداد الحافّة ثم تُعاد تحميلها.
النشر في الموضع نفسه بـ rsync. فمجلّد الموقع مربوط bind mount بالحاوية.
واستبداله بأكمله (mv) يترك الحاوية ناظرةً إلى الـ inode القديم، فلا يظهر
المحتوى الجديد إطلاقًا. أمّا rsync فيحدّث الملفات في موضعها، فيبقى الربط
صالحًا.
مراسي العناوين الكيريلية. إذ تحذف أداة slugify القياسية في امتداد toc
المحارفَ غير اللاتينية، فيحصل العنوان ## Танилт على id فارغ وتتعطّل الروابط
الداخلية بصمت. فانتقلنا إلى pymdownx.slugs.slugify التي تحافظ على اليونيكود.
تفعيل validation.anchors. ففحص المراسي في MkDocs يأتي معطَّلًا
افتراضيًا. ومن دونه يعبر الرابطُ المكسور المشيرُ إلى #قسم مرحلةَ البناء ويصل
إلى الإنتاج. أمّا الآن فيُسقط --strict.
كل ما يدخل docs/ يصير علنيًا. ولذلك وُضعت التفاصيل التشغيلية على حدة، في
مجلّد لا يدخل الموقع.
2. ملكية إعدادات الحافّة¶
هذا أكبر تغيير معماري.
الحال سابقًا¶
كانت مضيفات النطاقات الافتراضية كلّها في ملف مركزي واحد. والنتيجة: أنّ تغيير
إعدادٍ صغير لـ docs.gerege.mn يقتضي إرسال طلب دمج إلى مستودع آخر وانتظار نشر
فريق آخر. فالملكية غائمة والتغيير بطيء.
الحال الآن¶
the edge nginx configuration directory
├── (shared files) ← owned by the combined stack's repository
│ sso · dan · gsign · xyp
├── docs.gerege.mn.conf ← docs-gerege-mn
├── developer.gerege.mn.conf ← developer-gerege-mn
└── template.gerege.mn.conf ← template-gerege-mn
صار مضيفُ كل نطاق يعيش في مستودع خدمته، ويتولّى نشرُها هو تثبيتَه. فينتهي التغيير داخل مستودع واحد.
لماذا ينجح هذا¶
مجلّد الإعداد موجود فيزيائيًا داخل نسخة عمل مستودعٍ آخر، ونشرُ ذلك المستودع
ينفّذ git reset --hard. غير أنّ git reset --hard لا يستعيد إلّا الملفات
المتعقَّبة — ولا يمسّ غير المتعقَّبة. ولذلك يبقى الملف المُثبَّت من مستودع خارجي
حيًّا.
ثلاثة شروط للاستقلال التام¶
يجب ألّا يعتمد المضيف الافتراضي على الملفات المشتركة في أي شيء:
| الشرط | السبب |
|---|---|
limit_req_zone خاصة به |
فالرجوع إلى ملف نطاقات مشترك يُنشئ اعتمادًا عليه |
كتلة listen 80 خاصة به (ACME + إعادة توجيه) |
فيعمل تجديد الشهادة استقلالًا |
| إعادة التثبيت مع كل نشرة | فإن فُقد الملف استعاد نفسه |
ترتيب هجرةٍ بلا انقطاع¶
- أولًا يُثبَّت الملف الجديد. وحينها يكون النطاق الواحد معرَّفًا في موضعين،
لكنّ nginx لا يتعامل مع ذلك إلّا كـتحذير
conflicting server name— فلا يتغيّر السلوك، وكلاهما يشير إلى الوجهة نفسها. - ثمّ يُحذف من الملف المركزي. فيزول التكرار ويصير الملف الجديد نافذًا.
ولو عُكس الترتيب سقط النطاق بين الخطوتين.
لا مسارات مضيفات في مستودع مفتوح المصدر¶
template-gerege-mn مفتوح المصدر، والاصطلاح القائم أن تُحفَظ معلومات الخادم في
أسرار التكامل المستمر وحدها. ولذلك يستخرج المُثبِّت مسارَ مجلّد الإعداد بنفسه
من نقاط ربط حاوية الحافّة:
docker inspect <edge> --format \
'{{range .Mounts}}{{if eq .Destination "/etc/nginx/conf.d"}}{{.Source}}{{end}}{{end}}'
وهذا أوثق من كتابة المسار كتابةً صريحة، ولذلك اعتُمد لاحقًا في المستودعات الثلاثة جميعًا — فهو يواصل العمل عند تغيّر المضيف أو المسار.
شرط أمني مسبق¶
الشهادة أولًا ثم المضيف الافتراضي. فإضافةُ مضيف HTTPS من دون شهادة تُسقط
nginx -t، وعندها تصير جميع النطاقات في خطر. وتحدّي ACME يعمل عبر الخادم
الافتراضي العام على المنفذ 80، فلا يقتضي الحصولُ على الشهادة أي تعديل في
الإعداد.
وقبل الدفع، فُحص الإعدادُ النهائي بـ nginx -t في حاوية مؤقّتة، بشبكة حقيقية
وشهادات حقيقية.
3. التحصين التشغيلي¶
الحماية من الحذف العرضي¶
كانت هناك ملفات يقوم عليها الإنتاج وليست متعقَّبة في أي مستودع. وgit reset
--hard لا يمسّها، لكن git clean -fd يحذفها.
| الملف | إن فُقد | الحل |
|---|---|---|
| مضيفات النطاقات الثلاثة | تسقط 3 نطاقات في وقت واحد | .gitignore |
| ملف compose override على المضيف | تنفصل الحاوية عن شبكة الحافّة ← 502 | .gitignore + ملف مثال |
ولماذا يحلّ .gitignore المشكلة: لأنّ git clean من دون -x يتجاوز
الملفات المتجاهَلة. فيحميها من دون حاجة إلى تعقّبها.
ولا يجوز تعقّب ملف compose override: فـ compose يقرؤه تلقائيًا، ومن ثمّ
تُفرَض إعداداتُ الإنتاج على البيئة المحلّية لكل مطوّر. ولذلك يبقى الملف الحيّ غير
متعقَّب على المضيف، ولا يُحفَظ في المستودع إلّا مثالٌ للاستعادة. وقد تأكّد أنّ
المثال يُنتج ما يُنتجه الإعداد الحيّ بمقارنة خَرج docker compose config.
مراقبة السلامة¶
كان على المضيف نصٌّ للمراقبة من قبل، لكن تراكب عيبان: لم يكن مسجَّلًا في cron أصلًا، وبعض الحاويات المذكورة فيه غُيِّرت أسماؤها فلم تعد موجودة. والنصّ يتجاوز الحاوية المفقودة بصمت، فلم يعلم أحدٌ أنّ المراقبة توقّفت تمامًا.
القرارات الجوهرية في النسخة الجديدة:
تقديم فحص السلامة الخاص بالحاوية. فمدد الفحص وعدد المحاولات فيه مضبوطة سلفًا على تلك الخدمة بعينها.
إجراء فحص HTTP من داخل الحاوية. فلو فُحص كل شيء عبر الحافّة، لظهرت جميع الخدمات ساقطة كلّما سقطت الحافّة، فتُعاد تشغيلها جملةً ويُحجَب الخللُ الحقيقي. أمّا الآن فكل فحص قائم بذاته.
حدُّ فشلٍ متتالٍ مع فترة تهدئة. فالتعطّل العابر (نشر، أو جمع مهملات، أو حِمل) لا يُحدث إعادة تشغيل؛ والخدمة المعطوبة فعلًا لا تُطفأ وتُشغَّل مرارًا.
عدم إعادة تشغيل البنية ذات الحالة تلقائيًا. فقواعد البيانات والتخزين المؤقّت تُراقَب وتُسجَّل فحسب. وإعادة التشغيل لا تُصلح سببًا حقيقيًا كامتلاء القرص، بل تقطع معاملات حزمٍ متعدّدة وتزيد الضرر لا أكثر. وفي مثل ذلك يقرّر الإنسان.
تسجيل الحاوية المفقودة خطأً — كي لا يتكرّر العيب الأبرز في النسخة القديمة.
الحدّ · التهدئة · سياسة ذوات الحالة · الاستعادة · الحاوية المفقودة: خمسة سلوكيات فُحصت فحصًا فعليًا على حاوية اختبار معزولة.
تجديد الشهادات¶
لا يكفي أن ترى قيدًا في cron — بل جُرِّب بـ --dry-run هل يعمل التجديد فعلًا،
وتأكّد أنّ كل النطاقات تُجدَّد بنجاح. وهذا من نوع المخاطر التي تصمت حتى انقضاء
الأجل.
4. التغطية بسبع لغات¶
ما أُنجز¶
تُرجمت جميع صفحات الموقع إلى المنغولية إضافةً إلى اللغات الرسمية الست للأمم المتحدة: العربية · 中文 · English · Français · Русский · Español. وكانت الترجمة الإنجليزية جزئية من قبل (الصفحة الرئيسة، والمقدّمة، والطبقات، وقائمة المنصّات، والمصادقة)، فأُكملت وأُضيفت إليها خمس لغات.
القرارات الجوهرية¶
المنغولية تبقى المصدر. والست الأخرى ترجمات — إذ يُكتب الأصل بالمنغولية ويُحوَّل منها. فمتى وُجدت لغتا «مصدر» بدأ المحتوى يتباعد بصمت.
نترجم صفحةً صفحة لا لغةً لغة. فتحويل الوثيقة الواحدة إلى ست لغات في آنٍ واحد يُبقي المصطلحات وصفوف الجداول والبنية متطابقة. وعلى العكس — «الإنجليزية أولًا لكل الصفحات» — تظلّ اللغات المترجَمة لاحقًا تلاحق نصًّا أصليًا تغيّر بالفعل.
لم يُترجَم الترميز التقني. فالنطاقات وأسماء المستودعات والشيفرة وYAML ومسارات نقاط النهاية وأسماء المعايير (OIDC · PKCE · RFC 3161) تبقى كما هي في كل اللغات. فلو تُرجمت لتعذّر نسخها وتشغيلها.
أسماء الملفات لا تُترجَم. فهي platforms/sso.ru.md لا платформы/sso.md.
وبذلك يبقى مسار الرابط ثابتًا عند تغيير اللغة، وتظلّ الروابط العميقة الواردة من
مستودعات أخرى عاملة.
اتّجاه العربية من اليمين لم يُصنع يدويًا. فـ Material يتعرّف على لغة ar
ويضع <html dir="rtl"> ويقلب القائمةَ وتدفّقَ المحتوى بنفسه. أمّا كتل الشيفرة
والمخطّطات النصّية فتبقى من اليسار إلى اليمين — وهو الصواب، لأنّ الأوامر والروابط
يفسد معناها إن عُكس اتّجاهها.
أداة slugify اليونيكودية صارت الآن أهمّ ثلاث مرّات. فـ
pymdownx.slugs.slugify التي أُدخلت من أجل العناوين الكيريلية تحمل اليوم مراسي
العناوين العربية والصينية والروسية كذلك. ولو كانت الأداة القياسية لانكسرت بصمت
جميع الروابط الداخلية في اللغات الست.
fallback_to_default يبقى مُفعَّلًا. فكل الصفحات مترجَمة الآن، ومن ثمّ لا يعمل
الارتداد؛ لكنّه يبقى ضمانًا لبقاء الموقع كاملًا متى أُضيفت صفحة وتأخّرت ترجمتها.
نطاق التطبيق¶
تسري هذه السياسة على الوثائق على مستوى المنظومة، أي على هذا الموقع وحده. أمّا الوثائق التقنية المعمّقة لمنصّة بعينها (مخطّطات نقاط النهاية ومرجع حِزَم SDK) فتبقى بالمنغولية والإنجليزية داخل مستودعها؛ فقارئها مهندسٌ يعمل في ذلك المستودع أصلًا، ولذلك يقلّ عائدُ توسيع التغطية.
5. تسجيل الانتقال إلى Nexus (2026-08-07)¶
ما الذي جرى¶
أُنشئ مستودع open-gerege-nexus في 2026-08-05، وفي 08-07 أُعيدت تسمية المنصّة إلى
Gerege Nexus ونُقلت إلى nexus.gerege.mn. ثم تلاه فرعان: sso-gerege-nexus
(Gerege SSO) وeduge-mn-nexus (eduge.mn). ولمّا كان هذا يغيّر نموذج التوزيع
في المنظومة، جرى تحديث الوثائق ومساواتها في اللغات السبع جميعًا.
القرارات الأساسية¶
لم تُحذف أي صفحة منصّة قائمة. فـ Template وGerege Platform وSSO وKiosk جميعها ما تزال في الإنتاج. أُضيفت صفحة جديدة، ووُضع على الصفحات القائمة تنبيهٌ يبيّن أيّ حالة هي النافذة. وحذف الصفحة كان سيمحو وثائق نظام يعمل فعلًا.
قُسّمت الطبقة 3 إلى جيلين. فـ Nexus لا تحلّ محلّ القالب — بل يقيم كلاهما في الطبقة 3 في آنٍ واحد. وإضافة طبقة جديدة كانت ستُفرغ قاعدة الطبقات نفسها من معناها («لا تجاوز طبقةً إلى ما وراءها»).
مزوّد OIDC الخاص بـ Nexus ليس الطبقة 2. تحمل Nexus مزوّد OAuth2/OIDC، غير أنّه يخدم مستأجري تلك النشرة وعملاءها من الأطراف الثالثة. أمّا طريق المنظومة إلى تعريف المواطن فيبقى Gerege SSO. ولولا التصريح بذلك لخلص القارئ إلى أنّ «Nexus حلّت محلّ الدخول الموحّد».
فُحص كل نطاق يدويًا. تأكّد عمل nexus.gerege.mn وeduge.mn وgeregekiosk.mn
عبر DNS وHTTP وشهادات TLS. وقد كشف ذلك أمرين: أنّ geregekiosk.mn صار يقدّم
Nexus، وأنّ open.gerege.mn أُسقط من شهادة ذلك المضيف، فيفشل HTTPS بعدم
تطابق الاسم.
صُحّح وعدٌ فات أوانه. كانت صفحة القالب تزعم أنّ autosync ينقل التغييرات إلى المصبّ يوميًا؛ وقد أُوقفت تلك الأتمتة على مستوى الأسطول كلّه في 2026-08-06. والوعد الكاذب أسوأ من المعلومة الغائبة: إذ ينتظر المهندس أن يسافر الإصلاح من تلقاء نفسه.
سُدّت ثغرتان في الترجمة. تبيّن أنّ قسم «نطاقات العلامات المستقلّة» في خريطة النطاقات غائبٌ كليًّا عن الترجمات الستّ؛ وقد صارت السبع متساوية الآن.
خلاصة القرارات¶
| القرار | السند |
|---|---|
| الموقع الساكن في حاوية مستقلّة | إعادة إنشاء الحافّة تُسقط جميع النطاقات |
rsync لا mv |
ربط bind يبقى على الـ inode القديم |
| slugify يونيكودية | الأداة القياسية تُتلف مراسي العناوين الكيريلية |
تفعيل validation.anchors |
وإلّا وصلت الروابط المكسورة إلى الإنتاج |
| المضيف الافتراضي في مستودع الخدمة | ينتهي التغيير داخل مستودع واحد |
| مضيف افتراضي قائم بذاته تمامًا | الاعتماد على ملف مشترك يُفرغ الفصل من معناه |
| التثبيت قبل، والحذف بعد | والعكس يُسقط النطاق |
| استخراج المسار تلقائيًا | أوثق من كتابته صريحًا؛ ولا يترك مسارًا في مستودع مفتوح |
الحماية بـ .gitignore |
git clean يتجاوز الملفات المتجاهَلة |
| عدم تعقّب ملف override | compose يقرؤه تلقائيًا — فتُفرَض إعدادات الإنتاج محليًا |
| الفحص من داخل الحاوية | يمنع إعادة التشغيل الجماعية عند سقوط الحافّة |
| عدم إعادة تشغيل ذوات الحالة | إعادة التشغيل لا تُصلح السبب بل تزيد الضرر |
| المنغولية لغة المصدر الوحيدة | مع «مصدرين» يتباعد المحتوى بصمت |
| الترجمة بالصفحة لا باللغة | تبقى المصطلحات والبنية متطابقة في ست لغات |
| عدم ترجمة الشيفرة والنطاقات وأسماء المستودعات | إن تُرجمت تعذّر نسخها وتشغيلها |
| عدم ترجمة أسماء الملفات | يبقى مسار الرابط ثابتًا وتعمل الروابط العميقة |
كل لغة على مسار فرعي (/ar/) |
مع النطاقات الفرعية يتضخّم SAN · vhost · hreflang معًا |
ما لم يُفعل بقصد¶
لم تُفصَل نطاقات sso · dan · gsign · xyp. فشيفرتها داخل مستودع الحزمة
الموحّدة، ومن ثمّ فالملف المركزي هو مستودعها هي أصلًا. ولا داعي للفصل.
لم تُضَف نقطة ربط مستقلّة إلى حاوية الحافّة. فذلك يقتضي تعديل ملف compose للحزمة الموحّدة، ويستلزم فوق ذلك إعادة إنشاء الحاوية فتسقط جميع النطاقات لبرهة.
لم يُفرَض فهرس بحث للمنغولية. فـ lunr.js لا يدعم المنغولية، ومن ثمّ يعمل
البحث في اللغة الافتراضية بالتقطيع القياسي. وكتابة مُجذِّر (stemmer) خاص أكلفُ من
عائده الحالي.
لم يُخصَّص نطاق ولا نطاق فرعي لكل لغة. فمسارات مثل /ar/ و/zh/ تُحلّ
بشهادةٍ واحدة ومضيفٍ افتراضي واحد ونشرةٍ واحدة. أمّا الانتقال إلى نطاقات فرعية
فكان سيُضخّم حقولَ SAN في الشهادة وإعدادَ الحافّة وhreflang في وقت واحد.
الخطر المتبقّي¶
مضيفات النطاقات الثلاثة وملفّات override على المضيف محميّة بـ .gitignore، لكن
إن شغّل أحدهم git clean -fdx (وهو يشمل الملفات المتجاهَلة) حُذفت. والعلاج
إعادة تشغيل نصّ التثبيت في المستودع المعني — وقد دُوِّن ذلك في دليل تشغيل كلٍّ من
المستودعات الثلاثة.