تخطَّ إلى المحتوى

النسخ الاحتياطي والتصدير والاستيراد

كل ما يستطيع Control Center نسخه أو تسليمه أو اعتماده، والشكل الدقيق لكل ناتج. لأخذ نسخة فعلًا، انظر النسخ الاحتياطي والاستعادة؛ ولماذا ينقسم التخزين على هذا النحو، انظر مساحات العمل والعزل.

ثلاثة نواتج لنسخ قواعد البيانات، بنطاقات وسياسات حذف مختلفة.

الناتج يكتبه الشكل يغطي
لقطة التثبيت server.backupNow دليل بطابع زمني كل قاعدة بيانات على التثبيت
نسخ احتياطي لمساحة العمل خط أنابيب Workspace backup دليل بطابع زمني فيه ملف .db واحد قاعدة بيانات مساحة عمل واحدة
تصدير مساحة العمل workspace.export ملف .db واحد قاعدة بيانات مساحة عمل واحدة

تُكتب كلها بجملة VACUUM INTO في SQLite، وهي آمنة مع قاعدة WAL حيّة: تأخذ معاملة قراءة، وتنتج نسخة أُزيل تشتتها ومتسقة معامليًا، ولا تحتاج إلى إيقاف الخادم.

<dataDir>/backups/2026-07-28T09-12-33-000Z/
manifest.json
global.db
<workspaceId>/workspace.db one directory per workspace

يطابق التخطيط دليل البيانات الحي تمامًا، وهذا ما يجعل استعادة التثبيت نسخًا إلى الموضع لا ترجمة. اسم الدليل هو الطابع الزمني بتوقيت UTC بعد استبدال : و. بـ -، فيصلح على نظام ملفات Windows ويُرتَّب زمنيًا كنص عادي.

نسخ مساحات العمل المجدولة تعيش على حدة في <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db. لا تحمل ملف بيان ولا global.db وليست لقطات تثبيت. خطوة الاحتفاظ في خط الأنابيب الأسبوعي تحذف فقط نسخ مساحة العمل نفسها الأقدم من العمر المضبوط (30 يومًا افتراضيًا)؛ ولا يشمل دوران تلك الخطوة لقطات التثبيت المنشأة يدويًا. يسرد server.listBackups لقطات التثبيت فقط، بما فيها غير المكتملة.

الحقل النوع المعنى
version عدد صحيح إصدار صيغة البيان. حاليًا 1
created_at ISO-8601 UTC وقت التقاط اللقطة
global.file سلسلة نصية دائمًا global.db
global.schema_version عدد صحيح إصدار مخطط GlobalDatabase وقت الالتقاط
global.bytes عدد صحيح حجم global.db المكتوب
workspace_schema_version عدد صحيح إصدار مخطط WorkspaceDatabase المشترك بين كل ملفات مساحات العمل
workspaces[] مصفوفة مدخل واحد لكل مساحة عمل التُقطت
workspaces[].workspace_id سلسلة نصية مساحة العمل التي يحملها هذا الملف
workspaces[].file سلسلة نصية مسار نسبي من جذر اللقطة، <workspaceId>/workspace.db
workspaces[].bytes عدد صحيح حجم ذلك الملف
skipped_workspaces[] مصفوفة من سلاسل نصية مساحات العمل التي تعذّر التقاطها

تُتخطى مساحة العمل حين تكون مسجّلة ولم يُكتب إليها قط (فلا ملف بعد)، أو حين فشل VACUUM INTO الخاص بها. في الحالتين تكتمل اللقطة ويسمّي البيان ما ينقص.

يبلّغ server.listBackups بعلامة complete لكل لقطة. تكون خاطئة حين يغيب البيان أو يتعذّر تحليله، أو حين يغيب global.db، أو حين يسمّي البيان ملف مساحة عمل غير موجود على القرص.

تبقى اللقطة غير المكتملة مدرجة، لأن لقطة لا يراها المشغّل هي لقطة يظن أنه يملكها. حين يتعذّر قراءة البيان يرجع السرد إلى التخطيط نفسه ويبلّغ بأي ملفات <workspaceId>/workspace.db يجدها. تبقى تلك الملفات قابلة للاعتماد فرادى عبر workspace.import وإن كانت اللقطة كلها لا تستطيع استعادة تثبيت.

ما لا تحتويه النسخة الاحتياطية

قسم بعنوان “ما لا تحتويه النسخة الاحتياطية”

الناتجان كلاهما قواعد بيانات فقط. يحمل دليل مساحة العمل أكثر من قاعدتها، ولا ينتقل شيء من الباقي:

المسار في اللقطة؟ في تصدير مساحة العمل؟
global.db نعم لا
<workspaceId>/workspace.db نعم نعم (هو الملف نفسه)
<workspaceId>/blobs/ لا لا
<workspaceId>/skills/ لا لا
<workspaceId>/agents/ لا لا
<workspaceId>/chat_credentials/ لا لا
<workspaceId>/spaces/<spaceId>/ لا لا
<workspaceId>/pr_clones/ لا لا
secrets.json لا لا
models/ لا لا
meetings/<meetingId>/ لا لا
rigs/ لا لا

بعض ذلك يُستغنى عنه: يحمل spaces/ أشجار عمل بالنسخ عند الكتابة تُعاد تجهيزها من المستودعات، وpr_clones/ ذاكرة تخزين مؤقت، وmodels/ يُعاد تنزيله، وrigs/ حالة الآلة. وبعضه لا: يحمل blobs/ الصور الملصقة التي تشير إليها صفوف القاعدة، ويحمل skills/ وagents/ الملفات التي يعمل بها الوكيل، ويحمل secrets.json كل مفتاح اقتران وبيانات اعتماد مزوّد وإعداد SSO على التثبيت. انظر النسخ الاحتياطي والاستعادة لتغطية الباقي.

استدعاءات نسخ التثبيت الاحتياطي وتصدير مساحة العمل واستيرادها تقتصر على fullClient: الهاتف المقترن لا يستطيع إطلاقها. كلها غائبة تمامًا، لا مرفوضة بل مفقودة بنيويًا، على خادم بلا منفذ نسخ احتياطي موصول، كالخادم التجريبي.

العملية النوع النطاق الحد الأدنى للدور الوسائط ما يُعاد
server.backupNow تعديل التثبيت مالك التثبيت لا شيء {ok, path}
server.listBackups قراءة التثبيت مالك التثبيت لا شيء {backups: [...]}
server.deleteBackup تعديل التثبيت مالك التثبيت name {ok}
workspace.export قراءة مساحة العمل admin لا شيء {ok, path}
workspace.import تعديل مساحة العمل owner source_path {ok, workspace_id}
workspace.delete تعديل التثبيت* owner id صف السجل معلَّم محذوفًا
  • workspace.delete بلا نطاق لأن الصف الذي يعلّمه يعيش في السجل العام؛ ويتحقق معالجه من عضوية المستدعي في مساحة العمل المسماة ويشترط owner.

path في كل استجابة مسار على مضيف الخادم.

الأحدث أولًا، مرتبة باسم الدليل (وهو الطابع الزمني، فيثبت الترتيب حتى للقطة تعذّر قراءة بيانها).

{
"backups": [
{
"path": "/…/backups/2026-07-28T09-12-33-000Z",
"name": "2026-07-28T09-12-33-000Z",
"created_at": "2026-07-28T09:12:33.000Z",
"bytes": 481203712,
"complete": true,
"workspaces": [
{
"workspace_id": "w_9f2c…",
"path": "/…/backups/2026-07-28T09-12-33-000Z/w_9f2c…/workspace.db",
"bytes": 190840832
}
],
"skipped_workspace_ids": []
}
]
}

يُغفل created_at حين يتعذّر قراءة البيان. bytes في المستوى الأعلى هو الحجم الحقيقي على القرص للدليل كله، لا مجموع البيان نفسه: السؤال الذي يطرحه مشغّل يقلّم اللقطات هو كلفة الدليل، لا ما نوى النسخ الاحتياطي كتابته.

كل workspaces[].path هو بالضبط ما يأخذه workspace.import في source_path. هذا مقصود: «استعد مساحة العمل هذه من هذه اللقطة» هي عملية الاستيراد، فلا يفترق الاثنان في معاملة الملف نفسه.

قبل استبدال أي شيء، يُفتح الملف المرشّح للقراءة فقط باتصال SQLite خام قصير العمر، وتُقرأ صف workspace_meta.

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

عند القبول تُغلق قاعدة مساحة العمل الهدف وتُسقط من المدير قبل نسخ الملف فوقها (اتصال Drift مفتوح يمسك الملف وملف -wal)، ثم تُعاد فتحها حتى يعيد beforeOpen تثبيت مشغّلات FTS والمزامنة، ويُعاد بناء فهارس FTS. جداول المحتوى في الملف المستورَد ممتلئة، لكن فهرسه قد يكون قديمًا.

كل عملية أعلاه تتكلم بمسارات على جهة الخادم، وهذا جواب كافٍ فقط حين يكون الخادم جهازك. هذه الثلاثة تحمل البايتات، على ممر PSK الموقَّع نفسه الذي يستخدمه وسيط الوسائط ومخزن الصور. يوقّع المستدعي سلسلة الهدف بمفتاح الجهاز المشترك مسبقًا ويمرّر التوقيع في s.

المسار الأسلوب الاستعلام الهدف الموقَّع يشترط
/backup/workspace GET w، d، s backup-workspace:<workspaceId> مسؤول مساحة العمل
/backup/snapshot GET n، d، s backup-snapshot:<name> مالك التثبيت
/backup/restore POST w، d، s backup-restore:<workspaceId> مالك مساحة العمل

w معرّف مساحة عمل، وn اسم دليل اللقطة، وd معرّف الجهاز المستدعي، وs التوقيع. يُحل n مقابل قائمة النسخ الاحتياطي بدل ضمّه إلى جذر النسخ، فلا يمكن توجيه المسار إلى دليل ما كانت القائمة لتظهره.

الحالة السبب
400 وسيط استعلام مطلوب مفقود، أو جسم الرفع فارغ
403 جهاز مجهول أو مُلغى، أو توقيع غير صالح، أو المستدعي بلا الدور
404 لا منفذ نسخ احتياطي على هذا المضيف، أو ملف اللقطة أو مساحة العمل المسمّى غير موجود
405 استُدعي /backup/restore بغير POST
413 جسم الرفع يتجاوز 8 GiB، بحسب content-length المعلَن أو البايتات المقروءة فعلًا
500 فشل التصدير أو الأرشفة على جهة الخادم

يرد كلا التنزيلين بـ Cache-Control: no-store مع Accept-Ranges: none. كل طلب ينشئ نسخة جديدة ويحذفها بعد بثّها، فاستجابة من الذاكرة المؤقتة أو مستأنفة تضم بايتات تصديرين مختلفين في ملف واحد يبدو سليمًا وليس كذلك.

يعيد /backup/snapshot ملف <name>.zip، والمدخلات نسبية من جذر اللقطة حتى يعيد فك الضغط manifest.json + global.db + <workspaceId>/workspace.db. تُكتب المدخلات بترتيب مفرز، فنسختان من أرشيف اللقطة نفسها أرشيف واحد.

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

الشيء القيمة
اللقطات <dataDir>/backups/<timestamp>/
نسخ مساحات العمل المجدولة <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db
تصديرات مساحات العمل <dataDir>/backups/exports/<workspaceId>-<timestamp>.db
ترحيل النقل <dataDir>/backups/transfer/ — منضدة عمل، يكنسها المسار الذي يكتب إليها
اسم أرشيف اللقطة <snapshot directory name>.zip
سقف الرفع 8 GiB لكل POST /backup/restore
الاحتفاظ لقطات التثبيت: حذف يدوي. نسخ مساحات العمل: خط أنابيب أسبوعي، والافتراضي 30 يومًا

أدلة exports/ وtransfer/ وworkspace-backups/ ليست لقطات تثبيت، وهي مستبعدة من server.listBackups. الدليل الأخير وحده له احتفاظ مجدول؛ وحذف لقطة تثبيت يحتاج فعلًا صريحًا من مالك التثبيت.