feat/etage-e2e-reel #26

Merged
nicolas-fryder merged 6 commits from feat/etage-e2e-reel into main 2026-09-15 21:15:38 +00:00
No description provided.
#64 — le garde-fou refusait toute DDL sur-mesure
─────────────────────────────────────────────────
`refuser-genere.mjs` attrapait tout `prisma/migrations/**`, squelette
`--create-only` compris. Or c'est la SEULE voie documentée pour poser du SQL
que le schéma ne sait pas dire — déclencheur, fonction, vue, contrainte
CHECK — et éditer ce squelette est le but de l'option. Aucune DDL sur-mesure
n'était donc possible dans un satellite, et une frontière de sécurité
restait tenue par convention au lieu de l'être par la base.

Le rapporteur proposait de ne refuser qu'un `migration.sql` NON VIDE. J'ai
pris un autre discriminant : `--create-only` produit un squelette vide quand
le schéma n'a pas bougé, mais NON VIDE quand il a bougé — et éditer ce
second squelette avant de l'appliquer est tout aussi légitime. La question
n'est pas la taille du fichier, c'est « cette migration est-elle partie ».

Donc : refusée seulement si git la suit déjà. Une migration appliquée a été
committée, c'est ce qui la rend partageable ; un squelette qu'on vient de
créer n'est suivi par personne. Si git ne répond pas, on laisse passer — ce
hook rattrape une distraction, il n'est pas une frontière de sécurité, et un
refus à tort est ce que le ticket reprochait.

Éprouvé aux trois états : squelette neuf → passe, migration en historique →
refusée, fichier généré ordinaire → refusé.

Et le message, qui était faux : « effacée à la prochaine génération » ne
vaut pas pour une migration, qui est un historique que RIEN ne régénère.
Chaque entrée porte maintenant sa propre raison.

#63 — `db:dev` échoue au lieu d'attendre
────────────────────────────────────────
Sans `--name`, `prisma migrate dev` demande un nom au clavier : un appelant
non interactif reste bloqué, et l'interrompre laisse le verrou consultatif
de Prisma pris — la migration suivante attend alors indéfiniment sans dire
ce qu'elle attend.

`scripts/migrer.mjs` refuse en nommant ce qui manque. Un échec qui dit ce
qui manque vaut mieux qu'une attente muette : c'est la doctrine du socle au
démarrage, elle vaut ici.

AGENTS.md porte la forme non interactive, `--create-only` pour les DDL, et
une section sur le verrou avec la requête pour le lever — le symptôme « ça
ne rend pas la main » ne mène pas à la cause.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Il existait sur le papier : `test:e2e` déclaré, aucun Playwright installé,
aucune configuration, aucun fichier, et un `;` qui faisait rendre au
script le code de sortie du nettoyage plutôt que celui des tests. Même si
Playwright avait existé et échoué, la commande rendait 0.

Trente satellites héritent de ce fichier. Ils héritaient donc tous d'un
étage incapable de rougir, compté comme passé partout où on le regarde.

Un seul cas, et c'est délibéré : un gabarit n'a pas de métier à éprouver.
Ce qu'il doit livrer, c'est un étage qui MARCHE, pour que le premier vrai
cas d'un satellite tombe dans un dispositif déjà debout.

L'assertion sur la console vaut plus qu'elle n'en a l'air : une erreur
d'hydratation de React n'échoue jamais un test de rendu — la page finit
par s'afficher, seulement reconstruite côté client. Elle ne se voit que là.

`eqs-platform` pose en parallèle `testing.etage-declare-vide`, qui rend ces
trois motifs bloquants pour qu'aucun satellite n'y retombe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Trois correctifs remontés depuis `eqs-demo`, où ils ont été trouvés en
faisant tourner l'application pour de vrai.

Le rendu passe en dynamique. La CSP du socle porte un nonce et
`strict-dynamic` ; `strict-dynamic` annule `'self'`, et Next ne peut pas
poser de nonce sur une page prérendue. Sans cette ligne, onze scripts
bloqués, page jamais hydratée, accueil figé sur « Chargement… » — sans
message, avec des sondes HTTP à 200.

Playwright ne réutilise plus un serveur déjà là. Sur la démo, le port par
défaut était pris par une autre application de la machine : la suite a
tourné contre elle une exécution entière, et un cas est passé. Un étage
qui atteste de ce qu'il n'a pas regardé est pire que pas d'étage.

Et une icône, parce que chaque navigateur demande `/favicon.ico` et que
chaque déploiement journalisait un 404.

`EqsProvider` avait déjà le bon `baseUrl` ici : c'est la démo qui avait
divergé. Troisième fois aujourd'hui qu'un correctif du gabarit n'avait pas
été propagé, ou l'inverse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Le dépôt en déclarait TROIS : `^0.8.0` dans les applications, `^0.7.0`
oublié dans `variantes/next-fullstack`, alors que la démo était déjà en
`^0.9.0`. Deux versions de retard pour le dépôt que trente satellites
clonent, et une troisième cachée deux niveaux sous un dossier que personne
n'ouvre.

Personne ne pouvait le voir : chaque `package.json` est cohérent avec
lui-même, et rien ne regardait les jointures. `eqs-platform` pose en
parallèle `testing.versions-eqs-melangees`, qui refuse qu'un dépôt en
déclare plusieurs et nomme qui déclare quoi.

Les dix paquets sortent ensemble (D-022) et ne sont éprouvés qu'ensemble :
un socle mixte est une combinaison que personne n'a jouée.

Et `refuser-genere.mjs` ne dit plus `--filter api` en dur : il déduit le
projet de `apps/<nom>/…`. Copié tel quel dans la démo, qui n'a pas d'app
`api`, il envoyait vers une commande inexistante — un garde-fou qui refuse
ET indique une fausse issue coûte deux fois.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`deepmerge-ts` < 8 (GHSA-ggr8-5vv4-36mx, épuisement de pile) arrivait par
`prisma > @prisma/config` ; `js-yaml` < 4.3.2 par `@nestjs/swagger` et `orval`.
Les deux sont forcés à leur version corrigée dans `pnpm-workspace.yaml` — c'est
là que pnpm 11 lit les `overrides`, et pas dans `package.json`. La dispense de
`deepmerge-ts` est retirée : l'avis n'existe plus, et une dispense qui survit à
son objet finit par couvrir autre chose.

`pnpm audit` ne trouve plus rien. Les deux consommateurs de `js-yaml` ont été
joués : `eqs openapi export` écrit le contrat, `orval` génère le client.

Les deux hooks `.claude/` deviennent des relais vers `@eqs/cli` (chasse 14 : la
copie locale de `refuser-genere` avait 84 lignes d'écart avec celle de la démo).

ATTENTION, fenêtre ouverte : `@eqs/cli@0.9.0`, le candidat publié, n'expose pas
encore `refuser-genere` ni `typer-apres-ecriture`. Les relais le disent à chaque
appel et laissent passer l'écriture — le garde est donc INACTIF jusqu'à la
prochaine publication du socle. C'est assumé : une copie divergente qui refuse
la mauvaise chose coûte plus qu'un garde absent qui l'annonce.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`main` avait gagné deux fusions depuis que cette branche a été coupée : la
montée « Socle 0.8.1 » (#21) et le correctif du `pre-push` (#20).

Les quatre conflits venaient tous du même endroit : `^0.8.1` contre `^0.9.0`
dans les trois manifestes et le lockfile. L'alignement 0.9.0 est gardé — il est
postérieur, et `testing.versions-eqs-melangees` refuse qu'un dépôt en déclare
plusieurs. Vérifié que le côté `main` n'apportait rien d'autre dans ces
sections : aucune ligne perdue.

Le lockfile n'a pas été résolu à la main mais régénéré, et il ne porte plus
aucune entrée 0.8.1. `pnpm check` est vert.

Le seul apport net de `main` est donc `.githooks/pre-push`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nicolas-fryder deleted branch feat/etage-e2e-reel 2026-09-15 21:15:39 +00:00
Sign in to join this conversation.
No reviewers
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!26
No description provided.