# OPS — Localhost auto-sync, cockpit local et supervision NAS ## Objet Ce document remplace et prolonge la première version de l’architecture `localhost auto-sync`. Il fige désormais **l’architecture opératoire complète** obtenue à l’issue de la session de stabilisation du cockpit local d’exploitation. Le périmètre ne se limite plus à : - garder `localhost` aligné sur `origin/main` ; - séparer correctement le repo canonique de développement et le miroir local. Il couvre maintenant aussi : - le **deuxième environnement local de travail** sur `4322` ; - le **cockpit local d’exploitation** sur `4310/4311` ; - la **supervision NAS** via `stack-health.json` ; - l’**instrumentation distante** de staging et prod via `__ops/health.json` ; - la **lecture causale** des conteneurs critiques ; - la **gradation des alertes** ; - la **fraîcheur temporelle** du cache NAS. --- ## 1. Architecture finale retenue L’architecture locale repose désormais sur **cinq espaces / rôles distincts**. ### A. Repo canonique de développement Chemin : ```text /Volumes/FunIA/dev/archicratie-edition/site ``` Usage : - développement normal ; - branches ; - commits ; - PR ; - tests manuels de nouvelles fonctionnalités ; - exécution du serveur de dev local sur `4322`. ### B. Worktree miroir local de `main` Chemin : ```text ~/ops-local/archicratie/localhost-worktree ``` Branche locale : ```text localhost-sync ``` Usage : - refléter automatiquement `origin/main` ; - servir le **miroir local de vérité** sur `http://127.0.0.1:4321` ; - ne jamais servir de lieu de développement de fond. ### C. Dossier d’ops local hors repo Chemin : ```text ~/ops-local/archicratie ``` Usage : - scripts ; - logs ; - fichiers d’état ; - cache NAS ; - artefacts du cockpit ; - LaunchAgents ; - PID files. ### D. Cockpit local d’exploitation Chemin : ```text ~/ops-local/archicratie/cockpit ``` Usage : - UI locale en `http://127.0.0.1:4310` ; - API locale en `http://127.0.0.1:4311` ; - lecture unifiée des états Git, LaunchAgents, serveurs Astro, staging, prod et stack NAS ; - déclenchement d’actions unitaires et composées. ### E. NAS DSM 7.3 Chemins clés : ```text /volume2/docker/archicratie_ops /volume2/docker/archicratie_ops/public/stack-health.json /volume2/docker/archicratie_ops/generate-stack-health.sh ``` Usage : - produire l’état de santé des conteneurs critiques ; - exposer un JSON simple rapatrié ensuite sur le Mac ; - rester la source de vérité côté Docker Synology. --- ## 2. Vue d’ensemble opératoire ### 2.1 Miroir local `4321` Le miroir local `4321` est la **vérité de `main`**. Flux : 1. `origin/main` avance. 2. Un script d’auto-sync local fetch le repo canonique. 3. Le worktree `localhost-sync` est réaligné. 4. `astro dev` tourne depuis `~/ops-local/archicratie/localhost-worktree`. 5. `http://127.0.0.1:4321` reflète alors `main`. ### 2.2 Atelier local `4322` Le port `4322` est le **vrai atelier de développement**. Flux : 1. on travaille dans `/Volumes/FunIA/dev/archicratie-edition/site` ; 2. le serveur de dev local est lancé manuellement depuis ce repo ; 3. le cockpit peut le démarrer / l’arrêter ; 4. un agent local de sync peut réaligner le repo canonique sur `origin/main` quand la branche est `main` et propre. ### 2.3 Cockpit `4310/4311` Le cockpit lit en continu : - l’état Git du repo canonique ; - l’état Git du miroir `localhost-sync` ; - les réponses HTTP de `4321` et `4322` ; - les réponses distantes staging / prod ; - les LaunchAgents locaux ; - les logs récents ; - les événements opératoires ; - le cache NAS rapatrié via SSH. ### 2.4 Supervision NAS Le NAS génère périodiquement : ```json stack-health.json ``` Ce fichier est ensuite rapatrié sur le Mac, mis en cache localement, puis injecté dans le cockpit. --- ## 3. Distinction conceptuelle consolidée ### 3.1 `4321 = miroir` - automatique ; - worktree dédié ; - vérité de `main` ; - ne pas utiliser pour le développement normal. ### 3.2 `4322 = atelier` - manuel ; - repo canonique ; - branches et travail vivant ; - peut être aligné automatiquement avec `origin/main` **uniquement** si le repo est propre et sur `main`. ### 3.3 `4310/4311 = cockpit` - interface d’exploitation ; - ne sert pas le site éditorial ; - supervise, diagnostique, orchestre et documente l’état global. --- ## 4. Scripts locaux stabilisés Le dossier `~/ops-local/archicratie` contient maintenant un ensemble cohérent de scripts. ### 4.1 Scripts du miroir `4321` ```text ~/ops-local/archicratie/auto-sync-localhost.sh ~/ops-local/archicratie/run-astro-localhost.sh ~/ops-local/archicratie/doctor-localhost.sh ~/ops-local/archicratie/install-localhost-sync.sh ``` Rôles : - vérifier runtime et dépendances ; - fetch `origin/main` ; - réaligner le worktree ; - exécuter `npm ci` si besoin ; - redémarrer le serveur miroir ; - produire un diagnostic global. ### 4.2 Scripts de l’atelier `4322` ```text ~/ops-local/archicratie/auto-sync-dev-main.sh ~/ops-local/archicratie/run-dev-4322.sh ~/ops-local/archicratie/stop-dev-4322.sh ``` Rôles : - fetch du repo canonique ; - réalignement automatique **seulement** si branche `main` + repo propre ; - démarrage manuel du dev sur `127.0.0.1:4322` ; - arrêt manuel du dev. Principe important : - si le repo canonique est sale, le script note `skip_dirty_main` et ne casse rien ; - si le repo canonique est déjà aligné, le script note `noop_main_aligned`. ### 4.3 Scripts du cockpit ```text ~/ops-local/archicratie/run-cockpit.sh ~/ops-local/archicratie/stop-cockpit.sh ``` Rôle : - démarrer / arrêter le cockpit avec son UI Vite et son API Node ; - standardiser l’exploitation pour éviter les commandes manuelles dispersées. ### 4.4 Script de rapatriement NAS ```text ~/ops-local/archicratie/pull-stack-health.sh ``` Rôle : - ouvrir une session SSH vers le NAS ; - lire le fichier `/volume2/docker/archicratie_ops/public/stack-health.json` ; - le recopier localement dans : ```text ~/ops-local/archicratie/cache/stack-health.json ``` - écrire un log d’exploitation. --- ## 5. Fichiers d’état et journaux locaux ### 5.1 Dossier ops ```text ~/ops-local/archicratie ``` Contient notamment : ```text astro-localhost.pid dev-4322.pid dev-main-4322.pid cockpit.pid last-sync.env last-dev-main-sync.env cockpit-events.jsonl ``` ### 5.2 Logs utiles ```text ~/ops-local/archicratie/logs/auto-sync-localhost.log ~/ops-local/archicratie/logs/astro-localhost.log ~/ops-local/archicratie/logs/pull-stack-health.log ``` Et côté LaunchAgents : ```text ~/Library/Logs/archicratie-pull-stack-health.out.log ~/Library/Logs/archicratie-pull-stack-health.err.log ``` ### 5.3 Cache NAS local ```text ~/ops-local/archicratie/cache/stack-health.json ``` Ce fichier est devenu un **artefact stratégique** : - il permet au cockpit de lire la stack NAS sans dépendre d’un appel live direct au NAS ; - il permet une supervision plus robuste ; - il rend possible une **alerte de fraîcheur**. --- ## 6. LaunchAgents et automatisation locale L’automatisation locale repose désormais sur **trois moteurs indépendants**. ### 6.1 Sync miroir Rôle : - tourner périodiquement ; - réaligner le worktree `localhost-sync` ; - maintenir `4321` fidèle à `origin/main`. Cadence constatée : - environ **toutes les 60 secondes**. ### 6.2 Sync dev-main Rôle : - surveiller le repo canonique ; - le fetch régulièrement ; - le réaligner si, et seulement si : - la branche est `main` ; - l’arbre de travail est propre. Cadence constatée : - environ **toutes les 75 secondes**. ### 6.3 Pull stack-health NAS LaunchAgent : ```text me.archicratie.pull-stack-health ``` Rôle : - rapatrier le cache NAS via SSH ; - mettre à jour le fichier local ; - nourrir la supervision causale. Cadence constatée : - environ **toutes les 60 secondes**. Pilotage manuel du LaunchAgent : ### Désactiver temporairement le rapatriement local ```bash launchctl bootout "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.pull-stack-health.plist ``` ### Réactiver le rapatriement local ```bash launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.pull-stack-health.plist ``` ### Interprétation : - bootout retire volontairement l’agent du domaine utilisateur courant ; - bootstrap recharge ce même agent dans le domaine utilisateur courant ; - en fonctionnement nominal, cet agent doit rester actif ; - après bootstrap, le fichier ~/ops-local/archicratie/cache/stack-health.json doit recommencer à être rafraîchi ; - dans le cockpit, launchAgents.pullStackHealth.loaded doit redevenir true. ### Point d’attention : - bootout sert au test contrôlé, au diagnostic ciblé ou à une maintenance volontaire ; - bootout ne constitue pas une commande d’exploitation normale ; - après tout usage de bootout, il faut restaurer l’état nominal avec bootstrap. --- ## 7. SSH Mac ↔ NAS ### 7.1 Situation initiale La copie du fichier NAS vers le Mac a rencontré plusieurs problèmes : - nom d’hôte local non résolu ; - port SSH non standard ; - `scp` indisponible / mal supporté dans la configuration DSM observée ; - authentification par mot de passe trop lourde. ### 7.2 Paramètres réels retenus - IP locale NAS : `192.168.1.20` - port SSH : `44322` - utilisateur : `archicratia` ### 7.3 Méthode de copie finalement retenue Plutôt que `scp`, la méthode robuste retenue a été : - `ssh ... 'cat /chemin/fichier' > fichier_local` Cela a permis : - de s’affranchir du problème `scp subsystem request failed`; - de garder un protocole simple ; - d’intégrer facilement le mécanisme dans `pull-stack-health.sh`. ### 7.4 Authentification par clé Une clé dédiée a été générée côté Mac et installée côté NAS. Le point bloquant n’était pas la clé elle-même, mais les permissions du `HOME` du compte Synology. Correctif déterminant côté NAS : - retirer les permissions `go-w` sur le `HOME` ; - conserver : - `~/.ssh` en `700` - `authorized_keys` en `600` Après cette correction : - l’authentification par clé est devenue fonctionnelle ; - le LaunchAgent de pull a pu fonctionner sans mot de passe. ### 7.5 Alias SSH local Une entrée `~/.ssh/config` a ensuite permis d’utiliser un alias opératoire du type : ```text transhands-ops ``` ce qui a simplifié les scripts de pull. --- ## 8. Supervision NAS : génération de `stack-health.json` ### 8.1 Script côté NAS Fichier : ```text /volume2/docker/archicratie_ops/generate-stack-health.sh ``` Rôle : - inspecter plusieurs conteneurs Docker clés ; - écrire un JSON simple ; - exposer cet état dans `public/stack-health.json`. ### 8.2 Exécution et droits Constat clé : - sans privilèges suffisants, le script peut échouer ou signaler `docker_unavailable` ; - via le planificateur DSM 7.3, exécuté correctement, le fichier est bien régénéré. Le comportement retenu : - exécution via tâche planifiée DSM avec les droits nécessaires ; - sortie du JSON écrite dans : ```text /volume2/docker/archicratie_ops/public/stack-health.json ``` ### 8.3 Problème rencontré Un comportement bloquant est apparu : - fichier existant possédé par `root` ; - exécution interactive sans privilège ; - `mv` demandant confirmation ou échouant ; - `chmod` impossible. Conclusion : - la génération doit être pensée comme **opération root planifiée**, pas comme simple commande utilisateur interactive. ### 8.4 Horodatage local Le champ `generatedAt` a d’abord été produit en UTC (`...Z`), ce qui déplaisait à l’exploitation locale. Le script a été ajusté pour produire désormais une heure locale explicite, par exemple : ```text 2026-03-18T13:26:32+01:00 ``` --- ## 9. Périmètre de la stack NAS désormais supervisée Le JSON NAS couvre désormais au moins les conteneurs suivants : - `edge-traefik` - `auth-authelia` - `auth-lldap` - `auth-redis` - `archicratie-web-blue` - `archicratie-web-green` - `gitea-old-2026-02-09-105211` - `gitea-act-runner` Le cockpit les remappe en : - `edgeTraefik` - `authelia` - `lldap` - `authRedis` - `webBlue` - `webGreen` - `gitea` - `giteaActRunner` --- ## 10. Déploiement staging / prod : instrumentation `__ops/health.json` ### 10.1 Problème initial Le cockpit savait tester : - le HTTP public staging ; - le HTTP public prod. Mais il ne savait pas lire proprement **le build réellement servi** par `web_blue` et `web_green`. ### 10.2 Cause Les conteneurs Nginx servaient bien le site, mais pas de manifeste d’état applicatif dédié. Les tentatives d’accès à : ```text /__ops/health.json ``` retournaient d’abord : - `404` côté conteneurs ; - puis `302` via Authelia côté domaine public. ### 10.3 Solution produite Deux modifications complémentaires ont été apportées. #### A. Côté build / déploiement Un script : ```text scripts/write-ops-health.mjs ``` écrit désormais un manifeste : ```text public/__ops/health.json ``` avec des champs du type : - `service` - `env` - `upstream` - `buildSha` - `builtAt` Ce manifeste est produit pendant le workflow de déploiement pour : - staging / `web_blue` - prod / `web_green` #### B. Côté edge / Traefik / Authelia Le routage a été ajusté pour que : ```text https://staging.../__ops/health.json https://archicratie.../__ops/health.json ``` restent **lisibles sans redirection Authelia**, tout en laissant le reste du site inchangé. ### 10.4 Correction de l’heure `builtAt` Comme pour `generatedAt`, le champ `builtAt` a été réaligné sur l’heure locale France via : ```text TZ=Europe/Paris ``` dans le workflow de déploiement. --- ## 11. Cockpit local d’exploitation ### 11.1 Emplacement ```text ~/ops-local/archicratie/cockpit ``` ### 11.2 Ports - UI : `http://127.0.0.1:4310` - API : `http://127.0.0.1:4311` ### 11.3 Démarrage Le cockpit est lancé via : ```bash ~/ops-local/archicratie/run-cockpit.sh ``` et arrêté via : ```bash ~/ops-local/archicratie/stop-cockpit.sh ``` ### 11.3 bis Mode opératoire recommandé Le pilotage normal du cockpit doit se faire via les scripts bash d’exploitation : ```bash ~/ops-local/archicratie/run-cockpit.sh ~/ops-local/archicratie/stop-cockpit.sh ``` et non via un lancement manuel dispersé du type npm run dev ou node server/index.mjs exécuté séparément. ### Justification : - run-cockpit.sh démarre correctement l’ensemble du cockpit ; - l’UI et l’API sont lancées ensemble dans le bon ordre logique ; - l’exploitation reste homogène et rejouable ; - stop-cockpit.sh fournit un arrêt propre, cohérent avec les PID et l’usage opératoire retenu. ### Autrement dit : - 4310 = façade visuelle ; - 4311 = moteur d’état ; - les scripts bash = méthode normale d’exploitation. ### 11.4 Architecture interne - UI React / Vite - API Node locale - lecture des états système via scripts, logs, fichiers JSON et `launchctl` ### 11.4 bis Source de vérité interne Le cockpit ne repose pas sur une simple interface décorative. La source de vérité opérationnelle est l’API locale : ```text http://127.0.0.1:4311/api/status ``` ### L’UI affichée sur : ```text http://127.0.0.1:4310 ``` n’est qu’une projection visuelle de cet état consolidé. ### Conséquence pratique : - si un doute existe sur l’exactitude de l’interface, il faut interroger directement GET /api/status ; - c’est cette réponse JSON qui fait foi pour : - l’état Git ; - les LaunchAgents ; - les serveurs 4321 et 4322 ; - staging / prod ; - la stack NAS ; - les alertes ; - les événements. Cette distinction est importante : l’UI montre, l’API atteste. ### 11.5 Endpoints utiles L’API du cockpit expose au moins : - `GET /api/health` - `GET /api/status` - `POST /api/action` - `POST /api/event` - `POST /api/events/clear` ### Remarques d’exploitation : - `GET /api/health` vérifie simplement que l’API locale répond ; - `GET /api/status` est l’endpoint central de supervision ; - `POST /api/action` déclenche une action opératoire unitaire ; - `POST /api/event` permet d’écrire un événement dans l’historique local ; - `POST /api/events/clear` vide explicitement l’historique des événements. En cas de diagnostic, `GET /api/status` doit être considéré comme la lecture machine de référence. --- ## 12. Ce que le cockpit sait lire Le cockpit agrège désormais : ### 12.1 Git - branche du repo canonique ; - SHA local ; - `origin/main` ; - état de propreté (`clean`, `modified`, `untracked`, etc.). ### 12.2 Miroir 4321 - port HTTP ; - PID ; - cwd du process ; - dernier sync ; - SHA du miroir. ### 12.3 Atelier 4322 - port HTTP ; - PID ; - branche du repo canonique ; - dernier sync dev-main ; - statut `noop_main_aligned` ou `skip_dirty_main`. ### 12.4 Staging et prod - HTTP public ; - lecture de `__ops/health.json` ; - `env` ; - `upstream` ; - `buildSha` ; - `builtAt`. ### 12.5 LaunchAgents - état chargé / non chargé ; - exit code ; - compteur de runs. ### 12.6 Logs récents - sync miroir ; - sync dev-main ; - Astro miroir ; - Astro dev ; - pull stack-health. ### 12.7 Stack NAS - chemin du cache local ; - `generatedAt` ; - `dockerAccessMode` ; - services détaillés. --- ## 13. Centre d’alertes et hiérarchie de gravité La supervision n’est pas seulement binaire ; elle est maintenant **qualifiée**. ### 13.1 Niveau `info` Exemple : - `giteaActRunner` indisponible Justification : - cela dégrade la chaîne de pipeline / déploiement ; - cela ne casse pas automatiquement le service public. ### 13.2 Niveau `warn` Exemples : - `authRedis` indisponible - `gitea` indisponible Justification : - impact opératoire réel ; - système encore potentiellement utilisable ; - attention nécessaire. ### 13.3 Niveau `critical` Exemples : - cache NAS trop ancien - services cœur réellement cassés - rupture forte de la lecture de confiance ### 13.4 Exemple d’alerte informative Quand `gitea-act-runner` a été arrêté, le cockpit a correctement affiché : - une alerte **Info** - sans transformer à tort l’état global du service public en catastrophe. ### 13.5 Exemple d’alerte `warn` Quand `auth-redis` a été arrêté, le cockpit a affiché : - `Redis d’authentification indisponible` - niveau **Attention** - avec la stack causale montrant le conteneur `exited / unhealthy`. ### 13.6 Exemple d’alerte `warn` sur la forge Quand Gitea a été arrêté, le cockpit a affiché : - `Forge Gitea indisponible` - niveau **Attention** - avec staging / prod encore sains. --- ## 14. Fraîcheur du cache NAS ### 14.1 Problème conceptuel identifié Même avec un bon `stack-health.json`, le cockpit pouvait mentir par omission si : - le scheduler DSM était cassé ; - ou le pull SSH Mac était stoppé ; - ou le cache local restait figé. ### 14.2 Solution Une lecture d’âge du cache a été ajoutée dans `buildAlerts(...)`. Règles de seuil : - pas d’alerte si le cache est frais ; - **warn** au-delà d’environ 3 minutes ; - **critical** au-delà d’environ 6 minutes. ### 14.3 Test réel effectué Le LaunchAgent `pull-stack-health` a été volontairement stoppé. Résultats observés : - dans une fenêtre intermédiaire : le cockpit a bien produit une alerte **Attention** ; - au-delà du seuil haut : le cockpit a bien produit **Cache NAS trop ancien** avec niveau **Critique**. Les commandes utilisées pour le test contrôlé de vieillissement du cache sont les suivantes. ### Interrompre volontairement le rapatriement local ```bash launchctl bootout "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.pull-stack-health.plist ``` ### Restaurer le fonctionnement nominal ```bash launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.pull-stack-health.plist ``` ### Lecture correcte du test ### Pendant ce test : - launchAgents.pullStackHealth.loaded peut passer à false ; - ce n’est pas une panne mystérieuse du cockpit ; - c’est l’effet recherché, puisque le LaunchAgent a été volontairement déchargé ; - le fichier ~/ops-local/archicratie/cache/stack-health.json reste alors figé à sa dernière valeur connue. ### Point d’interprétation essentiel Le cockpit peut encore afficher une stack NAS apparemment OK tout en levant une alerte de fraîcheur warn puis critical. Ce comportement est correct. Il signifie : - que le dernier cache disponible décrivait un état sain ; - mais que ce cache est désormais trop ancien pour constituer une vérité d’exploitation suffisamment fiable. Autrement dit, le cockpit ne dit pas : “la stack est saine avec certitude” Il dit : “le dernier état connu de la stack était sain, mais cette information est devenue trop ancienne pour être pleinement digne de confiance”. ### Conclusion : - la supervision ne dépend plus uniquement de l’existence du cache ; - elle qualifie aussi sa **fraîcheur temporelle**. --- ## 15. Actions opératoires disponibles dans le cockpit Le cockpit fournit maintenant : ### 15.1 Actions composées - réparer le miroir ; - préparer l’atelier dev. ### 15.1 bis Composition réelle Les actions composées ne sont pas des actions magiques indépendantes. Elles orchestrent plusieurs actions unitaires dans un ordre déterminé. Composition retenue : - **réparer le miroir** : 1. exécuter `doctor-localhost` 2. exécuter le sync miroir `4321` - **préparer l’atelier dev** : 1. exécuter le sync `dev-main` 2. démarrer le serveur local `4322` Règle d’exécution : - si la première étape échoue, la chaîne s’arrête ; - la deuxième étape n’est pas lancée si la première n’est pas valide. Règle de traçabilité : - les actions composées écrivent un **événement composite** synthétique dans l’historique ; - les sous-actions internes peuvent être exécutées en mode silencieux pour éviter un doublonnage inutile dans le journal. ### 15.2 Actions unitaires - lancer `doctor-localhost` ; - forcer le sync miroir `4321` ; - forcer le sync dev-main ; - démarrer `4322` ; - arrêter `4322`. ### 15.2 bis Périmètre et garde-fous Les actions unitaires du cockpit pilotent avant tout **l’exploitation locale sur le Mac**. Elles agissent notamment sur : - les scripts d’ops sous `~/ops-local/archicratie` ; - le miroir local `4321` ; - le serveur de dev local `4322` ; - les états et journaux locaux. Elles ne constituent pas un mécanisme de mutation directe de staging ou prod. Staging et prod sont principalement : - lus ; - sondés ; - comparés ; - diagnostiqués. Points importants : - `démarrer 4322` et `arrêter 4322` n’affectent que l’atelier local ; - `sync dev-main` ne doit pas casser le repo canonique : le réalignement automatique n’a lieu que si le repo est sur `main` et propre ; - certaines actions sont volontairement désactivées dans l’UI selon l’état courant ; - une confirmation utilisateur peut être demandée avant déclenchement. ### 15.3 Journal d’événements Les actions déclenchées depuis le cockpit peuvent être journalisées dans : ```text ~/ops-local/archicratie/cockpit-events.jsonl ``` ### Ce journal peut contenir : - des événements unitaires ; - des événements composites. ### Chaque événement conserve au moins des informations du type : - horodatage ; - type d’action ; - libellé ; - succès / échec ; - code de sortie ; - durée ; - script concerné ; - résumé opératoire. ### Ce journal constitue une mémoire locale d’exploitation utile pour : - relire les actions effectuées ; - comprendre un enchaînement opératoire ; - garder une trace minimale des gestes réalisés depuis le cockpit. ### Le cockpit sait aussi vider cet historique via l’API dédiée : - POST /api/events/clear ### Point important : - vider l’historique des événements ne supprime pas les logs techniques ; - cela ne modifie ni les LaunchAgents, ni les PID, ni les fichiers d’état, ni les repos Git ; - cela efface uniquement la mémoire locale des événements cockpit. --- ## 16. Règles d’exploitation consolidées ### 16.1 Règle d’or Le repo canonique n’est pas le miroir local. ### 16.2 Règle miroir `4321` doit raconter la vérité de `main`, pas l’état du travail en cours. ### 16.3 Règle atelier `4322` est le lieu du travail vivant, du test manuel et des branches. ### 16.4 Règle d’ops Les scripts d’ops et LaunchAgents vivent sous `HOME`, pas sur `/Volumes/...`. ### 16.5 Règle de vérité Un état n’est réellement fiable que si l’on connaît : - le SHA ; - le cwd ; - le process réel ; - la fraîcheur de la donnée ; - la causalité de la panne. --- ## 17. Commandes de contrôle essentielles ### 17.1 SHA et branches ```bash git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD git -C /Volumes/FunIA/dev/archicratie-edition/site rev-parse HEAD git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main git -C ~/ops-local/archicratie/localhost-worktree branch --show-current ``` ### 17.2 Cockpit ```bash ~/ops-local/archicratie/run-cockpit.sh ~/ops-local/archicratie/stop-cockpit.sh curl -s http://127.0.0.1:4311/api/status | python3 -m json.tool | sed -n '1,260p' ``` ### 17.3 Dev 4322 ```bash ~/ops-local/archicratie/run-dev-4322.sh ~/ops-local/archicratie/stop-dev-4322.sh ``` ### 17.4 Pull stack-health ```bash ~/ops-local/archicratie/pull-stack-health.sh launchctl print "gui/$(id -u)/me.archicratie.pull-stack-health" | sed -n '1,120p' cat ~/ops-local/archicratie/cache/stack-health.json tail -n 20 ~/ops-local/archicratie/logs/pull-stack-health.log ``` # Commandes complémentaires de test contrôlé : ```bash launchctl bootout "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.pull-stack-health.plist launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.pull-stack-health.plist ``` ### 17.5 Miroir et doctor ```bash ~/ops-local/archicratie/auto-sync-localhost.sh ~/ops-local/archicratie/doctor-localhost.sh ``` --- ## 18. Procédures de secours ### 18.1 Si `4321` ment Vérifier : - SHA du worktree ; - process Astro ; - cwd réel ; - logs du miroir ; - doctor. ### 18.1 bis Lecture correcte du symptôme Quand `4321` “ment”, il faut d’abord déterminer de quel mensonge il s’agit réellement : - le worktree n’est pas aligné sur `origin/main` ; - le bon worktree existe, mais le mauvais process sert le port `4321` ; - le sync a bien eu lieu, mais l’interface observée ne reflète pas encore le bon état. Ordre de lecture recommandé : 1. vérifier le SHA du worktree miroir ; 2. vérifier le SHA attendu de `origin/main` ; 3. vérifier le process réellement attaché au port `4321` ; 4. vérifier le `cwd` réel de ce process ; 5. relire les logs du sync miroir et du serveur Astro ; 6. terminer par `doctor-localhost` si le doute persiste. Principe : - un `4321` trompeur est rarement un problème “front” ; - c’est presque toujours un problème de **SHA**, de **process**, de **cwd**, ou de **chaîne de sync**. ### 18.2 Si `4322` ne suit plus `main` Vérifier : - branche du repo canonique ; - propreté de l’arbre ; - logs `auto-sync-dev-main.sh`. ### 18.2 bis Ne pas confondre dérive normale et panne Le port `4322` n’a pas vocation à refléter automatiquement `main` dans tous les cas. Deux situations sont normales et ne doivent pas être interprétées comme des pannes : - le repo canonique est sur une autre branche que `main` ; - le repo canonique est sur `main` mais l’arbre est localement modifié. Dans ces cas, le cockpit ou les scripts peuvent produire des états du type : - `skip_dirty_main` - ou absence de réalignement automatique Ce comportement est volontaire. Principe : - `4322` est un **atelier de travail vivant** ; - il ne doit pas être réaligné de force si cela risque d’écraser ou de perturber le travail local. La bonne question n’est donc pas seulement : - “est-ce que `4322` suit `main` ?” mais : - “avait-il vocation à suivre `main` dans l’état courant du repo ?” ### 18.3 Si le cockpit dit n’importe quoi sur le NAS Vérifier : - `stack-health.json` sur le NAS ; - le planificateur DSM ; - le LaunchAgent `pull-stack-health` ; - la fraîcheur du cache local. - si nécessaire, couper puis relancer explicitement le LaunchAgent avec `launchctl bootout ...` puis `launchctl bootstrap ...`. ### 18.3 bis Distinguer panne NAS, panne de rapatriement et cache périmé Si la lecture NAS semble incohérente, il faut distinguer trois cas très différents : #### A. Le NAS produit mal son état Indices possibles : - `stack-health.json` absent ou invalide côté NAS ; - `dockerAccessMode` incohérent ; - conteneurs signalés `docker_unavailable` ; - problème de tâche planifiée DSM ou de privilèges côté génération. #### B. Le NAS produit bien son état, mais le Mac ne le rapatrie plus Indices possibles : - `stack-health.json` correct sur le NAS ; - cache local figé sur le Mac ; - `launchAgents.pullStackHealth.loaded = false` ; - logs de `pull-stack-health` arrêtés. #### C. Le dernier cache local est encore lisible, mais il est trop ancien Indices possibles : - services encore affichés comme `OK` ; - alerte de fraîcheur `warn` ou `critical` ; - `generatedAt` ancien ; - aucun rafraîchissement récent du cache. La bonne méthode n’est donc pas seulement de “regarder la stack”, mais de répondre successivement à trois questions : 1. le NAS génère-t-il correctement le fichier ? 2. le Mac le rapatrie-t-il encore ? 3. la donnée affichée est-elle encore fraîche ? ### 18.4 Si staging / prod n’exposent plus `__ops/health.json` Vérifier : - le workflow de déploiement ; - `scripts/write-ops-health.mjs` ; - le routage Traefik / Authelia ; - les endpoints internes `8081` / `8082`. ### 18.4 bis Méthode de tri diagnostique Quand `__ops/health.json` n’est plus lisible, il faut d’abord identifier **à quel étage** se situe la panne. #### Cas 1 — l’endpoint interne est déjà en erreur Si : - `http://127.0.0.1:8081/__ops/health.json` - ou `http://127.0.0.1:8082/__ops/health.json` retourne `404` ou une autre erreur, alors le problème est plutôt : - côté build ; - côté contenu servi par Nginx ; - ou côté déploiement du manifeste. #### Cas 2 — l’endpoint interne fonctionne mais le domaine public redirige ou bloque Si l’interne fonctionne, mais que le domaine public renvoie `302`, `401` ou un comportement auth inattendu, alors le problème est plutôt : - côté Traefik ; - côté règles de routage ; - côté Authelia / exemptions ; - côté exposition publique de `__ops/health.json`. #### Cas 3 — l’endpoint répond `200`, mais le contenu est incohérent Si `__ops/health.json` existe et répond, mais que `env`, `upstream`, `buildSha` ou `builtAt` sont faux ou obsolètes, alors le problème est plutôt : - dans la génération du manifeste ; - dans le workflow de déploiement ; - ou dans le moment précis où le manifeste est écrit dans l’image livrée. Principe : - `404` interne → problème de build / image / contenu servi ; - `302` ou `401` public → problème de routage / auth ; - `200` mais mauvais contenu → problème de génération ou d’injection du manifeste. --- ## 19. Tests réels désormais qualifiés Les validations suivantes ont été observées pendant la session : - staging / prod exposent bien `__ops/health.json` en public ; - `buildSha` et `builtAt` sont lisibles ; - `builtAt` est revenu à l’heure locale souhaitée ; - la stack NAS est rapatriée côté Mac ; - le cockpit sait afficher les services : - `authRedis` - `gitea` - `giteaActRunner` - arrêt du runner Gitea → alerte `info` - arrêt de Redis auth → alerte `warn` - arrêt de Gitea → alerte `warn` - vieillissement artificiel du cache NAS → `warn` puis `critical` --- ## 20. État final de référence Quand tout fonctionne correctement, l’état attendu est : - `4321` = miroir fidèle de `origin/main` - `4322` = atelier local maîtrisé - `4310/4311` = cockpit lisible et opératoire - staging = build lisible via `__ops/health.json` - prod = build lisible via `__ops/health.json` - stack NAS = lisible via cache local frais - alertes = hiérarchisées et causales - actions cockpit = pilotage rapide sans confusion --- ## 21. Ce qu’il ne faut pas oublier Cette architecture n’est plus seulement une astuce de localhost. C’est une **micro-ingénierie d’exploitation locale complète**. Elle repose sur : - séparation des rôles ; - automatisation légère mais fiable ; - lecture causale ; - instrumentation des sites ; - cache NAS rapatrié ; - cockpit local ; - mémoire documentaire durable. --- ## 22. Résumé ultra court ### Pour voir la vérité de `main` ```text http://127.0.0.1:4321 ``` ### Pour travailler vraiment ```text /Volumes/FunIA/dev/archicratie-edition/site ``` ### Pour superviser et piloter ```text http://127.0.0.1:4310 ``` ### Pour lire l’état machine consolidé ```text http://127.0.0.1:4311/api/status ``` ### Pour vérifier la stack NAS ```text ~/ops-local/archicratie/cache/stack-health.json ``` ### Pour réparer vite ```bash ~/ops-local/archicratie/doctor-localhost.sh ~/ops-local/archicratie/auto-sync-localhost.sh ~/ops-local/archicratie/pull-stack-health.sh ``` --- ## 23. Pistes futures à forte valeur Les prochaines améliorations les plus pertinentes seraient : - journal automatique des incidents détectés / résolus ; - diagnostic synthétique de cause probable dans le cockpit ; - regroupement visuel des services NAS par familles : - service public - authentification - forge / déploiement ; - raffinement documentaire dans `START-HERE.md` et doc d’exploitation. --- ## Conclusion L’architecture locale est désormais passée : - d’un simple `localhost auto-sync` - à un **dispositif d’exploitation local complet**. Le résultat essentiel est le suivant : - on sait **où** se trouve la vérité ; - on sait **quel** serveur sert quoi ; - on sait **pourquoi** une alerte remonte ; - on sait **comment** diagnostiquer et réparer ; - on sait **rejouer** l’installation ; - on a désormais une mémoire technique durable de l’ensemble.