
# Migrer la base de données

Sovrium migre normalement votre base au démarrage du serveur. `sovrium migrate` sépare les
deux : la commande fait évoluer le schéma puis rend la main, sans lancer de serveur ni
ouvrir de port.

```bash
sovrium migrate
```

Cette séparation apporte deux choses. Une plateforme peut exécuter les migrations dans une
**phase de release** plutôt qu'à l'intérieur du processus web. Et lorsqu'un déploiement ne
démarre plus, il vous reste un chemin vers sa propre base : la commande ne construit aucun
runtime applicatif, elle reste donc disponible là où `sovrium start` n'arrive plus au bout.

Il lui suffit de la connexion : `DATABASE_URL` pour PostgreSQL, ou rien du tout pour le
SQLite embarqué. Un chemin de configuration est accepté, et découvert automatiquement quand
il est omis, exactement comme pour `start`.

## Trois modes

| Commande                    | Question à laquelle elle répond                | Sortie                   |
| --------------------------- | ---------------------------------------------- | ------------------------ |
| `sovrium migrate [config]`  | Fais évoluer cette base.                       | `0` appliqué, `1` échoué |
| `sovrium migrate --dry-run` | Qu'est-ce qui _changerait_ ?                   | `0` sauf refus           |
| `sovrium migrate --check`   | Cette base peut-elle être migrée sereinement ? | `0` sûr, `1` bloqué      |

`--dry-run` et `--check` n'écrivent rien ni l'un ni l'autre, et ne peuvent pas être
combinés : ils posent deux questions différentes, et les lancer ensemble rendrait la
réponse ambiguë.

## Ce que la commande migre

« Migration » désigne deux systèmes indépendants dans Sovrium, et cette commande prend les
deux en charge.

|               | Migrations livrées                                | Tables de configuration                   |
| ------------- | ------------------------------------------------- | ----------------------------------------- |
| Source        | Les fichiers de migration fournis avec le binaire | `tables` dans votre configuration         |
| Couvre        | Tables d'authentification, système et internes    | Vos propres tables, vues et index         |
| Déterminé par | Le journal de migration inscrit dans votre base   | Une empreinte de vos définitions de table |

Les migrations livrées passent **toujours en premier**. Un champ `user` produit une vraie
clé étrangère vers les tables d'authentification : vos propres tables ne peuvent donc pas
être créées avant les migrations qui les construisent. N'en exécuter que la moitié
laisserait `sovrium start` faire du travail de schéma dans le processus web — précisément le
couplage que cette commande existe pour rompre.

## Appliquer les migrations

```bash
sovrium migrate app.yaml
```

```text
  Dialect: sqlite
  Migrations: /srv/app/drizzle/sqlite

  ✓ Applied 14 pending migrations. The journal is at 14 of 14.
    0000_mute_cassandra_nova
    0001_famous_leper_queen
    …
    0013_jazzy_karma

  ✓ Config tables reconciled: notes.
```

Chaque migration est nommée, et la position du journal est donnée sous forme de fraction :
« n'a rien appliqué » et « en a appliqué quatorze » ne se ressemblent jamais vues de
l'extérieur.

La commande est **idempotente**. Relancée sur une base déjà à jour, elle n'applique rien et
sort en `0` :

```text
  ✓ No pending migrations. The journal is at 14 of 14.

  ✓ Config tables reconciled: notes.
```

C'est ce qui la rend sûre comme crochet de déploiement : chaque déploiement peut l'appeler,
seuls ceux qui ont du travail en feront.

## Prévisualiser avec `--dry-run`

```bash
sovrium migrate app.yaml --dry-run
```

Nomme chaque migration en attente et chaque instruction qui serait exécutée sur vos propres
tables, sans rien écrire :

```text
  ⚠ Dry run — nothing was written.

  Dialect: sqlite
  Migrations: /srv/app/drizzle/sqlite

  would apply 14 pending migration(s)
    0000_mute_cassandra_nova
    …
    0013_jazzy_karma

  would create table notes
    CREATE TABLE IF NOT EXISTS notes (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
  updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
  deleted_at TEXT,
  title TEXT
)

  Re-run without --dry-run to apply this plan.
```

Quelques changements reconstruisent une table et y recopient les lignes. Les instructions
exactes de ces opérations dépendent de l'état de la table au moment où elles s'exécutent :
elles ne peuvent pas être rendues à l'avance. Elles sont donc **nommées et signalées comme
non simulées, jamais omises** — une prévisualisation qui sous-estime discrètement est pire
que pas de prévisualisation du tout, puisque c'est sur elle que vous décidez s'il faut
ouvrir une fenêtre de maintenance.

## Contrôle préalable avec `--check`

```bash
sovrium migrate app.yaml --check
```

Indique où en est la base — quel moteur, quel dossier de migrations, et quelle part du
journal elle a appliquée — puis rend un verdict :

```text
  Dialect: sqlite
  Migrations: /srv/app/drizzle/sqlite
  Applied: 0 of 14
  Pending: 14

  Pending migrations:
    0000_mute_cassandra_nova
    …
    0013_jazzy_karma

  ✓ Safe to migrate.
```

Sur une base déjà au schéma courant, le verdict devient `No pending migrations. This
database is at the current schema.` — également en sortie `0`.

Une sortie `1` signifie que la migration s'interromprait en cours de route, pour l'une de
ces trois raisons :

- **Identités de compte en double** — deux lignes d'authentification qu'une contrainte
  d'unicité introduite par une migration ultérieure ne peut pas conserver toutes les deux.
- **Identifiants client OAuth en double** — la même collision sur les clients du serveur
  OAuth.
- **Une migration publiée réécrite** — un fichier de migration dont l'empreinte enregistrée
  ne correspond plus au fichier livré par cette version.

Chaque cas est signalé en nommant les lignes fautives. Rien n'est réparé automatiquement :
supprimer l'une des deux lignes d'authentification en collision couperait l'accès de
quelqu'un. La commande les nomme et s'arrête, et c'est vous qui décidez laquelle survit.

:::callout
**`--check` est un pré-vol, pas une garantie.** Il signale les conditions dont il peut
prouver qu'elles bloqueraient la migration. Un rapport propre signifie qu'aucune n'a été
trouvée — pas que la migration réussira.
:::

## Dans une chaîne de déploiement

Parce qu'elle est idempotente et n'a besoin que de la connexion, la commande trouve sa place
dans la phase de release d'une plateforme :

```bash
sovrium migrate app.yaml && sovrium start app.yaml
```

Les séparer garde le travail de schéma hors du processus web, et donne à une migration
échouée son propre code de sortie plutôt qu'un démarrage qui meurt sans explication.
Associez-y `--check` en intégration continue, en amont du déploiement, pour découvrir une
migration bloquée avant d'interrompre le service.

## Ce que la commande ne fait pas

**Elle ne revient pas en arrière.** Les migrations publiées ne vont que vers l'avant et ne
sont jamais réécrites. Se remettre d'une mauvaise mise à jour passe par la restauration
d'une sauvegarde — voir [Mise à niveau et rollback](/fr/docs/upgrade-rollback).

**Elle n'écrit aucune donnée.** Les migrations façonnent le schéma ; les lignes viennent de
[`sovrium seed`](/fr/docs/cli-seed) ou de l'application elle-même. Elle laisse également de
côté le travail au mieux que le démarrage effectue une fois le schéma en place, pour qu'une
commande nommée `migrate` n'ait pas d'effets que son nom ne promet pas.

**Elle ne remplace pas un démarrage correct.** `sovrium start` migre toujours de lui-même.
Cette commande rend une mise à jour ratée récupérable et une chaîne de déploiement
explicite : c'est un chemin vers la base, pas une correction de la séquence de démarrage.

## Pages liées

- [Migrations de schéma](/fr/docs/migrations) — comment le schéma évolue au démarrage du serveur.
- [Mise à niveau et rollback](/fr/docs/upgrade-rollback) — sauvegarder avant un changement de version, restaurer après.
- [Charger des données](/fr/docs/cli-seed) — remplir le schéma que cette commande crée.
- [Infrastructure de base de données](/fr/docs/database-infrastructure) — SQLite par défaut, PostgreSQL via `DATABASE_URL`.
- [Aperçu du CLI](/fr/docs/cli) — résolution de la configuration et surface complète des commandes.
