./research / verifiable-audit-layer
طبقة تدقيق قابلة للتحقق للذكاء الاصطناعي.
طبقة تدقيق تكشف العبث، لاستدلال النماذج وتنفيذ الوكلاء: تسلسل قانوني، وتجزئة بفصل المجالات، وتواقيع DSSE، ورسم Merkle DAG لكل تشغيل، وسلسلة Merkle Mountain Range عبر التشغيلات تثبت أنه لم يُحذف أي تشغيل. اختير كل بدائي من قياس أداء مباشر أمام البدائل الحقيقية، مع إيداع البيانات الخام. هذه المذكرة هي التصميم والتجارب التي وراءه.
نموذج التهديد
نفترض خصمًا يتحكم في التخزين ويستطيع إعادة كتابة السجلات بأثر رجعي، بمن فيهم المشغّل الذي أنتجها. الهدف أن يكون أي تعديل على تشغيل مختوم قابلًا للكشف، وأن يبقى السجل قابلًا للتحقق طوال مدة احتفاظ تُقاس بالسنين، وألا يكشف التحقق أي مدخلات خاصة. تُبقى خاصيتان متمايزتين طوال الوقت: سلامة تشغيل واحد، واكتمال مجموعة التشغيلات. يعطي إيصال كل تشغيل الأولى ولا يقول شيئًا عن الثانية، لذا تُهندَس كلتاهما على حدة.
اتُّخذ كل خيار أدناه بالطريقة نفسها. لا نزعم أن بدائيًا هو الأفضل؛ بل نقارنه بالبدائل الموثوقة على الآلة ذاتها ونودع البيانات الخام، بحيث يُعاد إنتاج أي رقم هنا بأمر واحد. الأزمنة هي الأسرع من عدة تشغيلات بعد طرح الإحماء، مع الاحتفاظ بالمتوسط والانحراف المعياري كي يُعلَّم قياس غير مستقر بدل إخفائه. الأرقام من مضيف AMD64 واحد على CPython 3.14 وهي ذات معنى كنسب، لا كقيم مطلقة.
التجارب والنتائج
كان كل مَعلَم اختبارًا مباشرًا أمام البدائل الحقيقية، لا قياسًا مفردًا. النظرة العامة أدناه؛ والنتائج التفصيلية لكل منها في الأقسام التالية.
| المَعلَم | اختُبر أمام | النتيجة |
|---|---|---|
| الصورة القانونية | JSON ساذج، CBOR | JCS، مطابق بايتًا ببايت، ~3x كلفة |
| التجزئة | SHA-256، BLAKE3، keccak-256 | keccak أصيل 17x، البايتات ذاتها |
| النواة الأصيلة | خلفيات pip مقابل Rust | ختم 6x، جذر مطابق بايتًا ببايت |
| التوقيع | ECDSA، BLS، ML-DSA | Ed25519، 64 B، حتمي |
| ما بعد الكم | ML-DSA 44 / 65 / 87 | على مراحل، تحقق متكافئ، 38x حجمًا |
| أثر كل تشغيل | 8 هجمات تزوير، عبء إضافي | كلها التُقطت، ~121 us / حدث |
| سجل عبر التشغيلات | إعادة بناء Merkle ساذجة | MMR، إلحاق مسطّح، 483x |
التسلسل القانوني
يجب أن تتجزّأ الكبسولة إلى البايتات ذاتها في نواتنا بلغة Python، وفي عميلنا بلغة TypeScript، وفي أداة المدقّق الخاصة، وإلا فشل سجل صالح في التحقق. نستخدم RFC 8785 (JSON Canonicalization Scheme)، الذي يثبّت تنسيق الأرقام، وترتيب المفاتيح بوحدة ترميز UTF-16، ورفض القيم غير المنتهية. اختبرناه أمام JSON بمفاتيح مرتّبة ترتيبًا ساذجًا وأمام CBOR.
| المقاربة | Python مقابل Node | الكلفة |
|---|---|---|
| JSON مرتّب ساذج | يتباين على Unicode والأرقام | خط الأساس |
| RFC 8785 JCS | مطابق بايتًا ببايت | نحو 3x عند التسلسل |
| CBOR | ثنائي، يحتاج مفكّكًا لقراءته | مُدمَج |
يتباين JSON الساذج بين بيئات التشغيل في ترتيب Unicode وتنسيق الأرقام، فيكسر بصمت التحقق بين اللغات. أما JCS فمطابق بايتًا ببايت في كليهما، بنحو 3x زمن التسلسل، يُدفع مرة لكل تجزئة ويُهمَل أمام التجزئة وعمل الشبكة المحيط. نحتفظ بتطبيق واحد له تمامًا. وحين جلبت وحدتنا الأصيلة مُسلسِل JSON خاصًا بها، أزلناه، لأن مُقنِّنًا ثانيًا يتفق على المدخلات العادية ويتباين على الحالات الحدّية التي يستطيع الخصم اختيارها أسوأ من لا شيء.
التجزئة والنواة الأصيلة
تُجزّأ الأوراق بـ BLAKE3 وعُقد Merkle بـ keccak-256، كلاهما بفصل مجالات RFC 6962 (بادئات متمايزة للأوراق والعُقد الداخلية) لإغلاق صنف الصورة الأولية الثانية حيث تُقدَّم عقدة داخلية بوصفها ورقة. keccak-256 ليس SHA3-256؛ يتشاركان تبديلًا لكنهما يختلفان في بايت حشو واحد، والمتحقِّق على السلسلة يتكلم keccak، فأي استبدال صامت يجعل كل جذر يفشل على السلسلة. لذا تحسب طبقة التجزئة الخوارزمية المطلوبة أو ترمي خطأ، لا شبيهًا أبدًا، وتسجّل الخوارزمية في كل كبسولة كي يعيد المتحقِّق إنتاج الدالة بالضبط بدل استنتاجها مما هو مثبَّت محليًا.
| البدائي، دخل 64 B | الإنتاجية | ملاحظة |
|---|---|---|
| SHA-256 (stdlib) | 1٫50M ops/s | خط الأساس، حاضر دومًا |
| BLAKE3 (pip) | 1٫44M ops/s | متكافئ مع SHA-256 |
| keccak-256 (pip) | 99k ops/s | أبطأ 15x، عنق الزجاجة |
| keccak-256 (نواة Rust) | 1٫69M ops/s | أسرع 17x من pip |
ليس لـ keccak تطبيق في المكتبة القياسية، وهذا ما جعل الوحدة الأصيلة جديرة بالبناء. الفجوة أوسع عند مدخلات بحجم حدث لأن كلفة pycryptodome هناك تخصيص كائنات لكل نداء لا تجزئة، وهو تمامًا الحجم الذي يجزّئه أثر التدقيق أكثر ما يجزّئ؛ من الطرف إلى الطرف، ترفع النواة الأصيلة ختم تشغيل من 1000 حدث من 78 إلى 491 ختمًا في الثانية، نحو 6x. والأهم: تمكين المسرِّع لا يمكن أن يغيّر النتيجة: ختم التشغيل ذاته بوجود الحزمة ودونها يعطي جذرًا مطابقًا بتًا ببت، وتفحص مجموعة توافق كلا المسارين أمام المتجهات التي نشرها مؤلفو الخوارزمية، ويبني CI عجلة واحدة بـ ABI مستقر (abi3) ويتحقق من هذا الأثر الوحيد على كل Python من 3.10 إلى 3.14. تركيبها يغيّر السرعة ولا شيء غير ذلك.
تواقيع لسجل يدوم عقدًا
يجب أن يصمد توقيع على سجل تدقيق ما دام السجل قابلًا للنزاع، والتزامات تسجيل الذكاء الاصطناعي تقترب الآن من عقد. إن انكسر المخطط والسجل ما يزال في نافذة احتفاظه، أمكن للخصم تزويره وتأريخه بأثر رجعي، فيفشل الأرشيف كله دفعة واحدة. قِسنا Ed25519 أمام ECDSA وBLS وعائلة NIST ما بعد الكم ML-DSA، في الإنتاجية والأحجام.
| المخطط | التحقق (ops/s) | حجم التوقيع |
|---|---|---|
| ECDSA P-256 | 16 887 | ~72 B |
| ML-DSA-44 (ما بعد الكم) | 10 725 | 2420 B |
| Ed25519 | 10 375 | 64 B |
| BLS12-381 | تطبيق مرجعي فقط | 96 B، يجمّع |
قلبت نتيجتان افتراضات حملناها معنا، ونُبقي كلتيهما في السجل. Ed25519 ليس الأسرع في التحقق: قِيس ECDSA P-256 أسرع بنحو 1٫6x، على تجميعة مكتبية مُحسَّنة. يبقى Ed25519 الافتراضي في حجم التوقيع وفي الحتمية (RFC 8032)، التي تزيل عطل إعادة استخدام nonce في ECDSA الذي يسرّب مفتاحًا خاصًا بينما التواقيع لا تزال تتحقق. وتواقيع ما بعد الكم ليست بطيئة في التحقق: تجاوز ML-DSA-44 بالكاد Ed25519، وكلفته في التوقيع (أبطأ نحو 13x) وفي الحجم (نحو 38x بايتًا). ولأن الأثر يُوقَّع مرة ويُتحقَّق منه سنين، فالجانب المكلِف هو ما نفعله أقل. رُفض BLS على متطلَّب لا على رقم: يطوي التجميع تواقيع كثيرة في 96 بايتًا، لكن المجمَّع يُتحقَّق منه بكل شيء أو لا شيء ويحتاج كل مفتاح ورسالة، وهذا لا يتوافق مع كشف فرع واحد من قرار دون إظهار البقية.
إعادة التأطير المهمة: التواقيع ليست سرية، فلا ينطبق «احصد الآن، فُكّ لاحقًا»، والتهديد الحقيقي هو التزوير الرجعي داخل نافذة الاحتفاظ. رسو جذر إلى دفتر عام يثبت متى وُجد سجل مستقلًا عن مخطط التوقيع، فمفتاح مكسور يكلّف القدرة على إثبات من ختم سجلًا لكن لا متى ولا ماذا. لذا الرسو على المسار الحرج وML-DSA مصفوف خلفه على مراحل، مع إبقاء مظروف DSSE مرنًا خوارزميًا وتسجيل الخوارزمية لكل كبسولة.
أثر التدقيق لكل تشغيل
كل تشغيل تسلسل أحداث للإلحاق فقط ومسلسل بالتجزئة (نداءات LLM، نداءات أدوات، استرجاعات، توليد وكلاء فرعيين، موافقات بشرية، قرارات حاجز حماية)، بجذر Merkle فوقها جميعًا وتوقيع DSSE فوق الجذر. لا تُخزَّن إلا تجزئات المدخلات والمخرجات، لا الحمولات أبدًا، فيصون الأثر الخصوصية افتراضيًا. لا يكتفي المتحقِّق بإرجاع صالح أو غير صالح؛ بل يسمّي الضمانة التي انكسرت.
| العملية (تشغيل 102 حدث) | الكلفة | التوسّع |
|---|---|---|
| تسجيل حدث واحد | ~121 us | مسطّح، دون 0٫01% من خطوة |
| الختم، بناء الجذر | 0٫15 ms | خطي بالأحداث |
| التحقق، إعادة حساب كل الأوراق | 9٫2 ms | خطي، نحو 60x الختم |
التسجيل أقل من جزء من مئة من واحد بالمئة من خطوة وكيل نموذجية، تهيمن عليها رحلة الذهاب والإياب إلى النموذج، فالعبء ليس سببًا لأخذ العيّنات ويبقى الأثر كاملًا لا إحصائيًا. التحقق أثقل بكثير من الختم لأنه يعيد حساب كل ورقة من المحتوى بينما يبني الختم الشجرة فوق تجزئات حاضرة أصلًا. هذا اللاتماثل صحيح لأثر تدقيق، حيث التسجيل ثابت والتحقق نادر، وهو يعلّم إعادة التحقق الجماعية بوصفها المكان الذي تُثمر فيه النواة الأصيلة والتوازي تاليًا. ولتجسيد الضمانات، يهاجم عرض توضيحي تشغيلًا مختومًا بثماني طرق، تُرفَض كل واحدة بسبب محدد:
| الهجوم | رُفض بوصفه |
|---|---|
| إعادة كتابة مخرَج نموذج | عدم تطابق تجزئة ورقة |
| حذف حدث أو إدراجه | عدم تطابق عدد الأحداث |
| إعادة ترتيب الأحداث | كسر السلسلة |
| بتر التشغيل | عدم تطابق رأس السلسلة |
| تخفيض خوارزمية التجزئة | عدم تطابق تجزئة ورقة |
| التقديم تحت المفتاح الخطأ | لا يتحقق التوقيع |
سجل الشفافية عبر التشغيلات
كبسولة صالحة لكل تشغيل لا تثبت أن مجموعة التشغيلات مكتملة. المشغّل الذي يُسقِط تشغيلًا محرجًا يملك مجموعة كبسولات كلٌّ منها مثالية، وتاريخًا فيه ثقب. نُغلق ذلك بسجل واحد للإلحاق فقط من جذور الكبسولات، يدعم براهين الإدراج (تشغيل موجود في السجل) وبراهين الاتساق (السجل عند حجم سابق بادئة مضبوطة للسجل الآن). يمسك الاتساق الرقابة: سجل أُعيد بناؤه بعد إزالة تشغيل يكون سليم البنية داخليًا وكل كبسولة ناجية لا تزال تتحقق، لكنه يفشل في فحص اتساق أمام الجذر المنشور سابقًا، والفحص ذاته يرفض إدراجًا مؤرّخًا بأثر رجعي. لا يعمل هذا إلا أمام جذر أُودع قبل العبث، فلا بد أن يقيم ذلك الجذر في مكان لا يستطيع المشغّل مراجعته، كمرساة عامة.
نستخدم Merkle Mountain Range بدل شجرة Merkle الساذجة لأن الإلحاق يضيف عُقدًا فحسب ولا يعيد كتابة أي عقدة، ما يتيح للسجل أن يقيم على تخزين يُكتب مرة أو تخزين كائنات ويُبقي براهين الإدراج القديمة صالحة مع نمو السجل. هذه الخاصية شبه مثلى لا مجرد مريحة: يثبت ePrint 2025/234 أن أي التزام مقتضب للإلحاق فقط لا بد أن يستحث عددًا فوق-خطي من تحديثات الشهود، ومتغيّر MMR قريب يبلغ الحد جوهريًا.
| حجم السجل | بناء MMR | إعادة بناء ساذجة |
|---|---|---|
| 500 | 1٫3 ms | 158 ms (120x) |
| 1000 | 2٫6 ms | 618 ms (237x) |
| 2000 | 5٫2 ms | 2491 ms (483x) |
يبقى الإلحاق مسطّحًا مع نمو السجل (نحو 390k إلحاق في الثانية عند 100 وعند 10 000 مُدخَل) بينما تهبط إعادة بناء شجرة ساذجة من 8176 إلى 84 جذرًا في الثانية على المدى ذاته، بصمة التربيعي مقابل الخطي-اللوغاريتمي. يستقر التخزين على 2٫00 تجزئة مخزَّنة لكل مُدخَل، وتنمو براهين الإدراج من 7 إلى 17 خطوة فقط بين 100 و100 000 مُدخَل. حيث نخسر: براهين اتساقنا O(log^2 n)، تحمل مسارًا لكل قمة من السجل القديم بدل O(log n) القابل للتحقيق، بضعة كيلوبايت عند 100 000 مُدخَل ومقايضة متعمَّدة لبنية يستطيع مراجِع فحصها بالقراءة.
حدود لا نتجاوزها
تعطي التجزئة دليل العبث، لا مناعة منه. الخصم الذي يعيد بناء تشغيل ويعيد حساب جذره ينتج سجلًا متسقًا مع ذاته، لأن جذر Merkle يثبت أن الأحداث تطابق الجذر، لا أن الجذر هو المنشور. يمسك التوقيع ذلك، وتثبت المرساة العامة الزمن. يستند سجل الشفافية في الكبير إلى الافتراض ذاته: لا يكشف تشغيلًا محذوفًا إلا نسبةً إلى جذر أُودع قبل الحذف. نُعلن هذه الحدود في المنتج وعروضه، ويؤكّد اختبار أن عرض التزوير يظل يُظهر الهجوم الذي لا نوقفه، كي لا تستطيع هذه الحالة الأمينة أن تختفي بصمت.
قابلية إعادة الإنتاج
كل رقم هنا يأتي من قياس أداء مُودَع يُعاد تشغيله بأمر واحد، إلى جانب الاختبارات، ومجموعات التوافق بين اللغات وبين التطبيقات، ومصفوفة CI التي تُشغّل Python من 3.10 إلى 3.14 بالنواة الأصيلة وبدونها. المنهجية، وJSON الخام، وملاحظات القرار (بما فيها الأبعاد التي يخسر عندها كل خيار) في المستودع، لأن طبقة تجعل الذكاء الاصطناعي قابلًا للتدقيق يجب أن تكون هي ذاتها قابلة للتدقيق.