> ## Documentation Index
> Fetch the complete documentation index at: https://docs.casebender.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Runbook de migration du stockage

> Copier, vérifier, basculer et annuler le stockage fournisseur sans perte de données

Ce runbook migre les objets CaseBender sans modifier les clés d'objets. Il
utilise une sémantique copy-first : la source reste autoritaire et intacte
jusqu'à expiration de la fenêtre de rollback. Il s'applique aux systèmes de
fichiers locaux, au stockage MinIO/compatible S3, à AWS S3 et à GCS via des
remotes `rclone`.

## Préconditions

* Lisez la politique de support du stockage et les notes de version des deux
  fournisseurs.
* Confirmez que la version utilise l'outbox de suppression durable neutre
  vis-à-vis du fournisseur. L'écart historique de suppression MinIO-only est
  corrigé ; n'emportez pas cette limitation obsolète dans une nouvelle
  conception.
* Confirmez la capacité, le chiffrement, le versioning, la rétention, le
  cycle de vie, la taille d'objet, les métadonnées et le comportement de
  nommage de la destination.
* Créez des identités de migration en moindre privilège lecture-source et
  écriture-destination.
* Configurez la confiance TLS ; n'utilisez jamais `--no-check-certificate`.
* Prenez et testez une sauvegarde de cohérence de PostgreSQL et du stockage
  source.
* Enregistrez le nombre d'objets, le total d'octets, les
  versions/instantanés source et la configuration.
* Définissez une fenêtre de changement qui permet la mise au repos des
  écritures et le rollback.

Générez et protégez l'inventaire d'objets PostgreSQL faisant autorité :

```sh theme={null}
pnpm storage:backup-verify inventory \
  --output '<protected-manifest.json>'
chmod 600 '<protected-manifest.json>'
```

Chaque élément migré doit identifier une version/génération d'objet source
exacte, une taille et un SHA-256. PostgreSQL et ces versions exactes
constituent un seul ensemble de cohérence. Ne migrez pas un objet « latest »
flottant lorsqu'une version est enregistrée.

Les exemples ci-dessous utilisent `source:casebender` et
`destination:casebender`. Conservez la configuration et les journaux rclone
hors du dépôt et protégez-les comme sensibles.

## 1. Inventaire et essai à blanc

```sh theme={null}
rclone version
rclone size source:casebender --json > source-size.before.json
rclone lsf source:casebender --recursive --files-only \
  > source-objects.before.txt
rclone copy source:casebender destination:casebender \
  --checksum --metadata --dry-run --log-level INFO \
  --log-file migration-dry-run.log
```

Examinez les avertissements de métadonnées non supportées. Le chiffrement,
la rétention, la conservation légale, l'ACL et l'historique de versions
spécifiques au fournisseur peuvent ne pas se copier comme métadonnées
d'objet ordinaires ; configurez ces contrôles à la destination et préservez
les versions source dans la sauvegarde. N'utilisez jamais `sync` pour la
copie initiale car il peut supprimer des objets de destination.

## 2. Copie d'amorçage pendant que l'application est en ligne

```sh theme={null}
rclone copy source:casebender destination:casebender \
  --checksum --metadata --fast-list --transfers 8 --checkers 16 \
  --log-level INFO --log-file migration-seed.log
```

Réglez la concurrence en dessous des limites de limitation du fournisseur.
Réessayez les objets en échec et conservez le journal complet. N'inférez
pas l'intégrité à partir des ETags : les objets multipartie et chiffrés
peuvent avoir des ETags non MD5.

## 3. Mettre les écritures au repos et capturer le point de cohérence

Bloquez les écritures utilisateur et d'intégration via la procédure de
maintenance de la version. Mettez en pause l'ingestion et les workers
uniquement après que la file est vidée ou conservée de façon durable.
Enregistrez l'horodatage/LSN de la base de données, la
version/instantané du bucket source et les réplicas de déploiement.
Vérifiez qu'aucune écriture de stockage n'a lieu.

Exécutez le delta final :

```sh theme={null}
rclone copy source:casebender destination:casebender \
  --checksum --metadata --fast-list --transfers 8 --checkers 16 \
  --log-level INFO --log-file migration-final.log
```

Ne supprimez pas et ne désactivez pas la source.

## 4. Vérifier avant la bascule

```sh theme={null}
rclone check source:casebender destination:casebender \
  --download --one-way --combined migration-check.txt
rclone size source:casebender --json > source-size.final.json
rclone size destination:casebender --json > destination-size.final.json
```

`rclone check --download` hache le contenu téléchargé et évite
l'ambiguïté des ETags fournisseur. Exigez zéro objet manquant, modifié ou
illisible. Examinez les différences de comptage dues aux objets
marqueurs du fournisseur ou aux sidecars locaux `.meta.json` ; ne
dispensez pas les différences sans explication enregistrée.

Exécutez le test de contrat de destination depuis le réseau de
l'application :

```sh theme={null}
STORAGE_TEST_PROVIDER=s3 \
STORAGE_TEST_ENDPOINT=https://storage.example.com \
STORAGE_TEST_BUCKET=casebender \
AWS_REGION=us-east-1 \
./scripts/storage/validate-storage.sh
```

Pour les exemples GCS ou local, voir l'usage du script. Échantillonnez
également les preuves de haute valeur, les objets multipartie volumineux,
les noms Unicode, les fichiers vides, les métadonnées MIME et les objets
rétentionnés.

## 5. Basculer

1. Enregistrez l'ancienne configuration du fournisseur et la version de
   ressource Secret dans l'enregistrement de changement chiffré.
2. Confirmez que les entrées `StorageMigrationLedger` sont `VERIFIED`. Le
   processeur de migration copie d'abord, relit, vérifie le SHA-256,
   enregistre la version fournisseur de destination, puis seulement
   bascule vers `CUTOVER`.
3. Modifiez uniquement les profils de fournisseur explicites et les
   identifiants. Préservez le contenu des buckets et les clés durables.
4. Redémarrez l'application web et attendez `/api/health/ready`.
5. Exécutez les tests applicatifs
   téléversement/téléchargement/listage/copie/suppression et vérifiez le
   SHA-256.
6. Vérifiez les pièces jointes et preuves existantes sur plusieurs âges et
   tailles.
7. Reprenez les workers et l'ingestion, puis les écritures utilisateur.
8. Surveillez en continu les erreurs de stockage, les suppressions en
   échec, la latence, la limitation, la profondeur de file et les
   événements d'audit pendant la fenêtre de rollback.

N'exécutez pas de réécritures de clés de base de données sauf si une
migration spécifique à la version l'exige explicitement.

Pendant une fenêtre de compatibilité documentée, les références héritage
peuvent être lues depuis la source tandis que les objets adossés au
registre utilisent la destination. N'implémentez pas d'écritures duales
non bornées. Fermez les lectures héritage uniquement après que la
réconciliation confirme qu'il n'y a pas de références manquantes et que
l'approbation de rollback le permet.

## 6. Rollback

Le rollback n'est sûr que tant que l'ancienne source est conservée et que
les nouvelles écritures peuvent être réconciliées.

1. Réentrez en mode maintenance et mettez les écritures au repos.
2. Enregistrez tous les objets écrits vers la destination depuis la
   bascule.
3. Copiez le delta inverse vers la source sans suppression :

```sh theme={null}
rclone copy destination:casebender source:casebender \
  --checksum --metadata --fast-list \
  --log-level INFO --log-file rollback-copy.log
rclone check destination:casebender source:casebender \
  --download --one-way --combined rollback-check.txt
```

4. Exigez une vérification propre, puis restaurez la configuration de
   fournisseur et la version d'identifiants précédentes.
5. Redémarrez, exécutez les tests de cycle de vie/intégrité applicatifs et
   reprenez le trafic.
6. Conservez les deux magasins et toutes les preuves jusqu'à la fin de la
   revue d'incident/changement.

Si la rétention ou la politique source empêche la copie inverse, arrêtez et
restaurez la sauvegarde de cohérence enregistrée ; n'improvisez pas une
synchronisation destructive.

## 7. Clôture

* Réconciliez les comptages/octets finaux et archivez les hachages, les
  journaux, les versions d'outils, les approbations, les versions de
  configuration et les résultats applicatifs échantillonnés.
* Effectuez la rotation des identifiants de migration temporaires.
* Conservez la source en lecture seule pendant la période de rollback
  approuvée.
* Après signature formelle et revue légale/rétention, supprimez les données
  source via le processus d'élimination audité du fournisseur.
* Mettez à jour l'enregistrement de support avec le produit/la version du
  fournisseur, les détails TLS/CA, le résultat de contrat, le résultat de
  performance, le résultat de sauvegarde et l'exercice de rollback.

Exécutez une vérification de restauration isolée avant l'élimination de la
source :

```sh theme={null}
pnpm storage:backup-verify verify-restore \
  --manifest '<protected-manifest.json>' \
  --target-profile '<isolated-restore-profile>' \
  --isolated-prefix 'tenants/<test-tenant>/restore-verification/<exercise-id>' \
  --evidence-output '<sanitized-restore-evidence.json>'
```

Enregistrez le point de reprise et le temps de reprise réels. Les objectifs
RPO/RTO sans exercice mesuré de restauration et de rollback ne sont pas
des preuves.

## Mises en garde spécifiques aux fournisseurs

* **S3/Ceph RGW :** préservez les ID de version et les marqueurs de
  suppression ; les copies ordinaires peuvent ne pas conserver l'état
  Object Lock/conservation légale. Requalifiez la version produit exacte
  et la CA privée.
* **GCS :** préservez les générations numériques ; la rétention de bucket,
  la rétention d'objet, les conservations événementielles et la politique
  CMEK nécessitent une attestation de destination séparée.
* **Azure :** préservez les ID de version de blob ; l'immuabilité et la
  conservation légale sont spécifiques à la destination et les blobs
  copiés reçoivent de nouveaux ID de version.
* **MinIO héritage :** conservez à la fois l'instantané de volume d'origine
  et l'export API S3. N'importez jamais la disposition interne du système
  de fichiers MinIO dans un autre fournisseur.

Voir [Sauvegarde et restauration](/fr/deployment/storage-backup-restore) et
[Cycle de vie MinIO](/fr/deployment/storage-minio-lifecycle).
