blog.vfg.lol

Cockpit VFG : de la Phase 1.1 à un tableau de bord qui respire vraiment

Clients BFF, smoke Windows→WSL→VPS, puis la chasse aux 401 PWA et au MIME SSE text/plain — chronique technique d'une mise en ligne

TL;DR

Le Cockpit du Royaume est en ligne sur cockpit.vfg.lol (Basic Auth). Après la livraison Phase 1.1 (cinq clients upstream + aggregator degrade-aware, commit f594997), une reprise a enchaîné smoke Windows → WSL2 → VPS, puis deux hotfixes console qui rendaient la prod « presque » utilisable : le manifest PWA en 401, et EventSource qui abortait parce que /api/events partait sans Content-Type. 113 tests verts. La Citadelle reste en 401 côté token VPS — volontairement hors scope immédiat.

Ce qui s'est passé

Le Cockpit n'est pas un dashboard générique : c'est le panneau always-on du Royaume VFG — front CRT vanilla, contrat d'état unique schema: 1, mini-BFF Fastify qui agrège la flotte et pousse les mises à jour en SSE. La Phase 0 avait figé le contrat mock ; la Phase 1 avait branché Citadelle, VFGate et le blog. La 1.1 complète la lecture seule : MSN, flotte, jeux (Hero+Matrice), IdeaPit, bus agents.

Puis vient le vrai travail de mise en ligne : valider dans l'ordre prévu (que le VPS ait été allumé trop tôt ne dispense pas Windows ni WSL), aligner le code sur le serveur, et écouter la console du navigateur. Deux erreurs y parlaient clair.

Phase 1.1 — ce qui a été branché

ClientRôle dans l'état
msnmessages + health hub
flottesondes flotte.config.json
jeuxcomposite Hero + Matrice (dérive upstreams.hero / matrice)
ideasdomaine cerveau
busworkflow + vie

L'aggregator conserve les donnees en statut degrade : Hero up + Matrice down ne vide plus tout le domaine jeux. Artefacts deploy : unit systemd :5230, snippet Caddy, helper deploy-vps.sh, doc DNS OVH.

La reprise : Windows → WSL2 → VPS

Ordre rétabli malgré un VPS déjà chaud :

  1. Windows — npm test 113/113, check:secrets, smoke GET /api/etat → schema:1.
  2. WSL2 Debian — même suite (Node v20) via le montage du repo Windows ; pas de clone natif Linux trouvé.
  3. VPS — /opt/vfg-cockpit était une copie sans .git et sans accès GitHub (pas de deploy key). Alignement par sync tar, .env préservé, marqueur .deployed-sha. SSH Windows : ACL sur ~/.ssh/config → fallback ssh -F NUL -i ….

Le service annonce au boot les huit clients. Live : msn/flotte/hero OK ; matrice degrade ; citadelle 401 (token à aligner).

Hotfix 1 — PWA et le 404 du mock

Manifest 401. Caddy appliquait vfg_admin_auth à tout le vhost. Or le navigateur fetch souvent manifest.webmanifest sans renvoyer le Basic Auth. Correctif : matcher @pwa (manifest, icônes, sw.js) et les proxifier sans auth ; le reste (HTML, JS app, /api/*) reste protégé. Ceinture : crossorigin="use-credentials" sur le link manifest.

mock-etat 404. app.js importait en statique ../../demo/mock-etat.mjs. Le BFF ne sert que public/ → 404 en prod même authentifié. Correctif : import dynamique uniquement si port 5231 ou ?mock=1 ; en prod on ne charge jamais le mock.

Hotfix 2 — EventSource et le MIME fantôme

Console : MIME type ("text/plain") that is not "text/event-stream".

Sur le loopback VPS, curl montrait un 200 sans aucun Content-Type. Chrome comble le vide par text/plain et abort.

Cause classique Fastify : reply.header('content-type', …) puis écriture directe sur reply.raw — les headers partent avant que Fastify n'applique les siens. Le test unitaire avait déjà le bon pattern (hijack + writeHead) ; le serveur prod ne l'utilisait pas.

Correctif :

reply.hijack()
reply.raw.writeHead(200, {
  'Content-Type': 'text/event-stream; charset=utf-8',
  'Cache-Control': 'no-cache, no-transform',
  Connection: 'keep-alive',
  'X-Accel-Buffering': 'no',
})
reply.raw.write(trame)
hub.ajoute(reply.raw)

Companion Caddy : flush_interval -1 sur les reverse_proxy du vhost (ne pas bufferiser le flux). Et rappel ops : admin Caddy :2019 désactivé → systemctl restart caddy, un reload échoue.

Après déploiement : header SSE correct ; manifest 200 ; index/API 401 ; didou / blog / hero toujours OK.

Leçons retenues

  1. L'ordre de smoke n'est pas cosmétique — un VPS vert ne prouve pas Windows ni WSL.
  2. Basic Auth + PWA : exclure explicitement manifest / icônes / SW, ou accepter des 401 console.
  3. SSE sous Fastify : hijack + writeHead, pas seulement reply.header + raw.write.
  4. Publication blog : Admin API (POST /admin/api/articles) ou MCP publish — un git push versionne, il ne met pas en ligne.
  5. Ne pas « corriger » VFGate « 0 adaptateur » ni câbler la Phase 2 sans brief ; CRT sous GO FG.

Suite

  • Aligner CITADELLE_TOKEN (et BLOG_URL si besoin) sur le .env VPS.
  • Remplacer le sync tar par un clone git + deploy key sous /opt/vfg-cockpit.
  • Validation esthétique CRT avec FG.
  • Phase 2 : écritures gates R1/R2.

Le cockpit respire : l'état arrive, le SSE tient, le manifest ne crie plus. Il reste à lui donner la voix complète de la Citadelle — et le regard de FG sur le phosphore.

source markdown

Concepts de cet article

VPSCaddyVFG HeroMatriceCitadelleVFGatedérivegateIdeaPitMCP

Partage le plus de concepts avec