Lolly
افتح التطبيق

نقل البيانات - حزمة lolly-backup

كل ما يجمعه مستخدم Lolly يعيش على جهازه - بلا حساب، بلا سحابة. حزمة نقل البيانات هي وسيلة انتقال تلك القيمة: صدّرها من تثبيت واحد، واحمل الملف بأي وسيلة (USB، AirDrop، بريد إلكتروني لنفسك، مشاركة شبكية) واستورده في تثبيت آخر. الملف هو وسيلة النقل. يمكن أن تكون الوجهة غير متصلة أو متصلة بالإنترنت. لا فرق، لأن لا شيء يتواصل مع خادم على الإطلاق.

الزران اللذان ينقلان تثبيتا كاملا: تصدير بياناتي يكتب ملفا مضغوطا واحدا، واستيراد بيانات يقرأه من جديد signed by Lollyvector SVG9 paths~4.9k nodes11 groups56 KBتحقق بنفسكاحصل على الملف الموقَّعالزران اللذان ينقلان تثبيتا كاملا: تصدير بياناتي يكتب ملفا مضغوطا واحدا، واستيراد بيانات يقرأه من جديد signed by Lollyvector SVG9 paths~4.9k nodes11 groups56 KBتحقق بنفسكاحصل على الملف الموقَّع

هذه الصفحة هي مواصفة التنسيق. لدليل المستخدم النهائي راجع ابحث عن عملك واستعده → نقل عملك إلى جهاز آخر. التنفيذ موجود في shells/web/src/data-transfer.ts، ويثبّت tests/data-transfer.test.ts عقد الذهاب والإياب.

النطاق. تحمل الحزمة بيانات المستخدم، لا أدوات الكتالوج. تُزامن أدوات الكتالوج وأصوله بشكل منفصل، ويُفترض أنها موجودة بالفعل على الجهاز الهدف (في أسوأ الحالات بإصدار أحدث)؛ أما الأدوات التي صنعها المستخدم بنفسه فتنتقل داخل profile.json. لا يقوم الاستيراد أبدا بتثبيت أداة كتالوج أو ترقيتها.

الأهداف

المغلّف

الحزمة ملف .zip عادي. يُسمّى التنزيل باسم الشخص الذي يخصّه - LollyTools-<First>-<Last>-<YYYY-MM-DD>-<n>.zip (على سبيل المثال LollyTools-Ada-Lovelace-2026-06-26-1.zip) - بحيث يبقى مجلد التنزيلات المليء بالنسخ الاحتياطية مقروءا. يأتي الاسم الأول والأخير من الملف الشخصي ويُحذفان عندما لا يكونان مضبوطين. عدم وجود ملف شخصي يعطي LollyTools-2026-06-26-1.zip، والاسم الأول وحده يعطي LollyTools-Ada-2026-06-26-1.zip. يُنقّى كل جزء إلى رمز آمن لاسم الملف (تُبقى حروف وأرقام Unicode، وتُحذف المسافات وعلامات الترقيم، بحد أقصى 32 حرفا). <n> تسلسل يومي لكل جهاز، بحيث لا تتصادم الصادرات المتكررة في اليوم نفسه وتبقى مرتبة. تبني backupFilename() في shells/web/src/data-transfer.ts الاسم. محتويات ملف zip متطابقة بصرف النظر عن الاسم. بداخله:

Pathمطلوبالمحتوى
manifest.jsonنعممعرّف التنسيق، والإصدارات، والأعداد، وسلامة كل جزء. أول شيء ينظر إليه القارئ.
profile.jsonعند ضبطهسجل me الخاص بالمستخدم بأكمله: الاسم، وجهة الاتصال، ومرجع الصورة الشخصية، والأعلام، إضافة إلى المجلدات، وسلة المهملات، ومخططات المشاريع، وقوالب المستخدم والأدوات التي صنعها، والمفضلة، والأدوات المخفية، واختيار اللغة والرموز التعبيرية. يُقرأ عبر host.profile.
sessions.jsonنعمكل جلسة محفوظة: الفتحة، معرّف/إصدار الأداة، التسمية، الصورة المصغّرة (data-URL) وكامل بيانات الإدخال. تُقرأ عبر host.state.
assets.jsonنعمبيانات وصفية لكل أصل مرفوع (صور، وخطوط، ورموز العلامة التجارية، وشعارات، ونسخ محفوظة من التنزيلات)، يشير كل منها إلى بايتاته تحت assets/blobs/.
assets/blobs/<n>.<ext>لكل أصلبايتات الأصل الخام (ملفات الصور والخطوط). تُخزَّن غير مضغوطة (تنسيقات مضغوطة أصلا). الامتداد تجميلي فقط. نوع MIME في assets.json هو المرجع الموثوق.
assets/blobs/<n>.c2paعند وجودهبيانات Content Credentials المستخرجة كبايتات ثنائية دقيقة، يشير إليها _credentialFile في سجل الأصل. وهذه ليست مفاتيح توقيع الجهاز.
design-systems.jsonعند وجودهأنظمة التصميم المصنوعة أو المضافة على هذا التثبيت، بصيغة { active, records }. تُدمج حسب المعرّف عند الاستيراد؛ ولا يُطبَّق اختيار الحزمة النشط إلا حين لا يملك الجهاز الهدف نظام تصميم خاصا به.
file-history.jsonاختياريلقطات إصدارات للأصول، وتقارير عمليات ملفات منتهية، وبيانات دفعات كاملة. يملك جزء السجل إصداره الخاص؛ يوفّره محوّل النسخ الاحتياطي الداخلي fileHistory الخاص بالقشرة.
revision-history.jsonاختياري، النسخ الاحتياطية اليدويةمعرّفات إنشاء ثابتة، ونقاط تفتيش محتفَظ بها، وصور مصغّرة، ومسودات استعادة متجددة. يوفّرها host.state.history.backup حيث يُدعم ذلك.
file-history/versions/لكل لقطةبايتات الأصل السابقة وبيانات الاعتماد المستخرجة، بصرف النظر عن استمرار وجود الأصل الحالي.
file-history/results/لكل عملية مكتملةبايتات الخرج الدقيقة. لا يُحتفظ بأي ملف أصلي اختير للتحويل ولا يُدرَج.
prefs.jsonنعمتفضيلات محلية يملكها المستخدم: theme، وsidebarWidth، وعدّاد نشاط ct-metrics.
lolly.txtنعمملخص مقروء للبشر عن الحزمة (الأعداد، الملف الشخصي، اسم الملف) لأي شخص يفتح ملف zip دون Lolly. يُعاد توليده مع كل تصدير ويُتعرَّف عليه عند الاستيراد، لذا لا يُحتسب أبدا كجزء متخطى. يُكتب بعد خريطة السلامة، لذا يبقى خارجها.

الحزمة ملف zip عادي عن قصد: تنجو سليمة من أي وسيلة نقل، ويمكن لأي أداة فك ضغط فحصها.

profile.json هو أصغر جزء والجزء الذي يراه القارئ أولا في التطبيق: التفاصيل التي يملؤها المُنشئ مرة واحدة، بالإضافة إلى الموافقة التي تسمح للأدوات باستخدامها.

نموذج تفاصيل الملف الشخصي الذي يصبح profile.json: الاسم، وبيانات التواصل، والصورة الشخصية signed by Lollyvector SVG15 paths~1.2k nodes30 groups1 image40 KBتحقق بنفسكاحصل على الملف الموقَّع

manifest.json

{
  "format": "lolly-backup",
  "formatVersion": 3,
  "minReader": 1,
  "app": "lolly",
  "exportedAt": "2026-06-22T09:30:00.000Z",
  "counts": { "profile": true, "sessions": 2, "userAssets": 4, "prefs": 3, "assetVersions": 1, "fileOperations": 1 },
  "integrity": {
    "profile.json": "sha256-…",
    "sessions.json": "sha256-…",
    "assets.json": "sha256-…",
    "assets/blobs/0.bin": "sha256-…",
    "file-history.json": "sha256-…",
    "file-history/versions/0.bin": "sha256-…",
    "file-history/results/0.bin": "sha256-…",
    "prefs.json": "sha256-…"
  }
}
الحقلالمعنى
formatدائما lolly-backup. يُرفض الملف الذي يفتقده باعتباره "ليس نسخة احتياطية من Lolly".
formatVersionالتخطيط الذي كُتبت به هذه الحزمة. يُرفع عند أي تغيير في مجموعة الأجزاء أو أشكالها. لا يستند القارئ إليه في القرار.
minReaderالحد الأدنى لإصدار القارئ اللازم لاستيراد هذه الحزمة بأمان. هذا هو الحقل الذي يستند إليه القارئ في القرار.
appمعرّف التطبيق المُنتِج، للتشخيص.
exportedAtالطابع الزمني ISO الذي أُنشئت فيه الحزمة.
countsما وضعه الكاتب، للعرض والتحقق من السلامة.
integrityاختياري. يربط كل جزء عدا manifest.json بملخّص (digest) بنمط SRI ‏sha256-<base64> لبايتاته غير المضغوطة.

سياسة الإصدارات (التوافق المستقبلي)

الفصل بين formatVersion وminReader هو ما يسمح للتنسيق بالنمو دون التخلي عن التثبيتات الأقدم:

قاعدة عملية للمؤلفين: إذا كان كل قارئ موجود سيتصرف بشكل صحيح رغم تجاهل إضافتك، فهي إضافية - ارفع formatVersion واترك minReader. وإلا فارفع minReader.

السلامة

عندما يكون manifest.integrity موجودا، يتحقق القارئ من SHA-256 لكل جزء مُدرج قبل كتابة أي شيء. عدم التطابق ("failed its integrity check") أو غياب جزء ("incomplete") يُلغي الاستيراد بأكمله - لا استعادة جزئية. يلتقط هذا التلف الذي قد تُحدثه وسيلة نقل الملف (عملية AirDrop مبتورة، بوابة بريد إلكتروني أعادت ترميز المرفق، قطاع USB تالف).

السلامة مبذولة على أساس أفضل جهد بالتصميم: تُكتب فقط حيث تتوفر Web Crypto (كل سياق متصفح آمن وكل Node حديث)، وتُتحقَّق منها فقط عندما تتوفر الخريطة وWeb Crypto معا. تُستورَد الحزمة الخالية من الخريطة - مثلا حزمة من قبل وجود السلامة - دون تغيير. "لا يمكن التحقق" لا تُعامَل أبدا كـ"تالفة".

لا يُدرج البيان نفسه ولا ملف lolly.txt التمهيدي المُعاد توليده. تغطي الملخصات (digests) الأجزاء التي يكفلها البيان.

دلالات الاستيراد

الاستيراد دمج، وليس استبدالا كليا أبدا:

تُعيد الجلسات المحفوظة الربط بصورها تلقائيا: تُحفظ إشارات الأصول بالمعرّف، ويُعيد الجسر تحليلها بعد استعادة الصور المرفوعة (وهو مضطر لذلك على أي حال، لأن روابط blob: لا تنجو من إعادة التحميل).

يُبلّغ ملخص الاستيراد عن { profile, sessions, userAssets, prefs, skipped, failedAssets }. يحسب failedAssets الأصول المرفوعة التي تعذّرت استعادتها (امتلاء تخزين الجهاز، مثلا). وهو متمايز عن skipped، الذي يحسب الأجزاء من كاتب أحدث متوافق مستقبليا لم يتعرف عليها هذا الإصدار. تُظهر الواجهة skipped ("… · N newer items skipped")، بحيث تكون الاستعادة صادقة بشأن ما تركته وراءها.

عند وجود سجل الملفات، يحمل الملخص أيضا assetVersions وfileOperations وfailedHistory. وقد يتسبب نفاد التخزين أو تعارضات المعرّفات غير القابلة للتغيير في استعادة جزئية؛ وتخبر الواجهة المستخدم بالاحتفاظ بالنسخة الاحتياطية المصدر. ولا تُقدّم المزامنة السحابية مراجعتها المطبَّقة بعد استعادة جزئية أو غير مدعومة، فتبقى اللقطة متاحة لإعادة المحاولة. والاستعادة ليست معاملة واحدة عبر كل مخازن الملف الشخصي/الجلسة/الأصل/السجل.

سجل الإنشاء (v3)

تتضمن النسخ الاحتياطية اليدوية من مضيف ويب يدعم السجل ملف revision-history.json بمخطط خاص به هو { version: 1, documents, revisions, recoveries }. ويحمل المعرّفات المحتفَظ بها، ولقطات الإدخال القياسية، وطوابع الإصدار، والمعاينات النقطية، ومسودات الكاتب المنفصلة. ويلتقط محوّل السجل الجلسات الحالية ورؤوسها في معاملة قراءة واحدة؛ ويستخدم sessions.json تلك اللقطات الحالية نفسها للقراء الأقدم.

تتحقق الاستعادة من SHA-256 للحمولة وعدد البايتات، والهويات الفريدة، وعلاقات المستند/الرأس، والنسب، والطوابع الزمنية، وأنواع المعاينة، والحدود، قبل تثبيت الأرشيف في معاملة واحدة. وقد تكون مراجع الأصل المضغوطة غائبة. ولا يُستبدَل العمل الحالي الموجود أبدا بصمت: حين يوجد إنشاء في الطرفين، يصبح الطرف غير المحتفَظ به كحالي مسودة محمية. ويُتحقق صراحة من حد النقل البالغ 384 ميبيبايت للأرشيف، وتُفرض حدود التخزين دون اقتطاع نقاط التفتيش المحتفَظ بها. ولا يزال النسخ الاحتياطي الكلي يستخدم تنفيذ ZIP في الذاكرة وليس أرشيفا يبثّ تدريجيا.

يضيف الملخص revisions وrecoveryDrafts، فيحسب فقط ما أضافه هذا الاستيراد، وadded وkept وreplaced وcopies وhidden لبيان كيف دُمج كل إنشاء. وتستعيد القشرة التي تفتقر إلى هذه القدرة الجلسات العادية فقط وتُبلغ عن جزء السجل بأنه متخطى. ويبقى سجل نظام الملفات الأصلي غير مدعوم إلى أن يوفّر محوّله معاملات سجل دائمة. ولا تملك حالة الضيف في P2P أي سجل دائم أو أرشيف استعادة.

تستثني مزامنة اللقطة الشخصية سجل الإنشاء صراحة. وتطبيق لقطة على مستند محلي يحمل سجلا يحفظ حالة عمله السابقة كمسودة استعادة منفصلة، ويُبطل رمز الكتابة الخاص بأي محرر مفتوح. وتبقى نقاط تفتيشه غير القابلة للتغيير على الجهاز. وهذا يحمي السجل المحلي أثناء استبدال اللقطة؛ ولا يدمج سجلات أجهزة متزامنة.

تُحفظ إشارات الأصول التاريخية، بينما لا يزال العرض يحلّ الأصول عبر مكتبة الوجهة الحالية. ولا يضمن هذا الأرشيف بعد بايتات الأصل القديمة الدقيقة أو عمليات عرض الأداة القديمة. وتستمر بايتات إصدار الأصل ونتيجة الملف في الانتقال عبر جزء النسخ الاحتياطي المنفصل الحالي الخاص بها.

الإصدارات المحفوظة ونتائج الملفات (v2)

يحتوي جزء السجل الاختياري على { version: 2, assetVersions: [...], operations: [...], batches: [...] }؛ ويقبل القراء أيضا شكل history-v1 الأقدم دون الدفعات. وتُعرِّف كل لقطة معرّف الأصل الثابت وإصداره الدقيق، ووقت حفظه، وطول بايتاته، و SHA-256 السداسي، إضافة إلى سجل أصل يشير حقلاه _file و_credentialFile الاختياري إلى أجزاء ثنائية. وتحمل العمليات حقائق الملف الأصلي، والطلب، والتقرير، والطوابع الزمنية، وحقل _file الاختياري للنتيجة؛ ولا تنتقل أسماء أنظمة التخزين الخلفية، ولا مقابض OPFS، ولا عقود التنفيذ. ويرفض القراء الأقدم من نوع history-v1 فقط إصدار السجل الجديد قبل الاستيراد، بدل إسقاط عضوية الدفعة بصمت.

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

ولا يزال بإمكان القراء الأقدم قبول مغلّف v2 (minReader: 1) واستعادة الأجزاء المألوفة، مع احتساب أجزاء السجل غير المدعومة كمتخطاة. وتتطلب الاستعادة الكاملة للسجل قشرة تملك محوّل fileHistory؛ وهذا خط تماس داخلي للقشرة، لا قدرة جديدة تواجه الأداة في HostV1. وتغطي بوابة Chromium المحلية الاستعادة الحقيقية بين جهازين؛ ويبقى قبول استعادة Tauri/iOS/Android المثبَّتة منفصلا.

ما لا ينتقل

يفصّل مقياس التخزين الانقسام نفسه. تنتقل الجلسات المحفوظة وMy images ونتائج الملفات وإصداراتها داخل الحزمة. أما ذاكرة الأصول المؤقتة ومعاينات الأدوات والتثبيتات غير المتصلة أسفلها فكلها قابلة لإعادة الاشتقاق، لذا تبقى خلفا.

مقياس التخزين يقسّم بيانات هذا الجهاز إلى فئات مسمّاة، مع تتبّع Saved sessions وMy images بشكل منفصل عن Asset cache، هنا في تثبيت جديد حيث لا تزال كل فئة فارغة signed by Lollyvector SVG37 paths~4.9k nodes85 groups65 KBتحقق بنفسكاحصل على الملف الموقَّعمقياس التخزين يقسّم بيانات هذا الجهاز إلى فئات مسمّاة، مع تتبّع Saved sessions وMy images بشكل منفصل عن Asset cache، هنا في تثبيت جديد حيث لا تزال كل فئة فارغة signed by Lollyvector SVG37 paths~4.9k nodes85 groups65 KBتحقق بنفسكاحصل على الملف الموقَّع

ضمان عبر القشرات

لا تقرأ وحدة data-transfer.ts وتكتب إلا عبر جسر القدرات (host.profile، وhost.state، وhost.assets) وتفضيلات localStorage المشتركة. وتقرأ الوحدة نفسها المغلّف المشترك وتكتبه على الويب وTauri، فوق تخزين IndexedDB أو نظام الملفات. ولا تظهر أجزاء السجل الاختيارية إلا حيث يتوفر المحوّل المطابق؛ ويُبلَّغ عن الجزء غير المدعوم كمتخطى عند الاستيراد. وتُمرِّن مجموعة الاختبارات غير المرئية (headless) الأجزاء المشتركة مقابل جسر في الذاكرة، بينما تملك معاملات السجل أيضا اختبارات متصفح حقيقية.

يقع غلافان خارج هذا الضمان، لأسباب مختلفة:

نقاط امتداد محجوزة

المغلف عبارة عن بيان إضافة إلى مجموعة من الأجزاء المسماة بالتصميم، بحيث يمكن لأنواع جديدة من البيانات القابلة للنقل أن تُحمل عليه لاحقا دون تغيير جذري (breaking change). تُدرج كأجزاء إضافية (formatVersion جديد، ونفس minReader)، ويتجاهل القارئ الحالي ما لا يتعرف عليه. ولم تُبنَ هذه الأجزاء بعد. الأسماء محجوزة هنا حتى يبقى التنسيق متسقا عند إضافتها.

أي شيء خارج هذه الأسماء المحجوزة والأجزاء أعلاه يُعامله القارئ كجزء غير معروف: يُترك دون مساس ويُحسب ضمن skipped.

مرجع