Clepit
لمحة سريعة
- الفئة
- منصة للمطوّرين
- الموقع
- clepit.com
- لوحة التحكم
- app.clepit.com
- التوثيق
- clepit.com/en/docs
- واجهة GraphQL
- api.clepit.com/graphql
- البث الفوري
- ws.clepit.com
- واجهة MCP
- api.clepit.com/mcp
- الصفحات المنشورة
- clepit.space
ينتهي معظم النص المنسّق داخل قاعدة البيانات ككتلة من HTML. لا بأس بذلك حتى تحتاج إلى شيء آخر غير عرضه من جديد: أن تجد كل صفحة تذكر عميلاً بعينه، أو تعرض المستند نفسه في صفحة ويب وبريد إلكتروني وتطبيق جوال، أو تدع شخصين يحرّرانه معاً دون أن يفقد أحدهما فقرة. عندها تكون الكلمات وتنسيقها قد تشابكا، ولا يبقى ما يستطيع قراءة المستند بثقة سوى المحرّر الذي كتبه.
يفصل كليبيت بينهما. الصفحة قائمة من الكتل، كل كتلة كائن صغير محدّد النوع، والمستند نفسه JSON: لا ترميز يحتاج إلى تحليل، ولا حاجة إلى محرّر كي تقرأه. ولهذا أيضاً يقف المحرّر وحده. فحزمة @clepit/core منشورة على npm برخصة MIT ولا تعرف شيئاً عن الجانب المستضاف، بينما مساحة العمل على app.clepit.com هي ما تصير إليه المستندات نفسها حين تُمنح متعاونين وصلاحيات وسجلّ نسخ وعنواناً على الويب العام.
الصفحة قائمة من الكتل
الكتلة أربعة حقول: معرّف، ونوع، والبيانات التي يحدّدها ذلك النوع، وأي ضبط طُبّق عليها. بيانات الفقرة لها شكل مختلف عن بيانات الجدول، والنوع هو ما يخبرك بالشكل المتوقّع، فيصير المستند المخزَّن قابلاً للتحقّق لا لمجرّد التحليل. الصفحة كاملةً هي ختم زمني ونسخة والكتل مرتّبة، وهذا صغير بما يكفي لتقرأه بعينك وتراجعه في طلب دمج. ولا شيء فيه يصف كيف ينبغي أن تبدو الصفحة: ذلك شأن ما يرسمها، وهو ما يتيح لمستند واحد أن يصير صفحة ويب وبريداً إلكترونياً وشاشة هاتف دون أن توجد منه ثلاث نسخ.
رسم مستند من دون متصفّح
العارض لا يكتب إلى المتصفّح مباشرة. إنه يرسم عبر طبقة رقيقة خلفها سندان: أحدهما يبني عقد صفحة حقيقية، والآخر يبني نصاً، ويعمل الكود نفسه للكتلة على كليهما. هكذا تُرسم صفحة منشورة على خادم لا متصفّح فيه، وهكذا يكون ما ينتجه الخادم هو المستند نفسه الذي كان المحرّر سيعرضه، لا تطبيقاً ثانياً يُترك ليبتعد شيئاً فشيئاً. سند النص يطلب مُعقِّماً كمُعامل إلزامي وليس له افتراضي عن قصد: فمُعقِّم الحزمة المعتاد يبني صفحة كي يحلّل، فلا يستطيع العمل هناك، والرجوع الصامت إلى الهروب من الرموز كان سينزع التنسيق الداخلي من كل مستند دون أن يقول ذلك. فتُركت الثغرة ظاهرة عند موضع الاستعمال بدل أن تُخبّأ داخل قيمة افتراضية.
القراءة لا تكلّف القارئ أي JavaScript
يشحن محوّل React نصفيه منفصلين، لأن لكلٍّ منهما مطلباً معاكساً. مكوّن المحتوى يعمل على الخادم ويُخرج ترميزاً جاهزاً أثناء بناء الصفحة، فيتلقّى القارئ المستند في أول استجابة. أما مكوّن المحرّر فيعمل على العميل وحده، لأنه يتولّى دورة حياة المحرّر، ولا شيء يُتولّى قبل وجود متصفّح. ولذلك فقراءة مستند كليبيت لا تحتاج إلى JavaScript البتّة. أما الكتابة فهي الموضع الذي يصل عنده وقت التشغيل.
ما الذي يمكن أن تحمله الصفحة
ستّ وعشرون نوعاً من الكتل تأتي مع الحزمة. معظمها ما يحتاجه أي محرّر: عناوين وفقرات وقوائم وقوائم مهام واقتباسات وشيفرة وجداول وصور وصوت وفيديو وملفات وتنبيهات وفواصل. أما البقية فموجودة لأن كتابة التوثيق تطلب أشياء تتجاهلها أدوات الكتابة عادةً. جدول محتويات يبني نفسه من عناوين المستند ويربط بكل واحد منها. أقسام قابلة للطيّ وأعمدة. بطاقة تنوب عن صفحة أخرى. رسم حرّ باليد. وكتلة نشاط تخزّن أي مستند تراقب، لا نسخةً من نشاطه، فتظلّ تعرض ما يجري الآن بدل أن تتجمّد عند يوم إدراجها. أما التنسيق داخل الكتلة فيشمل العلامات المعتادة: العريض والمائل والمسطَّر والمشطوب والشيفرة داخل السطر والتظليل والروابط، إضافة إلى التلميحات وشارات الحالة والإشارات إلى الأشخاص. والحزمة نفسها ليس لها أي اعتماديات وقت التشغيل.
المعادلات والمخطّطات، مرسومة داخل الحزمة
كتلتان من تلك الكتل تعرضان LaTeX وMermaid، وكلتاهما تؤدّيان العمل كاملاً داخل الحزمة: تحلّلان المصدر، وتحسبان التخطيط، وترسمان النتيجة. لا مكتبة رسم تحتهما، ولا نداء إلى خدمة كي تحوّل معادلة أو مخطّط تدفّق إلى صورة. وهذا أقرب إلى نتيجة لسند النص منه إلى تفضيل بشأن الاعتماديات. فكتلة تمدّ يدها إلى شيء لا يوفّره إلا متصفّح، أو إلى الشبكة، ما كانت لتُرسم على الخادم الذي يخدم الصفحات المنشورة، وعندها كانت الصفحة ستظهر بشكل مختلف باختلاف من يطلبها.
مرجع واجهة برمجية يعيش داخل الصفحة
أعطِ كتلة OpenAPI مواصفةً، ملصوقةً أو مُشاراً إليها بعنوان، فترسم ما تصفه تلك المواصفة: العمليات ومساراتها ومعاملاتها، ومخطّطات الطلب والاستجابة، وطريقة التوثّق. ولكل عملية تبني أيضاً مقتطف طلب بلغة cURL وTypeScript وDart وPython، مولَّداً من المواصفة لا مكتوباً بيد مؤلّف سينسى تحديثه. وكتلة التضمين ترى العالم الخارجي بالنظرة نفسها: فهي تتعرّف على حفنة من الخدمات تستطيع عرضها فعلاً، وتعامل الرابط العادي كنتيجة سليمة لا كإخفاق فيما عدا ذلك، وترفض رفضاً صريحاً أن ترسم عنواناً لا تثق به.
شخصان في الفقرة نفسها
الصفحة التي تُحرَّر مباشرةً تمسكها مهمة واحدة على الخادم، واحدة لكل صفحة، وكل تحديث يمرّ عبرها بالترتيب. وهذا ما يجعل التحرير المتزامن سهل التعقّل: لا كاتب ثانٍ يسابق الأول. والمستند نفسه بنية CRDT، فشخصان يكتبان في الفقرة ذاتها يندمج عملهما بدل أن يمحو أحدهما الآخر، والعميل الذي تخلّف يلحق بتبادل ما ينقص كل طرف. كل تحديث يُضاف إلى سجل الكتابة المسبق قبل أن يُبثّ إلى أحد، فما يراه بقية الموجودين في المستند قد سُجّل بالفعل تسجيلاً دائماً لا مجرّد تمريره. والصلاحية تُفرض على الخادم لا في الواجهة: فمن ينضمّ دون حقّ التحرير يُخفَّض إلى القراءة، والجلسة تعيد فحص ذلك الحق دورياً ما دام المستند مفتوحاً، حتى يصل سحب الصلاحية إلى من يكتب فعلاً بدل انتظار إعادة تحميل الصفحة.
كل كتابة تمرّ من باب واحد
يمكن أن يتغيّر المستند بيد شخص يكتب فيه وببرنامج ينادي الواجهة البرمجية، وكان هذان المساران قادرين من قبل على الكتابة في الصفحة نفسها كلٌّ على حدة. لم يعودا كذلك. فالكتابة القادمة من الواجهة تُحوَّل إلى الجلسة ذاتها التي تمسك المستند الحيّ، حيث تُطبَّق كمعاملة واحدة إلى جانب التحريرات المباشرة، فيكون هناك ترتيب واحد للأحداث بدل كاتبَين لكلٍّ رأيه فيما تقوله الصفحة. وتُحفظ معرّفات الكتل عند إعادة كتابة المستند، لأن التعليقات مثبّتة عليها، ومصالحةٌ تُنشئ معرّفات جديدة كانت ستترك كل تعليق يشير إلى لا شيء. وحين تكون مجموعة الكتل الناتجة مطابقة لما هو مخزَّن أصلاً، لا يُكتب شيء البتّة.
الناقل الوحيد الذي لا يبلغه مفتاح آليّ
مفتاح واجهة برمجية شخصي يعمل مع REST وGraphQL ومقبس اشتراكات GraphQL وMCP. ولا يعمل مع مقبس التعاون، وذلك عن قصد. فكل تحديث تعاوني يُختم باسم من أجراه، وتلك الأختام تصير هي نسبة التأليف المسجَّلة في تاريخ الصفحة. ولو حرّر هناك كيان آليّ لكتب مؤلّفاً لم يكتبه إنسان، والتراجع عن ذلك لاحقاً يعني إعادة كتابة التاريخ لا حذف سطر. والفارق ليس بين مقابس الويب وHTTP: بل هو ما إذا كان الناقل يكتب تاريخاً منسوباً إلى مؤلّف. والقاعدة تفرضها بنية الكود لا الذاكرة، إذ يتطلّب قبول المفتاح انتقالاً متعمَّداً إلى نداء توثّق مختلف، ويسقط اختبارٌ إن فعل ناقلٌ ذلك.
مساحة عمل على عنوان خاص بها
كل مساحة عمل مستأجرٌ له نطاق فرعي خاص به منذ لحظة إنشائه، ويُستدلّ على المستأجر من العنوان الذي وصل عليه الطلب. وهكذا يتقرّر في أي مستأجر أنت قبل أن تُقرأ أي من بياناتك، لا بمرشّح يُطبَّق بعد ذلك وقد ينساه أحد. وتحت ذلك، تفرض قاعدة البيانات الحدّ بنفسها عبر أمن مستوى الصف: كل طلب يسحب اتصالاً، ويختم هويّة صاحب النداء عليه، ويمحو المجمّع تلك الحالة عند إعادة الاتصال، فلا تتسرّب هويّة طلبٍ إلى استعلامات الطلب الذي يليه.
المطالبة بنطاق ليست إثباتاً له
مساحة العمل على خطة المؤسسات تستطيع تقديم صفحاتها من نطاق خاص بها. والمطالبة بنطاق والتقديم منه خطوتان منفصلتان عن عمد: يُخزَّن النطاق غير موثَّق، ويتجاهله المحلِّل تجاهلاً تاماً إلى أن يظهر سجل تحقّق في نظام أسماء النطاقات. أي شخص يستطيع كتابة عنوان شركة أخرى في نموذج. ومن يملك السيطرة على ذلك النطاق وحده يستطيع نشر السجل الذي يجعله فاعلاً.
كل نسخة مرّت بها الصفحة
يحتفظ كليبيت بالنسخ لا بحالة واحدة راهنة. تُلتقط لقطة تلقائياً والناس يعملون، مكبوحةً كي لا تُنتج الكتابة العادية مئات منها: تُكتب لقطة جديدة إذا مرّت عشر دقائق أو تغيّرت عشر كتل، أيّهما جاء أولاً. والاستعادة معاملة واحدة: تُطبَّق اللقطة القديمة، وتُصالَح الكتل، وتُكتب الاستعادة نفسها كنسخة جديدة، فيكون الرجوع إلى الوراء مسجَّلاً لا ممحوّاً في صمت. والمصالحة تحفظ معرّفات كتل المصدر عن قصد، لأن التعليقات مثبّتة على الكتل، واستعادة صفحة بمعرّفات جديدة كانت ستترك كل تعليق فيها بلا مرساة.
أن تجده من جديد
يعمل البحث على إسقاطٍ للصفحات، ويمرّ الاستعلام عبر محلّل البحث الشبكي الخاص بـPostgres بدل أن يُركَّب يدوياً في SQL، فيستطيع المرء كتابة علامات اقتباس وإشارات ناقص دون أن يكون في ذلك أي سطح للحقن. أما ما يهمّ في مساحة عمل مشتركة فهو موضع فحص الصلاحية. البحث يضمّ جدول الصفحات، وأمن مستوى الصف الخاص بذلك الجدول يسري على الضمّ نفسه، فتكون النتائج محصورة سلفاً في الصفحات التي يحقّ للسائل رؤيتها. أما المرشّحات، وهي جزء من شجرة الصفحات، ومن راجع الصفحة آخر مرة، ومتى حُرّرت آخر مرة، فتُركَّب فوق ذلك كشروط إضافية. كل واحد منها يضيّق، ولا يستطيع أيّ منها أن يوسّع، لأنها كلها تقع خلف الفحص ذاته.
النشر يجمّد، والمشاركة لا تجمّد
هذان أمران مختلفان، ويعاملهما كليبيت معاملتين مختلفتين عن قصد. نشر الصفحة يجمّد المستند الحالي كنسخة، ويوجّه الصفحة إليها، ويجعلها علنية: فما يقرأه الزائر على clepit.space، على عنوان مثل acme.clepit.space/handbook، هو تلك النسخة المجمّدة لا التحريرات التي جرت بعدها. وإلغاء النشر يمسح المؤشّرات لكنه يبقي العنوان العلني، فالنشر من جديد لاحقاً يعود إلى العنوان نفسه بدل أن يكسر كل رابط يشير إليه. أما رابط المشاركة فعلى النقيض: يقدّم المستند الحيّ، فيتغيّر ما يراه المتلقّي كلما تغيّرت الصفحة.
رابط تستطيع استرجاعه
رابط المشاركة رمزٌ تستطيع إبطاله، ويمكن أن يُمنح تاريخ انتهاء لحظة إنشائه. ولا يُخزَّن منه إلا بصمته، فيُعرض الرابط مرة واحدة عند الإنشاء ولا يمكن استرجاعه من قاعدة البيانات بعد ذلك، لا منّا ولا ممن يبلغها. وهذه الروابط تمنح القراءة لا التعليق: فالتعليق يحتاج إلى مؤلّف، وحاملُ رابطٍ ليس مؤلّفاً.
تسجيل الدخول من دليلك أنت
تستطيع مساحة العمل أن تُسلّم التوثّق إلى مزوّد الهوية الخاص بها: OpenID Connect على خطة الأعمال، وSAML على خطة المؤسسات، ومعه SCIM لمزامنة الدليل. ويغطي SCIM مورد المستخدم الذي تقوده أوكتا وإنترا فعلاً، ويخالف قراءةً بديهيةً للمعيار مخالفةً مقصودة: فالحذف يعطّل العضو بدل أن يمحوه. المواصفة تسمح بذلك، والبديل مزامنةُ دليلٍ قادرةٌ على إتلاف محتوى مساحة عمل لمجرّد إخراج أحدهم من مجموعة.
أربع طرق للتخاطب معه
يغطّي REST أربعاً وأربعين عملية تحت /v1، يصفها مستند OpenAPI مولَّد من المسارات نفسها لا مكتوب إلى جانبها، ويقارن التكامل المستمر ناتجه بالنسخة المودعة، فلا يمرّ في صمت تغييرُ مسارٍ تخطّى السجل. وGraphQL يغطّي نموذج التطبيق ويحمل الاشتراكات على مقبسه الخاص. أما البثّ الحيّ فعملية منفصلة، ولهذا لا تُسقط إعادةُ تشغيل البوابة سطحَ الطلبات معها، وهو يصرّح لكل مقبس لا لكل غرفة: فمع كل حدث تُقيَّم كل الاتصالات داخل المستأجر في فحص واحد مجمَّع، ولا يستقبله إلا من يحقّ له رؤيته. وMCP يعرض العمليات ذاتها لوكلاء الذكاء الاصطناعي كأدوات، ولا تثق أي أداة بمعرّف قادم من المنادي كي تحدّد مساحة العمل التي تعمل فيها؛ والكتابات تمرّ عبر الخدمات نفسها التي تستعملها الواجهة، فتكون فحوص الصلاحية وسجل التدقيق هي ذاتها.
لمن هذا المنتج
الفرق التي تحتاج محرّرًا تتحكم به، والمطوّرون الذين يدمجون محتوى منظّمًا داخل منتجهم.
زيارة Clepit: clepit.com