4 Comparatif DevOps
Corentin JOGUET edited this page 2026-09-30 15:09:08 +02:00

Comparatif attendu / reel — Wakdo, volet DevOps (Bloc 5)

Constat date. Ce volet decrit la version 11271f7 du 27/09. Depuis, la production sert aab4e96 (29/09) : plusieurs ecarts releves ici sont corriges, et les valeurs « justes » proposees pour le dossier ont bouge. Pour le dossier, reprendre les valeurs a jour (voir Home et la Synthese) : 2610 tests PHP (8924 assertions) et 492 tests JavaScript (recomptage du 30/09, en production depuis la release du 30/09, f841027), 158 routes (57 sous /admin/api), 24 tables, 20 fiches de decision, 18 entrees de journal, 141 fichiers PHP sous src/app dont 33 controleurs (23 au premier niveau, 10 sous Admin/Api, plus 1 trait), 934 mesures d'accessibilite sur 19 ecrans (mesure du 29/09, non rejouee depuis).

Ce qui a ete compare, a quelle version, quand

Ce rapport compare l'attendu (referentiel RNCP 37805 Bloc 5, docs/, wiki deja redige, brouillons du dossier de soutenance et export du Google Doc de l'auteur) au reel du perimetre construire / verifier / deployer / exploiter de Wakdo : integration continue, deploiement continu, conteneurs, variables d'environnement, sauvegarde et remise a zero de la demonstration, securite de la chaine, et tests.

Le reel a ete mesure le 27 septembre 2026, contre :

  • le code de la release deployee, commit 11271f7 (copie de travail en lecture seule copie de travail de 11271f7, verifiee identique a la production) ;
  • la production en ligne : GET /api/health renvoie {"version":"11271f7", "deployed_at":"2026-09-27T15:13:55+00:00", "app_env":"production", "db":"ok"} ;
  • l'API Forgejo (/actions/tasks, /branch_protections, /actions/variables, /actions/secrets), jeton lu dans .env de production, non affiche a aucun moment ;
  • l'hote de production (docker ps, docker logs wakdo-cron, docker compose -f docker-compose.prod.yml config, docker-compose.prod.yml reel — lectures seules, aucun conteneur wakdo-* recree, arrete ou modifie) ;
  • une execution reelle des trois suites de tests (PHPUnit, JS, shell) via des conteneurs jetables independants de la pile de production, pour recompter les chiffres cites ailleurs plutot que de les recopier.

Important sur le perimetre attendu : la consigne demandait de verifier « chaque critere revendique dans docs/soutenance/preuves/README.md » pour le Bloc 5. Ce fichier existe mais ne couvre que le Bloc 1 (front-end) — aucune preuve Bloc 5 n'y figure, aucun dossier preuves/ dedie au DevOps n'existe dans le depot. L'attendu Bloc 5 a donc ete verifie a la place contre docs/_ref/rncp-37805-index.md (liste des 13 criteres) et docs/PROJECT_CONTEXT.md sections 6-8 (mapping critere -> feature), qui sont les seules sources du depot a assumer ce role pour le DevOps. Ce point est lui-meme signale plus bas (section « A verifier »).


Tableau des ecarts

# Sujet Attendu (source) Reel (preuve) Cas Action proposee Gravite
1 Mode de declenchement du deploiement continu docs/PROJECT_CONTEXT.md:274 : « CD : deploiement scripte a declenchement humain [...] L'automatisation visee est pull-based : un job cron cote hote qui detecte un nouveau main [...] (a armer ensuite) » .forgejo/workflows/deploy.yml:24-26 : on: push: branches: [main]. Automatique depuis le commit 8c5d942 (23/06/2026). Confirme par l'API Forgejo : le run 579 (deploiement, cle-de-deploiement) s'est declenche seul a 17:13 le 27/09, immediatement apres la fusion de la PR #177, sans action humaine separee observee. Meme jour d'edition (24/09), docs/architecture/deployment.md decrit ce meme mecanisme comme push-based. a Corriger la section 7 de PROJECT_CONTEXT.md : le CD est deja push-based et automatique depuis juin ; retirer le plan « pull-based a armer », deja realise autrement. haute
2 Portee reelle du scan de secrets local .gitleaks.toml:3-4 : « Utilise par : le hook pre-commit local (defense en profondeur) [...] le job CI Forgejo Actions » .githooks/pre-commit lu integralement : il fait seulement (1) refuser un commit direct sur main/dev, (2) lancer php -l. Aucun appel a gitleaks trouve dans ce fichier. Confirme par command -v gitleaks sur l'hote : gitleaks not found. Seule la CI (job secret-scan) execute reellement gitleaks. a Corriger le commentaire de .gitleaks.toml (retirer la mention pre-commit), ou cabler reellement gitleaks dans .githooks/pre-commit si la defense en profondeur locale est voulue. haute
3 Tache planifiee d'expiration des commandes en attente (Cr 7.b.3) docker/cron/crontab:28 : 0 2 * * * php /var/www/html/bin/order-expire.php (active, non commentee), documentee comme transition d'etat T6 dans docs/uml/state-commande.md:99 et docs/merise/mlt.md:749 docker-compose.prod.yml reel (hote, hors depot) : le service wakdo-cron ne porte ni le montage ./src:/var/www/html:ro ni la variable ORDER_PENDING_EXPIRY_MINUTES, contrairement au docker-compose.yml versionne qui porte les deux pour ce meme service. Le Dockerfile du conteneur cron ne copie pas src/ dans l'image (seul /scripts y est copie). docker logs wakdo-cron (lu integralement) montre l'execution reelle du job le 27/09 a 02h00 : exit status 1 from user root php /var/www/html/bin/order-expire.php, contre exit status 0 pour les trois autres taches actives la meme nuit. b Corrige le 2026-09-27 a 15h43 UTC, sur l'hote : les deux lignes ajoutees au service wakdo-cron de docker-compose.prod.yml (diff limite a ces deux lignes, fichier d'avant sauvegarde), seul ce conteneur recree (up -d --no-deps --force-recreate wakdo-cron ; wakdo-db, wakdo-app, wakdo-web inchanges, heure de demarrage relevee avant/apres). Verification : php /var/www/html/bin/order-expire.php -> delai=60min examinees=0 expirees=0 ignorees=0, code de sortie 0 ; montage en lecture seule confirme (ecriture refusee). Reste a faire : un controle automatique qui compare ce service entre les deux fichiers de composition et echoue sur divergence, puisque le fichier de production vit hors depot. haute (corrigee)
4 Nombre de taches cron actives docs/PROJECT_CONTEXT.md:268-272 : « Cron tab avec 3 jobs actifs » (backup, purge audit, purge throttle) ; l'expiration de commandes n'apparait pas dans cette liste docker/cron/crontab (lu integralement) : 4 lignes actives (non commentees) — 0 2 order-expire.php, 0 3 backup-db.sh, 15 4 purge-audit-log.sh, 45 4 purge-throttle.sh. Le wiki DevOps.md et le dossier (partie-4-devops.md:142, Google Doc section C7.b) disent « quatre taches actives » : seul PROJECT_CONTEXT.md sous-compte. a Corriger PROJECT_CONTEXT.md : 4 jobs actifs, pas 3 ; ajouter l'expiration des commandes a la liste. basse
5 Variables d'environnement de securite configurees en production .env.prod.example documente 46 cles, dont les seuils argon2id/throttle/lockout, comme « parametres securite [...] documentes » (docs/PROJECT_CONTEXT.md:271) ; docs/journal/2026-09-22--remediation-cd-mono-hote-et-bloc1.md:411 notait deja « 15 reglages de securite tournent sur les defauts du code » comme ouvert, priorite 1 Recompte exact par docker compose -f docker-compose.prod.yml config (lecture seule) : 15 variables de securite absentes (plus 4 de conservation et d'expiration : AUDIT_LOG_RETENTION_DAYS, ORDER_PENDING_EXPIRY_MINUTES, ORDER_RETENTION_DAYS, THROTTLE_PURGE_AFTER_HOURS, recompte du 28/09) du .env reel de production (noms seulement, aucune valeur affichee) : ACCOUNT_LOCKOUT_BASE_SECONDS, ACCOUNT_LOCKOUT_MAX_SECONDS, ACCOUNT_LOCKOUT_THRESHOLD, ARGON2_MEMORY_COST, ARGON2_THREADS, ARGON2_TIME_COST, IP_THROTTLE_MAX_ATTEMPTS, IP_THROTTLE_WINDOW_SECONDS, PASSWORD_RESET_TTL, PIN_THROTTLE_BASE_SECONDS, PIN_THROTTLE_MAX_SECONDS, PIN_THROTTLE_THRESHOLD, PIN_THROTTLE_WINDOW_SECONDS, STAFF_PIN_MAX_LENGTH, STAFF_PIN_MIN_LENGTH. App\Core\Config::get() (src/app/Core/Config.php:17-28) traite une variable vide comme absente et retombe sur un defaut code en dur — verifie ligne a ligne dans PasswordHasher.php, ThrottlePolicy.php, PinThrottle.php, PinVerifier.php, PasswordResetService.php : chaque defaut code en dur correspond a la valeur documentee dans .env.prod.example. Aucune degradation de securite constatee dans ce recompte, mais les 19 cles ne sont pas pilotables depuis .env en production tant qu'elles n'y sont pas ajoutees. d Le constat est deja trace comme ouvert (journal du 22/09, priorite 1) mais pas recorrige depuis, et le compte exact (15 de securite, plus 4 de conservation) n'avait pas ete retrace. Ajouter les 19 cles a l'.env reel de l'hote (memes valeurs que .env.prod.example, deja identiques aux defauts), et mettre a jour le compte dans le journal. moyenne
6 Sous-reseau Docker explicite (correctif de l'incident de saturation du 30/04/2026) docs/notes/docker-network-pools-rfc1918.md documente le correctif (bloc ipam, sous-reseau 192.168.148.0/24) ; le gabarit versionne docker-compose.prod.yml.example est cense porter la configuration de reference pour tout hote Le fichier reel docker-compose.prod.yml (hote) porte le bloc ipam (subnet: 192.168.148.0/24, verifie ligne a ligne). Mais le gabarit versionne docker-compose.prod.yml.example ne le porte pas (aucune occurrence de ipam ni 192.168 trouvee) : quiconque regenere docker-compose.prod.yml depuis ce gabarit, comme le recommande le quickstart de docs/architecture/deployment.md, perd le correctif et risque de retomber sur l'incident de saturation d'origine. d Reporter le bloc ipam dans docker-compose.prod.yml.example, pour que le correctif survive a une regeneration du fichier hote. moyenne
7 Compte systeme dedie au deploiement docs/architecture/deployment.md:84,119 : « Creer un utilisateur dedie au deploiement [...] sudo useradd -m -G docker deploy » ; tableau des variables de la forge : DEPLOY_USER = deploy Lecture de la variable reelle sur la forge (GET /actions/variables, valeur non secrete au sens Forgejo) : DEPLOY_USER vaut le compte personnel de l'auteur sur l'hote, pas un compte deploy dedie. Le canal SSH a commande forcee borne ce que la cle peut declencher (seulement scripts/deploy.sh), ce qui reduit le risque, mais le compte porteur n'est pas isole comme documente. d Soit creer le compte deploy dedie et y deplacer la cle CI (conforme a la doc), soit documenter explicitement le choix d'utiliser le compte personnel et pourquoi (fiche de decision). moyenne
8 Chiffres de tests cites dans le wiki et le dossier Wiki Home.md:40-41,48 (version de travail, non publiee) : « 1684 (4866 assertions) » PHP, « 356 » JS, date « 2026-09-26, version deployee deb8942 ». Dossier partie-4-devops.md:266 et Google Doc (section C7.d) : « 755 tests PHP (1962 assertions) et 233 tests JavaScript », date « 22 septembre 2026 » Recompte reel sur 11271f7 (commandes executees, conteneurs jetables) : docker run ... phpunit.phar -c phpunit.xml -> 2352 tests, 6124 assertions (406 auto-ignores sans base, 0 echec) ; npm run test:js -> 399 tests, 0 echec, 0 ignore. Chaque document reste coherent avec sa propre date de redaction ; les trois sont maintenant depasses par la croissance continue de la suite (755 -> 1684 -> 2352 tests PHP entre le 22 et le 27/09, au fil des demandes de fusion #147 a #177). a Rafraichir les trois chiffres avant l'oral avec la commande donnee ci-dessus ; envisager de generer ce nombre depuis la CI plutot que de le recopier a la main a chaque fois — c'est le risque que Home.md decrit lui-meme en introduction. basse
9 Valeur de APP_ENV en production Dossier partie-4-devops.md:37 : « APP_ENV vaut dev en production [...] ouvert, priorite 1 » (redige le 23/09, avant 567bb0a) GET /api/health (27/09) : "app_env":"production". Different de ce que le dossier decrivait a sa redaction. a Mettre a jour le dossier : ce point precis est resolu, bonne nouvelle a faire valoir a l'oral plutot qu'a presenter comme un residu ouvert. Depasse depuis 567bb0a (deja corrige avant meme cette version). basse
10 Version servie par la production vs. main Dossier partie-4-devops.md:299-301 et couverture du Google Doc : « la version publique consultee le 25 septembre sert encore le commit 1e28a8f [...] positionne sur dev [...] differe de la version annoncee » GET /api/health (27/09) : version":"11271f7", qui correspond au HEAD de main (verifie par git rev-parse HEAD sur la copie de travail). dev et main sont au meme contenu apres la fusion #177 (« release dev -> main v0.5.0 »). Le retard documente est resorbe. a Depasse : mettre a jour le dossier avec le nouvel etat (production = HEAD de main, plus de decalage dev/main). basse
11 Nombre de travaux du pipeline CI, coherence interne du fichier .forgejo/workflows/ci.yml:7 (commentaire d'en-tete) : « Jobs (quatre, independants) » suivi de la liste secret-scan/php-lint/static-tests/js-tests Le meme fichier definit cinq jobs : le job shell-tests existe (.forgejo/workflows/ci.yml:176) et tourne (confirme vert sur les runs 578/579 de l'API Forgejo). Incoherence interne au fichier lui-meme, entre le commentaire d'en-tete et le contenu qui suit. a Corriger le commentaire d'en-tete de ci.yml : cinq jobs, pas quatre ; ajouter shell-tests a la liste descriptive. basse
12 Portee du « garde-fous CI » decrit dans SECURITY.md SECURITY.md:34-36 : trois jobs listes (secret-scan, php-lint, static-tests), avec « static-tests [...] s'activent quand le code PHP arrive en P2 » ; fichier modifie pour la derniere fois le 24/09/2026 (« mise en verite des preuves ») Le pipeline reel compte cinq jobs (voir ecart 11) ; js-tests et shell-tests n'y sont pas mentionnes. Le projet est en version 0.5.0 complete (release #177) : la formulation « s'activent quand le code PHP arrive en P2 » decrit un etat de plusieurs mois anterieur, non mis a jour lors de la derniere edition du fichier. a Mettre a jour SECURITY.md : lister les cinq jobs, retirer la formulation « P2 » devenue sans objet. basse

Ecarts avec le sujet d'examen / le referentiel (chemin de satisfaction alternatif)

  • L'absence de dossier preuves/ dedie au Bloc 5 (voir paragraphe d'introduction) laisse les 13 criteres du Bloc 5 sans la meme structure de preuve nominative que le Bloc 1 (fichier NN-xxx.md + statut + artefact reproductible par critere). Le critere reste couvert par un autre chemin : docs/PROJECT_CONTEXT.md sections 6-8 fournit un mapping critere -> feature explicite pour les 13 criteres du Bloc 5, et chaque fichier cite (docker-compose.yml, .forgejo/workflows/*.yml, docker/, scripts) est lui-meme verifiable directement dans le depot — ce rapport le fait pour l'essentiel des criteres C7.a a C7.d. Rien n'est donc « non satisfait » au sens du referentiel, mais la structure de preuve est moins auditable en un coup d'oeil que celle du Bloc 1.
  • Cr 7.c.1 (VM operationnelle) et Cr 7.c.2 (OS pour conteneur installe dans la VM) : le dossier lui-meme (partie-4-devops.md:170,176) reconnait deja que l'hote est un serveur physique/VPS Debian sans hyperviseur identifie dans le depot (systemd-detect-virt repond none), donc que ces deux criteres ne sont pas couverts au sens strict. Ce rapport confirme cette auto-evaluation (l'hote de production est bien celui interroge par les commandes ci-dessus) ; c'est deja trace comme un ecart voulu et assume dans le dossier — cas (c), rien a ajouter au tableau des ecarts.

Conforme (verifie et tient)

  • Version deployee et sonde de sante : GET https://corentin-wakdo-admin.stark.a3n.fr/api/health renvoie version":"11271f7", deployed_at":"2026-09-27T15:13:55+00:00", identique au HEAD de la copie de travail (git rev-parse HEAD = 11271f7...) et a la reponse mesuree.
  • CI verte sur la release : les cinq jobs (secret-scan, php-lint, static-tests, js-tests, shell-tests) sont success sur le run 578 (API Forgejo /actions/tasks), commit 11271f7.
  • CD vert et automatique : les deux jobs (cle-de-deploiement, deploiement) du run 579 sont success, declenches par le push de la fusion #177 sur main, sans intervention manuelle observee.
  • Cinq conteneurs, quatre longs + un one-shot : docker-compose.yml declare exactement wakdo-db, wakdo-migrate (one-shot), wakdo-app, wakdo-web, wakdo-cron — conforme a docs/PROJECT_CONTEXT.md et au wiki.
  • En-tetes CSP par vhost : mesures reellement (curl -sI) — borne : script-src 'self' sans unsafe-inline ; admin : style-src 'self' 'unsafe-inline'. Conforme mot pour mot a docker/apache/vhost.conf:145,247 et a la correction annoncee dans docs/soutenance/preuves/README.md (PR #123).
  • Durcissement php.ini : docker/php-fpm/php.ini porte expose_php = Off, allow_url_fopen/include = Off, cgi.fix_pathinfo = 0, disable_functions incluant exec,passthru,shell_exec,system,proc_open,popen — conforme mot pour mot a SECURITY.md.
  • Checks requis par la protection de branche : l'API Forgejo (/branch_protections) confirme exactement quatre contextes requis sur main et dev (secret-scan, php-lint, static-tests, js-tests) — conforme a ARCHITECTURE.md:261-263, TESTING.md:104, DEVELOPER.md:127, qui ne pretendent pas non plus que shell-tests soit requis.
  • Correctif du sous-reseau applique sur l'hote : docker-compose.prod.yml reel porte le bloc ipam (192.168.148.0/24) — meme si le gabarit versionne ne le porte pas (voir ecart 6).
  • Instantane de reference et remise a zero : demo-snapshots/reference date de 2026-09-27T15:14:29+00:00 (juste apres le deploiement) ; scripts/demo-reset.sh -f docker-compose.prod.yml --dry-run s'execute proprement, confirme les 17 migrations compatibles, et decrit les six etapes documentees dans docs/ops/demo-reset.md et le wiki DevOps.md.
  • E2E hors CI, par choix trace : docs/TESTING.md section 5, docs/architecture/deployment.md, le journal du 2026-09-22 et le wiki DevOps.md donnent la meme explication et pour la meme raison mesuree (le conteneur de l'executeur a le socket Docker mais ne le transmet pas aux jobs) — coherent partout, rien a corriger.
  • Suite de tests shell : execution reelle de tests/shell/demo-snapshot-lib.test.sh -> 37 assertions OK, 0 echec, conforme au statut vert de la CI.
  • Quickstart README.md : la sequence git clone / cp .env.example .env / docker compose up -d correspond a la chaine de dependances (service_completed_successfully sur wakdo-migrate) qui garantit schema + donnees avant que l'app ne serve.
  • Page wiki DevOps.md : c'est le document le mieux aligne sur le reel de tout le corpus verifie ici — cinq jobs CI, quatre taches cron actives, CD push-based sur fusion dev -> main, tout est exact au jour de cette verification.
  • Variables Forgejo optionnelles : DEPLOY_HOST est absente de la forge, mais docs/architecture/deployment.md:117 la dit explicitement facultative avec une valeur par defaut codee dans deploy.yml (62.210.93.152) — coherent, pas un ecart.

A verifier (hypotheses non prouvees)

  • Le message d'erreur precis produit par order-expire.php (ecart 3) n'a pas pu etre lu : les journaux de crond (docker logs wakdo-cron) ne remontent que le code de sortie (exit status 1), pas la sortie standard de la commande. L'explication (fichier absent faute de montage) est une deduction forte a partir du Dockerfile et des deux fichiers compose, pas une lecture directe du message d'erreur.
  • Le contenu exact d'authorized_keys sur l'hote (options no-pty,no-port-forwarding,... et commande forcee telles que documentees dans docs/architecture/deployment.md:91-95) n'a pas ete relu : ce fichier est hors du perimetre de lecture assigne a cet audit (config SSH de l'hote, pas un fichier du depot ni un des points explicitement listes). Le comportement observe (deploiement reussi, aucune commande transmise via SSH selon deploy.yml) est coherent avec la documentation, sans la confirmer directement.
  • L'etat du conteneur forgejo-runner-wakdo (limites de ressources non appliquees depuis le 16/09, decrit dans partie-4-devops.md:245-247) n'a pas ete reinspecte : ce conteneur est hors perimetre (infrastructure de la forge). Seule sa date de creation (docker ps, 2026-06-15, pas recreee depuis a cette lecture) corrobore indirectement que le constat du dossier reste plausible ; ce n'est pas une confirmation directe des limites memoire/CPU.
  • L'ecart entre le compte de fichiers de documentation annonce par le wiki (Home.md:53 : 297 fichiers) et le recompte brut (find docs -type f : 304) n'a pas ete instruit plus loin (methode de comptage possiblement differente, ou croissance depuis la redaction) : hors perimetre DevOps strict, signale sans etre elucide.
  • Le preload present dans l'en-tete Strict-Transport-Security reellement servi par la production (mesure par curl -sI) n'apparait dans aucune configuration versionnee du depot (le vhost Apache pose seulement max-age=31536000; includeSubDomains). Piste probable : ajoute par Traefik au niveau de l'hote, hors du perimetre du depot Wakdo. Non confirme faute d'acces a la configuration Traefik (hors perimetre assigne).
  • L'absence de dossier preuves/ dedie au Bloc 5 est constatee comme un fait (le fichier n'existe pas), mais il n'a pas ete possible de determiner si cette absence est un choix assume et trace ailleurs (aucune fiche de decision trouvee sur ce point precis) ou un simple oubli : range ici plutot que classe en (c) ou (d) sans preuve directe de l'un ou l'autre.

Pour le dossier

Passages a corriger dans les brouillons (dossier-soutenance/partie-4-devops.md (brouillons du dossier, hors depot), redige le 23/09, decrit comme couvrant jusqu'a 567bb0a du 24/09 par la version Google Doc) et dans le Google Doc lui-meme (« Version decrite : 567bb0a... »).

# Texte actuel Texte juste Statut
1 partie-4-devops.md:37-38 : « APP_ENV vaut dev en production [...] ouvert, priorite 1 » ; « Quinze reglages de securite [...] reposant sur les valeurs par defaut » APP_ENV vaut desormais production (confirme par /api/health le 27/09). Les reglages de securite encore sur defaut sont bien 15 (recompte du 28/09, noms seulement), plus 4 reglages de conservation et d'expiration, et restent ouverts. Le point APP_ENV est faux pour la version deployee actuelle (deja corrige avant meme 567bb0a) ; le point "15 reglages" est exact pour la securite, a completer par les 4 reglages de conservation ; le fond (ouvert, priorite 1) reste exact.
2 partie-4-devops.md:266 (et Google Doc, section C7.d) : « Au 22 septembre 2026, la suite de tests comptait 755 tests PHP (1 962 assertions) et 233 tests JavaScript » Au 27 septembre 2026 (11271f7) : 2352 tests PHP (6124 assertions), 399 tests JS, tous verts. Depasse depuis 567bb0a (et deja depuis la redaction du 22/09 elle-meme) : croissance continue au fil des demandes de fusion suivantes, rien de faux en soi a la date ecrite.
3 partie-4-devops.md:299-301 : « la version publique consultee le 25 septembre sert encore le commit 1e28a8f [...] dev et main [...] pas encore [...] en accord » La production sert 11271f7, qui correspond au HEAD de main ; dev et main sont au meme contenu depuis la fusion #177 du 27/09. Depasse depuis 567bb0a : le decalage decrit a ete resorbe par la mise en production prevue, exactement comme le dossier l'annoncait comme a venir.
4 Couverture Google Doc, section C7.a (paragraphe sur les contraintes analysees) : ne mentionne pas explicitement le detail du montage ./src manquant pour wakdo-cron en production Ajouter, dans la meme veine que le paragraphe deja present sur le montage direct de ./src en production (deja signale comme un risque en 7.a.1/7.a.3), le constat precis : le service wakdo-cron de production n'a ni ce montage ni la variable d'expiration, ce qui fait echouer silencieusement la tache d'expiration des commandes. Absent des deux versions (brouillon et Google Doc) : ce n'est pas un passage a corriger mais un paragraphe a ajouter, portant sur un fait decouvert par ce rapport et non connu au moment de la redaction.
5 partie-4-devops.md:142 tableau des taches cron : correct (« quatre taches actives »), a l'inverse de docs/PROJECT_CONTEXT.md qui en compte trois Rien a changer dans le dossier sur ce point precis — c'est docs/PROJECT_CONTEXT.md qui est en tort (voir ecart 4 du tableau principal). Le dossier est deja juste ici ; signale pour eviter qu'une correction malencontreuse n'aligne le dossier sur le chiffre errone de PROJECT_CONTEXT.md.

Hors ce tableau, aucun autre passage DevOps du dossier ou du Google Doc n'a ete trouve en contradiction avec le reel mesure le 27 septembre 2026 ; le reste (description de l'architecture a hote unique, du canal de deploiement a commande forcee, du choix bash pour les scripts, de la non-couverture stricte de Cr 7.c.1/7.c.2) reste exact au jour de cette verification et est deja redige avec les nuances et reserves attendues par la methode de ce comparatif.