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
inheritAllEnvetserviceVariables - Supprime les champs obsolètes
- Met à jour le schéma de version
Ajouter une migration
// 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 :
// 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 :
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é :
yarn workspace @runeya/packages-shared buildSans cette étape, les nouveaux exports (ImagePartSchema, ImagePart) ne seront pas disponibles et la compilation TypeScript échouera.
2. Installer les nouvelles dépendances
yarn installLes 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 :
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.
| Variable | Contexte | Description |
|---|---|---|
RUNEYA_LAN_PROXY | Mode LAN | Lorsque 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
partsimage (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/.