Sauvegarde, export et import
Tout ce que Control Center peut copier, transmettre ou adopter, et la forme exacte de chaque artefact. Pour effectuer réellement une sauvegarde, consultez Sauvegarder et restaurer ; pour savoir pourquoi la persistance est scindée de cette façon, consultez Espaces de travail et isolation.
Artefacts
Section intitulée « Artefacts »Il existe trois artefacts de copie de base de données, aux portées et aux politiques de suppression différentes.
| Artefact | Écrit par | Forme | Couvre |
|---|---|---|---|
| Instantané de l’installation | server.backupNow |
Un répertoire horodaté | Chaque base de données de l’installation |
| Sauvegarde d’espace de travail | pipeline Workspace backup |
Répertoire horodaté avec un seul .db |
La base de données d’un espace de travail |
| Export d’espace de travail | workspace.export |
Un seul fichier .db |
La base de données d’un espace de travail |
Tous sont écrits avec VACUUM INTO de SQLite, qui est sûr face à une base de données WAL
active : il prend une transaction de lecture, produit une copie défragmentée et cohérente
du point de vue transactionnel, et n’exige jamais d’arrêter le serveur.
Arborescence d’un instantané
Section intitulée « Arborescence d’un instantané »<dataDir>/backups/2026-07-28T09-12-33-000Z/ manifest.json global.db <workspaceId>/workspace.db one directory per workspaceL’arborescence reproduit exactement le répertoire de données actif, et c’est ce qui fait de la
restauration d’une installation une copie en retour plutôt qu’une transposition. Le nom du
répertoire est l’horodatage UTC avec les : et les . remplacés par des - : il est donc
sans danger pour les systèmes de fichiers Windows et se trie chronologiquement comme une
simple chaîne.
Les sauvegardes d’espace de travail planifiées résident séparément sous
<dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db.
Elles ne comportent ni manifeste ni global.db et ne sont pas des instantanés de
l’installation. L’étape de rétention du pipeline hebdomadaire ne supprime que les
sauvegardes de son propre espace de travail plus anciennes que l’âge configuré (30 jours
par défaut) ; les instantanés de l’installation créés à la main ne sont jamais éliminés
par cette étape. server.listBackups ne liste que les instantanés de l’installation, y
compris les incomplets.
manifest.json
Section intitulée « manifest.json »| Champ | Type | Signification |
|---|---|---|
version |
int | Version du format du manifeste. Actuellement 1 |
created_at |
ISO-8601 UTC | Date à laquelle l’instantané a été pris |
global.file |
string | Toujours global.db |
global.schema_version |
int | Version du schéma GlobalDatabase au moment de la capture |
global.bytes |
int | Taille du global.db écrit |
workspace_schema_version |
int | Version du schéma WorkspaceDatabase partagée par chaque fichier d’espace de travail |
workspaces[] |
array | Une entrée par espace de travail capturé |
workspaces[].workspace_id |
string | L’espace de travail que contient ce fichier |
workspaces[].file |
string | Chemin relatif à la racine de l’instantané, <workspaceId>/workspace.db |
workspaces[].bytes |
int | Taille de ce fichier |
skipped_workspaces[] |
array of string | Espaces de travail que la sauvegarde n’a pas pu capturer |
Un espace de travail est ignoré lorsqu’il est enregistré mais qu’on n’y a jamais écrit (le
fichier n’existe donc pas encore), ou lorsque son VACUUM INTO a échoué. Dans un cas comme
dans l’autre, l’instantané est tout de même mené à son terme et le manifeste indique ce qui
manque.
Complétude
Section intitulée « Complétude »server.listBackups renvoie un indicateur complete par instantané. Il vaut faux lorsque le
manifeste est absent ou illisible, lorsque global.db manque, ou lorsque le manifeste
désigne un fichier d’espace de travail qui n’est pas sur le disque.
Un instantané incomplet est tout de même listé, car un instantané qu’un opérateur ne voit pas
est un instantané qu’il croit posséder. Lorsque le manifeste est illisible, la liste se rabat
sur l’arborescence elle-même et signale tous les fichiers <workspaceId>/workspace.db qu’elle
trouve — ceux-ci restent adoptables individuellement via workspace.import, même si
l’instantané dans son ensemble ne peut pas restaurer une installation.
Ce qu’une sauvegarde ne contient pas
Section intitulée « Ce qu’une sauvegarde ne contient pas »Les deux artefacts sont uniquement des bases de données. Un répertoire d’espace de travail contient plus que sa base de données, et rien du reste ne voyage :
| Chemin | Dans un instantané ? | Dans un export d’espace de travail ? |
|---|---|---|
global.db |
Oui | Non |
<workspaceId>/workspace.db |
Oui | Oui (c’est lui le fichier) |
<workspaceId>/blobs/ |
Non | Non |
<workspaceId>/skills/ |
Non | Non |
<workspaceId>/agents/ |
Non | Non |
<workspaceId>/chat_credentials/ |
Non | Non |
<workspaceId>/spaces/<spaceId>/ |
Non | Non |
<workspaceId>/pr_clones/ |
Non | Non |
secrets.json |
Non | Non |
models/ |
Non | Non |
meetings/<meetingId>/ |
Non | Non |
rigs/ |
Non | Non |
Une partie de tout cela est jetable — spaces/ contient des arbres de travail copy-on-write
reprovisionnés depuis les dépôts, pr_clones/ est un cache, models/ est retéléchargé,
rigs/ est de l’état machine. Une autre ne l’est pas : blobs/ contient les images collées
vers lesquelles pointent des lignes de la base de données, skills/ et agents/ contiennent
les fichiers avec lesquels un agent s’exécute, et secrets.json contient chaque clé
d’appairage, identifiant de fournisseur et paramètre SSO de l’installation. Voir
Sauvegarder et restaurer
pour couvrir le reste.
Opérations
Section intitulée « Opérations »Les RPC de sauvegarde de l’installation et l’export/import d’espace de travail sont réservés
au client complet (fullClient) : un téléphone associé ne peut pas les déclencher.
Toutes sont entièrement absentes — non pas refusées, mais structurellement inexistantes — sur
un serveur où aucun port de sauvegarde n’est câblé, comme le serveur de démonstration.
| Op | Type | Portée | Rôle minimal | Arguments | Renvoie |
|---|---|---|---|---|---|
server.backupNow |
mutate | Installation | propriétaire de l’installation | aucun | {ok, path} |
server.listBackups |
read | Installation | propriétaire de l’installation | aucun | {backups: [...]} |
server.deleteBackup |
mutate | Installation | propriétaire de l’installation | name |
{ok} |
workspace.export |
read | Espace de travail | admin |
aucun | {ok, path} |
workspace.import |
mutate | Espace de travail | owner |
source_path |
{ok, workspace_id} |
workspace.delete |
mutate | Installation* | owner |
id |
ligne de registre marquée comme supprimée |
workspace.deleteest sans portée, car la ligne qu’elle marque réside dans le registre global ; son gestionnaire vérifie l’appartenance de l’appelant à l’espace de travail nommé et exige le rôleowner.
Le path de chaque réponse est un chemin sur l’hôte du serveur.
Réponse de server.listBackups
Section intitulée « Réponse de server.listBackups »Du plus récent au plus ancien, triés par nom de répertoire (qui est l’horodatage : l’ordre tient donc même pour un instantané dont le manifeste n’a pas pu être lu).
{ "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 est omis lorsque le manifeste n’a pas pu être lu. bytes au premier niveau est
la taille réelle sur disque du répertoire entier, et non la somme inscrite dans le manifeste —
ce qu’un opérateur qui élague des instantanés cherche à savoir, c’est ce que coûte le
répertoire, pas ce que la sauvegarde avait l’intention d’écrire.
Chaque workspaces[].path est exactement ce que workspace.import attend comme
source_path. C’est délibéré : « restaurer cet espace de travail depuis cet
instantané » est l’opération d’import, si bien que les deux ne peuvent pas diverger vers
des traitements différents du même fichier.
Validation de workspace.import
Section intitulée « Validation de workspace.import »Avant que quoi que ce soit ne soit remplacé, le fichier candidat est ouvert en lecture seule
au moyen d’une connexion SQLite brute de courte durée, et sa ligne workspace_meta est lue.
| Condition | Résultat |
|---|---|
Base SQLite illisible, ou absence de workspace_meta |
Refusé. Rien n’est touché |
| Identifiant d’espace de travail enregistré ≠ la cible | Autorisé, journalisé. C’est ainsi qu’un espace de travail est dupliqué ou restauré sous un nouvel identifiant |
| Identifiant d’installation enregistré ≠ cette installation | Autorisé, journalisé. Ses appareils associés et ses identifiants utilisateur appartiennent à cette installation et ne se résoudront pas ici |
| Identifiant d’espace de travail invalide, ou fichier inexistant | Refusé |
En cas d’acceptation, la base de données de l’espace de travail cible est fermée et retirée du
gestionnaire avant que le fichier n’y soit copié par-dessus (une connexion Drift ouverte
retient le fichier et son -wal), puis rouverte de sorte que beforeOpen réinstalle les
déclencheurs FTS et de synchronisation, et les index FTS sont reconstruits — les tables de
contenu d’un fichier importé sont remplies, mais son index peut être périmé.
Routes de transfert
Section intitulée « Routes de transfert »Chaque opération ci-dessus s’exprime en chemins côté serveur, ce qui n’est une réponse
complète que lorsque le serveur est votre propre machine. Ces trois routes transportent les
octets, sur la même voie signée par PSK que celle qu’utilisent le proxy multimédia et le
magasin de blobs. L’appelant signe une chaîne cible avec la clé pré-partagée de son appareil
et transmet la signature sous le nom s.
| Route | Méthode | Requête | Cible signée | Exige |
|---|---|---|---|---|
/backup/workspace |
GET | w, d, s |
backup-workspace:<workspaceId> |
admin de l’espace de travail |
/backup/snapshot |
GET | n, d, s |
backup-snapshot:<name> |
propriétaire de l’installation |
/backup/restore |
POST | w, d, s |
backup-restore:<workspaceId> |
propriétaire de l’espace de travail |
w est un identifiant d’espace de travail, n un nom de répertoire d’instantané, d
l’identifiant de l’appareil appelant, s la signature. n est résolu par rapport à la liste
des sauvegardes plutôt que concaténé à la racine des sauvegardes : la route ne peut donc pas
être pointée vers un répertoire que la liste n’aurait pas montré.
| Statut | Cause |
|---|---|
400 |
Un paramètre de requête obligatoire manque, ou le corps d’un envoi est vide |
403 |
Appareil inconnu ou révoqué, signature invalide, ou l’appelant n’a pas le rôle requis |
404 |
Aucun port de sauvegarde sur cet hôte, ou le fichier d’instantané/d’espace de travail nommé n’existe pas |
405 |
/backup/restore appelé avec autre chose que POST |
413 |
Le corps de l’envoi dépasse 8 GiB, d’après la longueur de contenu déclarée ou les octets réellement lus |
500 |
L’export ou l’archivage a échoué côté serveur |
Les deux téléchargements répondent Cache-Control: no-store avec Accept-Ranges: none.
Chaque requête génère une copie fraîche et la supprime une fois diffusée en flux : une
réponse mise en cache ou reprise recollerait donc des octets de deux exports différents dans
un seul fichier qui a l’air valide sans l’être.
/backup/snapshot renvoie <name>.zip, avec des entrées relatives à la racine de
l’instantané, de sorte que la décompression reproduit manifest.json + global.db +
<workspaceId>/workspace.db. Les entrées sont écrites dans un ordre trié : deux archives
du même instantané sont donc la même archive.
/backup/restore diffuse le corps directement vers un fichier de transit au lieu de le
mettre en mémoire tampon, le borne avant et pendant la lecture, et supprime le fichier mis en
transit sur toutes les voies de sortie, y compris en cas de refus.
Chemins et limites
Section intitulée « Chemins et limites »| Élément | Valeur |
|---|---|
| Instantanés | <dataDir>/backups/<timestamp>/ |
| Sauvegardes d’espace de travail planifiées | <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db |
| Exports d’espace de travail | <dataDir>/backups/exports/<workspaceId>-<timestamp>.db |
| Transit des transferts | <dataDir>/backups/transfer/ — un atelier, balayé par la route qui y écrit |
| Nom de l’archive d’instantané | <snapshot directory name>.zip |
| Plafond d’envoi | 8 GiB par POST /backup/restore |
| Rétention | Instantanés de l’installation : suppression manuelle. Sauvegardes d’espace de travail : pipeline hebdomadaire, 30 jours par défaut |
Les répertoires exports/, transfer/ et workspace-backups/ ne sont pas des instantanés de
l’installation et sont exclus de server.listBackups. Seul le dernier répertoire a une
rétention planifiée ; supprimer un instantané de l’installation exige une action explicite du
propriétaire de l’installation.
Voir aussi
Section intitulée « Voir aussi »- Sauvegarder et restaurer — les recettes auxquelles ces opérations appartiennent
- Espaces de travail et isolation — pourquoi un espace de travail est un seul fichier
- CLI
cc_server— le répertoire de données où résident ces chemins - Carte des routes — où se trouve l’interface
- Architecture — la séparation client/serveur que ces chemins suivent