Aller au contenu

État runtime certifié — 12 septembre 2026

Status: CURRENT / CERTIFIED / 2026-09-12

Ce document est la source de vérité opérationnelle pour l'état live certifié après la migration du stockage Docker/containerd, la convergence de l'observabilité vers Alloy et le cut contrôlé vers le worker self-contained.

Il complète les documents historiques runtime-current-state.md, deployment.md et monitoring.md. Les baselines P0/P1 antérieures restent utiles comme preuves historiques, mais ne décrivent plus à elles seules le runtime courant.

Résumé exécutif

La production est certifiée dans l'état suivant :

release runtime live   0cb30193acfd245717e2b1203b0f6309f6697e36
projet Compose         cmonchoix-platform
checkout live          /mnt/data/cmonchoix-platform
release authority      /mnt/data/cmonchoix-release-authority/<SHA>
Docker data-root       /mnt/data/docker
containerd root        /mnt/data/containerd
WordPress Core host    ABSENT
Promtail container     ABSENT
log collector active   Grafana Alloy

Le runtime live reste volontairement attaché à la release certifiée 0cb30193acfd245717e2b1203b0f6309f6697e36. Les commits GitHub ultérieurs qui ne modifient que l'outillage ou la documentation ne déclenchent pas un redéploiement de production par eux-mêmes.

Worker self-contained

Le worker de production est autonome : WordPress Core, plugin CCX, mu-plugin, src/ et vendor/ sont embarqués dans l'image immuable. Aucun WordPress Core n'est matérialisé dans le checkout hôte.

Image certifiée :

ghcr.io/neweden52/cmonchoix-platform-worker@sha256:fa23328f8f5076ebce06963cadc0108d6c1a9d2b3983dccbcd1d3a8e1a64d3ef

Le worker conserve exactement deux bind mounts mutables :

/mnt/data/cmonchoix-platform/wordpress/wp-content/uploads
→ /var/www/html/wp-content/uploads

/mnt/data/cmonchoix-platform/runtime-spool
→ /mnt/data/cmonchoix-platform/runtime-spool

Sont interdits dans le worker :

  • un bind root /var/www/html ;
  • un bind host du plugin ;
  • un bind host de src/ ou vendor/ ;
  • un bind host du thème ou des mu-plugins ;
  • un volume wordpress_runtime monté dans le worker.

Le cut final a certifié :

  • worker running ;
  • RestartCount=0 ;
  • wp core version et wp core is-installed valides ;
  • wp ccx --help disponible ;
  • wp ccx sync doctor --feed=samsung idle, sans lock ni claimed row ;
  • wp ccx health projections PASS ;
  • IDs WordPress, MariaDB et Redis inchangés pendant le cut.

WordPress Core sur l'hôte

Le checkout live ne doit contenir aucun des chemins suivants :

wordpress/wp-admin
wordpress/wp-includes
wordpress/wp-load.php
wordpress/wp-settings.php
wordpress/wp-blog-header.php

Le WordPress Core du service WordPress appartient à son runtime Docker. Le WordPress Core du worker est embarqué dans l'image self-contained. Aucun retour à un Core host-tracké ou host-monté n'est autorisé.

Stockage Docker et containerd

Les données techniques Docker ont été déplacées hors du filesystem racine :

Docker      /mnt/data/docker
containerd  /mnt/data/containerd

Les unités systemd de Docker/containerd sont protégées par la disponibilité du mount /mnt/data avant démarrage.

Les anciens répertoires /var/lib/docker et /var/lib/containerd ne constituent plus l'autorité de stockage active.

Les consommateurs d'observabilité qui ont besoin de voir Docker utilisent l'autorité /mnt/data côté hôte tout en conservant leurs chemins internes attendus :

Alloy
/mnt/data/docker/containers
→ /var/lib/docker/containers:ro

cAdvisor
/mnt/data/docker
→ /var/lib/docker:ro

Observabilité courante

Chaîne active

logs système / Docker
        │
        ▼
      Alloy
        │
        ▼
       Loki

cAdvisor / node-exporter / Alloy / Alertmanager
        │
        ▼
    Prometheus
        │
        ▼
      Grafana

Alloy est l'unique collecteur actif de logs de la plateforme. Le conteneur ccx_promtail a été retiré après preuve qu'un événement syslog généré après sa suppression arrivait bien dans Loki via Alloy seul.

L'ancien état Promtail est volontairement conservé :

/mnt/data/cmonchoix-infra/observability/promtail

Alloy peut le monter en lecture seule pour la compatibilité des positions historiques. Ne pas supprimer ce répertoire sans chantier explicite de retrait de rollback.

L'état Alloy est séparé :

/mnt/data/cmonchoix-infra/observability/alloy

Prometheus

Prometheus est Docker-internal et n'est pas publié directement sur Internet.

La certification finale exige les cinq jobs actifs suivants :

prometheus   up
node         up
cadvisor     up
alertmanager up
alloy        up

Le job Alloy scrape :

alloy:12345

et conserve les métriques ccx_* prévues par la configuration versionnée.

Une URL locale de type 127.0.0.1:9095 n'est pas une exposition permanente de Prometheus : elle ne fonctionne que lorsqu'un tunnel SSH local correspondant est ouvert.

Loki

Loki doit répondre sur son endpoint interne /ready et accepter les requêtes LogQL. La certification du 12 septembre a confirmé :

  • /ready HTTP 200 après convergence ;
  • ring actif ;
  • API labels HTTP 200 ;
  • requête {job="docker"} HTTP 200 avec entrées récentes ;
  • absence d'erreur de push Alloy vers Loki.

Un 503 transitoire de /ready pendant une convergence ne doit pas être masqué : il doit être diagnostiqué avant de poursuivre une mutation dépendante de Loki.

Grafana

Grafana reste Docker-internal sur 3000. L'accès opérateur permanent est :

https://grafana.cmonchoix.com
→ Nginx Proxy Manager
→ ccx_grafana:3000

Le port 3000 ne doit pas être exposé directement sur Internet.

Les dashboards/provisioning sont montés depuis la release authority en lecture seule. Les données Grafana restent sur le stockage persistant Docker adossé à /mnt/data.

Permissions des release worktrees

Un incident de préparation de release a été identifié pendant le cut : avec umask 077, un worktree Git pouvait matérialiser ses répertoires en 0700 et ses fichiers en 0600.

Conséquences observées :

  • Grafana, exécuté avec son UID non-root, ne pouvait pas traverser les répertoires de provisioning ;
  • Prometheus, exécuté comme nobody, ne pouvait pas lire /etc/prometheus/prometheus.yml ;
  • les services pouvaient donc être running ou redémarrer alors que l'autorité de configuration était illisible.

La correction structurelle est versionnée dans :

scripts/release-authority-prepare.sh

Ce helper :

  • exige un SHA Git complet ;
  • refuse un repo source dirty ;
  • crée ou revalide un worktree détaché ;
  • refuse un worktree étranger, dirty ou sur un mauvais HEAD ;
  • normalise les répertoires en 0755 ;
  • restaure les fichiers suivis selon le mode Git : 100644 → 0644, 100755 → 0755 ;
  • conserve les symlinks ;
  • exige à nouveau un worktree propre et le HEAD exact après normalisation.

La préparation d'une future release doit donc passer par ce helper au lieu d'un git worktree add manuel isolé.

Exemple :

CCX_TARGET_SHA=<SHA_COMPLET_CERTIFIE> \
CCX_RELEASE_SOURCE_REPO=/mnt/data/cmonchoix-platform \
CCX_RELEASE_BASE=/mnt/data/cmonchoix-release-authority \
bash scripts/release-authority-prepare.sh

Le marqueur attendu est :

CCX_RELEASE_AUTHORITY_PREPARE=PASS

Déploiement worker

Le déploiement worker continue à utiliser l'autorité versionnée :

scripts/platform-worker-safe-deploy.sh

Préflight :

CCX_TARGET_SHA=<SHA_COMPLET_CERTIFIE> \
CCX_RELEASE_ROOT=/mnt/data/cmonchoix-release-authority/<SHA_COMPLET_CERTIFIE> \
bash /mnt/data/cmonchoix-release-authority/<SHA_COMPLET_CERTIFIE>/scripts/platform-worker-safe-deploy.sh preflight

Déploiement :

CCX_TARGET_SHA=<SHA_COMPLET_CERTIFIE> \
CCX_RELEASE_ROOT=/mnt/data/cmonchoix-release-authority/<SHA_COMPLET_CERTIFIE> \
bash /mnt/data/cmonchoix-release-authority/<SHA_COMPLET_CERTIFIE>/scripts/platform-worker-safe-deploy.sh deploy

Le rollout worker doit rester ciblé :

--no-deps
--no-build
--pull never

Ne jamais utiliser --remove-orphans comme raccourci pendant un cut contrôlé.

Certification finale obligatoire

Après un changement runtime significatif, la certification live officielle est :

CCX_LIVE_ROOT=/mnt/data/cmonchoix-platform \
CCX_GUARD_COMPOSE_FILE=/mnt/data/cmonchoix-release-authority/<SHA>/docker-compose.yml \
bash /mnt/data/cmonchoix-release-authority/<SHA>/scripts/runtime-readonly-guard.sh --runtime

La certification du 12 septembre s'est terminée avec :

RUNTIME_GUARD_FAILURES=0
RUNTIME_GUARD_WARNINGS=0
RUNTIME_GUARD_STATUS=PASS
CCX_RUNTIME_GUARD_V2_RUNTIME=PASS
FINAL_RUNTIME_CERTIFICATION=PASS

Aucun déploiement ne doit être déclaré terminé si le Runtime Guard v2 live n'est pas vert.

Rollback et preuves à conserver

Le safe-deploy worker conserve son état de rollback sous :

~/.local/state/cmonchoix/deployments/<timestamp>/

La migration Promtail → Alloy a également conservé une preuve de rollback sous :

~/.local/state/cmonchoix/promtail-retirement/<timestamp>/

Ces répertoires sont des preuves opérationnelles. Ne pas les nettoyer dans une opération de maintenance générique.

Invariants live

Le runtime est conforme uniquement tant que les invariants suivants restent vrais :

  1. WordPress Core reste absent du checkout hôte.
  2. Le worker utilise une image immuable par RepoDigest.
  3. Le worker possède exactement deux bind mounts mutables.
  4. Docker et containerd utilisent /mnt/data comme autorité de stockage.
  5. Alloy est le collecteur de logs actif ; ccx_promtail reste absent.
  6. Prometheus scrape alloy, cadvisor, node, alertmanager et lui-même avec des targets up.
  7. Grafana reste derrière Nginx Proxy Manager et n'expose pas son port 3000 publiquement.
  8. Les release worktrees sont préparés par l'autorité versionnée et restent propres sur un SHA complet.
  9. Aucun rollout ciblé n'utilise docker compose down, --build, --remove-orphans ou un prune de volumes.
  10. Le Runtime Guard v2 live reste le verdict final de conformité.

Références