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

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

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

92/100جاهزية الإطلاق
13/13وثيقة زاتكا في محاكاة الهيئة
851هجرة قاعدة بيانات
1,964ملف اختبار

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من سبتمبر إلى اليوم — الجاهزية ٩٢ من ١٠٠

مذكرة الجاهزية تقيس المنصّة على ما يحتاجه أوّل يوم تشغيلٍ حقيقيّ. كانت ٦٧ من ١٠٠ في ١٨ أكتوبر، وصارت ٩٢ في ٢٠ أكتوبر — والنقاط الثماني الباقية كلّها تحتاج تجربةً على جهازٍ حقيقيّ أو خطوةً منّي. كلُّ بندٍ هنا مبنيّ وعليه اختبارٌ يمرّ.

ZATCA phase 2توقيعٌ مباشر مع الهيئة بلا وسيط: ختمٌ، ثم تحقّقٌ من التوقيع قبل الإرسال، ثم إبلاغ. ١٣ وثيقة (بيع، إشعار دائن، إلغاء، ضيافة، رسم توصيل، أسعار غير شاملة) خُتمت وأُبلغت كلّها بنجاح في بيئة المحاكاة لدى الهيئة في ١٩ أكتوبر — المحاكاة، لا الإنتاج
link ZATCAزرّ «اربط زاتكا» يربط به المالك وحدة الفوترة بنفسه، وتنبيهٌ إن بقيت فاتورةٌ ٢٠ ساعة دون إبلاغ، وإشعارٌ دائن عند كل مرتجع
till dayيومُ كاشيرٍ كامل في اختبارٍ آليّ: فتح الوردية، كاش وشبكة وتقسيم الدفع، خصمٌ بإذن المدير، كوبون، نقاط وأختام، مرتجع، إلغاء، ثم إقفال الدرج
offline guardsقبل البيع بلا نت يُفحص الجهاز (القائمة، الجلسة، ساعة الجهاز، تغيّر السعر)؛ والطلب لا يُحسب مرّتين لو انقطع الردّ أو فُتح تبويبان؛ وأرقام الطلبات لا تتكرّر بين الأجهزة حتى بلا نت
recipe stockالبيع ينقص المخزون بالوصفة بالضبط، وجردٌ يسجّل حركةً لكل صنف، ونقلٌ بين الفروع إرسالاً واستلاماً، وتنبيهُ نفاد
Z reportتقرير الإقفال والتقارير والقاعدة تتطابق بالهللة
Foodics importالمنيو والمخزون والإضافات تُستورد من ملفات فودكس مباشرةً، مع تراجعٍ عن الاستيراد إن لزم
9 rolesتسعة أدوار، والمشرف محصورٌ بفرعه — ومن التسجيل إلى أوّل بيعة لمقهىً جديد في اختبارٍ آليّ واحد

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

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

153 daysأوّل كوميت ٢١ مايو ٢٠٢٦ إلى ٢١ أكتوبر — النشاط في ٩٢ يوم عمل، بمعدّل ١٦ كوميتاً في اليوم النشط (١٬٤٦٢ كوميتاً إجمالاً). ويسبقها شهرٌ من التصميم قبل أن يُكتب سطرٌ واحد
232 tables · 1,247 functionsفي مخطّط public كما تظهر في الأنواع المولَّدة من القاعدة (بلا أقسام السجلّ الشهرية) — وكلُّ كتابةٍ تمرّ بدالّةٍ مختومة، لا بكتابةٍ مباشرة من العميل
1,000+ error codesلكلّ حالة فشلٍ رمزٌ ورسالةٌ عربيّة — لا «حدث خطأ ما» — كلُّها في كتالوجٍ واحدٍ داخل القاعدة
1,964 test files١٬٢٨٢ بـvitest و٦١٤ بـpgTAP داخل القاعدة و٦٨ رحلة e2e في المتصفّح — ١٣٬٦٤٥ توكيداً مخطّطاً في pgTAP
358 suites as a userسويتات قاعدةٍ تعمل بصفة مستخدمٍ مسجّل لا بصلاحية المشرف — فتختبر الصلاحيات وعزل البيانات كما يعيشها المستخدم فعلاً
143,333 linesاختبارات SQL وحدها — أي ٦٢٪ من حجم الهجرات نفسها
70+ race proofsبراهين سباقٍ باتّصالين حقيقيين على قاعدةٍ معزولة — لا اختبار قاعدةٍ واحدة
17 edge fnsمكتوبة، وكلُّها منشورةٌ في الإنتاج

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

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

  • العدّاد يبدأ من أوّل كوميت، لا من أوّل يوم عمل. سبق البرمجةَ شهرٌ كامل من التصميم وبناء التصوّر — ولا أثر له في المستودع، لأن git لا يقيس إلا ما كُتب فيه. فكلّ رقمٍ هنا يصف الشيفرة لا المشروع.
  • أكثر من ١٣ ألف توكيدٍ ليست برهان صحّة. التوكيدات تختبر ما خطر لكاتبها — وليلةٌ واحدة كشفت عطباً مالياً حيّاً كانت فوقه سويتٌ خضراء.
  • الأرقام هنا عُدّت من الشيفرة، ولم يُعَد تشغيل الاختبارات لهذه الصفحة. آخر جولة e2e كاملة (١٨–٢٠ أكتوبر): ١٩٢ نجحت و٠ فشلت.
  • لا فاتورة زاتكا من مقهىً حقيقيّ بعد. التوقيع المباشر والإبلاغ اجتازا ١٣ وثيقة من ١٣ في بيئة المحاكاة لدى الهيئة، لكن لا مقهى مسجَّلاً في الإنتاج — وهذا يحتاج مقهىً حقيقياً.
  • البيع بلا نت والطباعة وجهاز الشبكة لم تُجرَّب بعد على أجهزة مقهى. مبنيّة ومختبرة في المتصفّح، ولا ورقة طُبعت بعد من النسخة السحابية — والتجربة الميدانية هي الخطوة التالية.
  • لا حركة إنتاج بعد. كلّ ما سبق هندسة، والاختبار الحقيقي أوّل مقهىً يشتغل عليه بمالٍ حقيقي.
  • مراجعٌ بشريٌّ واحد. العمق يأتي من الحرّاس والتوكيدات لا من عيونٍ كثيرة — وهذا حدٌّ معروف، لا مُنكَر.