diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 4f764f2..44ab76b 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -37,6 +37,7 @@ - [التمثيل الوسيط SIR](backend/sir.md) - [توليد LLVM (المترجم sadc)](backend/llvm.md) - [الآلة الافتراضية (VM)](backend/vm.md) +- [دراسة حالة: توحيد هاش/شفّر/فك_تشفير](backend/crypto-unification.md) # الجزء السادس · أنظمة اللغة @@ -44,6 +45,7 @@ - [نظام الأنواع وفاحص الأنواع](systems/types.md) - [نظام الأخطاء والتشخيص](systems/errors.md) - [الدوال المضمنة والوحدات](systems/builtins.md) +- [محرّك تخطيط SadUI والمحاذاة المتقاطعة RTL](systems/sadui-layout.md) # الجزء السابع · المساهمة والحوكمة diff --git a/src/backend/crypto-unification.md b/src/backend/crypto-unification.md new file mode 100644 index 0000000..b857ef7 --- /dev/null +++ b/src/backend/crypto-unification.md @@ -0,0 +1,107 @@ +# دراسة حالة: توحيد هاش/شفّر/فك_تشفير بين المحرّكين + +مثال متكامل على **إزالة تباعُد** بين المفسّر والمترجم (لا إضافة ميزة جديدة): دالّتا +`هاش`/`شفّر`/`فك_تشفير` في وحدة `تأكيدات` كانتا مُنفَّذتين مرّتين بخوارزميّتين +مختلفتين تمامًا — والمترجم كان يملك **نسخة ثالثة** منفصلة لهدف Android لم يمسّها أحد. +المرجع اللغويّ للمستخدم في +[sadlang-docs](https://github.com/sadlang/sadlang-docs/blob/main/src/language/security.md)؛ +هذه الصفحة للمساهم في **التنفيذ**. + +> **المبدأ الأهمّ:** التوحيد بين المحرّكين لا يعني «اختيار نسخة والحذف» فقط — +> يعني أيضًا **البحث عن كل نسخة**. النسخة الثالثة في مُصدِّر Android كانت لتبقى +> متباعدة لو لم تكشفها مراجعة مستقلّة قبل الدفع (انظر «الفخّ» أدناه). + +## الوضع قبل التوحيد + +```mermaid +flowchart TD + MOD["وحدة تأكيدات: هاش / شفّر / فك_تشفير"] + MOD --> INT["المفسّر
builtin_module_assertions.cpp
SHA-256 + SHA-256-CTR حقيقيّ"] + MOD --> CMP["المترجم (سطح مكتب/Windows/Linux)
sad_embedded_runtime.c
FNV-1a + XOR بسيط"] + MOD --> AND["المترجم (هدف Android)
compiler_driver_android_linker.cpp
نسخة ثالثة منفصلة: FNV-1a"] + DEAD["stdlib/crypto/*
Hash/HMAC/AES/Base64 عبر OpenSSL"] -.->|"لا مستهلك — ميتة"| MOD +``` + +ثلاث حقائق متزامنة سبّبت الالتباس: +1. **`هاش("نفس النص")` يُعطي قيمتين مختلفتين** حسب المحرّك المُشغِّل — FNV-1a + (عدد صحيح) في المترجم مقابل SHA-256 حقيقيّ (نصّ ست عشريّ) في المفسّر. +2. **`شفّر`/`فك_تشفير` غير متبادلين عبر المحرّكين** — XOR بسيط في المترجم لا + يفكّه SHA-256-CTR الذي شفّر به المفسّر، والعكس. +3. **`stdlib/crypto/` كانت تبدو الحلّ الصحيح** (OpenSSL كامل: Hash/HMAC/AES/ + Base64) لكن بلا أيّ مستهلك في المفسّر أو المترجم — بُنِيت واختُبِرت (هدف + CMake `crypto_tests`) دون أن تُربَط بأيّ مسار تنفيذ فعليّ. + +## القرار: SHA-256 هو المصدر الحقيقيّ، لا OpenSSL + +الخيار الأول (ربط `stdlib/crypto` بالمترجم) يعمّق الانقسام بدل إغلاقه: لا يزال +يترك FNV-1a قائمًا في مسارات لا تستورد `stdlib/crypto` صراحةً، ويكسر **هدف +الوضع الحرّ** (freestanding) الذي لا يمكنه الربط بـOpenSSL أو أيّ مكتبة نظام +تشغيل مضيف — قيد قائم أصلًا على +[`tools/compiler/runtime/sad_embedded_runtime.c`](https://github.com/sadlang/s-programming-language/blob/dev/tools/compiler/runtime/sad_embedded_runtime.c) +(راجع تعليقات SEM019 فيه). القرار: **حذف `stdlib/crypto` كليًّا**، ونقل خوارزميّة +SHA-256/SHA-256-CTR **الذاتيّة التنفيذ** (self-rolled، بلا اعتماديّات) من المفسّر +إلى وقت تشغيل المترجم — لا العكس. + +## التنفيذ عبر الطبقات + +| الطبقة | قبل | بعد | +|---|---|---| +| **المفسّر** ([`builtin_module_assertions.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/interpreter/src/builtins/builtin_module_assertions.cpp)) | SHA-256 حقيقيّ (بلا تغيير — هو المرجع) | — | +| **وقت تشغيل المترجم** ([`sad_embedded_runtime.c`](https://github.com/sadlang/s-programming-language/blob/dev/tools/compiler/runtime/sad_embedded_runtime.c)) | `sad_security_hash` يُرجع `long long` (FNV-1a)؛ XOR بسيط | `sad_sha256_raw`/`sad_sha256_rotr` + `sad_security_hash` يُرجع `const char *` (سلسلة ست عشريّة 64 حرفًا)؛ CTR بنفس بنية nonce+عدّاد للمفسّر | +| **واجهة SIR الأماميّة** ([`builtins_security.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/compiler/src/frontend/builders/builtins_security.cpp)) | نوع الإرجاع `SadTypeKind::Integer` لـHASH | `SadTypeKind::String` | +| **مولِّد LLVM** ([`security_builtins_ops.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/compiler/src/backend/llvm/builders/builtins/security_builtins_ops.cpp)) | توقيع `sad_security_hash`: `(i8*) -> i64` | `(i8*) -> i8*` | +| **مُصدِّر Android** ([`compiler_driver_android_linker.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/tools/compiler/compiler_driver_android_linker.cpp)) | نسخة ثالثة FNV-1a منفصلة تمامًا | نفس SHA-256 (`sad_sha256_rotr`/`sad_sha256_raw`/`sad_security_hash`) — هذا الهدف لا يملك `sad_security_encrypt`/`decrypt` أصلًا | + +`sad_security_encrypt`/`decrypt` نُقِلا بنفس بنية المفسّر: مقطع `nonce` عشوائيّ +8 بايت في بداية الناتج، وكل كتلة 32 بايت تُخفى بـ`SHA-256(مفتاح ‖ nonce ‖ عدّاد)` +كتيّار مفاتيح XOR. + +```mermaid +flowchart LR + SRC["هاش(نص) / شفّر(نص، مفتاح)"] --> INTP["المفسّر: تقييم مباشر
sha256 lambda"] + SRC --> SIR["المترجم: CALL sad_security_*
(SadTypeKind::String الآن)"] + SIR --> RT["sad_embedded_runtime.c
sad_sha256_raw مطابق للمفسّر"] + INTP -.->|"تكافؤ حرفيّ + تبادليّة عابرة للمحركين"| RT +``` + +## الفخّ: نسخة ثالثة كادت تفوت المراجعة + +التغيير الأوّلي مسّ `sad_embedded_runtime.c` فقط (المسار المشترك لسطح +المكتب/Windows/Linux). مراجعة مستقلّة قبل الدفع (وفق سياسة الفريق: مراجع مستقلّ +إلزاميّ قبل أيّ `git push`) كشفت أنّ +[`compiler_driver_android_linker.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/tools/compiler/compiler_driver_android_linker.cpp) +يحمل **نسخة كاملة منفصلة** من دوال وقت التشغيل لهدف Android — بما فيها FNV-1a +القديمة — لم يكن `grep` الأوّلي على `sad_security_hash` عبر شجرة الكود قد +شملها لأنّها بحث لم يُعَد على كامل الشجرة. الدرس: **البحث عن كل نسخة يسبق +حذف/توحيد أيّ منطق مكرَّر** — لا يكفي تتبّع نقطة تسجيل الدالّة المضمنة الواحدة +(`compiler_strategy: RUNTIME_CALL` في SoT) لأنّ نقطة **الربط الفعليّ** +(linker) قد تتفرّع حسب الهدف. + +كما كُشِف تسريب أمنيّ ثانويّ في نفس المراجعة: تشفير/فكّ التشفير كانا يستعملان +مخزنًا ثابت الحجم على المكدس (`unsigned char input[8+8+256]`) يقتطع المفاتيح +الأطول من 256 بايت **صامتًا** بدل رفضها أو دعمها — أُصلح بتخصيص ديناميكيّ +(`malloc(klen + 16)`). + +## نقطة الحسم: هل يُذكَر خطأ فكّ_تشفير على مدخل غير صالح؟ + +بقي تباعُد واحد **موثَّق عمدًا لا مُصلَح**: عند مدخل ست عشريّ غير صالح، المفسّر +يرمي استثناء لغويًّا قابلًا للالتقاط بـ`حاول`/`امسك`، بينما وقت تشغيل المترجم +(دالّة C خالصة) يطبع رسالة على `stderr` ويُعيد النصّ الأصليّ دون رمي استثناء — +لأنّ ربط دالّة C خارجيّة بآليّة الاستثناءات المبنيّة على LLVM +([`exception_ops.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/compiler/src/backend/llvm/builders/arithmetic/exception_ops.cpp)) +تغيير معماريّ أعمق من نطاق التوحيد الحاليّ. مُوثَّق في وصف `DECRYPT` بـ +[`language-truth/builtins/assertions.yaml`](https://github.com/sadlang/s-programming-language/blob/dev/language-truth/builtins/assertions.yaml) +وفي `RISK.md` الخاصّ بقسم اختبارات المكتبة القياسيّة، بدل إخفائه خلف اختبار +لا يغطّي مسار الخطأ. + +## الاختبار (تكافؤ مزدوج) + +`tests/behavior/sections/09_المكتبة_القياسية/04_تشفير/` — أربعة ملفّات: +شعاعات FIPS 180-4 الرسميّة لـ`هاش("")`/`هاش("abc")`، تبادليّة `شفّر`/`فك_تشفير` +عبر نصوص عربيّة/مختلطة/متعدّدة الكتل، شعاع ثابت مُسجَّل يدويًّا كمرساة انحدار، +واختبار مفتاح أطول من 256 بايت (يرصد رجوع باغ الاقتطاع الصامت). كلّ ملفّ يُشغَّل +عبر `sad-run.exe` **و**`sadc.exe` ويُقارَن الناتج حرفيًّا (ADR-03) — هذا ما +يضمن ألّا يعود التباعُد. + +--- +**اقرأ بعده:** [دوال مضمنة ووحدات](../systems/builtins.md) · [نظام معالجة الأخطاء](../systems/errors.md). diff --git a/src/systems/builtins.md b/src/systems/builtins.md index c9051b7..e48e3b8 100644 --- a/src/systems/builtins.md +++ b/src/systems/builtins.md @@ -35,4 +35,5 @@ shared/builtins/generated/builtin_registry_generated.h ← مُولَّد > التفاصيل في مهارة `sad-lang-dev` (`references/builtins-system.md`). --- -**اقرأ بعده:** [سير عمل الفروع](../contributing/workflow.md). +**اقرأ بعده:** [دراسة حالة: توحيد هاش/شفّر/فك_تشفير](../backend/crypto-unification.md) · +[سير عمل الفروع](../contributing/workflow.md). diff --git a/src/systems/sadui-layout.md b/src/systems/sadui-layout.md new file mode 100644 index 0000000..627529f --- /dev/null +++ b/src/systems/sadui-layout.md @@ -0,0 +1,58 @@ +# محرّك تخطيط SadUI والمحاذاة المتقاطعة (RTL) + +> **الغرض:** شرح محرّك تخطيط واجهات SadUI (`LayoutEngine`) ومنظومة المحاذاة +> المتقاطعة مع دعم **RTL** الأصيل — كيف تُوضَع أبناء الحاويات، وخاصّيّة «محاذاة»، +> والهامش والأوزان، ومصدر حقيقة مفاتيح الخصائص. + +إطار SadUI **عربيّ RTL-أوّلًا**: الافتراض `LayoutDirection::RTL` في كلّ الطبقات. +لذا يبدأ محتوى الشاشة من **اليمين** لا اليسار. + +## المرحلتان المدموجتان + +محرّك التخطيط (`features/graphics/core/src/layout.cpp`) يجمع منطقَي **القياس** +و**الترتيب** في **تمريرة تنازليّة واحدة**: `layout()` يستدعي `arrange()` من الجذر +للأوراق، و`arrange` يستدعي `measure()` عند كلّ مستوًى حسب الحاجة. + +- **المحور الرئيسيّ:** للعمود عموديّ (تكديس رأسيّ)، وللصفّ أفقيّ. +- **المحور المتقاطع:** المحور الآخر — للعمود أفقيّ (اتّجاهيّ RTL/LTR)، وللصفّ + عموديّ (غير اتّجاهيّ). + +## خاصّيّة «محاذاة» المتقاطعة + +| الوضع | العمود (RTL) | العمود (LTR) | الصفّ | +|---|---|---|---| +| `بداية` (افتراضيّ) | اليمين | اليسار | الأعلى | +| `وسط` | توسيط | توسيط | توسيط عموديّ | +| `نهاية` | اليسار | اليمين | الأسفل | +| `تمدّد` | يملأ العرض | يملأ العرض | يملأ الارتفاع | + +- **تمدّد** يجعل الابن يملأ المحور المتقاطع كاملًا فيتخطّط هو وأحفاده بالمقاس + الكامل؛ الابن ذو **المقاس الصريح** في ذلك المحور يفوز على التمدّد (كـ + `align-items: stretch` في CSS). +- **حدّ:** «محاذاة» يُكرِّمها **العمود والصفّ حصرًا**؛ الشبكة/المكدّس/الالتفاف/ + التمرير لها تموضع RTL مبيَّت خاصّ لكنّها تتجاهلها. + +## الهامش والحشو والأوزان + +- **حشو:** إزاحة داخليّة تُقلّص منطقة المحتوى من الجانبين. +- **هامش:** إزاحة خارجيّة تُقحِم المحتوى `[هامش+حشو، العرض−هامش−حشو]`، ويُخصم + من قيود الأبناء فلا يتجاوز الابن مالئ-المحور فجوة الهامش. +- **وزن (وزن/flex):** حصّة الابن من المساحة المتبقّية على المحور الرئيسيّ؛ توزيعه + يحترم المقاس الصريح للحاوية (إن وُجد فالتوزيع ضمنه، وإلّا يتمدّد ليملأ القيد). + +## مصدر حقيقة مفاتيح الخصائص (SoT) + +كلّ مفتاح خاصّيّة (نحو «محاذاة»/«حشو»/«عرض») معرَّف في +`language-truth/ui_props.yaml` (٨٢ مفتاحًا)، يُولَّد منه +`sad_ui/prop_keys.h` (ثوابت `sad::ui::props::`) عبر `x.py gen`. **لا سلسلة +مفتاح خام في كود الرسوميّات** — يُقرأ المفتاح دائمًا عبر الثابت المولَّد: + +```cpp +node.findProperty(props::ALIGN) // ✓ لا findProperty("محاذاة") +``` + +يحرسه `check_no_raw_props.py` + `check_ui_props_consistency.py` ضمن +`x.py gen --check` (محلّيًّا + CI)، وworkflow `props-literals-lint.yml`. + +> التفصيل المعماريّ الكامل (مع الأمثلة والرسوم) في مستودع اللغة: +> `docs/architecture/sadui-layout-alignment.md`. diff --git a/sync/sources.yaml b/sync/sources.yaml index ab212de..793136d 100644 --- a/sync/sources.yaml +++ b/sync/sources.yaml @@ -91,6 +91,20 @@ chapters: - language-truth/builtins - interpreter/src/builtins + - file: src/systems/sadui-layout.md + sources: + - features/graphics/core/src/layout.cpp + - features/graphics/core/include/sad_ui/prop_keys.h + - language-truth/ui_props.yaml + - scripts/codegen/gen_ui_props.py + + - file: src/backend/crypto-unification.md + sources: + - compiler/src/frontend/builders/builtins_security.cpp + - compiler/src/backend/llvm/builders/builtins/security_builtins_ops.cpp + - interpreter/src/builtins/builtin_module_assertions.cpp + - language-truth/builtins/assertions.yaml + - file: src/sot/philosophy.md sources: - language-truth/_schemas