Scope workspace roots per account

This commit is contained in:
Hamza Ayed
2026-10-03 01:44:00 +03:00
parent 1b56f70aa6
commit 4345e43e29
10 changed files with 250 additions and 54 deletions
+11 -10
View File
@@ -2,7 +2,7 @@
هذه خارطة تنفيذ تدريجية للمشروع الحالي. التطبيق اليوم Flutter، وواجهة الخدمة FastAPI، والتخزين SQLite، وتوليد النص عبر خادم Ollama محلي. لا نبدأ بتدريب نموذج من الصفر؛ نبني منتجًا قابلًا لتبديل النموذج ونقيس كل مرحلة قبل توسيع الصلاحيات.
## الحالة الحالية — 2026-10-02
## الحالة الحالية — 2026-10-03
- الأساس المحلي يعمل: Flutter Windows Debug ↔ FastAPI ↔ Ollama، مع سجل SQLite للمحادثات ونسخ الإجابات. Gemma 4 E2B هو الافتراضي للنصوص، وطلبات الصور وPDFات الممسوحة تتحول تلقائيًا إلى Ministral 3:3b المحلي عند توفره. أضيف عقد أدوات الوكيل وسجل تدقيق للبيانات الوصفية فقط؛ وضع الوكيل ينفذ الآن خطوة اختيار أداة واحدة ثم يعيد النتيجة إلى Gemma لصياغة الرد. توجد ثلاث مهارات محلية قابلة للاختيار مع قائمة أدوات مسموحة يتحقق منها الخادم. فهرس SQLite يدعم FTS5 وتضمينات Granite محلية اختيارية لملفات النص والكود وPDF الرقمي والممسوح والمختلط؛ PDF الممسوح يفهرس أول 3 صفحات عبر OCR الاختياري. الوكيل يسترجع المقاطع نصيًا ودلاليًا ويهمل النتائج القديمة عند تغير الملف. تجربة تضمين API حقيقية أعادت الملف المقصود أولًا في 3/3 أسئلة عربية؛ بقي توسيع التقييم على ملفات واقعية ومعايرة OCR وترتيب الأعمدة.
- اكتملت وظائف المحادثة الأساسية وطبقة مزوّد Ollama، بما فيها جداول Markdown القابلة للتمرير والقوائم المتداخلة ومربعات مهام GFM؛ اجتاز التطبيق تحليل Flutter و10 اختبارات واجهة وحالة.
@@ -22,12 +22,12 @@
- إعدادات عنوان API والنموذج المختار والإشعارات والمظهر الداكن تُحفظ محليًا: ملف إعدادات عبر `path_provider` للأجهزة و`localStorage` للويب. عند غياب plugin يُبلّغ التطبيق أن الإعداد لن يستمر بعد الجلسة. Windows Debug أنشأ ملف الإعدادات فعليًا؛ اختبار Cubit أكد الاستعادة بعد إعادة إنشائه، واختبار الواجهة أكد تبديل السمة، وبناء Flutter Web نجح (2026-10-02).
- `/v1/models` يعرض القدرات التي يعلنها Ollama فعلًا لكل نموذج، مع علامة تحقق واضحة؛ قائمة Flutter تعرض النص/الصور/الصوت/الأدوات/التفكير/التضمينات دون تخمين. تحقق حي أظهر Gemma 4 E2B: نص، صور، صوت، أدوات، تفكير؛ Ministral 3:3b: نص، صور، أدوات.
- أضيف زر البحث العميق متعدد المصادر وزرا اختيار الملفات إلى الواجهة؛ أضيف تقييم الإجابة بإعجاب/عدم إعجاب محفوظ لكل نسخة في SQLite. التقييم يجمع بيانات تقييم، ولا يدرّب أوزان Gemma تلقائيًا.
- Flutter Windows Debug وFastAPI يعملان محليًا؛ مسار تحليل المرفقات يدعم PDF الرقمي، ويحوّل أول 3 صفحات من PDF الممسوح محليًا ثم يرسلها لنموذج الرؤية المحلي. تجربة حية على صورة اللقاء استخرجت العنوان والمكان عمان والتاريخ 15 تشرين الأول والوقت 6:30 مساءً دون ذكر سنة غير ظاهرة. أُضيفت جلسات حسابات وعزل سجل المحادثات والمعرفة والتدقيق، لكن واجهة الدخول وصلاحيات نظام الملفات وحدود الدخول لم تكتمل؛ لا يوجد نشر شبكي آمن بعد. الصوت يعتمد على Groq خارجي.
- Flutter Windows Debug وFastAPI يعملان محليًا؛ مسار تحليل المرفقات يدعم PDF الرقمي، ويحوّل أول 3 صفحات من PDF الممسوح محليًا ثم يرسلها لنموذج الرؤية المحلي. تجربة حية على صورة اللقاء استخرجت العنوان والمكان عمان والتاريخ 15 تشرين الأول والوقت 6:30 مساءً دون ذكر سنة غير ظاهرة. اكتملت واجهة الحساب، وتحديد محاولات الدخول، وتعيين جذور ملفات منفصلة للحسابات بإعداد مسؤول الخادم. عزل عملية FastAPI على مستوى نظام التشغيل، واستعادة كلمة المرور، وTLS، والتخزين الآمن للويب ما زالت مفتوحة؛ لا يوجد نشر شبكي آمن بعد. الصوت يعتمد على Groq خارجي.
- التدريب والضبط الدقيق وتوزيع Windows مراحل لاحقة، وليست مما يفعّله التطبيق حاليًا.
- 2026-10-03: اكتمل فرض Bearer على كل عمليات `/v1` الخاصة (عدا الصحة وقائمة النماذج ومسارات بدء المصادقة العامة)، وربط Flutter بالجلسة لكل طلب محادثة/وكيل/ملف/معرفة/ويب/صوت. أصبحت ملكية فهرس المعرفة وسجل التدقيق حسب الحساب، ومعاينة تعديل الملف لا تُطبق إلا بجلسة صاحبها. تحقق OpenAPI وواجهات رفض الرمز وعزل حسابين وترحيل SQLite: 61 اختبار Python ناجح، و11 اختبار Flutter وتحليل Flutter بلا ملاحظات. يبقى قصر الوصول إلى مسارات نظام الملفات لكل مستخدم، وواجهة الدخول وتخزين الرمز الآمن وحدود محاولات الدخول؛ لذلك يظل التشغيل loopback فقط.
- 2026-10-03: أضيفت شاشة Flutter للحساب (إنشاء/دخول/خروج)، وعند تبديل الهوية تمسح المحادثات المحملة ثم تعيد قراءتها تحت الجلسة الجديدة. رمز الحساب يمر عبر `flutter_secure_storage` ويُستعاد بالتحقق من `/v1/auth/me`؛ اختبار Flutter 11/11 و`flutter analyze` بلا ملاحظات. Android مضبوط على API 23. **لم يكتمل بناء Windows:** Visual Studio Build Tools يفتقد ATL (`atlstr.h`) المطلوب من الإضافة، ومحاولة إضافة المكوّن لم تُثبته؛ يجب إصلاح مكوّن البناء ثم إعادة `flutter build windows --debug` قبل اعتبار خطوة Windows مجربة. بناء الويب بدأ لكن لم يُحسم بعد.
- 2026-10-03: أضيف تحديد دائم لمحاولات الدخول عبر SQLite: خمس كلمات مرور خاطئة لكل حساب أو عنوان اتصال خلال 15 دقيقة، وحدّ إنشاء 30 حسابًا لكل اتصال في الساعة. تُخزن بصمات SHA-256 للمفاتيح بدل البريد أو IP الخام، ويرجع الخادم 429 و`Retry-After`. تحقق اختبار انقضاء النافذة ومجموعة Python الكاملة: 62 اختبارًا ناجحًا، و`compileall` و`git diff --check` ناجحان. لا يزال هذا حدًا أوليًا خلف خدمة loopback، وليس سياسة كافية وحده لخدمة عامة.
- 2026-10-03: أضيفت قائمة سماح جذور لمساحات العمل على مستوى الخدمة؛ اختيار المجلد يتطلب أن يقع داخل جذر يحدده المسؤول في `SOVEREIGNAI_ALLOWED_WORKSPACES`. اختُبر رفض المسار الخارجي وقبول المسار الداخلي، ونجحت مجموعة Python الآن بـ63 اختبارًا مع `compileall` و`git diff --check`. ما زال ربط الجذر بالحساب مستقلًا مطلوبًا.
- 2026-10-03: أضيفت شاشة Flutter للحساب (إنشاء/دخول/خروج)، وعند تبديل الهوية تمسح المحادثات المحملة ثم تعيد قراءتها تحت الجلسة الجديدة. رمز الحساب يمر عبر `flutter_secure_storage` ويُستعاد بالتحقق من `/v1/auth/me`؛ اختبار Flutter 11/11 و`flutter analyze` بلا ملاحظات. Android مضبوط على API 23. ثُبت مكوّن ATL ثم نجح `flutter build windows --debug`، وأُطلقت نسخة Windows Debug متصلة بخادم تجريبي على `127.0.0.1:8100` وقاعدة `.live-api-data`؛ فحص `/health` أعاد HTTP 200. لم أتحقق من التفاعل المرئي للشاشة بعد.
- 2026-10-03: عُزلت مساحة العمل حسب الحساب عبر `SOVEREIGNAI_USER_WORKSPACES`؛ يتحقق الخادم من أن كل مسار داخل جذور المسؤول، ويرفض الجذور المتداخلة أو غير المخصصة، مع تحويل المنع إلى HTTP 403. أضيفت تغطية لحسابين وجذور منفصلة. تحقق API حي منفصل على 8100: إنشاء جلسة loopback ثم إرسال تحية عربية إلى `POST /v1/chat/completions` عبر Gemma 4 أعاد ردًا وHTTP 200. فحص `/health` أيضًا HTTP 200. هذا يثبت API والنموذج؛ اتصال نافذة Flutter بهذا المنفذ لم يُثبت، ولا تسجل الخدمة طلبًا صادرًا من التطبيق حتى الآن. تحديث الاختبارات الكامل لم يُعَد في هذه الجولة لأن `pytest` غير موجود في بيئة Python المتاحة، و`unittest discover` لا يشغل اختبارات pytest ويصطدم بإنشاء ملفات مؤقتة خارج مساحة العمل. الاختبار الكامل السابق كان 65 اختبارًا ناجحًا قبل هذا التغيير الصغير في معرّف المستخدم المحلي؛ يلزم إعادة تشغيل pytest في بيئة مناسبة.
- 2026-10-03: حد الدخول محفوظ في SQLite: خمس كلمات مرور خاطئة لكل حساب أو اتصال خلال 15 دقيقة، وحدّ إنشاء 30 حسابًا لكل اتصال في الساعة. تُخزن بصمات SHA-256، ويرجع API حالة 429 و`Retry-After`. أضيفت الآن جذور منفصلة لكل حساب بإعداد `SOVEREIGNAI_USER_WORKSPACES`؛ طلب API أكد أن الحساب لا يختار مساحة حساب آخر، والجذور المتداخلة مرفوضة. مجموعة Python كاملة 65/65، و`compileall` و`git diff --check` ناجحان.
## المرحلة 1 — تجربة المحادثة
@@ -66,14 +66,15 @@
- [x] ربط CRUD المحادثات والتقييم بهوية الجلسة، والتحقق من أن حسابًا ثانيًا لا يقرأ محادثة الحساب الأول.
- [x] فرض Bearer على جميع عمليات `/v1` الخاصة وإرسال الجلسة من Flutter للمحادثة/الوكيل/الملفات/المعرفة/البحث والصوت؛ فحص OpenAPI يضمن ألا توجد عملية خاصة بلا HTTP Bearer.
- [x] عزل فهرس المعرفة وسجل التدقيق بمعرّف الحساب، وربط رمز معاينة تعديل الملفات بصاحبها؛ اختبار API أثبت عدم استرجاع حساب لمحتوى فهرسه حساب آخر.
- [ ] ربط جذور مساحة العمل بكل حساب على حدة، وإزالة صلاحيات FastAPI العامة عن ملفات المضيف قبل السماح بعميل شبكي أو خدمة مستضافة.
- [x] إضافة قائمة سماح على مستوى الخادم عبر `SOVEREIGNAI_ALLOWED_WORKSPACES`؛ يرفض API الآن أي مجلد خارج الجذور المعتمدة عند ضبطها. هذا يقلل الوصول إلى المضيف لكنه لا يعزل حسابين داخل الجذر نفسه، ولا يغني عن إعدادها في كل خدمة تشغيل.
- [x] ربط جذور مساحة العمل بالحساب عبر إعداد مسؤول الخدمة `SOVEREIGNAI_USER_WORKSPACES` (بريد الحساب ← مسارات مخصصة تحت القائمة العامة)؛ يرفض API الحساب الذي لا يملك تخصيصًا، ويرفض المسارات المتداخلة بين الحسابات. اختبار API أكد أن لكل حساب جذره فقط (2026-10-03).
- [ ] عزل عملية FastAPI عن ملفات المضيف غير المصرح بها على مستوى نظام التشغيل قبل السماح بعميل شبكي أو خدمة مستضافة؛ القائمة البرمجية وحدها لا تحد صلاحيات العملية نفسها.
- [x] إضافة قائمة سماح على مستوى الخادم عبر `SOVEREIGNAI_ALLOWED_WORKSPACES`؛ يرفض API أي مجلد خارج الجذور المعتمدة. مع `SOVEREIGNAI_USER_WORKSPACES` يطبق الخادم كذلك حدود جذور كل حساب. لا يغني ذلك عن عزل صلاحيات عملية FastAPI على مستوى نظام التشغيل.
- [x] بناء واجهة إنشاء الحساب/الدخول والخروج وربطها بجلسات API؛ عند تبديل الحساب تمسح الواجهة الحالة المحلية ثم تعيد تحميل المحادثات والمهارات تحت الهوية الجديدة.
- [x] حفظ رمز الحساب عبر `flutter_secure_storage` في مخزن النظام على المنصات المدعومة، واستعادة `/v1/auth/me` عند بدء التطبيق؛ Android مضبوط على API 23 كحد أدنى. تخزين الويب تجريبي ويعتمد على المتصفح، لذلك لا يُعامل كحماية نظام تشغيل.
- [ ] إضافة حدود لمحاولات الدخول/التسجيل وتدفق استعادة كلمة المرور واختبار نشر محلي عبر TLS قبل الوصول الشبكي.
- [x] حد أولي دائم لتخمين كلمات المرور وإنشاء الحسابات في SQLite مع نافذة انتهاء و`Retry-After`؛ يلزم اختبار API كامل ومراجعة الحدود تحت reverse proxy موثوق قبل أي نشر خارجي.
- [ ] إضافة تدفق استعادة كلمة المرور واختبار نشر محلي عبر TLS قبل الوصول الشبكي.
- [x] حد أولي دائم لتخمين كلمات المرور وإنشاء الحسابات في SQLite مع نافذة انتهاء و`Retry-After`؛ اختبرته مجموعة Python كاملة، وتبقى مراجعة الحدود تحت reverse proxy موثوق قبل أي نشر خارجي.
- [ ] تهيئة تخزين آمن للحساب على الويب أو تعطيل حفظ الرمز هناك؛ التحقق من متطلبات Linux keyring وWindows/macOS على منصات بناء فعلية.
- [ ] تثبيت/تفعيل مكوّن C++ ATL في Visual Studio Build Tools وإعادة بناء Windows؛ المحاولة بتاريخ 2026-10-03 ما زالت تُظهر الخطأ `atlstr.h` المفقود.
- [x] تثبيت مكوّن C++ ATL في Visual Studio Build Tools؛ تحقق وجود `atlstr.h` ونجح `flutter build windows --debug` (2026-10-03).
- تصميم بيانات المستخدمين والمحادثات والمرفقات ونسخ الإجابات مع ملكية واضحة وفهارس وترحيلات قاعدة بيانات.
- SQLite مناسب لنسخة محلية أحادية الجهاز. عند تشغيل خدمة لعدة مستخدمين/أجهزة، ننتقل إلى PostgreSQL، مع نسخ احتياطية وسياسة حذف وتصدير.
- تخزين الملفات الكبيرة في مساحة ملفات منظّمة، وحفظ بياناتها الوصفية ومراجعها في قاعدة البيانات، لا في سجل الرسائل ككتل ضخمة.