Correctifs repris d'AJEAN : chiffrement, preset externe, heartbeat, commande du moteur

- Désactivation du chiffrement (amont cac0cda, 19918c6) : une valeur
  illisible ne bloque plus tout (quarantaine datée + copie du keyvault), et la
  reprise au démarrage déchiffre aussi les conversations au lieu de retirer la
  clé après les seules pages. Propre à Loki : les images de conversation
  (chatimg/) sont maintenant déchiffrées elles aussi — elles restaient
  chiffrées sans clé. Les .bak chiffrés devenus illisibles sont retirés.
- Preset externe (amont #95) : `loki serve` sort sans erreur (plus de boucle
  systemd « MODEL non défini »), le pré-vol l'accepte, le superviseur du
  conteneur ne le prend plus pour un plantage.
- Unité systemd du moteur : TimeoutStopSec=5 (bascule de preset bloquée 90 s
  en pleine génération).
- Heartbeat SSE (amont #105) : plus d'écriture après le retour du handler.
- Paramètres → Configuration : commande exacte du moteur copiable (clé API
  masquée, Strata compris) et nombre de couches du modèle à côté de NGL, lu
  dans l'en-tête GGUF (amont #108, #43) ; aussi dans l'éditeur de preset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Opus 5.5 committed 2026-10-07 09:28:42 +02:00
1 parent 4a9a5a1712
commit 127013b32b
16 files changed
+479 -34

No files matched your search

+32 -8
View File
@@ -188,18 +188,41 @@ func reencryptChatStores() error {
// decryptChatStores remet en clair les buckets de conversation. Exige la DEK.
func decryptChatStores() error {
_, err := decryptChatStoresSkipping()
return err
}
// unreadableValue : une valeur chiffrée qui ne se déchiffre pas avec la clé
// actuelle (écrite avec une autre clé, ou abîmée). Gardée telle quelle.
type unreadableValue struct {
Bucket string `json:"bucket"`
Key string `json:"key"`
Blob []byte `json:"blob"` // base64 en JSON
Error string `json:"error"`
}
// decryptChatStoresSkipping déchiffre tout ce qui peut l'être et RENVOIE ce qui
// ne le peut pas, au lieu de s'arrêter au premier échec : une seule valeur
// illisible bloquait toute la désactivation du chiffrement, sans dire laquelle
// (amont, 2026-10-03).
func decryptChatStoresSkipping() ([]unreadableValue, error) {
persistQ.flush() // même raison que reencryptChatStores
var bad []unreadableValue
for _, b := range encryptedBuckets {
if err := decryptBucket(b); err != nil {
return err
u, err := decryptBucket(b)
if err != nil {
return bad, err
}
bad = append(bad, u...)
}
return nil
return bad, nil
}
// decryptBucket remet en clair toutes les valeurs chiffrées d'un bucket. Exige
// la DEK en RAM. Sûr à rejouer.
func decryptBucket(bucket string) error {
// la DEK en RAM. Sûr à rejouer. Une valeur indéchiffrable est laissée telle
// quelle et renvoyée ; seule une erreur d'écriture est fatale.
func decryptBucket(bucket string) ([]unreadableValue, error) {
var bad []unreadableValue
for k, v := range allKV(bucket) {
raw := []byte(v)
if !looksEncrypted(raw) {
@@ -207,11 +230,12 @@ func decryptBucket(bucket string) error {
}
plain, err := decodeMemContent(raw)
if err != nil {
return err
bad = append(bad, unreadableValue{Bucket: bucket, Key: k, Blob: raw, Error: err.Error()})
continue
}
if err := putBytes(bucket, k, plain); err != nil {
return err
return bad, err
}
}
return nil
return bad, nil
}