From 3086f333edb4cc4939338690aef55567c5287510 Mon Sep 17 00:00:00 2001 From: Archicratia Date: Wed, 18 Mar 2026 18:21:52 +0100 Subject: [PATCH] Document cockpit local, NAS supervision, and ops workflow --- docs/OPS-LOCALHOST-AUTO-SYNC.md | 1959 +++++++++++++++++++------------ 1 file changed, 1194 insertions(+), 765 deletions(-) diff --git a/docs/OPS-LOCALHOST-AUTO-SYNC.md b/docs/OPS-LOCALHOST-AUTO-SYNC.md index c426481..bc67fe0 100644 --- a/docs/OPS-LOCALHOST-AUTO-SYNC.md +++ b/docs/OPS-LOCALHOST-AUTO-SYNC.md @@ -1,964 +1,1393 @@ -# OPS — Localhost auto-sync +# OPS — Localhost auto-sync, cockpit local et supervision NAS ## Objet -Ce document fige l’architecture locale qui permet de garder le **localhost éditorial** aligné sur `origin/main`, sans dépendre de la mémoire de l’opérateur. +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. -But recherché : +Le périmètre ne se limite plus à : -- quand une PR est mergée sur `main`, le **localhost** doit pouvoir se réaligner automatiquement ; -- le serveur local Astro doit tourner depuis un **worktree dédié** ; -- le dépôt de développement principal ne doit pas être pollué par ce mécanisme ; -- l’exploitation doit rester simple à diagnostiquer ; -- l’installation doit pouvoir être **réappliquée proprement** après oubli, incident, ou redémarrage machine. +- 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. --- -## Principes +## 1. Architecture finale retenue -L’architecture locale repose sur **trois espaces distincts** : +L’architecture locale repose désormais sur **cinq espaces / rôles distincts**. -1. **Repo canonique de développement** - - Chemin : - `/Volumes/FunIA/dev/archicratie-edition/site` - - Usage : - développement normal, nouvelles fonctionnalités, corrections manuelles, branches de travail, commits, PR. +### A. Repo canonique de développement -2. **Worktree localhost dédié** - - Chemin : - `~/ops-local/archicratie/localhost-worktree` - - Branche locale : - `localhost-sync` - - Usage : - exécuter `astro dev` sur une copie locale réalignée automatiquement sur `origin/main`. - -3. **Ops local hors repo** - - Chemin : - `~/ops-local/archicratie` - - Usage : - scripts d’exploitation, logs, état, automatisation LaunchAgent. - ---- - -## Pourquoi cette séparation - -Il ne faut pas utiliser le dépôt de développement principal comme serveur localhost permanent. - -Sinon on mélange : - -- travail en cours ; -- commits non poussés ; -- essais temporaires ; -- état réellement publié sur `main`. - -Le résultat devient ambigu. - -Le **worktree localhost** sert donc de **miroir exécutable de `main`**, tandis que le repo canonique reste l’espace de développement. - ---- - -## Vue d’ensemble - -Flux logique : - -1. `origin/main` avance après merge d’une PR. -2. Un agent local de sync : - - fetch `origin/main` depuis le repo canonique ; - - réaligne le worktree localhost ; - - exécute `npm ci` si nécessaire ; - - déclenche le redémarrage de l’agent Astro local. -3. Un agent Astro local : - - démarre `astro dev` depuis le worktree localhost ; - - écoute sur `127.0.0.1:4321`. -4. Le site local accessible sur `http://127.0.0.1:4321` reflète alors `main`. - ---- - -## Référence des chemins - -### Repo canonique +Chemin : ```text /Volumes/FunIA/dev/archicratie-edition/site ``` -### Worktree localhost +Usage : -```text -/Users/s-funia/ops-local/archicratie/localhost-worktree -``` - -### Ops local - -```text -/Users/s-funia/ops-local/archicratie -``` - -### Scripts principaux - -```text -/Users/s-funia/ops-local/archicratie/auto-sync-localhost.sh -/Users/s-funia/ops-local/archicratie/run-astro-localhost.sh -/Users/s-funia/ops-local/archicratie/doctor-localhost.sh -/Users/s-funia/ops-local/archicratie/install-localhost-sync.sh -``` - -### Logs ops - -```text -/Users/s-funia/ops-local/archicratie/logs/auto-sync-localhost.log -/Users/s-funia/ops-local/archicratie/logs/astro-localhost.log -``` - -### État du dernier sync - -```text -/Users/s-funia/ops-local/archicratie/last-sync.env -``` - -### LaunchAgents - -```text -~/Library/LaunchAgents/me.archicratie.localhost-sync.plist -~/Library/LaunchAgents/me.archicratie.localhost-astro.plist -``` - -### Logs launchd - -```text -~/Library/Logs/archicratie-localhost-sync.out.log -~/Library/Logs/archicratie-localhost-sync.err.log -~/Library/Logs/archicratie-localhost-astro.out.log -~/Library/Logs/archicratie-localhost-astro.err.log -``` - ---- - -## Architecture retenue - -### 1. Le repo canonique - -Le repo canonique reste la source locale de travail : - -```bash -cd /Volumes/FunIA/dev/archicratie-edition/site -``` - -C’est ici qu’on fait : - -- création de branches ; -- développement ; -- tests manuels de nouvelles fonctionnalités ; +- développement normal ; +- branches ; - commits ; -- pushes ; -- PR. +- PR ; +- tests manuels de nouvelles fonctionnalités ; +- exécution du serveur de dev local sur `4322`. -### 2. Le worktree localhost +### B. Worktree miroir local de `main` -Le localhost ne tourne **pas** depuis le repo canonique. -Il tourne depuis un worktree dédié : +Chemin : -```bash -cd ~/ops-local/archicratie/localhost-worktree -git branch --show-current +```text +~/ops-local/archicratie/localhost-worktree ``` -Branche attendue : +Branche locale : ```text localhost-sync ``` -Ce worktree suit `origin/main` via le script d’auto-sync. +Usage : -### 3. Le dossier ops local +- 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. -Les scripts d’exploitation ne doivent pas être mis dans le repo, ni sur un volume externe soumis à des restrictions de lancement. -Ils sont placés sous `HOME` : +### C. Dossier d’ops local hors repo + +Chemin : ```text ~/ops-local/archicratie ``` -Motif : +Usage : -- compatibilité avec `launchd` ; -- logs persistants ; -- visibilité claire ; -- indépendance du dépôt. +- scripts ; +- logs ; +- fichiers d’état ; +- cache NAS ; +- artefacts du cockpit ; +- LaunchAgents ; +- PID files. ---- +### D. Cockpit local d’exploitation -## Pourquoi les scripts et le worktree localhost ne sont plus sur `/Volumes/...` - -Deux difficultés réelles ont été rencontrées. - -### 1. Exécution LaunchAgent depuis un volume externe - -Erreur observée : +Chemin : ```text -/bin/bash: /Volumes/FunIA/dev/_ops-local/archicratie/auto-sync-localhost.sh: Operation not permitted +~/ops-local/archicratie/cockpit ``` -Conclusion : +Usage : -- le LaunchAgent peut échouer si le script est lancé depuis un chemin sur volume externe ; -- le plus robuste est de placer les scripts ops sous `HOME`. +- 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. -### 2. Exécution Astro depuis l’ancien localhost sous `/Volumes/...` +### E. NAS DSM 7.3 -Erreur observée : +Chemins clés : ```text -Error: EPERM: operation not permitted, open '/Volumes/FunIA/dev/archicratie-localhost/node_modules/astro/bin/astro.mjs' +/volume2/docker/archicratie_ops +/volume2/docker/archicratie_ops/public/stack-health.json +/volume2/docker/archicratie_ops/generate-stack-health.sh ``` -Conclusion : +Usage : -- l’ancien localhost situé sur `/Volumes/FunIA/dev/archicratie-localhost` n’est **plus** une base fiable pour l’exploitation automatisée ; -- le worktree localhost doit lui aussi être placé sous `HOME`. - -Donc : - -- **bon choix** : `~/ops-local/archicratie` -- **mauvais choix** : `/Volumes/FunIA/dev/_ops-local/...` -- **ancien chemin obsolète** : `/Volumes/FunIA/dev/archicratie-localhost` +- 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. --- -## Rôle exact du script `auto-sync-localhost.sh` +## 2. Vue d’ensemble opératoire -Le script a quatre responsabilités : +### 2.1 Miroir local `4321` -1. **Vérifier l’environnement** - - `git` - - `bash` - - `node` - - `npm` +Le miroir local `4321` est la **vérité de `main`**. -2. **Garantir le runtime Node** - - Node `22.x` - - npm `10.x` +Flux : -3. **Réaligner le worktree localhost** - - fetch du repo canonique ; - - s’assurer que le worktree localhost existe ; - - checkout `localhost-sync` ; - - reset hard sur `origin/main` ; - - clean si nécessaire ; - - `npm ci` si nécessaire. +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`. -4. **Déclencher le redémarrage d’Astro** - - relancer l’agent LaunchAgent Astro ; - - laisser `run-astro-localhost.sh` porter le démarrage réel du serveur. +### 2.2 Atelier local `4322` ---- +Le port `4322` est le **vrai atelier de développement**. -## Rôle exact du script `run-astro-localhost.sh` +Flux : -Ce script a une responsabilité unique : +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. -- démarrer `astro dev` **depuis le worktree localhost** ; -- sur `127.0.0.1:4321` ; -- avec le bon runtime Node ; -- en produisant les logs Astro dédiés. +### 2.3 Cockpit `4310/4311` -Il ne doit jamais démarrer depuis le repo canonique. +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. -## Rôle exact du script `doctor-localhost.sh` +### 2.4 Supervision NAS -Le doctor sert à produire un **diagnostic lisible et opératoire** sur : - -- le runtime Node ; -- les LaunchAgents ; -- le worktree localhost ; -- l’alignement sur `origin/main` ; -- l’état du serveur Astro ; -- la réponse HTTP de `localhost:4321` ; -- les fichiers d’état et les logs. - -C’est la **commande de référence** pour savoir si l’installation est saine. - ---- - -## Rôle exact du script `install-localhost-sync.sh` - -Le script d’installation sert à **reconstruire proprement toute l’architecture locale** : - -- écrire ou réécrire `auto-sync-localhost.sh` ; -- écrire ou réécrire `run-astro-localhost.sh` ; -- écrire ou réécrire les deux LaunchAgents ; -- recharger les LaunchAgents ; -- exécuter `doctor-localhost.sh` en fin d’installation. - -C’est la **commande de réinstallation standard** après oubli, casse, dérive ou changement de configuration. - ---- - -## Runtime Node requis - -Le projet exige : +Le NAS génère périodiquement : ```json -{ - "node": ">=22 <23", - "npm": ">=10 <11" -} +stack-health.json ``` -Le runtime retenu localement est donc : - -```text -/opt/homebrew/opt/node@22/bin/node -/opt/homebrew/opt/node@22/bin/npm -``` - -Vérification : - -```bash -"$(brew --prefix node@22)/bin/node" -v -"$(brew --prefix node@22)/bin/npm" -v -``` - -Résultat attendu : - -```text -v22.x -10.x -``` +Ce fichier est ensuite rapatrié sur le Mac, mis en cache localement, puis injecté dans le cockpit. --- -## LaunchAgents +## 3. Distinction conceptuelle consolidée -L’architecture finale repose sur **deux LaunchAgents**, avec des responsabilités distinctes. +### 3.1 `4321 = miroir` +- automatique ; +- worktree dédié ; +- vérité de `main` ; +- ne pas utiliser pour le développement normal. -### 1. LaunchAgent sync +### 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`. -Fichier : +### 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 -~/Library/LaunchAgents/me.archicratie.localhost-sync.plist +~/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 : -- réaligner périodiquement le worktree localhost sur `origin/main` ; -- relancer l’agent Astro si nécessaire. +- démarrer / arrêter le cockpit avec son UI Vite et son API Node ; +- standardiser l’exploitation pour éviter les commandes manuelles dispersées. -### 2. LaunchAgent Astro - -Fichier : +### 4.4 Script de rapatriement NAS ```text -~/Library/LaunchAgents/me.archicratie.localhost-astro.plist +~/ops-local/archicratie/pull-stack-health.sh ``` Rôle : -- exécuter `run-astro-localhost.sh` ; -- lancer `astro dev` depuis le worktree localhost. - ---- - -## Contenu de référence du LaunchAgent sync - -```xml - - - - - Label - me.archicratie.localhost-sync - - ProgramArguments - - /bin/bash - /Users/s-funia/ops-local/archicratie/auto-sync-localhost.sh - - - RunAtLoad - - - StartInterval - 60 - - WorkingDirectory - /Users/s-funia - - EnvironmentVariables - - HOME - /Users/s-funia - PATH - /opt/homebrew/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin - LANG - fr_FR.UTF-8 - LC_ALL - fr_FR.UTF-8 - - - StandardOutPath - /Users/s-funia/Library/Logs/archicratie-localhost-sync.out.log - - StandardErrorPath - /Users/s-funia/Library/Logs/archicratie-localhost-sync.err.log - - -``` - ---- - -## Contenu de référence du LaunchAgent Astro - -```xml - - - - - Label - me.archicratie.localhost-astro - - ProgramArguments - - /bin/bash - /Users/s-funia/ops-local/archicratie/run-astro-localhost.sh - - - RunAtLoad - - - KeepAlive - - - WorkingDirectory - /Users/s-funia - - EnvironmentVariables - - HOME - /Users/s-funia - PATH - /opt/homebrew/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin - LANG - fr_FR.UTF-8 - LC_ALL - fr_FR.UTF-8 - - - StandardOutPath - /Users/s-funia/Library/Logs/archicratie-localhost-astro.out.log - - StandardErrorPath - /Users/s-funia/Library/Logs/archicratie-localhost-astro.err.log - - -``` - ---- - -## Installation / réinstallation des LaunchAgents - -### Vérifier les plists - -```bash -plutil -lint ~/Library/LaunchAgents/me.archicratie.localhost-sync.plist -plutil -lint ~/Library/LaunchAgents/me.archicratie.localhost-astro.plist -``` - -### Recharger proprement - -```bash -launchctl bootout "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.localhost-sync.plist 2>/dev/null || true -launchctl bootout "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.localhost-astro.plist 2>/dev/null || true - -launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.localhost-sync.plist -launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.localhost-astro.plist - -launchctl kickstart -k "gui/$(id -u)/me.archicratie.localhost-sync" -launchctl kickstart -k "gui/$(id -u)/me.archicratie.localhost-astro" -``` - -### Inspecter l’état - -```bash -launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,160p' -launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,160p' -``` - -État attendu : - -- pas d’erreur `Operation not permitted` ; -- pas d’erreur `EX_CONFIG` ; -- le LaunchAgent sync tourne périodiquement ; -- le LaunchAgent Astro peut être vu comme `running`, `spawn scheduled` ou `not running` selon le moment d’observation ; -- l’état réel de vérité reste le **doctor** et la **réponse HTTP sur 4321**. - ---- - -## Vérifications de bon fonctionnement - -### 1. Vérifier que le worktree suit bien `origin/main` - -```bash -git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD -git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main -``` - -Les deux SHA doivent être identiques. - -### 2. Vérifier la branche du worktree localhost - -```bash -git -C ~/ops-local/archicratie/localhost-worktree branch --show-current -``` - -Résultat attendu : +- ouvrir une session SSH vers le NAS ; +- lire le fichier `/volume2/docker/archicratie_ops/public/stack-health.json` ; +- le recopier localement dans : ```text -localhost-sync +~/ops-local/archicratie/cache/stack-health.json ``` -### 3. Vérifier le dernier état sync +- écrire un log d’exploitation. -```bash -cat ~/ops-local/archicratie/last-sync.env -``` +--- -Exemple attendu : +## 5. Fichiers d’état et journaux locaux + +### 5.1 Dossier ops ```text -LAST_SYNC_AT="2026-03-16 20:29:43" -LAST_SYNC_SHA="a1bfbf4405d1342c635caec5b219c14b83b36d5e" -LAST_SYNC_STATUS="noop" +~/ops-local/archicratie ``` -### 4. Vérifier les logs de sync +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 -tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log +launchctl bootout "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.pull-stack-health.plist ``` -### 5. Vérifier les logs Astro +### Réactiver le rapatriement local ```bash -tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log +launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.pull-stack-health.plist ``` -### 6. Vérifier qu’Astro écoute bien sur 4321 +### 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 -lsof -nP -iTCP:4321 -sTCP:LISTEN +~/ops-local/archicratie/run-cockpit.sh ``` -### 7. Vérifier le processus Astro exact +et arrêté via : ```bash -PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)" -ps -p "$PID" -o pid=,command= -lsof -a -p "$PID" -d cwd +~/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 ``` -Attendu : +### L’UI affichée sur : -- commande contenant `astro dev` -- cwd = `~/ops-local/archicratie/localhost-worktree` +```text +http://127.0.0.1:4310 +``` -### 8. Vérifier le contenu servi +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 : -```bash -curl -s http://127.0.0.1:4321/archicrat-ia/prologue/ | grep -n "taxe Zucman" -``` +- `giteaActRunner` indisponible -Le texte renvoyé doit correspondre à la version attendue sur `main`. +Justification : -### 9. Vérifier globalement toute l’installation +- 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 -~/ops-local/archicratie/doctor-localhost.sh +launchctl bootout "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.pull-stack-health.plist ``` +### Restaurer le fonctionnement nominal -Verdict attendu : +```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 -✅ aucun problème bloquant détecté -✅ aucun avertissement +~/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. --- -## Interprétation des statuts +## 16. Règles d’exploitation consolidées -### `status=updated` +### 16.1 Règle d’or +Le repo canonique n’est pas le miroir local. -Le worktree localhost a été réaligné sur un nouveau SHA ou nettoyé, puis l’agent Astro a été relancé. +### 16.2 Règle miroir +`4321` doit raconter la vérité de `main`, pas l’état du travail en cours. -### `status=noop` +### 16.3 Règle atelier +`4322` est le lieu du travail vivant, du test manuel et des branches. -Le worktree localhost était déjà aligné et le serveur local tournait correctement. -Aucun changement de contenu n’était nécessaire. +### 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. --- -## Usage normal au quotidien +## 17. Commandes de contrôle essentielles -### Cas A — travail produit / publié - -Quand on veut simplement consulter localement l’état réel de `main` : - -- on laisse tourner les LaunchAgents ; -- on consulte `http://127.0.0.1:4321`. - -Dans ce mode, le localhost doit être considéré comme : - -**un miroir local exécutable de `origin/main`**. - -### Cas B — développement de nouvelles fonctionnalités - -Quand on veut modifier du code, tester un comportement, créer une branche : - -```bash -cd /Volumes/FunIA/dev/archicratie-edition/site -git switch -c feat/ma-branche -npm run dev -``` - -Dans ce mode, on travaille dans le **repo canonique**, pas dans le worktree localhost. - ---- - -## Règle d’or - -Il existe désormais **deux usages distincts** : - -### 1. Voir ce qui est réellement sur `main` - -Utiliser : - -```text -http://127.0.0.1:4321 -``` - -qui sert depuis : - -```text -~/ops-local/archicratie/localhost-worktree -``` - -### 2. Développer / tester du neuf - -Utiliser : - -```text -/Volumes/FunIA/dev/archicratie-edition/site -``` - -avec branche locale, commandes manuelles, tests de dev. - ---- - -## Ce qu’il ne faut pas faire - -### Ne pas développer dans le worktree localhost - -Le worktree localhost est un miroir piloté. -Il peut être reset automatiquement. - -Donc : - -- pas de commits dedans ; -- pas de modifications de fond dedans ; -- pas de dev feature dedans. - -### Ne pas utiliser le repo canonique comme miroir auto-sync - -Sinon on mélange : - -- environnement de dev ; -- état publié ; -- serveur local permanent. - -### Ne pas conserver l’ancien chemin localhost comme référence - -Le chemin : - -```text -/Volumes/FunIA/dev/archicratie-localhost -``` - -n’est plus la référence opérationnelle. -Il est obsolète pour cette architecture. - -### Ne pas déplacer les scripts ops sur un volume externe - -Sinon `launchd` peut échouer avec : - -```text -Operation not permitted -``` - ---- - -## Procédure de redémarrage machine - -Après reboot, le comportement attendu est : - -1. les LaunchAgents se rechargent ; -2. le script d’auto-sync s’exécute ; -3. le worktree localhost est réaligné ; -4. Astro redémarre sur `127.0.0.1:4321`. - -### Vérification rapide après reboot - -```bash -launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,120p' -launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,120p' -tail -n 80 ~/ops-local/archicratie/logs/auto-sync-localhost.log -lsof -nP -iTCP:4321 -sTCP:LISTEN -``` - ---- - -## Procédure de secours manuelle - -### Forcer un resync - -```bash -~/ops-local/archicratie/auto-sync-localhost.sh -``` - -### Forcer un diagnostic complet - -```bash -~/ops-local/archicratie/doctor-localhost.sh -``` - -### Réinstaller tout le dispositif - -```bash -~/ops-local/archicratie/install-localhost-sync.sh -``` - ---- - -## Symptômes fréquents et diagnostic - -### Symptôme 1 — localhost ne montre pas les dernières modifs - -Vérifier : - -```bash -git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD -git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main -``` - -Si les SHA diffèrent : -- le sync n’a pas tourné ; -- ou le LaunchAgent sync ne s’exécute pas. - -### Symptôme 2 — SHA bon, mais contenu web pas à jour - -Vérifier : - -```bash -lsof -nP -iTCP:4321 -sTCP:LISTEN -PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)" -ps -p "$PID" -o pid=,command= -lsof -a -p "$PID" -d cwd -``` - -Cause probable : -- Astro tourne depuis le mauvais dossier ; -- ou un ancien `astro dev` manuel tourne encore ailleurs. - -### Symptôme 3 — LaunchAgent présent, mais rien ne tourne - -Vérifier : - -```bash -tail -n 80 ~/Library/Logs/archicratie-localhost-sync.err.log -tail -n 80 ~/Library/Logs/archicratie-localhost-astro.err.log -tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log -tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log -``` - -Causes possibles : -- mauvais PATH ; -- Node 22 absent ; -- script non exécutable ; -- erreur dans un plist ; -- ancien chemin encore référencé ; -- worktree localhost absent ; -- `node_modules` non installés dans le worktree. - -### Symptôme 4 — erreur `Operation not permitted` - -Cause probable : -- script ops ou agent lancé depuis un chemin sous `/Volumes/...`. - -Résolution : -- conserver les scripts sous `~/ops-local/archicratie`. - -### Symptôme 5 — erreur `EBADENGINE` - -Cause probable : -- Node 23 utilisé à la place de Node 22. - -Résolution : -- forcer PATH avec `node@22` dans les LaunchAgents et dans les scripts. - -### Symptôme 6 — erreur `EPERM` sur `astro.mjs` - -Cause probable : -- Astro essaie encore de démarrer depuis l’ancien emplacement localhost ; -- ou une incohérence persiste dans les chemins des scripts. - -Résolution : -- vérifier que **tous** les scripts pointent vers `~/ops-local/archicratie/localhost-worktree` ; -- vérifier que `doctor-localhost.sh` confirme le bon cwd ; -- réinstaller via `install-localhost-sync.sh`. - ---- - -## Commandes de contrôle essentielles - -### État Git +### 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 ``` -### État LaunchAgents +### 17.2 Cockpit ```bash -launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,160p' -launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,160p' +~/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' ``` -### État logs +### 17.3 Dev 4322 ```bash -tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log -tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log -tail -n 80 ~/Library/Logs/archicratie-localhost-sync.err.log -tail -n 80 ~/Library/Logs/archicratie-localhost-astro.err.log +~/ops-local/archicratie/run-dev-4322.sh +~/ops-local/archicratie/stop-dev-4322.sh ``` -### État serveur +### 17.4 Pull stack-health ```bash -lsof -nP -iTCP:4321 -sTCP:LISTEN -PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)" -ps -p "$PID" -o pid=,command= -lsof -a -p "$PID" -d cwd -curl -I -s http://127.0.0.1:4321/ | head -n 5 +~/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 ``` -### Vérification contenu +# Commandes complémentaires de test contrôlé : ```bash -curl -s http://127.0.0.1:4321/archicrat-ia/prologue/ | grep -n "taxe Zucman" +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 ``` --- -## Décision d’exploitation finale +## 18. Procédures de secours -La politique retenue est la suivante : +### 18.1 Si `4321` ment +Vérifier : -- **repo canonique** = espace de développement ; -- **worktree localhost** = miroir automatique de `main` ; -- **ops sous HOME** = scripts, logs, automation ; -- **LaunchAgent sync** = réalignement périodique ; -- **LaunchAgent astro** = exécution d’Astro ; -- **Astro local** = lancé uniquement depuis le worktree localhost. +- SHA du worktree ; +- process Astro ; +- cwd réel ; +- logs du miroir ; +- doctor. -Cette séparation rend le dispositif plus : +### 18.1 bis Lecture correcte du symptôme -- lisible ; -- robuste ; -- opérable ; -- antifragile. +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. --- -## Résumé opératoire +## 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` - -Ouvrir : - ```text http://127.0.0.1:4321 ``` -Le serveur doit provenir de : - -```text -~/ops-local/archicratie/localhost-worktree -``` - -### Pour développer - -Travailler dans : - +### Pour travailler vraiment ```text /Volumes/FunIA/dev/archicratie-edition/site ``` -avec tes commandes habituelles. +### 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 -``` - -### Pour tout réinstaller proprement - -```bash -~/ops-local/archicratie/install-localhost-sync.sh +~/ops-local/archicratie/pull-stack-health.sh ``` --- -## Mémoire courte +## 23. Pistes futures à forte valeur -Si un jour plus rien n’est clair, repartir de ces six commandes : +Les prochaines améliorations les plus pertinentes seraient : -```bash -git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD -git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main -launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,120p' -launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,120p' -lsof -nP -iTCP:4321 -sTCP:LISTEN -~/ops-local/archicratie/doctor-localhost.sh -``` - -Et lire : - -```bash -tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log -tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log -``` +- 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. --- -## Statut actuel visé +## Conclusion -Quand tout fonctionne correctement : +L’architecture locale est désormais passée : -- `~/ops-local/archicratie/localhost-worktree` pointe sur le même SHA que `origin/main` ; -- `astro dev` écoute sur `127.0.0.1:4321` ; -- son cwd est `~/ops-local/archicratie/localhost-worktree` ; -- le contenu servi correspond au contenu mergé sur `main`. +- d’un simple `localhost auto-sync` +- à un **dispositif d’exploitation local complet**. -C’est l’état de référence à préserver. \ No newline at end of file +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.