← عودة إلى المشاريع
دراسة حالة هندسية · أَثل

١٢٤ يوم برمجة، وسجلٌّ يشرح نفسه أدرتُ فروعَ مقهىً سنةً وأربعة أشهر، ثم بنيتُ المنصّة التي كنت أحتاجها. وكلُّ رقمٍ في هذه الصفحة يمكن إعادة قياسه.

أَثل منصّة سحابية متعدّدة المستأجرين لتشغيل المقاهي والمطاعم: نقطة بيعٍ تعمل دون اتصال، ومحطّات تحضير، ومخزون، وولاء، وفوترة زاتكا، وواجهة API مفتوحة. وهذه الصفحة ليست عرضاً للمنتج — بل لطريقة بنائه.

595طلب دمج
509هجرة قاعدة بيانات
1,109قرار معماريّ موثّق
386Kسطر شيفرة

01قبل السطر الأول — لم أزُر المقهى، بل أدرتُه

أكثر ما بُني في أَثل لم يأتِ من مواصفةٍ تقنية، بل من سنةٍ وأربعة أشهر خلف الطاولة نفسها.

مدير فرع · كوكي لاب تشغيل يوميّ لفرع مقهى: جدولة الموظفين، والمخزون، وأهداف المبيعات، وتجربة الزبون.
مدير فروع · كوكي لاب تشغيل عدّة فروع معاً: تنسيق الفرق، وتوحيد الإجراءات، ومتابعة المخزون والأداء عبر المواقع.

انتهى عملي مديرَ فروعٍ في أبريل ٢٠٢٦. وأوّل كوميت في أَثل كان في ٢١ مايو ٢٠٢٦. الشهر الذي بينهما هو شهر التصميم — وما بُني بعده منصّةٌ متعدّدة الفروع كتبها من كان يشغّل عدّة فروع قبل أسابيع.

وفوق ذلك، لم يُكتفَ بالتجربة الشخصية:

الميدان زياراتٌ ميدانية للمقاهي — مراقبة التشغيل الحقيقي وقت الذروة، لا وصفه في اجتماع.
ساعاتٌ من المقابلات ساعاتٌ مع إدارة كوكي لاب، ومع منسوبي مقاهٍ أخرى — كاشيرات ومُلّاك. طرفا الطاولة: من يشغّل النظام يومياً، ومن يدفع ثمنه.
نقاط الألم تُحدَّد وتُسمّى واحدةً واحدة — قبل أن يُقترح لها حلّ.
التصوّر الميزات تُشتقّ من نقاط الألم، لا من قائمة ميزات المنافسين.

الفرق يظهر في الشيفرة نفسها. حين اكتُشف لاحقاً أن شاشة الكاشير تُفرَّغ صامتةً بعد إرسال الطلب للمطبخ، لم يكن العطب تقنيّاً — الطلب أُرسل بنجاح والقاعدة سليمة. العطب أن الصمت كان يُقرأ «تمّت المحاسبة» بينما لم يُقبض شيء. حلُّه سطرٌ يقول الحقيقة: «أُرسل الطلب — لم يُحاسَب بعد».

عطبٌ كهذا لا يظهر في اختبار. يظهر لمن وقف خلف الكاشير ورأى كيف يقرأ الشاشة.

02الانعطافة — الانضباط وُلد من الفوضى

المنحنى الشهريّ ليس نمواً مطّرداً. فيه لحظةٌ تبدّل فيها طبع المشروع كلّه.

ميزات إصلاحات
89
7
مايو
12
5
يونيو
215
119
يوليو
47
135
أغسطس
27
19
سبتمبر
في مايو: ٨٩ ميزة مقابل ٧ إصلاحات. في أغسطس انقلبت النسبة: ٤٧ ميزة مقابل ١٣٥ إصلاحاً — لا لأن الجودة تراجعت، بل لأن النظام صار كبيراً بما يكفي ليُمسك أخطاءه بنفسه. وفي أوّل ثلاثة عشر يوماً من سبتمبر عادت الميزات تتقدّم (٢٧ مقابل ١٩) — فوق الحرّاس نفسها لا بدلاً منها.

وفي الوسط تقع نقطة التحوّل: خطّ التكامل verify.yml وُلد في ٢٢ يوليو، وأول طلب دمجٍ حقيقيّ في ٣١ يوليو — وهو نفسه أكثف يومٍ في تاريخ المستودع (١٠٩ كوميتات). ومن أول أغسطس صار الدمج بالسحق حصراً: ٣١٠ طلباً في شهر واحد.

الخلاصة التي تلخّص المشروع: الانضباط لم يسبق الفوضى — وُلد منها.

03طبقة الحرّاس

عشرة سكربتات وظيفتها الوحيدة منع خطأ يعرف المشروع أنه يقع — لأن كلّ واحدٍ منها كُتب بعد أن وقع ذلك الخطأ فعلاً وبلغ الفرع الرئيس.

check-migration-orderفرعٌ قديم يُنزل رقم هجرةٍ مكرَّراً — بلا تعارضٍ يُنبّه، لأن الاصطدام على الرقم لا الاسم
check-service-only-callersنداءٌ من المتصفّح لما يجب أن يبقى خادميّاً
check-db-types-no-lossأنواعٌ مولَّدة تنحرف صامتةً عن سكيما القاعدة
check-shell-utf8-varsمتغيّرٌ عارٍ يكسر النصّ العربي في سكربتات التشغيل
check-shared-db-driftقياسٌ يُؤخذ على قاعدةٍ انحرفت — فيُنسب عطبُ البيئة إلى الشيفرة
check-security-scanner-blockingفاحصٌ أمنيّ يمرّ في خطّ التكامل بلا أن يحجب شيئاً
check-workflow-runnerوظيفة تكاملٍ بلا عدّاءٍ يلتقطها — فتبدو ناجحةً وهي لم تعمل

وأربعةٌ منها لها اختبارها الخاص — حارسٌ للحارس، لأن حارساً أعمى أسوأ من غيابه: يمنح طمأنينةً بلا حماية.

04١٬١٠٩ قراراً — كلٌّ بقياسه

كل قرارٍ معماريٍّ في أَثل مسجَّلٌ بحكمه وبالقياس الذي برّره — و١٢٨ منها نقضها قرارٌ لاحق ولم تُمحَ. هذه ثلاثة منها.

قرارٌ نقض قراراً سابقاً — بالتنفيذ لا بالرأي #584

قرارٌ سابق حدّد موضع قفلٍ في مسار المال بناءً على تحليلٍ سليمٍ لدورةٍ واحدة. فأُعيد القياس باتّصالين متزامنين على قاعدةٍ معزولة، فظهر deadlock detected من أول محاولة — فسقط القرار السابق وحلّ محلّه علاجٌ أصغر: ترقية قراءةٍ قائمة بدل إضافة قفلٍ ثالث.

قرارٌ حكمُه: لا يُبنى شيء #544

دفترُ كلفةٍ يحمل صفوفاً كُتبت بسعرٍ قديم. والحكم كان ألّا تُصحَّح رجعيّاً، بسببٍ مكتوب: «لم أقس عدد الصفوف المصابة ولا أستطيع — وكتابة تحديثٍ على دفترٍ ماليٍّ بحجمٍ مجهول أخطر من الضرر الذي تعالجه».

قرارٌ أعلن حدَّه على نفسه #202

جلسةٌ نفّذت خطوةً قبل أن تتحقّق من شرطها. الأثر كان صفراً، لكن الترتيب كان خطأً — فسُجّل: «يُسجَّل كي لا يُقرأ صمتُ السجلّ موافقةً».

أيّ مشروعٍ يستطيع أن يعرض عدد اختباراته. أمّا سجلٌّ يوثّق لماذا لم يُبنَ شيء — وقد تكرّر ذلك عشرات المرات — فهو ما يجعل النظام قابلاً للبناء عليه بعد سنة.

05أسبوعان بعد النسخة الأولى من هذه الصفحة

ما دخل الفرع الرئيس بين ١ و١٣ سبتمبر — ٦٤ طلب دمج. كلُّ بندٍ هنا مدموجٌ في الشيفرة، لا مخطَّط — ولم يشتغل منه شيءٌ بعد على مقهىً حقيقيّ.

API · MCPمفاتيح لكل منشأة، وقرّاء /api/v1، وطابور ويبهوك، وخادم MCP فوقها — فيقرأ وكيلُ ذكاءٍ بيانات المقهى بمفتاح صاحبه لا بمفتاح المنصّة
prep stationsمحطّات تحضيرٍ يعرّفها كلُّ مقهى ويفعّلها لكل فرع، بلوحٍ لكل محطّة — وترفض المنصّة إطفاءَ محطّةٍ عليها شاشاتٌ حيّة
templatesقوالبُ تشغيلٍ جاهزة (أربعٌ للبداية): تُعايَن قبل التطبيق، وتُطبَّق بنداً بنداً لا دفعةً واحدة
delivery channelsوسمُ قناة التوصيل على الطلب — بسعرها وتسويتها وتقريرها — من نقطة البيع حتى المطبخ والمالية
curbsideالاستلام من السيارة (لوحة · لون · نوع) للطلب الإلكتروني، وزرُّ «وصلت» للزبون
refund linesالاسترجاع على مستوى السطر، يعكس معه النقاط والأختام على السطر نفسه
tenant lifecycleكاتبٌ واحدٌ لحالة المنشأة، وإيقافٌ بمهلة لا يقطع ورديةً مفتوحة في منتصفها
deployالهجراتُ تُرفع آلياً عند الدمج بعد نسخةٍ احتياطيّةٍ طازجةٍ إلزاميّة، والشيفرةُ لا تُنشر قبل هجرتها

06ستّة أيام — الضبط قبل التوسّع

منذ آخر تحديثٍ لهذه الصفحة (١٣ سبتمبر) — ٤٤ طلب دمج جديد. كلُّ بندٍ هنا مدموجٌ في الشيفرة، لا مخطَّط. ولا حركة إنتاج حقيقية بعد، إلا اختباراً ميدانياً واحداً لشاشة المخزون في ١٩ سبتمبر.

fraud controlsشاشة «الرقابة» لصاحب المنشأة، وأربعة كواشف تعمل عند إقفال الوردية، وموافقةٌ ثانية على الاسترجاع، وكلمة مرورٍ للتوقيع على إجراءات الضبط
Moyasarاتصال مدفوعات مستقلّ لكل مقهى، لا مفتاحاً واحداً للمنصّة كلّها
self-serve signupتسجيلٌ ذاتيّ من athl.cloud/register بفحص السجل التجاري، تعتمده المنصّة يدوياً لكل منشأة
inventory entryشاشة إضافة صنفٍ وتنبيهات نفاد المخزون — أوّل تشغيلٍ فعليّ لها كان في ١٩ سبتمبر، في اختبارٍ ميدانيّ
ZATCA phase 1–2سلسلة التوقيع المباشر مبنيّة؛ تسجيل كل مقهى لدى زاتكا (المرحلة التالية) قيد البناء — لا فاتورة زاتكا موقّعة صدرت من أَثل حتى الآن
offline boardsلوحات طلباتٍ للقراءة فقط، تعمل دون اتصال بالإنترنت
data importأساسٌ لاستيراد البيانات من أنظمةٍ سابقة — أساسٌ فقط، لا مسارُ ترحيلٍ كامل
Frankfurtالخوادم انتقلت لفرانكفورت قرب القاعدة، وتُبقى دافئةً بدالّةٍ مجدولة — البطء الأول كان بردَ البداية، لا ضعف النظام

07ما بُني — بالأرقام

كل رقمٍ هنا مأخوذ من المستودع بأمرٍ يمكن إعادة تشغيله.

124 daysأوّل كوميت ٢١ مايو ٢٠٢٦ إلى ٢٢ سبتمبر — النشاط في ٦٩ يوم عمل، بمعدّل ١٩ كوميتاً في اليوم النشط (١٬٢٨٥ كوميتاً إجمالاً). ويسبقها شهرٌ من التصميم قبل أن يُكتب سطرٌ واحد
105 tables · 355 RPCsكما تظهر في الأنواع المولَّدة من القاعدة — وكلُّ كتابةٍ تمرّ بدالّةٍ مختومة، لا بكتابةٍ مباشرة من العميل
474 error codesلكلّ حالة فشلٍ رمزٌ ورسالةٌ عربيّة — لا «حدث خطأ ما» — كلُّها في كتالوجٍ واحدٍ داخل القاعدة
786 test files٥٢٨ بـvitest (٦٬٢٤٢ اختباراً ناجحاً، ٤ متخطّاة) و٢٥٨ بـpgTAP داخل القاعدة — نحو ١١٬١٠٠ توكيدٍ مجموعاً
72,869 linesاختبارات SQL وحدها — أي ٧٠٪ من حجم الهجرات نفسها
19 race proofsبراهين سباقٍ باتّصالين حقيقيين على قاعدةٍ معزولة — لا اختبار قاعدةٍ واحدة
8 edge fnsمكتوبة، وواحدةٌ فقط منشورةٌ في الإنتاج

ما لا تُثبته هذه الأرقام

هذا القسم موجودٌ عمداً. سجلٌّ بلا حدودٍ معلَنة دعايةٌ لا سجلّ.

  • العدّاد يبدأ من أوّل كوميت، لا من أوّل يوم عمل. سبق البرمجةَ شهرٌ كامل من التصميم وبناء التصوّر — ولا أثر له في المستودع، لأن git لا يقيس إلا ما كُتب فيه. فكلّ رقمٍ هنا يصف الشيفرة لا المشروع.
  • نحو عشرة آلاف توكيدٍ ليست برهان صحّة. التوكيدات تختبر ما خطر لكاتبها — وليلةٌ واحدة كشفت عطباً مالياً حيّاً كانت فوقه سويتٌ خضراء.
  • نحو ٤٬٤٠٠ من التوكيدات «مخطّطة» لا مُثبَتة التشغيل هنا (pgTAP، تحتاج قاعدة). أمّا ٥٬٩٠٣ توكيد vitest فشُغّلت كاملةً في ١٩ سبتمبر وشوهدت خضراء، و٤ مُتخطّاة عمداً.
  • لا فاتورة زاتكا موقّعة صدرت من أَثل حتى الآن. سلسلة التوقيع المباشر مبنيّة، وتسجيل كل مقهى لدى زاتكا لم يُبنَ بعد — فلا ادّعاء بالجهوزية قبل أن يصدر أوّل فاتورة.
  • لا حركة إنتاج بعد. كلّ ما سبق هندسة، والاختبار الحقيقي أوّل مقهىً يشتغل عليه بمالٍ حقيقي.
  • مراجعٌ بشريٌّ واحد. العمق يأتي من الحرّاس والتوكيدات لا من عيونٍ كثيرة — وهذا حدٌّ معروف، لا مُنكَر.