L'en-tête de l'interface interroge /api/status en boucle : il est
désormais assemblé par la façade, à partir des aides portées (état du
service par le fichier PID, sonde /health, preset externe, cause d'un
échec de chargement lue dans le journal, pourcentage de chargement, preset
actif, alertes de volume et de FUSE). Sur une base réelle, sa réponse est
octet pour octet celle du Go.
Journal du moteur, emplacements et nombre de couches du modèle suivent.
L'état du moteur s'appuie sur la résolution des modèles de gguf.rs plutôt
que sur sa propre copie.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Le Go expose sa base à la façade par l'API interne : lecture, écriture,
suppression d'une clé et lecture d'un bucket entier. Il reste l'unique
propriétaire du fichier bbolt ; les écritures passent par putBytes/update
et invalident son cache comme une écriture locale. Base illisible : 503,
pour que Rust distingue « rien » de « pas pu lire ».
Côté Rust : client du store (seul point de passage, que la migration
finale de la base ne touchera qu'ici), routeur /api avec contexte partagé
et garde d'authentification réutilisable ; /api/ping y emménage. Modules
réservés aux aides portées ensuite (système, état du moteur, presets,
chemins, GGUF).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
L'interface (index, marked, service worker, manifeste, polices) est
désormais servie par loki-rs, embarquée par build.rs depuis la même source
que le go:embed — les deux binaires d'un build servent la même UI. Mêmes
en-têtes de cache que le Go, gzip à la première demande puis gardé en
mémoire, jamais sur les polices ni en HEAD.
L'authentification de pilotage est portée à l'identique (requireWebAuth,
crossSiteReject, localHostName, Bearer en temps constant, mêmes messages,
mêmes codes) ; les cas de TestCrossSiteReject sont repris un pour un. La
clé est demandée à l'API interne du Go à chaque requête ; si elle ne
répond pas proprement, la façade ferme (503). /api/ping est la première
route authentifiée servie par Rust.
Le jeton de l'API interne est tiré au hasard à chaque démarrage et passé
au Go par l'environnement. La façade rend 404 sur /internal/* venu de
l'extérieur et efface X-Loki-Internal entrant avant tout relais.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Premier lot de la migration vers Rust. Le binaire loki-rs :
- serve : prend le port public (8090), lance `loki web 8091` en écoute
locale et lui relaie tout — HTTP, flux SSE trame par trame, WebSocket.
Les en-têtes de bout en bout passent intacts (Host, Authorization,
Origin, Sec-Fetch-*, X-Forwarded-Proto : le Go en tire ses contrôles
d'accès) ; X-Loki-Via entrant est effacé, un client ne doit jamais
pouvoir se faire passer pour le tunnel. Go mort : relancé avec attente
croissante, 502 lisible entre-temps.
- self-update : lit la release « rolling », installe loki et loki-rs dans
$LOKI_HOME/bin/<build>/ après vérification SHA-256, bascule par
réécriture atomique de release.json. Les versions s'ordonnent par numéro
de run CI ; une ABI d'image différente n'est jamais installée. Toute
erreur laisse l'état précédent, le démarrage n'est jamais bloqué.
Le HTTPS passe par curl (présent dans l'image) : pas de pile TLS ici.
- which-bin : dossier d'où l'entrypoint prend les deux binaires, toujours
ensemble.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>