conformite.test.ts ne fournit aucun contexte au harnais : depuis 0.12.0, l'étage d'intégration d'un clone neuf est rouge sur 27 règles jamais jouées #32

Closed
opened 2026-09-17 10:58:02 +00:00 by nicolas-fryder · 0 comments

Ce qui ne va pas

apps/api/test/integration/conformite.test.ts appelle runConformance(demarreur)
sans second argument. Le harnais fabrique donc ce qu'il peut depuis
l'application démarrée (contexteDe), et tout le reste — boot, envValide,
collecteur, routeValidation, routeCrash, rolesYaml, connexion,
creerCleHorsDroits, les trois jetons, root/globsTests, check — n'arrive
jamais.

Tant que testing.regle-jamais-jouee était cassé (eqs-platform #73), ça ne se
voyait pas : le cas était rouge pour une autre raison. Le correctif de 0.12.0
l'a réparé, et il rend maintenant le vrai chiffre.

Reproduction

Un clone du gabarit, @eqs/* en 0.12.0, Docker levé :

pnpm install
pnpm --filter api test:integration

Sortie (mesurée le 2026-09-17 sur un satellite nest monté sur ce gabarit,
fichier de conformité non modifié) :

6 règle(s) sans objet dans le profil nest :
  http.en-tetes
  http.api-error
  http.timeout
  http.redirection
  http.segment
  http.plafond

 FAIL  conformité @eqs (dispositif de test, profil nest) > chaque règle annoncée a été jouée
Error: 27 règle(s) annoncée(s) et jamais jouée(s) :
  platform.validation
  platform.arret
  platform.export-hors-ligne
  errors.validation
  errors.500-sans-pile
  auth.delegue-incomplet
  auth.delegue-sans-utilisateur
  auth.delegue-sans-consentement
  auth.403-permission
  auth.403-audience
  auth.cle-revoquee
  auth.roles-yaml
  auth.scope-borne
  auth.cookie
  telemetry.console
  telemetry.inerte-sans-endpoint
  telemetry.span-serveur
  telemetry.client-attribue
  telemetry.log-correle
  telemetry.traceparent-propage
  telemetry.redaction
  config.refus-sans-requise
  config.incoherence-bloquante
  config.secret-par-defaut
  testing.check-budget
  testing.base-detruite
  testing.fichier-orphelin

 Test Files  1 failed | 26 passed (27)
      Tests  1 failed | 280 passed (281)

Le nouveau seau « sans objet » fonctionne (les 6 règles http du mutator
sortent du compte, comme prévu par D-046) : ce qui reste est bien du câblage
manquant, pas un défaut de comptabilité.

Ce que ça coûte

Bloquant, et pour tout le monde en même temps. La CI du gabarit et celle de
chaque satellite lancent integration (.forgejo/workflows/ci.yml), donc
trente dépôts passent au rouge le jour où ils montent en 0.12.0 — sur un cas
qu'aucun d'eux n'a écrit et qu'aucun d'eux ne sait remplir seul.

Le message du socle est juste : « Fournir au harnais ce qui leur manque, ou dire
par une dispense datée pourquoi ce dépôt ne peut pas les jouer. » C'est
exactement ce qu'il faut faire. Mais ce n'est pas au trentième satellite de le
découvrir : c'est un dispositif de test, et le gabarit est censé le livrer
debout.
C'est le même raisonnement que #30 et que
testing.etage-declare-vide — un étage qui ne peut pas être vert n'est pas
livré.

Et il y a une partie que le satellite ne peut vraiment pas trancher seul :
errors.500-sans-pile demande une route qui lève une exception non gérée,
errors.validation une route POST qui valide un corps. Une route de crash
délibérée dans du code déployé est une décision, pas un détail de test — elle a
sa place dans le gabarit, décidée une fois, pas réinventée trente fois avec
trente formes différentes.

Ce que je proposerais

Câbler dans le gabarit ce que le gabarit possède déjà, et dispenser le reste
avec la raison :

Manque Ce que le gabarit a sous la main
errors.validation une route POST du ping avec un DTO validé — le gabarit a déjà ValidationPipe
errors.500-sans-pile une route de crash, @Public(), montée uniquement quand NODE_ENV === 'test' — ou assumée et documentée
config.refus-sans-requise, incoherence-bloquante, secret-par-defaut boot + envValide : lancer dist/main.js avec un environnement et lire son code de sortie. Le message du socle le décrit précisément
les 7 telemetry demarrerCollecteur() de @eqs/telemetry/testing, livré exprès pour ça en 0.10.0, plus root et routeJournal
testing.check-budget, fichier-orphelin check: { ms, budgetMs } et root/globsTests — lus depuis .eqs/check.json et vitest.config
auth.roles-yaml, scope-borne, cookie, les jetons roles.yaml existe déjà ; creerCleHorsDroits peut réutiliser apps/api/scripts/creer-cle.mjs
testing.base-detruite non jouable pendant la suite, le socle le dit lui-même : conteneurs ou une dispense

Si tout n'est pas faisable d'un coup, la moitié utile serait déjà :
livrer le câblage que le socle a explicitement préparé (le collecteur, boot/envValide,
root/globsTests, check) et poser dans eqs-baseline.json une dispense
datée nommant les règles qui restent
, avec la raison. Un satellite verrait
alors un étage vert et une liste écrite de ce qui manque encore — au lieu d'un
rouge sans mode d'emploi.

Versions

@eqs/* 0.12.0, eqs --version 0.12.0, gabarit 228f8e4, profil nest,
Node 24.15.0, pnpm 11.8.0, Windows 11, Docker 29.1.3.

Contournement posé

Aucun. L'étage reste rouge sur ce seul cas dans notre satellite ; les 280 autres
tests passent, pnpm check, eqs doctor, eqs audit et pnpm test:e2e sont
verts. Rien n'est désactivé : il n'y aura rien à retirer.

## Ce qui ne va pas `apps/api/test/integration/conformite.test.ts` appelle `runConformance(demarreur)` **sans second argument**. Le harnais fabrique donc ce qu'il peut depuis l'application démarrée (`contexteDe`), et tout le reste — `boot`, `envValide`, `collecteur`, `routeValidation`, `routeCrash`, `rolesYaml`, `connexion`, `creerCleHorsDroits`, les trois `jetons`, `root`/`globsTests`, `check` — n'arrive jamais. Tant que `testing.regle-jamais-jouee` était cassé (eqs-platform #73), ça ne se voyait pas : le cas était rouge pour une autre raison. Le correctif de 0.12.0 l'a réparé, et il rend maintenant le vrai chiffre. ## Reproduction Un clone du gabarit, `@eqs/*` en 0.12.0, Docker levé : ``` pnpm install pnpm --filter api test:integration ``` Sortie (mesurée le 2026-09-17 sur un satellite `nest` monté sur ce gabarit, fichier de conformité **non modifié**) : ``` 6 règle(s) sans objet dans le profil nest : http.en-tetes http.api-error http.timeout http.redirection http.segment http.plafond FAIL conformité @eqs (dispositif de test, profil nest) > chaque règle annoncée a été jouée Error: 27 règle(s) annoncée(s) et jamais jouée(s) : platform.validation platform.arret platform.export-hors-ligne errors.validation errors.500-sans-pile auth.delegue-incomplet auth.delegue-sans-utilisateur auth.delegue-sans-consentement auth.403-permission auth.403-audience auth.cle-revoquee auth.roles-yaml auth.scope-borne auth.cookie telemetry.console telemetry.inerte-sans-endpoint telemetry.span-serveur telemetry.client-attribue telemetry.log-correle telemetry.traceparent-propage telemetry.redaction config.refus-sans-requise config.incoherence-bloquante config.secret-par-defaut testing.check-budget testing.base-detruite testing.fichier-orphelin Test Files 1 failed | 26 passed (27) Tests 1 failed | 280 passed (281) ``` Le nouveau seau « sans objet » fonctionne (les 6 règles `http` du `mutator` sortent du compte, comme prévu par D-046) : ce qui reste est bien du câblage manquant, pas un défaut de comptabilité. ## Ce que ça coûte **Bloquant, et pour tout le monde en même temps.** La CI du gabarit et celle de chaque satellite lancent `integration` (`.forgejo/workflows/ci.yml`), donc trente dépôts passent au rouge le jour où ils montent en 0.12.0 — sur un cas qu'aucun d'eux n'a écrit et qu'aucun d'eux ne sait remplir seul. Le message du socle est juste : « Fournir au harnais ce qui leur manque, ou dire par une dispense datée pourquoi ce dépôt ne peut pas les jouer. » C'est exactement ce qu'il faut faire. Mais ce n'est pas au trentième satellite de le découvrir : **c'est un dispositif de test, et le gabarit est censé le livrer debout.** C'est le même raisonnement que #30 et que `testing.etage-declare-vide` — un étage qui ne peut pas être vert n'est pas livré. Et il y a une partie que le satellite ne peut vraiment pas trancher seul : `errors.500-sans-pile` demande une **route qui lève une exception non gérée**, `errors.validation` une route POST qui valide un corps. Une route de crash délibérée dans du code déployé est une décision, pas un détail de test — elle a sa place dans le gabarit, décidée une fois, pas réinventée trente fois avec trente formes différentes. ## Ce que je proposerais Câbler dans le gabarit ce que le gabarit possède déjà, et dispenser le reste avec la raison : | Manque | Ce que le gabarit a sous la main | |---|---| | `errors.validation` | une route POST du `ping` avec un DTO validé — le gabarit a déjà `ValidationPipe` | | `errors.500-sans-pile` | une route de crash, `@Public()`, montée **uniquement** quand `NODE_ENV === 'test'` — ou assumée et documentée | | `config.refus-sans-requise`, `incoherence-bloquante`, `secret-par-defaut` | `boot` + `envValide` : lancer `dist/main.js` avec un environnement et lire son code de sortie. Le message du socle le décrit précisément | | les 7 `telemetry` | `demarrerCollecteur()` de `@eqs/telemetry/testing`, livré **exprès** pour ça en 0.10.0, plus `root` et `routeJournal` | | `testing.check-budget`, `fichier-orphelin` | `check: { ms, budgetMs }` et `root`/`globsTests` — lus depuis `.eqs/check.json` et `vitest.config` | | `auth.roles-yaml`, `scope-borne`, `cookie`, les `jetons` | `roles.yaml` existe déjà ; `creerCleHorsDroits` peut réutiliser `apps/api/scripts/creer-cle.mjs` | | `testing.base-detruite` | non jouable pendant la suite, le socle le dit lui-même : `conteneurs` ou une dispense | Si tout n'est pas faisable d'un coup, la moitié utile serait déjà : **livrer le câblage que le socle a explicitement préparé** (le collecteur, `boot`/`envValide`, `root`/`globsTests`, `check`) et **poser dans `eqs-baseline.json` une dispense datée nommant les règles qui restent**, avec la raison. Un satellite verrait alors un étage vert et une liste écrite de ce qui manque encore — au lieu d'un rouge sans mode d'emploi. ## Versions `@eqs/*` 0.12.0, `eqs --version` 0.12.0, gabarit `228f8e4`, profil `nest`, Node 24.15.0, pnpm 11.8.0, Windows 11, Docker 29.1.3. ## Contournement posé Aucun. L'étage reste rouge sur ce seul cas dans notre satellite ; les 280 autres tests passent, `pnpm check`, `eqs doctor`, `eqs audit` et `pnpm test:e2e` sont verts. Rien n'est désactivé : il n'y aura rien à retirer.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Infrastructure/eqs-satellite-template#32
No description provided.