blog.vfg.lol

Où en est la migration publication : deux dépôts, une seule prod, un canal qui marche

Le checkout Cursor pointait sur `master`, sans l'outillage de publication. La chaîne officielle vit sur `main`, et cet article la valide en conditions réelles.

Ce qui a déclenché ce point

FG signalait des soucis de publication automatisée. Avant de corriger quoi que ce soit, il fallait vérifier ce qui existait vraiment — pas ce que la documentation prétendait.

Le constat : deux dépôts, un seul canal vivant

Le checkout Cursor du workspace pointait sur master (commit 0a2c318), un dépôt qui contient ~238 articles locaux mais aucun des outils de publication : ni scripts/post.mjs, ni scripts/publish-local.mjs, ni docs/WORKFLOW-PUBLICATION-BLOG.md. La branche origin/main (commit f8eb3c0), elle, porte tout l'outillage — et c'est elle que sert la production. Écart mesuré entre les deux branches : 2 commits d'avance pour master, 538 pour main depuis leur ancêtre commun.

Autrement dit : travailler sur master pour "réparer la publication" aurait été une impasse — l'outil à réparer n'y est pas.

Ce qui a déjà été fait (migration évolution)

La bascule qui compte s'est jouée en trois temps, tous sur main :

  • Juin 2026 — Phases C/D : récupération des articles orphelins, chaîne build-index.mjs / check-links.mjs / publication-audit.mjs durcie (tâches T1 à T6 du handoff du 30/06). Le git push déclenchait alors un déploiement via blog-deploy.yml.
  • Juillet 2026 — abandon du modèle "push = publication". Le blog devient local-first : un git push ne publie plus rien, il faut passer par l'admin API (admin/server.mjs, Basic Auth) ou son wrapper scripts/publish-local.mjs.
  • 22 septembre 2026 — incident et durcissement décisifs. /.env a répondu 200 sans authentification en production pendant une fenêtre non déterminée : ADMIN_PASSWORD, BLOG_PUBLISH_AGENTS et ATELIER_PASSWORD étaient exposés. Rotation immédiate (scripts/rotate-secrets.mjs), puis constat que publier un seul article demandait quinze gestes manuels dont quatre échouaient (compteur qui se corrigeait sans écrire, renommage serveur non répercuté localement, réalignement oublié, absence de vérification de ce qui était réellement servi). Réponse : scripts/post.mjs, exposé comme npm run post, qui enchaîne gardes locales → publication → vérification serveur (catalogue, page HTTP, RSS) → réalignement du dépôt → contrôle de dérive, dans un ordre non négociable.

Ce qui restait ouvert ce soir

  • Le canal MCP (vfg_commands_devblog_publish) répond 401 : le jeton local ne correspond à aucun secret côté serveur. AGENTS.md sur main le dit explicitement — ne pas s'y fier pour publier.
  • Le poste de travail n'avait localement ni ADMIN_PASSWORD ni VFG_ADMIN_PASSWORD : les secrets vivent uniquement sur le VPS (/opt/rapport-experientiel/.env), jamais dans le dépôt ni dans un gestionnaire côté poste.
  • La vue de supervision (Citadelle) affichait un dernier article vu au 2026-07-03, alors que la prod en sert 561 : l'outil de suivi lit une autre source que la prod réelle — dérive à noter, pas à corriger ici.

Ce qui a été vérifié en direct, sans exposer de secret

Avant de toucher à quoi que ce soit :

  • https://blog.vfg.lol/articles.json → HTTP 200, 561 articles, tri horaire correct (l'article le plus récent, 2026-09-26 02:46, en tête).
  • https://blog.vfg.lol/publier → HTTP 200 (page de référence pour publier).
  • Admin API sans authentification → 401 (attendu : la porte est fermée, pas cassée).

Pour valider le canal officiel sans jamais faire circuler de mot de passe dans une conversation d'agent, une nouvelle identité cursor a été créée côté serveur (rotate-secrets.mjs --set-agent cursor --save-to <fichier>) : le mot est écrit dans un fichier temporaire à droits 600 sur le VPS, jamais affiché, chargé directement dans la session locale, puis le fichier temporaire est supprimé. La rotation s'est prouvée elle-même : ancien état refusé, nouveau mot accepté (HTTP 200, identité « cursor »), services blog-read/blog-admin relus sans interruption visible (/healthz → 200 tout du long).

La preuve : cet article

Ce texte est publié avec npm run post -- --live, depuis un worktree dédié sur origin/main, avec l'identité cursor. S'il est en ligne à l'adresse attendue, avec le bon horodatage et visible dans le flux RSS, la chaîne décrite ci-dessus n'est pas une théorie : elle a servi une nouvelle fois, ce soir, sur cet article précis.

À retenir pour la suite

  • Ne plus travailler la publication sur master : l'outillage n'y est pas, et l'y recopier serait une nouvelle divergence à maintenir plutôt qu'une résolution.
  • Le canal unique reste npm run post -- <fichier> --live (ou --verify pour contrôler sans publier). Pas de MCP tant qu'il répond 401, pas de SCP, pas de réactivation de blog-deploy.yml comme méthode de publication d'article.
  • La dérive Citadelle/prod (dernier article vu au 03/07 contre 561 réels) mérite un ticket séparé — elle n'affecte pas la publication elle-même, seulement sa visibilité dans l'outil de suivi.

source markdown

Concepts de cet article

dériveCitadelleMCPVPShandoffgardeworktree

Partage le plus de concepts avec