Skip to content

Migration du schéma de données

Runeya maintient la compatibilité avec les versions précédentes de ./.runeya/ via un système de migrations automatiques au démarrage.

Fonctionnement

Au démarrage, le serveur lit schema-version.json et applique les migrations nécessaires dans l'ordre :

schema-version.json: { "version": 2 }

                  migrations disponibles
                      v2 → v3 (appliquée)

                  schema-version.json: { "version": 3 }

Migrations disponibles

migrate-from-legacy.ts (v1 → v3)

Migration principale depuis le format legacy :

  • Crée des environnements service-scoped depuis les anciens inheritAllEnv et serviceVariables
  • Supprime les champs obsolètes
  • Met à jour le schéma de version

Ajouter une migration

typescript
// apps/server/src/migrations/v3-to-v4.ts
export async function migrateV3ToV4(dataDir: string): Promise<void> {
  const services = await readJson(join(dataDir, 'services.json'))

  const migrated = services.map(service => ({
    ...service,
    newField: 'default-value',  // nouveau champ avec valeur par défaut
  }))

  await writeJsonAtomic(join(dataDir, 'services.json'), migrated)
}

Puis dans le runner de migrations :

typescript
// apps/server/src/migrations/index.ts
const migrations = [
  { from: 1, to: 3, fn: migrateFromLegacy },
  { from: 3, to: 4, fn: migrateV3ToV4 },  // nouvelle
]

Écriture atomique

Toutes les migrations utilisent l'écriture atomique pour éviter la corruption :

typescript
async function writeJsonAtomic(path: string, data: unknown): Promise<void> {
  const tmp = path + '.tmp'
  await fs.writeFile(tmp, JSON.stringify(data, null, 2))
  await fs.rename(tmp, path)  // atomique sur POSIX
}

Migration — Image Support (2026-03-08)

Contexte

L'ajout du support d'images dans le chat crée un nouveau dossier de stockage temporaire et introduit deux services (ImageStorageService, ImageCleanupService) démarrés automatiquement. Aucune migration de schéma de données n'est requise.

Étapes pour une installation existante

1. Vérifier la version de packages/shared

Après git pull, reconstruire le package partagé :

sh
yarn workspace @runeya/packages-shared build

Sans cette étape, les nouveaux exports (ImagePartSchema, ImagePart) ne seront pas disponibles et la compilation TypeScript échouera.

2. Installer les nouvelles dépendances

sh
yarn install

Les packages multer et uuid sont ajoutés dans apps/server/package.json.

3. Démarrer le serveur

Au premier démarrage après mise à jour, le serveur crée automatiquement ~/.runeya/tmp/images/ avec les permissions 700. Aucune action manuelle n'est requise.

4. Vérifier les permissions du dossier (production)

Si le dossier existe déjà avec des permissions incorrectes :

sh
chmod 700 ~/.runeya/tmp/images/

OBLIGATOIRE en production. Des permissions trop larges (ex. 755) exposeraient les images uploadées à d'autres utilisateurs système.

5. Mode LAN (RUNEYA_LAN_PROXY=true) — point d'attention

L'endpoint POST /api/images/upload est actuellement non authentifié en mode LAN. La protection JWT est planifiée pour le sprint suivant. En attendant, évaluer l'exposition réseau selon votre contexte.

Variables d'environnement

Aucune nouvelle variable obligatoire pour le mode local par défaut.

VariableContexteDescription
RUNEYA_LAN_PROXYMode LANLorsque true, expose le port 9545 sur 0.0.0.0. Déclenche le modèle de menace LAN pour les endpoints images.

Rollback

En cas de problème, le rollback ne nécessite pas de migration inverse des données :

  • Les messages existants ne contiennent pas de parts image (rétrocompatibilité garantie).
  • Supprimer ~/.runeya/tmp/images/ libère l'espace disque sans affecter les conversations.

Backup avant migration

TIP

Runeya crée automatiquement un backup de ./.runeya/ avant d'appliquer des migrations. Les backups sont dans ./.runeya/backups/.

Publié sous licence MIT.