Sauvegarde, export et import
Tout ce que Control Center peut copier, céder ou adopter, et la forme exacte de chaque artéfact. Pour prendre réellement une sauvegarde, voir Sauvegarder et restaurer ; pour comprendre pourquoi la persistance est ainsi divisée, voir Espaces de travail et isolation.
Artéfacts
Section intitulée “Artéfacts”Il existe trois artéfacts de copie de base de données, aux portées et aux politiques de suppression différentes.
| Artéfact | É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 fichier .db unique |
La base de données d’un espace de travail |
Tous sont écrits avec VACUUM INTO de SQLite, qui ne craint pas 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.
Disposition des instantanés
Section intitulée “Disposition des instantanés”<dataDir>/backups/2026-07-28T09-12-33-000Z/ manifest.json global.db <workspaceId>/workspace.db one directory per workspaceLa disposition reflète exactement le répertoire de données actif, ce qui fait de la
restauration d’une installation une recopie plutôt qu’une conversion. Le nom du répertoire
est l’horodatage UTC, : et . remplacés par -, de sorte qu’il est sécuritaire pour le
système de fichiers sous Windows et qu’il se trie chronologiquement comme une simple
chaîne.
Les sauvegardes d’espace de travail planifiées vivent séparément à
<dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db.
Elles n’incluent 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 la durée configurée
(30 jours par défaut) ; les instantanés de l’installation créés manuellement ne sont
jamais supprimé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 | Moment où l’instantané a été pris |
global.file |
string | Toujours global.db |
global.schema_version |
int | Version du schéma de GlobalDatabase au moment de la capture |
global.bytes |
int | Taille du global.db écrit |
workspace_schema_version |
int | Version du schéma de 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 ce fichier contient |
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 n’a jamais été écrit (aucun
fichier n’existe encore), ou lorsque son VACUUM INTO a échoué. Dans un cas comme dans
l’autre, l’instantané se termine quand même et le manifeste nomme ce qui manque.
Complétude
Section intitulée “Complétude”server.listBackups signale un indicateur complete par instantané. Il est faux lorsque
le manifeste est absent ou impossible à analyser, lorsque global.db manque, ou lorsque
le manifeste nomme un fichier d’espace de travail qui n’est pas sur le disque.
Un instantané incomplet est tout de même listé, parce qu’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 la disposition elle-même et signale tous les fichiers
<workspaceId>/workspace.db qu’elle trouve — ceux-ci demeurent adoptables un par un au
moyen de 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 artéfacts sont des bases de données uniquement. 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 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 cela est jetable — spaces/ contient des arbres de travail copie sur
écriture qui sont reprovisionnés à partir des dépôts, pr_clones/ est un cache, models/
se retélécharge, rigs/ est un état de machine. Une autre partie ne l’est pas : blobs/
contient des 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, chaque identifiant de fournisseur et
chaque 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 ne sont
accessibles qu’aux fullClient : un téléphone appairé ne peut pas les déclencher. Tous
sont totalement absents — non pas refusés, mais structurellement manquants — sur un
serveur sans port de sauvegarde câblé, comme le serveur de démonstration.
| Op | Type | Portée | Rôle minimal | Arguments | Retourne |
|---|---|---|---|---|---|
server.backupNow |
mutation | Installation | propriétaire de l’installation | aucun | {ok, path} |
server.listBackups |
lecture | Installation | propriétaire de l’installation | aucun | {backups: [...]} |
server.deleteBackup |
mutation | Installation | propriétaire de l’installation | name |
{ok} |
workspace.export |
lecture | Espace de travail | admin |
aucun | {ok, path} |
workspace.import |
mutation | Espace de travail | owner |
source_path |
{ok, workspace_id} |
workspace.delete |
mutation | Installation* | owner |
id |
ligne du registre marquée supprimée |
workspace.deleten’a pas de portée parce que la ligne qu’il marque vit dans le registre global ; son gestionnaire vérifie l’appartenance de l’appelant à l’espace de travail nommé et exigeowner.
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é par nom de répertoire (qui est l’horodatage, de sorte que l’ordre tient 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. La valeur bytes du niveau
supérieur est la taille réelle sur le disque de tout le répertoire, et non la somme du
manifeste lui-même — la question que se pose un opérateur qui élague les instantanés est
ce que coûte le répertoire, et non ce que la sauvegarde comptait écrire.
Chaque workspaces[].path est exactement ce que workspace.import prend comme
source_path. C’est délibéré : « restaurer cet espace de travail à partir de cet
instantané » est l’opération d’import, de sorte 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 soit remplacé, le fichier candidat est ouvert en lecture seule
au moyen d’une connexion SQLite brute éphémère et sa ligne workspace_meta est lue.
| Condition | Résultat |
|---|---|
Base de données SQLite illisible, ou aucune workspace_meta |
Refusé. Rien n’est touché |
| Identifiant d’espace de travail enregistré ≠ la cible | Permis, journalisé. C’est ainsi qu’un espace de travail est dupliqué ou restauré sous un nouvel identifiant |
| Identifiant d’installation enregistré ≠ cette installation | Permis, journalisé. Ses appareils appairés et ses identifiants d’utilisateur appartiennent à cette installation et ne se résoudront pas ici |
| Identifiant d’espace de travail invalide, ou fichier inexistant | Refusé |
À l’acceptation, la base de données de l’espace de travail cible est fermée et retirée du
gestionnaire avant que le fichier soit copié par-dessus (une connexion drift ouverte
retient le fichier et son -wal), puis rouverte afin 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 peuplées, 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 qu’utilisent le proxy de médias et le magasin
d’images. L’appelant signe une chaîne cible avec la clé prépartagée de son appareil et
transmet la signature comme s.
| Route | Méthode | Requête | Cible signée | Exige |
|---|---|---|---|---|
/backup/workspace |
GET | w, d, s |
backup-workspace:<workspaceId> |
administrateur 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 à partir de la
liste des sauvegardes plutôt que joint à la racine des sauvegardes, de sorte que la route
ne peut pas viser 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 téléversement est vide |
403 |
Appareil inconnu ou révoqué, signature invalide, ou l’appelant n’a pas le rôle |
404 |
Aucun port de sauvegarde sur cet hôte, ou l’instantané ou le fichier d’espace de travail nommé n’existe pas |
405 |
/backup/restore appelé avec autre chose que POST |
413 |
Le corps du téléversement dépasse 8 GiB, selon 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 crée une copie fraîche et la supprime une fois diffusée, de sorte qu’une
réponse mise en cache ou reprise souderait les octets de deux exports différents en un
seul fichier qui a l’air valide sans l’être.
/backup/snapshot renvoie <name>.zip, dont les entrées sont 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 en ordre trié, de sorte que deux
archives du même instantané sont la même archive.
/backup/restore diffuse le corps directement vers un fichier de préparation plutôt que
de le mettre en mémoire tampon, le borne avant et pendant la lecture, et supprime le
fichier préparé sur chaque chemin 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 |
| Préparation des transferts | <dataDir>/backups/transfer/ — un établi, balayé par la route qui l’écrit |
| Nom de l’archive d’instantané | <snapshot directory name>.zip |
| Plafond de téléversement | 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 l’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 correspond à un fichier
- CLI
cc_server— le répertoire de données où se trouvent ces chemins - Carte des routes — où vit l’interface
- Architecture — la séparation client/serveur que suivent les chemins