Backup, export en import
Alles wat Control Center kan kopiëren, overdragen of overnemen, en de exacte vorm van elk artefact. Hoe je daadwerkelijk een back-up maakt, staat in Back-uppen en herstellen; waarom persistentie zo is opgesplitst, staat in Werkruimtes en isolatie.
Artefacten
Sectie getiteld “Artefacten”Er zijn drie artefacten die een database kopiëren, met verschillende bereiken en verwijderbeleid.
| Artefact | Geschreven door | Vorm | Dekt |
|---|---|---|---|
| Installatiemomentopname | server.backupNow |
Een map met tijdstempel | Elke database van de installatie |
| Werkruimteback-up | Pipeline Workspace backup |
Map met tijdstempel met één .db |
De database van één werkruimte |
| Werkruimte-export | workspace.export |
Eén .db-bestand |
De database van één werkruimte |
Alle drie worden geschreven met SQLite VACUUM INTO, wat veilig is tegen een actieve
WAL-database: het neemt een leestransactie, produceert een gedefragmenteerde en transactioneel
consistente kopie en vraagt er nooit om de server te stoppen.
Indeling van de momentopname
Sectie getiteld “Indeling van de momentopname”<dataDir>/backups/2026-07-28T09-12-33-000Z/ manifest.json global.db <workspaceId>/workspace.db one directory per workspaceDe indeling spiegelt de live datadir exact, en dat is wat het herstellen van een installatie een
terugkopie maakt in plaats van een vertaling. De mapnaam is de UTC-tijdstempel waarin : en .
zijn vervangen door -, dus hij is veilig voor het bestandssysteem op Windows en sorteert
chronologisch als een gewone tekenreeks.
Geplande werkruimteback-ups staan apart in
<dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db.
Ze bevatten geen manifest of global.db en zijn geen installatiemomentopnamen.
De bewaarstap van de wekelijkse pipeline verwijdert alleen back-ups van zijn eigen werkruimte
die ouder zijn dan de ingestelde leeftijd (standaard 30 dagen); handmatig gemaakte
installatiemomentopnamen worden door die stap nooit verwijderd. server.listBackups vermeldt
alleen installatiemomentopnamen, ook onvolledige.
manifest.json
Sectie getiteld “manifest.json”| Veld | Type | Betekenis |
|---|---|---|
version |
geheel getal | Versie van het manifestformaat. Momenteel 1 |
created_at |
ISO-8601 UTC | Wanneer de momentopname is gemaakt |
global.file |
tekenreeks | Altijd global.db |
global.schema_version |
geheel getal | Schemaversie van GlobalDatabase op het moment van vastleggen |
global.bytes |
geheel getal | Grootte van het geschreven global.db |
workspace_schema_version |
geheel getal | Schemaversie van WorkspaceDatabase, gedeeld door elk werkruimtebestand |
workspaces[] |
array | Eén vermelding per vastgelegde werkruimte |
workspaces[].workspace_id |
tekenreeks | De werkruimte die dit bestand bevat |
workspaces[].file |
tekenreeks | Pad ten opzichte van de hoofdmap van de momentopname, <workspaceId>/workspace.db |
workspaces[].bytes |
geheel getal | Grootte van dat bestand |
skipped_workspaces[] |
array van tekenreeksen | Werkruimtes die de back-up niet kon vastleggen |
Een werkruimte wordt overgeslagen wanneer hij is geregistreerd maar er nooit naar is geschreven
(er bestaat dus nog geen bestand), of wanneer zijn VACUUM INTO is mislukt. Hoe dan ook wordt de
momentopname alsnog voltooid en noemt het manifest wat er ontbreekt.
Volledigheid
Sectie getiteld “Volledigheid”server.listBackups rapporteert per momentopname een complete-markering. Die is onwaar wanneer
het manifest ontbreekt of niet te parsen is, wanneer global.db ontbreekt, of wanneer het
manifest een werkruimtebestand noemt dat niet op schijf staat.
Een onvolledige momentopname wordt toch vermeld, want een momentopname die een operator niet
ziet, is er een waarvan hij gelooft dat hij hem heeft. Wanneer het manifest onleesbaar is, valt
de lijst terug op de indeling zelf en rapporteert hij de <workspaceId>/workspace.db-bestanden
die hij vindt — die blijven afzonderlijk over te nemen via workspace.import, ook al kan de
momentopname als geheel geen installatie herstellen.
Wat een back-up niet bevat
Sectie getiteld “Wat een back-up niet bevat”Beide artefacten zijn alleen databases. Een werkruimtemap bevat meer dan zijn database, en niets daarvan reist mee:
| Pad | In een momentopname? | In een werkruimte-export? |
|---|---|---|
global.db |
Ja | Nee |
<workspaceId>/workspace.db |
Ja | Ja (het is het bestand) |
<workspaceId>/blobs/ |
Nee | Nee |
<workspaceId>/skills/ |
Nee | Nee |
<workspaceId>/agents/ |
Nee | Nee |
<workspaceId>/chat_credentials/ |
Nee | Nee |
<workspaceId>/spaces/<spaceId>/ |
Nee | Nee |
<workspaceId>/pr_clones/ |
Nee | Nee |
secrets.json |
Nee | Nee |
models/ |
Nee | Nee |
meetings/<meetingId>/ |
Nee | Nee |
rigs/ |
Nee | Nee |
Sommige daarvan is wegwerpbaar — spaces/ bevat copy-on-write-worktrees die opnieuw worden
geprovisioneerd vanuit de repo’s, pr_clones/ is een cache, models/ wordt opnieuw gedownload,
rigs/ is machinestatus. Sommige niet: blobs/ bevat geplakte afbeeldingen waar rijen in de
database naar verwijzen, skills/ en agents/ bevatten de bestanden waarmee een agent draait, en
secrets.json bevat elke koppelingssleutel, providerreferentie en SSO-instelling van de
installatie. Zie Back-uppen en herstellen
voor het dekken van de rest.
Bewerkingen
Sectie getiteld “Bewerkingen”Back-up-RPC’s voor de installatie en export/import van werkruimtes zijn alleen voor
fullClient: een gekoppelde telefoon kan ze niet starten. Ze zijn allemaal volledig afwezig
— niet geweigerd, maar structureel ontbrekend — op een server waar geen back-uppoort is
aangesloten, zoals de demoserver.
| Op | Soort | Bereik | Minimale rol | Argumenten | Retourneert |
|---|---|---|---|---|---|
server.backupNow |
mutate | Installatie | eigenaar van de installatie | geen | {ok, path} |
server.listBackups |
read | Installatie | eigenaar van de installatie | geen | {backups: [...]} |
server.deleteBackup |
mutate | Installatie | eigenaar van de installatie | name |
{ok} |
workspace.export |
read | Werkruimte | admin |
geen | {ok, path} |
workspace.import |
mutate | Werkruimte | owner |
source_path |
{ok, workspace_id} |
workspace.delete |
mutate | Installatie* | owner |
id |
registerrij gemarkeerd als verwijderd |
workspace.deleteheeft geen bereik omdat de rij die hij markeert in het globale register staat; zijn handler controleert het lidmaatschap van de aanroeper van de genoemde werkruimte en vereistowner.
path in elk antwoord is een pad op de serverhost.
Antwoord van server.listBackups
Sectie getiteld “Antwoord van server.listBackups”Nieuwste eerst, gesorteerd op mapnaam (dat is de tijdstempel, dus de volgorde klopt ook voor een momentopname waarvan het manifest niet kon worden gelezen).
{ "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 ontbreekt wanneer het manifest niet kon worden gelezen. bytes op het hoogste
niveau is de werkelijke grootte op schijf van de hele map, niet de som uit het manifest — de
vraag die een operator die momentopnamen opruimt stelt, is wat de map kost, niet wat de
back-up van plan was te schrijven.
Elke workspaces[].path is precies wat workspace.import als source_path aanneemt. Dat is
bewust: “deze werkruimte herstellen uit deze momentopname” is de importbewerking, dus de twee
kunnen niet uit elkaar lopen in verschillende behandelingen van hetzelfde bestand.
Validatie van workspace.import
Sectie getiteld “Validatie van workspace.import”Voordat er iets wordt vervangen, wordt het kandidaatbestand alleen-lezen geopend met een
kortstondige ruwe SQLite-verbinding en wordt de workspace_meta-rij gelezen.
| Voorwaarde | Resultaat |
|---|---|
Geen leesbare SQLite-database, of geen workspace_meta |
Geweigerd. Er wordt niets aangeraakt |
| Vastgelegd werkruimte-id ≠ het doel | Toegestaan, gelogd. Zo wordt een werkruimte gedupliceerd of onder een nieuw id hersteld |
| Vastgelegd installatie-id ≠ deze installatie | Toegestaan, gelogd. De gekoppelde apparaten en gebruikers-id’s horen bij die installatie en worden hier niet herleid |
| Ongeldig werkruimte-id, of bestand bestaat niet | Geweigerd |
Bij acceptatie wordt de database van de doelwerkruimte gesloten en uit de manager gehaald
voordat het bestand eroverheen wordt gekopieerd (een open drift-verbinding houdt het bestand en
zijn -wal vast), en daarna heropend zodat beforeOpen de FTS- en synctriggers opnieuw
installeert, en de FTS-indexen worden opnieuw opgebouwd — de inhoudstabellen van een
geïmporteerd bestand zijn gevuld, maar de index kan verouderd zijn.
Overdrachtroutes
Sectie getiteld “Overdrachtroutes”Elke bewerking hierboven spreekt in paden aan de serverkant, wat alleen een volledig antwoord is
als de server je eigen machine is. Deze drie dragen de bytes, op dezelfde met PSK ondertekende
baan die de mediaproxy en het blobarchief gebruiken. De aanroeper ondertekent een doeltekenreeks
met de vooraf gedeelde sleutel van zijn apparaat en geeft de handtekening mee als s.
| Route | Methode | Query | Ondertekend doel | Vereist |
|---|---|---|---|---|
/backup/workspace |
GET | w, d, s |
backup-workspace:<workspaceId> |
Werkruimte-beheerder |
/backup/snapshot |
GET | n, d, s |
backup-snapshot:<name> |
Installatie-eigenaar |
/backup/restore |
POST | w, d, s |
backup-restore:<workspaceId> |
Werkruimte-eigenaar |
w is een werkruimte-id, n een naam van een momentopnamemap, d het id van het aanroepende
apparaat, s de handtekening. n wordt herleid tegen de back-uplijst in plaats van aan de
backups-root te worden geplakt, zodat de route niet kan worden gericht op een map die de lijst
niet zou hebben getoond.
| Status | Oorzaak |
|---|---|
400 |
Een vereiste queryparameter ontbreekt, of de body van een upload is leeg |
403 |
Onbekend of ingetrokken apparaat, slechte handtekening, of de aanroeper mist de rol |
404 |
Geen back-uppoort op deze host, of de genoemde momentopname/het genoemde werkruimtebestand bestaat niet |
405 |
/backup/restore aangeroepen met iets anders dan POST |
413 |
De uploadbody is groter dan 8 GiB, volgens de opgegeven content-length of volgens de werkelijk gelezen bytes |
500 |
De export of het archief is aan de serverkant mislukt |
Beide downloads antwoorden met Cache-Control: no-store en Accept-Ranges: none. Elk verzoek
maakt een nieuwe kopie aan en verwijdert die zodra hij is gestreamd, dus een uit de cache
gehaald of hervat antwoord zou bytes van twee verschillende exports aaneenrijgen tot één bestand
dat geldig lijkt en het niet is.
/backup/snapshot retourneert <name>.zip, met items ten opzichte van de hoofdmap van de
momentopname, zodat uitpakken manifest.json + global.db + <workspaceId>/workspace.db
reproduceert. De items worden in gesorteerde volgorde geschreven, dus twee archieven van dezelfde
momentopname zijn hetzelfde archief.
/backup/restore streamt de body rechtstreeks naar een stagingbestand in plaats van hem te
bufferen, begrenst hem vóór en tijdens het lezen, en verwijdert het klaargezette bestand op
elk uitpad, ook bij een weigering.
Paden en limieten
Sectie getiteld “Paden en limieten”| Onderdeel | Waarde |
|---|---|
| Momentopnamen | <dataDir>/backups/<timestamp>/ |
| Geplande werkruimteback-ups | <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db |
| Werkruimte-exports | <dataDir>/backups/exports/<workspaceId>-<timestamp>.db |
| Staging voor overdrachten | <dataDir>/backups/transfer/ — een werkbank, opgeruimd door de route die hem schrijft |
| Naam van het momentopnamearchief | <snapshot directory name>.zip |
| Uploadplafond | 8 GiB per POST /backup/restore |
| Bewaring | Installatiemomentopnamen: handmatige verwijdering. Werkruimteback-ups: wekelijkse pipeline, standaard 30 dagen |
De mappen exports/, transfer/ en workspace-backups/ zijn geen
installatiemomentopnamen en zijn uitgesloten van server.listBackups. Alleen de laatste
map heeft geplande bewaring; het verwijderen van een installatiemomentopname vereist een
expliciete actie van de eigenaar van de installatie.
Zie ook
Sectie getiteld “Zie ook”- Back-uppen en herstellen — de recepten waar deze bewerkingen bij horen
- Werkruimtes en isolatie — waarom één werkruimte één bestand is
cc_serverCLI — de datadir waarin deze paden staan- Routekaart — waar de UI woont
- Architectuur — de client/server-splitsing die de paden volgen