> ## 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 migración de almacenamiento

> Copie, verifique, conmute y revierta el almacenamiento del proveedor sin pérdida de datos

Este runbook migra objetos de CaseBender sin cambiar las claves de objeto.
Usa semántica copy-first: el origen permanece autoritativo e intacto hasta
que expire la ventana de reversión. Se aplica a sistemas de archivos
locales, almacenamiento MinIO/compatible con S3, AWS S3 y GCS a través de
remotos `rclone`.

## Precondiciones

* Lea la política de soporte de almacenamiento y las notas de la versión
  de ambos proveedores.
* Confirme que la versión usa el outbox de eliminación durable
  independiente del proveedor. La brecha histórica de eliminación solo
  de MinIO está corregida; no arrastre esa limitación obsoleta a un
  diseño nuevo.
* Confirme la capacidad, el cifrado, el versionado, la retención, el
  ciclo de vida, el tamaño de objeto, los metadatos y el comportamiento
  de nomenclatura del destino.
* Cree identidades de migración de lectura en el origen y escritura en
  el destino con mínimo privilegio.
* Configure la confianza TLS; nunca use `--no-check-certificate`.
* Tome y pruebe una copia de seguridad de consistencia de PostgreSQL y
  del almacenamiento de origen.
* Registre el recuento de objetos, el total de bytes, las
  versiones/instantáneas de origen y la configuración.
* Establezca una ventana de cambio que permita la detención de
  escrituras y la reversión.

Genere y proteja el inventario autoritativo de objetos de PostgreSQL:

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

Cada elemento migrado debe identificar una versión/generación exacta de
objeto de origen, el tamaño y el SHA-256. PostgreSQL y esas versiones
exactas son un solo conjunto de consistencia. No migre un objeto
«latest» flotante cuando hay una versión registrada.

Los ejemplos siguientes usan `source:casebender` y
`destination:casebender`. Mantenga la configuración y los registros de
rclone fuera del repositorio y protéjalos como sensibles.

## 1. Inventario y dry run

```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
```

Revise las advertencias de metadatos no soportados. El cifrado, la
retención, la retención legal, las ACL y el historial de versiones
específicos del proveedor pueden no copiarse como metadatos ordinarios
de objeto; configure esos controles en el destino y preserve las
versiones de origen en la copia de seguridad. Nunca use `sync` para la
copia inicial porque puede eliminar objetos del destino.

## 2. Copia semilla mientras la aplicación está en línea

```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
```

Ajuste la concurrencia por debajo de los límites de limitación del
proveedor. Reintente los objetos fallidos y conserve el registro
completo. No infiera la integridad a partir de ETag: los objetos
multipart y cifrados pueden tener ETag que no son MD5.

## 3. Detenga las escrituras y capture el punto de consistencia

Bloquee las escrituras de usuario e integración usando el procedimiento
de mantenimiento de la versión. Pause la ingestión y los workers solo
después de que la cola se haya drenado o se haya retenido de forma
durable. Registre la marca de tiempo/LSN de la base de datos, la
versión/instantánea del bucket de origen y las réplicas de la
implementación. Verifique que no se estén produciendo escrituras de
almacenamiento.

Ejecute el 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
```

No elimine ni deshabilite el origen.

## 4. Verifique antes de la conmutación

```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` calcula el hash del contenido descargado y
evita la ambigüedad de ETag del proveedor. Exija cero objetos
faltantes, cambiados o ilegibles. Investigue las diferencias de
recuento procedentes de objetos marcadores del proveedor o de sidecars
locales `.meta.json`; no dispense las diferencias sin una explicación
registrada.

Ejecute la prueba de contrato del destino desde la red de la
aplicación:

```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
```

Para ejemplos de GCS o local, consulte el uso del script. Muestree
también evidencia de alto valor, objetos multipart grandes, nombres
Unicode, archivos vacíos, metadatos MIME y objetos retenidos.

## 5. Conmutación

1. Guarde la configuración del proveedor anterior y la versión de
   recurso del Secret en el registro de cambio cifrado.
2. Confirme que las entradas de `StorageMigrationLedger` están
   `VERIFIED`. El procesador de migración copia primero, lee de
   vuelta, verifica SHA-256, registra la versión del proveedor de
   destino y solo entonces transita a `CUTOVER`.
3. Cambie solo los perfiles de proveedor explícitos y las
   credenciales. Preserve el contenido de los buckets y las claves
   durables.
4. Reinicie la aplicación web y espere `/api/health/ready`.
5. Ejecute pruebas de carga/descarga/list/copy/delete de la
   aplicación y verifique SHA-256.
6. Verifique adjuntos y evidencia existentes de varias antigüedades
   y tamaños.
7. Reanude los workers y la ingestión, y después las escrituras de
   usuario.
8. Supervise de forma continua los errores de almacenamiento, las
   eliminaciones fallidas, la latencia, la limitación, la profundidad
   de cola y los eventos de auditoría durante la ventana de
   reversión.

No ejecute reescrituras de claves de la base de datos salvo que una
migración específica de la versión lo exija explícitamente.

Durante una ventana de compatibilidad documentada, las referencias
heredadas pueden leerse desde el origen mientras los objetos
respaldados por el ledger usan el destino. No implemente escrituras
duales sin límite. Cierre las lecturas heredadas solo después de que
la reconciliación confirme que no hay referencias faltantes y de que
la aprobación de reversión lo permita.

## 6. Reversión

La reversión es segura solo mientras se retenga el origen anterior y
las escrituras nuevas puedan reconciliarse.

1. Vuelva a entrar en modo de mantenimiento y detenga las escrituras.
2. Registre todos los objetos escritos en el destino desde la
   conmutación.
3. Copie el delta inverso al origen sin eliminación:

```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. Exija una comprobación limpia y, a continuación, restaure la
   configuración del proveedor anterior y la versión de la
   credencial.
5. Reinicie, ejecute pruebas de ciclo de vida/integridad de la
   aplicación y reanude el tráfico.
6. Conserve ambos almacenes y toda la evidencia hasta que se
   complete la revisión del incidente/cambio.

Si la retención o la política del origen impiden la copia inversa,
deténgase y restaure la copia de seguridad de consistencia
registrada; no improvise una sincronización destructiva.

## 7. Cierre

* Reconcilie los recuentos/bytes finales y archive hashes, registros,
  versiones de herramientas, aprobaciones, versiones de
  configuración y resultados de aplicación muestreados.
* Rote las credenciales temporales de migración.
* Mantenga el origen en solo lectura durante el período de reversión
  aprobado.
* Tras la firma formal y la revisión legal/de retención, elimine los
  datos de origen usando el proceso de eliminación auditado del
  proveedor.
* Actualice el registro de soporte con el producto/versión del
  proveedor, los detalles de TLS/CA, el resultado del contrato, el
  resultado de rendimiento, el resultado de la copia de seguridad y
  el ejercicio de reversión.

Ejecute una verificación aislada de restauración antes de eliminar
el origen:

```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>'
```

Registre el punto de recuperación y el tiempo de recuperación
reales. Los objetivos RPO/RTO sin un ejercicio medido de
restauración y reversión no son evidencia.

## Advertencias específicas del proveedor

* **S3/Ceph RGW:** preserve los ID de versión y los delete markers;
  las copias ordinarias pueden no retener el estado de Object
  Lock/retención legal. Recualifique la versión exacta del producto
  y la CA privada.
* **GCS:** preserve las generaciones numéricas; la retención del
  bucket, la retención de objetos, las retenciones basadas en
  eventos y la política CMEK necesitan atestación separada en el
  destino.
* **Azure:** preserve los ID de versión de blob; la inmutabilidad y
  la retención legal son específicas del destino y los blobs
  copiados reciben ID de versión nuevos.
* **MinIO heredado:** conserve tanto la instantánea original del
  volumen como la exportación de la API S3. Nunca importe el diseño
  interno del sistema de archivos de MinIO a otro proveedor.

Consulte [Copia de seguridad y restauración](/es/deployment/storage-backup-restore) y
[Ciclo de vida de MinIO](/es/deployment/storage-minio-lifecycle).
