@nodefony/devkit 10.0.0-alpha.6 → 10.0.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/decorate.js +1 -1
  2. package/dist/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/decorateMetadata.js +1 -1
  3. package/dist/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/decorateParam.js +1 -1
  4. package/dist/index.js +2 -2
  5. package/dist/nodefony/controllers/DevkitController.js +2 -2
  6. package/dist/nodefony/controllers/McpController.js +3 -3
  7. package/dist/nodefony/service/DevkitService.js +2 -2
  8. package/package.json +8 -8
  9. package/skills/nodefony-add-crud/SKILL.md +9 -0
  10. package/skills/nodefony-add-realtime-channel/SKILL.md +9 -0
  11. package/skills/nodefony-add-service/SKILL.md +9 -0
  12. package/skills/nodefony-browser/SKILL.md +19 -16
  13. package/skills/nodefony-dev/SKILL.md +273 -0
  14. package/skills/nodefony-dev/scripts/docs.mjs +544 -0
  15. package/skills/nodefony-devops/SKILL.md +198 -0
  16. package/skills/nodefony-devops/references/compose.md +125 -0
  17. package/skills/nodefony-devops/references/frontal.md +119 -0
  18. package/skills/nodefony-devops/references/image.md +136 -0
  19. package/skills/nodefony-devops/references/kubernetes.md +189 -0
  20. package/skills/nodefony-devops/references/podman.md +103 -0
  21. package/skills/nodefony-devops/references/secrets.md +108 -0
  22. package/skills/nodefony-devops/references/variables.md +174 -0
  23. package/skills/nodefony-migrate-schema/SKILL.md +29 -17
  24. package/skills/nodefony-protect-route/SKILL.md +9 -0
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
1
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorate.js
2
2
  function __decorate(decorators, target, key, desc) {
3
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateMetadata.js
1
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorateMetadata.js
2
2
  function __decorateMetadata(k, v) {
3
3
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4
4
  }
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateParam.js
1
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorateParam.js
2
2
  function __decorateParam(paramIndex, decorator) {
3
3
  return function(target, key) {
4
4
  decorator(target, key, paramIndex);
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import defaults, { devkitConfigSchema } from "./nodefony/config/config.js";
2
2
  import { defineDevkitConfig } from "./nodefony/config/defineModuleConfig.js";
3
3
  import { buildCard } from "./nodefony/src/card.js";
4
- import __decorateMetadata from "./_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
5
- import __decorate from "./_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
4
+ import __decorateMetadata from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
5
+ import __decorate from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
6
6
  import DevkitService_default from "./nodefony/service/DevkitService.js";
7
7
  import DevkitController_default from "./nodefony/controllers/DevkitController.js";
8
8
  import McpController_default from "./nodefony/controllers/McpController.js";
@@ -1,5 +1,5 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
3
3
  import { Controller, controller, route } from "@nodefony/framework";
4
4
  //#region nodefony/controllers/DevkitController.ts
5
5
  /**
@@ -1,6 +1,6 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
3
- import __decorateParam from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateParam.js";
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
3
+ import __decorateParam from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateParam.js";
4
4
  import { ACCESS_TOKEN_VERIFIER, JsonRpcError, Nodefony, authorizeProtectedResource, checkMcpAccess, collectMcpTools, handleMcpMessage, jsonRpcFailure, mcpCallerRoles, protectedResourceMetadataUrl, readBearerHeader } from "nodefony";
5
5
  import { Body, Controller, Headers, controller, route } from "@nodefony/framework";
6
6
  //#region nodefony/controllers/McpController.ts
@@ -1,7 +1,7 @@
1
1
  import defaults from "../config/config.js";
2
2
  import { buildCard } from "../src/card.js";
3
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
4
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
3
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
4
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
5
5
  import { Module, Nodefony, Service, extend, injectable, mcpDeclaredScopes } from "nodefony";
6
6
  //#region nodefony/service/DevkitService.ts
7
7
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodefony/devkit",
3
- "version": "10.0.0-alpha.6",
3
+ "version": "10.0.0-alpha.7",
4
4
  "type": "module",
5
5
  "description": "Outillage de développement d'une application Nodefony : carte de visite du projet et portes de découverte pour un agent de développement",
6
6
  "author": "Christophe CAMENSULI <ccamensuli@gmail.com>",
@@ -25,17 +25,17 @@
25
25
  "coverage": "vitest run --coverage"
26
26
  },
27
27
  "peerDependencies": {
28
- "@nodefony/framework": "^10.0.0-alpha.6",
29
- "@nodefony/http": "^10.0.0-alpha.6",
30
- "nodefony": "^10.0.0-alpha.6",
31
- "zod": "^4.6.1",
28
+ "@nodefony/framework": "^10.0.0-alpha.7",
29
+ "@nodefony/http": "^10.0.0-alpha.7",
30
+ "nodefony": "^10.0.0-alpha.7",
31
+ "zod": "^4.6.5",
32
32
  "playwright": "^1.50.0",
33
33
  "lighthouse": "^13.0.0"
34
34
  },
35
35
  "devDependencies": {
36
- "@nodefony/framework": "^10.0.0-alpha.6",
37
- "@nodefony/http": "^10.0.0-alpha.6",
38
- "nodefony": "^10.0.0-alpha.6"
36
+ "@nodefony/framework": "^10.0.0-alpha.7",
37
+ "@nodefony/http": "^10.0.0-alpha.7",
38
+ "nodefony": "^10.0.0-alpha.7"
39
39
  },
40
40
  "dependencies": {
41
41
  "axe-core": "4.13.0",
@@ -17,6 +17,15 @@ description: >
17
17
 
18
18
  # add-crud — une ressource complète, générée
19
19
 
20
+ > 🧭 **Tu es arrivé ici directement ? Charge aussi `nodefony-dev`** — il porte la conduite
21
+ > commune (par où commencer, comment prouver que c'est fait) et les pièges qui coûtent une heure,
22
+ > serveur comme front. Cette page-ci ne couvre QUE son geste.
23
+ >
24
+ > Et si une réponse te manque, elle est probablement INSTALLÉE : `rg` ne descend pas dans
25
+ > `node_modules`, donc 70 pages de documentation y paraissent absentes. Une commande les lit, avec
26
+ > la ligne exacte :
27
+ > `node node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs <termes>`.
28
+
20
29
  > ⚖️ **La confiance n'exclut pas le contrôle.** Ce que le générateur produit se relit ;
21
30
  > ce que tu écris à la main se prouve par un test.
22
31
 
@@ -13,6 +13,15 @@ description: >
13
13
 
14
14
  # add-realtime-channel — le temps réel par sa couche
15
15
 
16
+ > 🧭 **Tu es arrivé ici directement ? Charge aussi `nodefony-dev`** — il porte la conduite
17
+ > commune (par où commencer, comment prouver que c'est fait) et les pièges qui coûtent une heure,
18
+ > serveur comme front. Cette page-ci ne couvre QUE son geste.
19
+ >
20
+ > Et si une réponse te manque, elle est probablement INSTALLÉE : `rg` ne descend pas dans
21
+ > `node_modules`, donc 70 pages de documentation y paraissent absentes. Une commande les lit, avec
22
+ > la ligne exacte :
23
+ > `node node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs <termes>`.
24
+
16
25
  > ⚖️ **La confiance n'exclut pas le contrôle.** Un canal sans politique est **public par
17
26
  > construction** — c'est le comportement voulu du framework, pas un oubli. Ce qui n'est pas
18
27
  > déclaré fermé est ouvert.
@@ -14,6 +14,15 @@ description: >
14
14
 
15
15
  # add-service — un service que le conteneur connaît
16
16
 
17
+ > 🧭 **Tu es arrivé ici directement ? Charge aussi `nodefony-dev`** — il porte la conduite
18
+ > commune (par où commencer, comment prouver que c'est fait) et les pièges qui coûtent une heure,
19
+ > serveur comme front. Cette page-ci ne couvre QUE son geste.
20
+ >
21
+ > Et si une réponse te manque, elle est probablement INSTALLÉE : `rg` ne descend pas dans
22
+ > `node_modules`, donc 70 pages de documentation y paraissent absentes. Une commande les lit, avec
23
+ > la ligne exacte :
24
+ > `node node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs <termes>`.
25
+
17
26
  > ⚖️ **La confiance n'exclut pas le contrôle.** Un service qui compile n'est pas un service
18
27
  > enregistré. Le seul juge est l'application en marche.
19
28
 
@@ -1,28 +1,31 @@
1
1
  ---
2
2
  name: nodefony-browser
3
3
  description: >
4
- Ouvre un écran de ton application dans un navigateur piloté pour le VOIR et surtout le MESURER —
4
+ Ouvre un écran de ton application Nodefony dans un navigateur piloté pour le VOIR et surtout le MESURER —
5
5
  contrastes et tailles réellement calculés par le moteur de rendu, audit d'accessibilité par
6
- axe-core, erreurs de console, requêtes HTTP, frames WebSocket. Fonctionne sur ta machine
7
- (Playwright) ou dans un conteneur jetable, au choix. Porte les sondes prêtes à l'emploi, le choix
8
- du thème clair ou sombre — un défaut d'affichage n'existe souvent que dans l'un des deux —, les
9
- contraintes de réseau qui font répondre `421` ou `401` à une application pourtant saine, et les
10
- pièges qui font conclure FAUX : mesurer avant que l'écran soit peuplé, observer un bundle qui
11
- n'est plus celui du code, prendre une condition d'arrêt qui réussit toujours. Sait aussi piloter
12
- un socket temps réel de bout en bout : accueil, abonnement à un canal, action, latence médiane,
13
- pont API, reconnexion. À charger AVANT de conclure quoi que ce soit sur un écran.
6
+ axe-core, erreurs de console, requêtes HTTP, frames WebSocket, sur ta machine ou dans un
7
+ conteneur jetable. Porte les sondes prêtes à l'emploi, le thème clair ou sombre — un défaut
8
+ d'affichage n'existe souvent que dans l'un des deux —, et les pièges qui font conclure FAUX :
9
+ mesurer avant que l'écran soit peuplé, ou observer un bundle qui n'est plus celui du code. Sait
10
+ aussi piloter un socket temps réel de bout en bout. À charger AVANT de conclure quoi que ce
11
+ soit sur un écran.
14
12
  Déclencheurs : "regarde l'écran", "vérifie l'affichage", "est-ce que ça s'affiche ?",
15
- "montre-moi la page", "lis la console", "y a-t-il des erreurs JS ?", "mesure le contraste",
16
- "cette couleur est-elle lisible ?", "capture d'écran", "vérifie l'accessibilité",
17
- "audit accessibilité", "audit WCAG", "en mode clair", "en mode sombre", "le thème sombre",
18
- "la page est-elle rapide ?", "temps de chargement", "responsive ?",
19
- "quelles requêtes fait la page ?", "le temps réel arrive-t-il jusqu'à l'écran ?",
20
- "teste le socket", "mesure la latence du websocket", "le canal pousse-t-il ?",
21
- "l'application démarre-t-elle vraiment ?".
13
+ "lis la console", "y a-t-il des erreurs JS ?", "mesure le contraste", "capture d'écran",
14
+ "vérifie l'accessibilité", "audit WCAG", "en mode sombre", "la page est-elle rapide ?",
15
+ "quelles requêtes fait la page ?", "teste le socket".
22
16
  ---
23
17
 
24
18
  # see-screen — voir et MESURER un écran
25
19
 
20
+ > 🧭 **Tu es arrivé ici directement ? Charge aussi `nodefony-dev`** — il porte la conduite
21
+ > commune (par où commencer, comment prouver que c'est fait) et les pièges qui coûtent une heure,
22
+ > serveur comme front. Cette page-ci ne couvre QUE son geste.
23
+ >
24
+ > Et si une réponse te manque, elle est probablement INSTALLÉE : `rg` ne descend pas dans
25
+ > `node_modules`, donc 70 pages de documentation y paraissent absentes. Une commande les lit, avec
26
+ > la ligne exacte :
27
+ > `node node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs <termes>`.
28
+
26
29
  > ⚖️ **La confiance n'exclut pas le contrôle.** Un `curl` prouve qu'une route répond ; il ne dit
27
30
  > pas si l'écran se monte, s'alimente et ne crie pas dans la console.
28
31
 
@@ -0,0 +1,273 @@
1
+ ---
2
+ name: nodefony-dev
3
+ description: >
4
+ Conduit une tâche de développement de bout en bout dans une application Nodefony — comprendre
5
+ le code en place, choisir la bonne façade, générer plutôt qu'écrire à la main, retrouver la
6
+ référence installée qu'une recherche ordinaire ne voit pas, puis prouver que c'est fait — et se
7
+ charge AVANT la première modification, quelle que soit la tâche.
8
+ Les gestes spécialisés ont leur propre skill (ressource REST, service, canal temps réel, garde
9
+ de route, migration de schéma, écran vu au navigateur) ; celui-ci porte la conduite commune,
10
+ les pièges du serveur et du front, et dit lequel prendre.
11
+ Déclencheurs : "je veux ajouter une fonctionnalité", "comment on code dans ce framework",
12
+ "par où je commence", "où est la doc de ça", "comment ça marche ici", "avant de coder",
13
+ "est-ce que j'écris ça à la main", "comment vérifier que c'est bon", "mon changement
14
+ est-il fini", "je ne trouve rien sur ce sujet", "ce n'est pas documenté", "je touche au
15
+ frontend", "mon composant charge des données", "mon écran n'affiche rien".
16
+ metadata:
17
+ version: 1.1.0
18
+ ---
19
+
20
+ # nodefony-dev — développer dans cette application sans rien inventer
21
+
22
+ > **Maintenance** : vérité courante, jamais un journal. Éditer en place ; l'historique vit dans
23
+ > `git log`. Ce fichier n'a **pas** de `references/` — et c'est une décision mesurée, pas un
24
+ > oubli : sur 1020 transcripts d'agents lâchés dans une application générée, une page de
25
+ > `references/` a été ouverte **0 fois**, quand un script cité comme commande l'a été dans 80 %
26
+ > des cas. Ce qui doit atteindre un agent s'EXÉCUTE ou vit dans ce corps ; ce qu'on déporterait
27
+ > « pour alléger » n'atteindrait plus personne.
28
+
29
+ ## Passer la main — TON PREMIER GESTE
30
+
31
+ 🔴 **Ta tâche est dans cette table ? CHARGE ce skill MAINTENANT, avant d'écrire une ligne, avant
32
+ même d'ouvrir un fichier.** Ce n'est pas un conseil de lecture : c'est le premier geste de la
33
+ tâche. Reviens ici ensuite si tu en as encore besoin.
34
+
35
+ **Ce que coûte de ne pas le faire, mesuré au banc, six exécutions :** chaque agent qui a chargé le
36
+ skill de sa tâche a réussi ; **chacun de ceux qui ne l'ont pas chargé a échoué** — l'un en
37
+ cherchant la base de l'application au mauvais endroit puis en l'effaçant, l'autre en écrivant une
38
+ migration qu'il n'a jamais appliquée. Aucun ne manquait d'information : la table était sous leurs
39
+ yeux. Ils ont simplement continué sans elle.
40
+
41
+ Ces skills sont installés avec le framework et se chargent par leur nom. Chacun porte les pièges
42
+ de son geste, et ceux-là ne se devinent pas — ils se paient.
43
+
44
+ | Ce que tu t'apprêtes à faire | Le skill |
45
+ | -------------------------------------------------------------------- | ------------------------------- |
46
+ | Une ressource : table, validation, service, REST et WebSocket | `nodefony-add-crud` |
47
+ | Une logique métier réutilisable, hors de tout controller | `nodefony-add-service` |
48
+ | Un flux temps réel, un canal, un abonnement client | `nodefony-add-realtime-channel` |
49
+ | Réserver une route, un rôle, une zone, ouvrir à un partenaire | `nodefony-protect-route` |
50
+ | Changer une entité déjà en base, ou déployer un schéma changé | `nodefony-migrate-schema` |
51
+ | Conclure quoi que ce soit d'un ÉCRAN — affichage, contraste, console | `nodefony-browser` |
52
+
53
+ Aucune ligne ne correspond ? Alors seulement, continue ici. Et si ta tâche est EXACTEMENT celle
54
+ d'un spécialiste, va droit à lui : il n'y a pas à passer par cette page d'abord.
55
+
56
+ `ls .agents/skills/` liste ceux que TON projet a reçus ; `npx nodefony ai:sync` les remet à jour
57
+ après une montée de version. Ce sont des **pointeurs** : le contenu vit dans `node_modules` et
58
+ suit la version installée — les éditer ne servirait à rien.
59
+
60
+ ## 1. La règle qui gouverne tout
61
+
62
+ **N'invente jamais du code Nodefony : génère-le, imite-le, vérifie-le.**
63
+
64
+ Ton `AGENTS.md` porte les trois actes et les tables qui vont avec — les générateurs, les
65
+ vérités du framework, les gates. **Ce skill ne les recopie pas** : une règle écrite à deux
66
+ endroits diverge au premier changement, et c'est alors la copie qu'on lit. Il porte ce qui n'y
67
+ tient pas : la **conduite** d'une tâche, les pièges qui coûtent une heure, et l'outil qui répond
68
+ à « où est-ce documenté ? ».
69
+
70
+ Le réflexe, avant d'écrire le moindre fichier : **un générateur le produit-il ?**
71
+ `npx nodefony create --help` liste ceux de TA version — la liste s'allonge, ta mémoire non.
72
+
73
+ ## 2. Trouver la référence — ce que `rg` ne peut pas voir
74
+
75
+ C'est le trou le plus coûteux de ce framework, et il ne ressemble pas à un trou : **la
76
+ documentation est installée, complète, et invisible**. `rg "session"` lancé à la racine ne
77
+ descend pas dans `node_modules` (git l'ignore, `rg` le suit). Le sujet paraît absent alors qu'il
78
+ occupe quinze pages — mesuré sur une application générée : **70 pages, plus de 38 000 lignes**.
79
+
80
+ Conclure « ce n'est pas documenté » et réécrire à la main est l'erreur que ce script existe pour
81
+ empêcher :
82
+
83
+ ```bash
84
+ D=node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs
85
+
86
+ node $D session cookie # les pages qui répondent — chemin, LIGNE, extrait
87
+ node $D --list # tout ce qui est installé, par module
88
+ node $D --open firewall # le chemin d'une page, pour l'ouvrir
89
+ node $D upload --json # pour rechaîner
90
+ ```
91
+
92
+ Il ne stocke aucune documentation : il lit celle de TES paquets à l'exécution, et rend le chemin
93
+ **et la ligne**. Tu ouvres à l'endroit exact au lieu de relire une page entière. Classement par
94
+ titre, sujet, étiquettes puis corps — une ligne qui porte TOUS tes termes passe devant deux
95
+ lignes qui en portent un chacune ; les accents sont ignorés.
96
+
97
+ **Ses codes de sortie disent quoi faire**, et l'un d'eux compte plus que les autres :
98
+
99
+ | Code | Ce qu'il veut dire | Le geste |
100
+ | ---: | ----------------------- | ------------------------------------------------------------- |
101
+ | 0 | trouvé | ouvrir le fichier à la ligne rendue |
102
+ | 1 | rien sur ces termes | un seul mot, ou `--list` pour voir les sujets couverts |
103
+ | 78 | **rien n'est installé** | `npm install` — ce n'est PAS « le sujet n'est pas documenté » |
104
+ | 64 | drapeau inconnu | `--help` |
105
+
106
+ > 🔴 **`78` n'est pas une panne, c'est une information.** Un projet dont les dépendances ne sont
107
+ > pas installées n'a aucune documentation à lire. Le DIRE ; ne jamais réécrire de mémoire ce
108
+ > qu'on n'a pas pu lire.
109
+
110
+ Deux autres voies existent quand l'application **tourne** : l'outil MCP `nodefony_docs` (cherche
111
+ dans la doc chargée) et `nodefony_symbols` (rend la SIGNATURE réelle d'un symbole, que ce script
112
+ ne porte pas). Elles supposent un serveur démarré et la porte câblée (`npx nodefony ai:mcp`) ;
113
+ `docs.mjs`, lui, répond toujours.
114
+
115
+ ## 3. Conduire une tâche — la séquence, et ses points d'arrêt
116
+
117
+ 1. **Demande à l'application, ne déduis pas du code.** `npx nodefony inspect routes`,
118
+ `inspect services`, `inspect config` rendent l'état RÉEL — routes montées, services résolus,
119
+ valeur effective **et sa provenance**. Une route lue dans un fichier peut n'être montée nulle
120
+ part ; l'inverse aussi.
121
+ **Un argument RESTREINT la réponse** — `inspect routes auth` ne rend que les routes dont le
122
+ chemin, le nom, le contrôleur, l'action, le module ou les méthodes portent `auth` ;
123
+ `inspect schema http` fait de même sur les réglages d'un module. Ne tronque JAMAIS une sortie
124
+ d'inspection (`| head`) pour la faire tenir : une application en sert facilement plusieurs
125
+ centaines, et ce qu'on cherche est presque toujours dans la partie coupée — c'est ainsi qu'on
126
+ conclut « le framework ne fournit pas ça » et qu'on le réécrit à la main.
127
+ 2. **Cherche la référence** (§2) avant de choisir une façade. Le framework en a presque toujours
128
+ une, et la contourner compile — c'est tout le piège.
129
+ 3. **Génère.** Si un générateur couvre le besoin, lance-le et **imite sa sortie** pour le reste.
130
+ `--dry-run` montre le plan et les diffs sans rien écrire ; un refus n'écrit jamais rien.
131
+ 4. **Édite le moins possible**, et regroupe : toutes les modifications serveur d'une même
132
+ fonctionnalité, PUIS un seul cycle de reconstruction. Le frontend passe en HMR, zéro
133
+ redémarrage.
134
+ 5. **Prouve.** `npm run verify` — une seule commande : types, style, tests, câblage, dans cet
135
+ ordre. Elle s'arrête au premier rouge, et **ce rouge est ta tâche suivante**.
136
+
137
+ **Le point d'arrêt qu'on rate** : `npm test` seul ne prouve pas que ça compile — vitest
138
+ n'inspecte aucun type. Une application peut être verte et ne pas compiler.
139
+
140
+ ## 4. Les pièges du serveur
141
+
142
+ Chacun a déjà coûté au moins une heure à quelqu'un. Les quatre premiers sont les plus fréquents.
143
+
144
+ - **Ta route répond 404 alors qu'elle existe dans les sources.** Le runtime charge `dist/`, pas
145
+ le source : `npm run build`. C'est la cause n°1.
146
+ - **Une classe que rien ne déclare compile, passe ses tests, et casse au démarrage suivant** —
147
+ entité hors `@entities([…])`, controller hors `@controllers([…])`. Table jamais créée, route
148
+ en 404. C'est le mode d'échec de la COPIE : on recopie le voisin au lieu d'appeler le
149
+ générateur, qui, lui, déclare. `npx nodefony doctor` la NOMME.
150
+ - **Une clé de configuration mal orthographiée est retirée en silence.** `satisfies` sur le
151
+ fragment n'est pas décoratif : sans lui, la faute compile, puis la validation écarte la clé et
152
+ le module démarre sur son défaut. Personne ne le voit.
153
+ - **Tu lis une liste sans la BORNER.** Un `find` sans limite matérialise la table entière —
154
+ indolore sur les quelques lignes du poste de développement, fatal sur les dizaines de milliers
155
+ de la production. Le service d'une entité hérite `findPage({ limit: 25 })`.
156
+
157
+ ### Ce qui tue le processus, pas la requête
158
+
159
+ - 🔴 **Une promesse lancée sans `await` porte TOUJOURS un `.catch()`.** Audit, courriel,
160
+ notification, nettoyage différé : un rejet non capté ne casse pas la requête, il tue le
161
+ **processus entier** — donc toutes les requêtes en vol, pas seulement la tienne.
162
+ - 🔴 **Un handler ne bloque jamais la boucle d'événements.** Aucune API `*Sync`
163
+ (`readFileSync`, `pbkdf2Sync`, `zlib`, `child_process`), aucun `JSON.parse` sur un corps non
164
+ borné, aucune expression régulière à quantificateurs imbriqués sur une entrée utilisateur.
165
+ Au-delà d'une milliseconde de calcul, passe par `worker_threads` : un seul handler lourd
166
+ bloque **tous** les clients, pas seulement celui qui l'a déclenché.
167
+ - **Un `PATCH` au corps vide se refuse en `400`.** Le laisser passer produit un `updateOne({})`,
168
+ qui finit en `500 « No values to set »` — une erreur serveur pour une faute de client.
169
+
170
+ ### Quand ça ne va pas, et que le message ne suffit pas
171
+
172
+ - **Un test vert seul et rouge en suite accuse une RESSOURCE PARTAGÉE**, pas ton code : base ou
173
+ index réutilisé, port, store jamais purgé, assertion `count === N` qui suppose une table
174
+ vierge. Lance deux fichiers ENSEMBLE pour isoler la paire, puis cloisonne. **Ne sérialise
175
+ jamais la suite** pour faire passer le rouge : tu masques la cause et tu paies la lenteur à
176
+ chaque exécution.
177
+ - **Une suite lancée contre un serveur en `production` reçoit `404` partout** : les modules
178
+ `policy:"dev"` n'y sont pas. `NF_WITH_DEV_MODULES=1` déroge pour 30 minutes
179
+ (`NF_WITH_DEV_MODULES_TTL_MIN`, 4 h au plus), et le `CRITIC « arrêt automatique … dérogation »`
180
+ du journal est cette garde qui se referme — pas une panne.
181
+ - **Ton application a démarré AMPUTÉE et tout a l'air sain** — base injoignable, module écarté
182
+ par sa politique. Seul `npx nodefony doctor` le dit, en relisant `var/last-boot.json`.
183
+ ⚠️ Ce bilan a un ÂGE : il décrit le **dernier démarrage**, et une commande console (`inspect`,
184
+ une commande de module) ne l'écrase pas. C'est voulu — lis la date avant d'en conclure.
185
+ - **L'application ne démarre plus et le superviseur avale la sortie** :
186
+ `NF_DEV_CHILD=1 npx nodefony development` lance l'enfant seul et montre le crash brut.
187
+
188
+ ## 5. Les pièges du front
189
+
190
+ Ne concerne qu'une application qui a un frontend. Sauf mention, **vaut pour les quatre moteurs**
191
+ (React, Vue, Angular, Svelte) : le framework ne t'en impose aucun.
192
+
193
+ ### Ce qui fuit, et ce qui s'injecte
194
+
195
+ - 🔴 **Toute donnée non maîtrisée se rend en nœud TEXTE.** Jamais `dangerouslySetInnerHTML`
196
+ (React), `v-html` (Vue), `[innerHTML]` (Angular), `{@html}` (Svelte). Un Markdown se rend sans
197
+ HTML brut.
198
+ - 🔴 **L'identité est un cookie `HttpOnly` que le navigateur joint seul.** Aucun jeton en
199
+ `localStorage` ou `sessionStorage`, aucun en-tête `Authorization` écrit à la main. Un `401`
200
+ est un ÉTAT (« pas connecté »), pas une erreur à journaliser.
201
+ - 🔴 **Le bundle front n'importe jamais un module serveur** — `@nodefony/http`,
202
+ `@nodefony/security`, une entité ORM, `nodefony.config`, `.env`. Un type serveur passe par
203
+ `import type` ou un miroir. Le test qui tranche : **si l'import tire un `node:*`, arrête-toi**
204
+ — ce bundle est public.
205
+ - **Rien de secret ne part côté client.** Toute clé `VITE_*` est lue par le navigateur ; un
206
+ `console.*` de données committé est une fuite. Le front AFFICHE ce qu'il reçoit — la rédaction
207
+ des secrets est un travail de serveur.
208
+
209
+ ### Charger des données sans casser l'écran
210
+
211
+ - **Un écran qui charge a quatre états EXCLUSIFS**, dans cet ordre de priorité : erreur (avec un
212
+ « réessayer »), chargement (un squelette qui épouse la page), vide (qui dit POURQUOI), données.
213
+ Un seul visible à la fois.
214
+ - **Tout chargement porte un jeton de génération** : une réponse arrivée après démontage, ou
215
+ après un changement de paramètre, est IGNORÉE — sinon un écran affiche les données d'un autre.
216
+ `loading` vaut `true` dès le montage, jamais après. Le framework ne fournit pas de hook de
217
+ ressource : c'est à écrire, dans les quatre moteurs.
218
+ - **Au vrai changement de compte** (l'identifiant passe d'une valeur à une AUTRE), force
219
+ `disconnect()` puis `connect()` sur la socket partagée et purge les caches propres à
220
+ l'utilisateur. Jamais au démarrage ni au rechargement : tu couperais les requêtes en vol.
221
+
222
+ ### Un écran qui se met à jour tout seul
223
+
224
+ - **Un widget temps réel est invisible tant qu'il ne se passe rien.** Format par paliers (jamais
225
+ une valeur qui saute de millisecondes à secondes), `font-variant-numeric: tabular-nums` sur
226
+ tout nombre qui change, aucune animation rejouée à chaque tick, `prefers-reduced-motion`
227
+ respecté, et un contrôle pause/fréquence dès que ça bouge seul plus de 5 s (WCAG 2.2.2).
228
+ **Le test** : fixe l'écran 30 secondes — rien ne doit bouger sans cause.
229
+ - **N'anime que `transform` et `opacity`** ; `contain: content` sur chaque widget vivant,
230
+ `content-visibility: auto` sur les longues listes.
231
+ - **Accessibilité, le minimum qui se vérifie à l'œil** : un seul `<h1>` par page, `aria-label`
232
+ sur tout bouton-icône, `aria-expanded` sur tout bascule, `aria-live` sur les zones qui changent
233
+ seules, `role="img"` + `aria-label` sur un graphe SVG, jamais une information portée par la
234
+ **couleur seule**, `rel="noopener noreferrer"` sur les liens externes.
235
+
236
+ ### Le piège qui fait croire à un bug de code
237
+
238
+ - **Vite affirme qu'un export n'existe pas** (`does not provide an export named …`) alors qu'il
239
+ est bien dans le source — typiquement après un nouveau sous-chemin `nodefony/*`, une dépendance
240
+ ajoutée, ou un `git pull`. C'est son cache : `rm -rf node_modules/.vite`, puis relance. Ne
241
+ purge pas sans raison, ça coûte 5 à 20 s de ré-optimisation.
242
+
243
+ ## 6. Avant de dire « fait »
244
+
245
+ ```bash
246
+ npm run verify # types + style + tests + câblage
247
+ npm run test:e2e # boot réel + HTTP/WS — le gate LENT, hors `verify`
248
+ ```
249
+
250
+ Puis, en une phrase : **nomme ce que tu n'as PAS lancé.** Un vert ne couvre que le diff qui l'a
251
+ produit, et un banc sauté faute de son décor compte comme vert. Dire « e2e non lancé » coûte
252
+ cinq mots ; le taire coûte la confiance dans tout le reste.
253
+
254
+ Quatre règles de plus, chacune payée par une conclusion fausse qu'on a crue. Elles ne parlent
255
+ pas de ce framework en particulier — elles parlent de la façon dont une preuve se fabrique.
256
+
257
+ - 🔴 **Ta preuve porte sur l'artefact qu'on REÇOIT, pas sur ce que tu viens d'écrire.** Le
258
+ runtime charge `dist/`, une image embarque ce que le `Dockerfile` a copié, un paquet publié
259
+ contient ce que `files` laisse passer. Et avant de mesurer, vérifie que la transformation a
260
+ bien EU LIEU (date, empreinte) : dans une chaîne `a && b && c`, un maillon qui échoue laisse
261
+ mesurer l'ancienne version — et « prouver » qu'un correctif ne change rien.
262
+ - 🔴 **Un test que tu n'as jamais vu ROUGE ne prouve rien.** Écris-le, puis casse exprès ce
263
+ qu'il garde : retire le correctif, débranche le câblage. S'il reste vert, il ne mesure pas ce
264
+ que tu crois. Remets, et alors seulement crois-le. Un test écrit face au code déjà corrigé est
265
+ complaisant par construction.
266
+ - **Un décor SALE fabrique des verdicts faux** : un serveur resté ouvert sur le port, une base
267
+ jamais purgée, une variable d'environnement absente. Avant d'accuser ton code, qualifie le
268
+ rouge sur un décor NEUF — sinon tu corriges un problème qui n'existe pas, et tu laisses
269
+ intact celui qui existe.
270
+ - **Suspecte ton instrument avant de suspecter le code.** Une commande qui rend « 0 résultat »,
271
+ un compteur à zéro, un journal vide : demande-toi d'abord si l'outil regarde au bon endroit.
272
+ Une sortie tronquée, un filtre trop étroit, un chemin qui n'existe plus ne s'annoncent jamais
273
+ — ils rendent un silence qui ressemble à une réponse.