Sari la conținut

Backup, export și import

Tot ce poate Control Center să copieze, să predea sau să adopte, și forma exactă a fiecărui artefact. Pentru a face efectiv un backup, vezi Backup și restaurare; pentru motivul pentru care persistența este împărțită astfel, vezi Spații de lucru și izolare.

Există trei artefacte de copiere a bazei de date, cu sfere de aplicare și politici de ștergere diferite.

Artefact Scris de Formă Acoperă
Snapshot de instalare server.backupNow Un director cu marcă de timp Fiecare bază de date din instalare
Backup de spațiu de lucru pipeline-ul Workspace backup Director cu marcă de timp cu un .db Baza de date a unui spațiu de lucru
Export de spațiu de lucru workspace.export Un singur fișier .db Baza de date a unui spațiu de lucru

Toate sunt scrise cu SQLite VACUUM INTO, care este sigur față de o bază de date WAL activă: ia o tranzacție de citire, produce o copie defragmentată și consistentă tranzacțional și nu necesită niciodată oprirea serverului.

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

Structura oglindește exact directorul de date activ, ceea ce face ca restaurarea unei instalări să fie o simplă copiere la loc, nu o translație. Numele directorului este marca de timp UTC cu : și . înlocuite cu -, deci este sigur pentru sistemul de fișiere pe Windows și se sortează cronologic ca un șir simplu.

Backup-urile programate de spațiu de lucru se află separat la <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db. Ele nu includ un manifest sau global.db și nu sunt snapshot-uri de instalare. Pasul de retenție al pipeline-ului săptămânal elimină doar backup-urile propriului spațiu de lucru mai vechi decât vârsta configurată (30 de zile implicit); snapshot-urile de instalare create manual nu sunt niciodată rotite de acel pas. server.listBackups listează doar snapshot-uri de instalare, inclusiv pe cele incomplete.

Câmp Tip Semnificație
version int Versiunea formatului manifestului. În prezent 1
created_at ISO-8601 UTC Când a fost făcut snapshot-ul
global.file string Mereu global.db
global.schema_version int Versiunea schemei GlobalDatabase la momentul capturii
global.bytes int Dimensiunea fișierului global.db scris
workspace_schema_version int Versiunea schemei WorkspaceDatabase partajată de fiecare fișier de spațiu de lucru
workspaces[] array O intrare pentru fiecare spațiu de lucru capturat
workspaces[].workspace_id string Spațiul de lucru pe care îl conține acest fișier
workspaces[].file string Cale relativă la rădăcina snapshot-ului, <workspaceId>/workspace.db
workspaces[].bytes int Dimensiunea acelui fișier
skipped_workspaces[] array of string Spații de lucru pe care backup-ul nu le-a putut captura

Un spațiu de lucru este omis când este înregistrat, dar nu s-a scris niciodată în el (deci nu există încă niciun fișier), sau când VACUUM INTO al lui a eșuat. În ambele cazuri, snapshot-ul se finalizează totuși, iar manifestul numește ce lipsește.

server.listBackups raportează un indicator complete pentru fiecare snapshot. Acesta este fals când manifestul lipsește sau nu poate fi analizat, când global.db lipsește sau când manifestul numește un fișier de spațiu de lucru care nu este pe disc.

Un snapshot incomplet este totuși listat, pentru că un snapshot pe care un operator nu îl vede este un snapshot despre care crede că îl are. Când manifestul nu poate fi citit, listarea se bazează pe structura propriu-zisă și raportează orice fișiere <workspaceId>/workspace.db găsește — acelea rămân adoptabile individual prin workspace.import, chiar dacă snapshot-ul în ansamblu nu poate restaura o instalare.

Ambele artefacte sunt doar baze de date. Un director de spațiu de lucru conține mai mult decât baza lui de date, iar nimic din rest nu călătorește:

Cale Într-un snapshot? Într-un export de spațiu de lucru?
global.db Da Nu
<workspaceId>/workspace.db Da Da (chiar este fișierul)
<workspaceId>/blobs/ Nu Nu
<workspaceId>/skills/ Nu Nu
<workspaceId>/agents/ Nu Nu
<workspaceId>/chat_credentials/ Nu Nu
<workspaceId>/spaces/<spaceId>/ Nu Nu
<workspaceId>/pr_clones/ Nu Nu
secrets.json Nu Nu
models/ Nu Nu
meetings/<meetingId>/ Nu Nu
rigs/ Nu Nu

O parte din asta este de unică folosință — spaces/ conține worktree-uri copy-on-write care sunt reprovisionate din repo-uri, pr_clones/ este un cache, models/ se descarcă din nou, rigs/ este stare de mașină. O parte nu este: blobs/ conține imaginile lipite spre care indică rânduri din baza de date, skills/ și agents/ conțin fișierele cu care rulează un agent, iar secrets.json conține fiecare cheie de asociere, acreditare de provider și setare SSO din instalare. Vezi Backup și restaurare pentru acoperirea restului.

RPC-urile de backup la nivel de instalare și exportul/importul de spațiu de lucru sunt numai pentru fullClient: un telefon asociat nu le poate declanșa. Toate lipsesc complet — nu sunt refuzate, lipsesc structural — pe un server fără un port de backup configurat, cum este serverul demo.

Op Tip Sferă Rol minim Argumente Returnează
server.backupNow modificare Instalare proprietar al instalării niciunul {ok, path}
server.listBackups citire Instalare proprietar al instalării niciunul {backups: [...]}
server.deleteBackup modificare Instalare proprietar al instalării name {ok}
workspace.export citire Spațiu de lucru admin niciunul {ok, path}
workspace.import modificare Spațiu de lucru owner source_path {ok, workspace_id}
workspace.delete modificare Instalare* owner id rând de registru marcat ca șters
  • workspace.delete nu are sferă pentru că rândul pe care îl marchează trăiește în registrul global; handler-ul lui verifică apartenența apelantului la spațiul de lucru numit și cere owner.

path din fiecare răspuns este o cale pe hostul serverului.

Cel mai nou primul, sortate după numele directorului (care este marca de timp, deci ordinea se păstrează chiar și pentru un snapshot al cărui manifest nu a putut fi citit).

{
"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 este omis când manifestul nu a putut fi citit. bytes de la nivelul superior este dimensiunea reală pe disc a întregului director, nu suma din manifest — întrebarea pe care o pune un operator care curăță snapshot-uri este cât costă directorul, nu ce intenționa backup-ul să scrie.

Fiecare workspaces[].path este exact ce ia workspace.import ca source_path. Acest lucru este deliberat: „restaurează acest spațiu de lucru din acest snapshot” este operațiunea de import, așa că cele două nu pot ajunge la tratamente diferite ale aceluiași fișier.

Înainte de a se înlocui ceva, fișierul candidat este deschis doar-pentru-citire cu o conexiune SQLite brută de scurtă durată, iar rândul lui workspace_meta este citit.

Condiție Rezultat
Nu este o bază de date SQLite care poate fi citită sau nu are workspace_meta Refuzat. Nu se atinge nimic
Id-ul de spațiu de lucru înregistrat ≠ cel al țintei Permis, înregistrat în jurnal. Așa se duplică un spațiu de lucru sau se restaurează sub un id nou
Id-ul de instalare înregistrat ≠ această instalare Permis, înregistrat în jurnal. Dispozitivele asociate și id-urile de utilizator ale lui aparțin acelei instalări și nu se vor rezolva aici
Id de spațiu de lucru invalid sau fișierul nu există Refuzat

La acceptare, baza de date a spațiului de lucru țintă este închisă și eliminată din manager înainte ca fișierul să fie copiat peste ea (o conexiune drift deschisă ține fișierul și -wal-ul lui), apoi redeschisă, astfel încât beforeOpen reinstalează trigger-ele FTS și de sincronizare, iar indecșii FTS sunt reconstruiți — tabelele de conținut ale unui fișier importat sunt populate, dar indexul lui poate fi învechit.

Fiecare operațiune de mai sus vorbește în căi de pe partea de server, ceea ce este un răspuns complet doar când serverul este propria ta mașină. Aceste trei transportă octeții, pe același canal semnat cu PSK pe care îl folosesc proxy-ul de media și depozitul de blob-uri. Apelantul semnează un șir țintă cu cheia pre-partajată a dispozitivului său și trece semnătura ca s.

Rută Metodă Interogare Țintă semnată Necesită
/backup/workspace GET w, d, s backup-workspace:<workspaceId> admin al spațiului de lucru
/backup/snapshot GET n, d, s backup-snapshot:<name> proprietar al instalării
/backup/restore POST w, d, s backup-restore:<workspaceId> proprietar al spațiului de lucru

w este un id de spațiu de lucru, n un nume de director de snapshot, d id-ul dispozitivului apelant, s semnătura. n este rezolvat față de listarea backup-urilor, nu concatenat la rădăcina backup-urilor, așa că ruta nu poate fi îndreptată spre un director pe care listarea nu l-ar fi arătat.

Status Cauză
400 Lipsește un parametru de interogare obligatoriu sau corpul unui upload este gol
403 Dispozitiv necunoscut sau revocat, semnătură greșită sau apelantul nu are rolul
404 Nu există un port de backup pe acest host sau fișierul de snapshot/spațiu de lucru numit nu există
405 /backup/restore apelat cu orice altceva decât POST
413 Corpul upload-ului depășește 8 GiB, după content-length declarat sau după octeții citiți efectiv
500 Exportul sau arhivarea a eșuat pe partea de server

Ambele descărcări răspund cu Cache-Control: no-store și Accept-Ranges: none. Fiecare cerere creează o copie proaspătă și o șterge după ce a fost transmisă în flux, așa că un răspuns din cache sau reluat ar îmbina octeți din două exporturi diferite într-un singur fișier care pare valid și nu este.

/backup/snapshot returnează <name>.zip, cu intrări relative la rădăcina snapshot-ului, astfel încât dezarhivarea reproduce manifest.json + global.db + <workspaceId>/workspace.db. Intrările sunt scrise în ordine sortată, așa că două arhive ale aceluiași snapshot sunt aceeași arhivă.

/backup/restore transmite corpul direct într-un fișier de pregătire, în loc să îl pună în buffer, îl limitează înainte și în timpul citirii și șterge fișierul pregătit pe fiecare cale de ieșire, inclusiv la un refuz.

Element Valoare
Snapshot-uri <dataDir>/backups/<timestamp>/
Backup-uri programate de spațiu de lucru <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db
Exporturi de spațiu de lucru <dataDir>/backups/exports/<workspaceId>-<timestamp>.db
Pregătire pentru transfer <dataDir>/backups/transfer/ — un atelier, curățat de ruta care îl scrie
Numele arhivei de snapshot <snapshot directory name>.zip
Plafon de upload 8 GiB per POST /backup/restore
Retenție Snapshot-uri de instalare: ștergere manuală. Backup-uri de spațiu de lucru: pipeline săptămânal, 30 de zile implicit

Directoarele exports/, transfer/ și workspace-backups/ nu sunt snapshot-uri de instalare și sunt excluse din server.listBackups. Doar ultimul director are retenție programată; ștergerea unui snapshot de instalare necesită acțiunea explicită a proprietarului instalării.