Lewati ke konten

Cadangan, ekspor, dan impor

Semua yang bisa disalin, diserahkan, atau diadopsi Control Center, beserta bentuk persis setiap artefaknya. Untuk benar-benar membuat cadangan, lihat Cadangkan dan pulihkan; untuk alasan persistensi dipisah seperti ini, lihat Ruang kerja dan isolasi.

Ada tiga artefak salinan basis data, dengan cakupan dan kebijakan penghapusan yang berbeda.

Artefak Ditulis oleh Bentuk Cakupan
Snapshot instalasi server.backupNow Direktori bertanda waktu Setiap basis data di instalasi
Cadangan ruang kerja Pipeline Workspace backup Direktori bertanda waktu dengan satu .db Basis data satu ruang kerja
Ekspor ruang kerja workspace.export Satu file .db Basis data satu ruang kerja

Semuanya ditulis dengan VACUUM INTO SQLite, yang aman terhadap basis data WAL yang aktif: perintah ini mengambil transaksi baca, menghasilkan salinan yang didefragmentasi dan konsisten secara transaksional, serta tidak pernah memerlukan penghentian server.

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

Tata letaknya mencerminkan direktori data aktif dengan persis, itulah yang membuat pemulihan sebuah instalasi sekadar menyalin kembali, bukan menerjemahkan. Nama direktorinya adalah stempel waktu UTC dengan : dan . diganti -, jadi aman untuk sistem berkas di Windows dan terurut secara kronologis sebagai string biasa.

Cadangan ruang kerja terjadwal berada terpisah di <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db. Cadangan itu tidak menyertakan manifest atau global.db dan bukan snapshot instalasi. Langkah retensi pipeline mingguan hanya menghapus cadangan ruang kerjanya sendiri yang lebih tua dari usia yang dikonfigurasi (bawaannya 30 hari); snapshot instalasi yang dibuat secara manual tidak pernah dipangkas oleh langkah itu. server.listBackups hanya mendaftarkan snapshot instalasi, termasuk yang tidak lengkap.

Kolom Tipe Arti
version int Versi format manifest. Saat ini 1
created_at ISO-8601 UTC Kapan snapshot diambil
global.file string Selalu global.db
global.schema_version int Versi skema GlobalDatabase pada saat perekaman
global.bytes int Ukuran global.db yang ditulis
workspace_schema_version int Versi skema WorkspaceDatabase yang sama untuk setiap file ruang kerja
workspaces[] array Satu entri per ruang kerja yang terekam
workspaces[].workspace_id string Ruang kerja yang dimuat file ini
workspaces[].file string Path relatif terhadap akar snapshot, <workspaceId>/workspace.db
workspaces[].bytes int Ukuran file itu
skipped_workspaces[] array of string Ruang kerja yang tidak bisa direkam oleh cadangan

Sebuah ruang kerja dilewati ketika ruang kerja itu terdaftar tetapi belum pernah ditulisi (jadi filenya belum ada), atau ketika VACUUM INTO-nya gagal. Dengan cara apa pun, snapshot tetap selesai dan manifest menyebutkan apa yang hilang.

server.listBackups melaporkan flag complete per snapshot. Flag itu bernilai false ketika manifest tidak ada atau tidak bisa diurai, ketika global.db hilang, atau ketika manifest menyebut file ruang kerja yang tidak ada di disk.

Snapshot yang tidak lengkap tetap didaftarkan, karena snapshot yang tidak bisa dilihat operator adalah snapshot yang mereka yakini mereka miliki. Ketika manifest tidak bisa dibaca, daftar itu beralih ke tata letak itu sendiri dan melaporkan file <workspaceId>/workspace.db apa pun yang ditemukannya — file-file itu tetap bisa diadopsi satu per satu melalui workspace.import meskipun snapshot secara keseluruhan tidak bisa memulihkan instalasi.

Kedua artefak itu hanya basis data. Direktori ruang kerja memuat lebih dari sekadar basis datanya, dan tidak ada bagian lain yang ikut berpindah:

Path Ada di snapshot? Ada di ekspor ruang kerja?
global.db Ya Tidak
<workspaceId>/workspace.db Ya Ya (itulah filenya)
<workspaceId>/blobs/ Tidak Tidak
<workspaceId>/skills/ Tidak Tidak
<workspaceId>/agents/ Tidak Tidak
<workspaceId>/chat_credentials/ Tidak Tidak
<workspaceId>/spaces/<spaceId>/ Tidak Tidak
<workspaceId>/pr_clones/ Tidak Tidak
secrets.json Tidak Tidak
models/ Tidak Tidak
meetings/<meetingId>/ Tidak Tidak
rigs/ Tidak Tidak

Sebagian dari itu bisa dibuang — spaces/ menyimpan worktree copy-on-write yang disediakan ulang dari repo, pr_clones/ adalah cache, models/ diunduh ulang, rigs/ adalah status mesin. Sebagiannya lagi tidak: blobs/ menyimpan gambar yang ditempelkan dan dirujuk baris-baris di basis data, skills/ dan agents/ menyimpan file yang dipakai agen untuk berjalan, dan secrets.json menyimpan setiap kunci pemasangan, kredensial penyedia, dan pengaturan SSO di instalasi. Lihat Cadangkan dan pulihkan untuk menutupi sisanya.

RPC cadangan instalasi dan ekspor/impor ruang kerja hanya untuk fullClient: ponsel yang dipasangkan tidak bisa memicunya. Semuanya sama sekali tidak ada — bukan ditolak, melainkan tidak ada secara struktural — pada server yang tidak memiliki port cadangan, seperti server demo.

Operasi Jenis Cakupan Peran minimum Argumen Hasil
server.backupNow mutasi Instalasi pemilik instalasi tidak ada {ok, path}
server.listBackups baca Instalasi pemilik instalasi tidak ada {backups: [...]}
server.deleteBackup mutasi Instalasi pemilik instalasi name {ok}
workspace.export baca Ruang kerja admin tidak ada {ok, path}
workspace.import mutasi Ruang kerja owner source_path {ok, workspace_id}
workspace.delete mutasi Instalasi* owner id baris pendaftaran ditandai terhapus
  • workspace.delete tidak bercakupan karena baris yang ditandainya berada di pendaftaran global; handler-nya memeriksa keanggotaan pemanggil pada ruang kerja yang disebut dan mewajibkan owner.

path di setiap respons adalah path di host server.

Terbaru lebih dulu, diurutkan berdasarkan nama direktori (yang merupakan stempel waktu, jadi urutannya tetap berlaku bahkan untuk snapshot yang manifest-nya tidak bisa dibaca).

{
"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 dihilangkan ketika manifest tidak bisa dibaca. bytes di tingkat teratas adalah ukuran nyata di disk dari seluruh direktori, bukan jumlah dari manifest itu sendiri — pertanyaan yang diajukan operator yang memangkas snapshot adalah berapa biaya direktori itu, bukan berapa yang dimaksudkan untuk ditulis oleh cadangan.

Setiap workspaces[].path persisnya adalah nilai yang diterima workspace.import sebagai source_path. Itu memang sengaja: “memulihkan ruang kerja ini dari snapshot ini” adalah operasi impor, jadi keduanya tidak bisa menyimpang menjadi perlakuan yang berbeda terhadap file yang sama.

Sebelum apa pun diganti, file kandidat dibuka dalam mode hanya baca dengan koneksi SQLite mentah yang berumur pendek dan baris workspace_meta-nya dibaca.

Kondisi Hasil
Bukan basis data SQLite yang bisa dibaca, atau tidak ada workspace_meta Ditolak. Tidak ada yang disentuh
Id ruang kerja yang tercatat ≠ target Diizinkan, dicatat di log. Beginilah ruang kerja diduplikasi atau dipulihkan dengan id baru
Id instalasi yang tercatat ≠ instalasi ini Diizinkan, dicatat di log. Perangkat yang dipasangkan dan id pengguna milik instalasi itu tidak akan dikenali di sini
Id ruang kerja tidak valid, atau file tidak ada Ditolak

Saat diterima, basis data ruang kerja tujuan ditutup dan dilepas dari pengelola sebelum file disalin menimpanya (koneksi drift yang terbuka memegang file itu beserta -wal-nya), lalu dibuka kembali sehingga beforeOpen memasang ulang pemicu FTS dan sinkronisasi, dan indeks FTS dibangun ulang — tabel konten file yang diimpor terisi, tetapi indeksnya mungkin sudah usang.

Setiap operasi di atas berbicara dalam path sisi server, yang merupakan jawaban lengkap hanya ketika server itu mesin Anda sendiri. Ketiga rute ini yang membawa byte-nya, di jalur bertanda tangan PSK yang sama dengan yang dipakai proksi media dan penyimpanan blob. Pemanggil menandatangani string target dengan kunci pra-bersama perangkatnya dan meneruskan tanda tangannya sebagai s.

Rute Metode Kueri Target bertanda tangan Memerlukan
/backup/workspace GET w, d, s backup-workspace:<workspaceId> admin ruang kerja
/backup/snapshot GET n, d, s backup-snapshot:<name> pemilik instalasi
/backup/restore POST w, d, s backup-restore:<workspaceId> pemilik ruang kerja

w adalah id ruang kerja, n nama direktori snapshot, d id perangkat pemanggil, s tanda tangannya. n diselesaikan terhadap daftar cadangan alih-alih digabungkan ke akar cadangan, sehingga rute itu tidak bisa diarahkan ke direktori yang tidak akan ditampilkan oleh daftar.

Status Penyebab
400 Parameter kueri yang diwajibkan hilang, atau isi unggahan kosong
403 Perangkat tidak dikenal atau dicabut, tanda tangan buruk, atau pemanggil tidak memiliki peran itu
404 Tidak ada port cadangan di host ini, atau snapshot/file ruang kerja yang disebut tidak ada
405 /backup/restore dipanggil dengan apa pun selain POST
413 Isi unggahan melebihi 8 GiB, baik menurut content-length yang dideklarasikan maupun menurut byte yang benar-benar dibaca
500 Ekspor atau arsip gagal di sisi server

Kedua unduhan merespons Cache-Control: no-store dengan Accept-Ranges: none. Setiap permintaan membuat salinan baru dan menghapusnya setelah dialirkan, jadi respons yang di-cache atau dilanjutkan akan menyambung byte dari dua ekspor berbeda menjadi satu file yang tampak valid padahal tidak.

/backup/snapshot mengembalikan <name>.zip, dengan entri relatif terhadap akar snapshot sehingga penguraiannya mereproduksi manifest.json + global.db + <workspaceId>/workspace.db. Entri ditulis dalam urutan terurut, jadi dua arsip dari snapshot yang sama adalah arsip yang sama.

/backup/restore mengalirkan isinya langsung ke file staging alih-alih menampungnya di buffer, membatasinya sebelum dan selama pembacaan, dan menghapus file yang di-staging pada setiap jalur keluar termasuk saat penolakan.

Hal Nilai
Snapshot <dataDir>/backups/<timestamp>/
Cadangan ruang kerja terjadwal <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db
Ekspor ruang kerja <dataDir>/backups/exports/<workspaceId>-<timestamp>.db
Staging transfer <dataDir>/backups/transfer/ — sebuah meja kerja, dibersihkan oleh rute yang menulisinya
Nama arsip snapshot <snapshot directory name>.zip
Batas unggahan 8 GiB per POST /backup/restore
Retensi Snapshot instalasi: penghapusan manual. Cadangan ruang kerja: pipeline mingguan, bawaan 30 hari

Direktori exports/, transfer/, dan workspace-backups/ bukan snapshot instalasi dan dikecualikan dari server.listBackups. Hanya direktori terakhir yang memiliki retensi terjadwal; menghapus snapshot instalasi memerlukan tindakan eksplisit dari pemilik instalasi.