Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
e4960af
docs(adr): aligner les ADR sur les décisions du socle API-first
mickael-coquer-igocreate Sep 7, 2026
95863fb
feat(server): routes API JSON, validation Zod et erreurs RFC 9457
mickael-coquer-igocreate Sep 7, 2026
bdf945b
feat(server): déclarations TypeScript sur l'API publique
mickael-coquer-igocreate Sep 7, 2026
9ffd02e
feat(server): squelettes api et api-ts
mickael-coquer-igocreate Sep 7, 2026
9a6d937
docs(server): documenter les API JSON
mickael-coquer-igocreate Sep 7, 2026
305b9f1
feat(server): rendre les erreurs API identifiables par programme
mickael-coquer-igocreate Sep 7, 2026
39fd3c4
docs(server): expliquer pourquoi le type d'igo est un URN
mickael-coquer-igocreate Sep 7, 2026
ffde138
docs(server): signaler que l'ordre de montage des routes API compte
mickael-coquer-igocreate Sep 7, 2026
c745d9a
chore: passer à TypeScript 7 et cibler Node 24 sur les squelettes API
mickael-coquer-igocreate Sep 7, 2026
f03f233
chore(server): accepter mocha 12 en peer dependency
mickael-coquer-igocreate Sep 7, 2026
7622837
feat(server): rendre le crash sur exception non capturée configurable
mickael-coquer-igocreate Sep 7, 2026
7fa707f
feat(server)!: un seul squelette API, en TypeScript
mickael-coquer-igocreate Sep 7, 2026
03cf440
feat(server): logs structurés et identifiant de requête
mickael-coquer-igocreate Sep 7, 2026
0bfe5b2
feat(server): identifier le service, la version et l'environnement da…
mickael-coquer-igocreate Sep 7, 2026
08f9276
feat(server): squelette front React
mickael-coquer-igocreate Sep 7, 2026
d70eb3c
feat(server): outillage projet dans les squelettes api et front
mickael-coquer-igocreate Sep 7, 2026
9cc99b3
feat(server): squelette fullstack et E2E Playwright
mickael-coquer-igocreate Sep 7, 2026
70ecf29
feat(server): formatage automatique par oxfmt dans les squelettes
mickael-coquer-igocreate Sep 7, 2026
fd46264
refactor(server)!: organiser les squelettes par feature, back devient…
mickael-coquer-igocreate Sep 7, 2026
e23b3e1
fix(server)!: harmoniser les CI des squelettes, MySQL en service, Valkey
mickael-coquer-igocreate Sep 7, 2026
e93ac85
feat(server): E2E Playwright dans le squelette front
mickael-coquer-igocreate Sep 7, 2026
403c138
fix(server): Playwright démarre l'API, et teste le build en CI
mickael-coquer-igocreate Sep 7, 2026
b93b60a
revert(server): retirer Playwright du squelette front
mickael-coquer-igocreate Sep 7, 2026
9eb0eee
docs(server): alléger les commentaires des workflows
mickael-coquer-igocreate Sep 7, 2026
0fd3ed1
docs: documenter les trois squelettes API-first
mickael-coquer-igocreate Sep 7, 2026
8a615e1
feat(server): docker-compose pour les dépendances locales
mickael-coquer-igocreate Sep 7, 2026
d27f34e
docs(skel): typer les erreurs métier du contrôleur d'exemple
mickael-coquer-igocreate Sep 7, 2026
b679add
fix(cli): accepter les seeds TypeScript
mickael-coquer-igocreate Sep 7, 2026
1dddeb4
feat(skel): ajouter migrate et seed aux squelettes API
mickael-coquer-igocreate Sep 8, 2026
cb54ea1
test(skel): vérifier que le contrôleur d'exemple type ses erreurs
mickael-coquer-igocreate Sep 8, 2026
cb48f4a
chore(skel): retirer l'exemple de conf nginx du squelette fullstack
mickael-coquer-igocreate Sep 8, 2026
d423c70
feat(skel): faire de e2e un paquet pnpm, avec page objects
mickael-coquer-igocreate Sep 8, 2026
a10d5c2
docs(skel): répartir les conventions entre la racine et les paquets
mickael-coquer-igocreate Sep 8, 2026
36beba0
chore: ignorer dump.rdb
mickael-coquer-igocreate Sep 8, 2026
295974b
docs(skel): mettre le ticket en tête du sujet de commit
mickael-coquer-igocreate Sep 8, 2026
140012a
docs(server): corriger les exemples de configuration
mickael-coquer-igocreate Sep 8, 2026
840d502
docs: documenter le socle API-first dans le CLAUDE.md racine
mickael-coquer-igocreate Sep 8, 2026
a800d39
ci: linter les points d'entrée des paquets
mickael-coquer-igocreate Sep 8, 2026
b134991
docs(adr): retirer la mesure en CI du poids des pages
mickael-coquer-igocreate Sep 8, 2026
85dc0b8
refactor(server)!: ne garder qu un squelette TypeScript
mickael-coquer-igocreate Sep 10, 2026
10a7f3f
feat(server): exposer un point d entrée pour charger le .env
mickael-coquer-igocreate Sep 10, 2026
1abee3b
feat(server): exporter redact() et la rendre configurable
mickael-coquer-igocreate Sep 10, 2026
b797634
feat(server): un identifiant unique et des logs de requête filtrables
mickael-coquer-igocreate Sep 10, 2026
3ca0ee7
fix(server): rendre ApiHandler assignable derrière un middleware
mickael-coquer-igocreate Sep 10, 2026
62df221
feat(server): émettre finish sur la réponse simulée des tests
mickael-coquer-igocreate Sep 10, 2026
501a8a7
feat(server): créer les .env et le dépôt git à la génération
mickael-coquer-igocreate Sep 10, 2026
866e033
fix(skel): rendre les ports configurables et raccourcir les délais E2E
mickael-coquer-igocreate Sep 10, 2026
70c5c93
feat(skel): livrer l observabilité du socle
mickael-coquer-igocreate Sep 10, 2026
38209a2
docs(skel): passer les commentaires du code en français
mickael-coquer-igocreate Sep 10, 2026
049e3e7
docs(skel): écrire les conventions manquantes
mickael-coquer-igocreate Sep 10, 2026
cca24e3
style(skel): aligner observability.ts sur oxfmt
mickael-coquer-igocreate Sep 10, 2026
419e26f
feat(skel): auditer l accessibilité dans les tests E2E
mickael-coquer-igocreate Sep 10, 2026
f004919
fix(server): rendre la CI verte et sortir les secrets du code généré
mickael-coquer-igocreate Sep 10, 2026
9b9309f
fix(server): identité de trace sur toute réponse, requêtes API sans m…
mickael-coquer-igocreate Sep 10, 2026
46e0a49
docs(server): aligner la documentation sur le trace id et les deux sq…
mickael-coquer-igocreate Sep 10, 2026
1e87eeb
refactor(skel): interface et libellés de test en français, types de l…
mickael-coquer-igocreate Sep 10, 2026
27a6505
docs(skel): déposer la couche API dans un projet igo existant
mickael-coquer-igocreate Sep 10, 2026
d3da150
feat(server): en-têtes de sécurité par défaut, CSP de la SPA, Faro sa…
mickael-coquer-igocreate Sep 10, 2026
12ac8bb
docs(skel): les README portent la documentation, les CLAUDE.md le har…
mickael-coquer-igocreate Sep 10, 2026
7490def
chore(skel): deploy/ pour nginx et Alloy, dependabot, commentaires du…
mickael-coquer-igocreate Sep 10, 2026
a4169de
feat(skel): garde de session sur la suppression d'un livre
mickael-coquer-igocreate Sep 10, 2026
6bd42dd
fix(skel): déclarer packageManager, sans quoi pnpm/action-setup échou…
mickael-coquer-igocreate Sep 10, 2026
af31d7d
chore(skel): actions GitHub aux versions courantes (checkout 7, setup…
mickael-coquer-igocreate Sep 10, 2026
70f4dfb
feat(server): sondes de liveness et de readiness
mickael-coquer-igocreate Sep 11, 2026
f9ad5da
fix(server): une dépendance facultative ne fait plus échouer la readi…
mickael-coquer-igocreate Sep 11, 2026
89055f6
fix(skel): le collecteur Faro refuse les envois sans identifiant de s…
mickael-coquer-igocreate Sep 11, 2026
6f1c689
refactor(skel): un collecteur par machine, un pour l'infrastructure
mickael-coquer-igocreate Sep 11, 2026
2773193
feat(skel): sonde de disponibilité, étiquettes de machine, plafond mé…
mickael-coquer-igocreate Sep 11, 2026
a012fd2
feat(skel): tableau de bord et règles d'alerte Grafana
mickael-coquer-igocreate Sep 11, 2026
a547834
fix(skel): Dependabot ne surveillait que le package.json de la racine
mickael-coquer-igocreate Sep 14, 2026
01e641a
refactor(skel): la garde d'authentification se nomme par son intention
mickael-coquer-igocreate Sep 14, 2026
ce66d47
fix(skel): une erreur d'API remonte avec la trace du serveur
mickael-coquer-igocreate Sep 14, 2026
2dcf364
refactor(skel): la technique se nomme en anglais
mickael-coquer-igocreate Sep 14, 2026
f82d85f
docs: alléger ce que le code dit déjà
mickael-coquer-igocreate Sep 14, 2026
a2221c8
refactor(server): le gestionnaire d'erreurs ne connaît plus les bases
mickael-coquer-igocreate Sep 14, 2026
7d204d6
refactor(server): isApiRequest quitte les documents de problème
mickael-coquer-igocreate Sep 14, 2026
8da61ed
fix(server): l'absence de TypeScript ne fait plus passer le test des …
mickael-coquer-igocreate Sep 14, 2026
225405c
docs: ne plus mentionner un en-tête qui n'a jamais été publié
mickael-coquer-igocreate Sep 14, 2026
b6e25e8
docs: le journal de requête porte un identifiant de trace
mickael-coquer-igocreate Sep 14, 2026
7d0a6bb
refactor(skel): la lecture de l'en-tête de trace se nomme en anglais
mickael-coquer-igocreate Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
node_modules
coverage
*.log
dump.rdb

docs/.vitepress/cache
docs/.vitepress/dist
Expand Down
9 changes: 8 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Igo is a Node.js full-stack web framework built on Express, providing ORM, templ
│ ├── server/ # @igojs/server - Express framework core
│ └── component/ # @igojs/component - Reactive components with SSR
├── docs/ # VitePress documentation (deployed to GitHub Pages)
│ └── adr/ # Architecture decision records (internal, not published)
├── package.json # Root workspace configuration
└── CHANGELOG.md # Version history
```
Expand Down Expand Up @@ -51,8 +52,12 @@ Igo is a Node.js full-stack web framework built on Express, providing ORM, templ
- i18next internationalization
- Redis caching, email (nodemailer + MJML)
- CLI for scaffolding and database commands
- JSON APIs: schema validation, RFC 9457 errors, structured logging
- **Entry:** `packages/server/src/index.js`
- **CLI:** `packages/server/cli/igo.js`
- **JSON API layer:** `packages/server/src/api/`
- **TypeScript types:** `packages/server/index.d.ts`
- **Project skeletons:** `packages/server/skel/` — `fullstack` scaffolds a TypeScript API + React SPA monorepo with its own tooling (pnpm, oxlint, oxfmt); `tailwind` is the server-rendered igo app

### @igojs/component (Reactive Components)
- Single-file `.dust` components (`<script>` + template)
Expand Down Expand Up @@ -160,6 +165,8 @@ Le package principal `@igojs/igo` (`packages/igo/`) est un meta-package qui depe
|------|---------|
| `packages/*/package.json` | Package configurations |
| `.mocharc.js` | Mocha test config |
| `.eslintrc.json` | ESLint rules |
| `eslint.config.js` | ESLint rules |
| `packages/dust/webpack.config.js` | Dust browser build config |
| `packages/server/cli/igo.js` | CLI entry point |
| `packages/server/index.d.ts` | TypeScript declarations for `@igojs/server` |
| `packages/server/skel/` | Templates used by `igo create` |
2 changes: 2 additions & 0 deletions docs/.vitepress/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ export default defineConfig({
items: [
{ text: 'Getting started', link: '/server/getting-started' },
{ text: 'Routes & controllers', link: '/server/routes' },
{ text: 'JSON APIs', link: '/server/api' },
{ text: 'Views', link: '/server/views' },
{ text: 'Forms', link: '/server/forms' },
{ text: 'Cache (Redis)', link: '/server/cache' },
{ text: 'Mailer', link: '/server/mailer' },
{ text: 'Flash scope', link: '/server/flash' },
{ text: 'i18n', link: '/server/i18n' },
{ text: 'Error handling', link: '/server/errors' },
{ text: 'Logging', link: '/server/logging' },
],
},
],
Expand Down
192 changes: 192 additions & 0 deletions docs/adr/architecture-front-de-reference.md

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions docs/adr/chaine-de-build-du-front.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Chaîne de build et de déploiement du front

**Statut** : accepté
**Date** : 2026-08-21

## Context and Problem Statement

L'ADR [Architecture front de référence](architecture-front-de-reference.md) a tranché la cible — front à composants buildé en assets statiques, API JSON, **un artefact**, assets servis par nginx. Il n'a pas dit **où vit la source du front**, **où tourne son build**, ni **comment on développe**.

Trois contraintes de l'existant cadrent la question :

- `ovh-ladom2` construit **sur le serveur** au déploiement : `npm ci` puis `npm run webpack-prod` dans une tâche Ansible. Le déploiement enchaîne `pm2 delete` et `pm2 start`, avec sa fenêtre d'indisponibilité. **Six environnements.**
- nginx sert déjà les statiques (`try_files $uri @app`). igo ne les sert pas.
- **Le seul « Mauvais » chiffré de l'option retenue** était la cohabitation de deux chaînes de build dans un même projet npm, jugée complexe par l'équipe — *« un projet vierge aurait été plus simple »*.

## Considered Options

**Où vit la source du front**

1. **Dans le projet npm existant** — une seule arborescence, deux chaînes de build à faire cohabiter.
2. **En projet npm frère, dans le même dépôt** — deux `package.json`, deux jeux de dépendances, un dépôt.
3. **Dans un dépôt séparé** — cycle de vie indépendant, artefact publié puis récupéré.

**Où tourne le build**

A. **Sur le serveur**, pendant le déploiement, comme le webpack actuel.
B. **En CI**, avec un artefact déposé que le déploiement recopie.

## Decision Outcome

**Option 2 + A : un dépôt par projet, front en projet npm frère du back, buildé sur le serveur au déploiement.**

- **Un dépôt par projet applicatif**, contenant le front et le back côte à côte. Pas de dépôt front partagé entre projets.
- **Le front est une SPA Vite ordinaire.** Sur ses routes, il possède la page entière : sa coquille est son propre `index.html`, produit par le build, servi par nginx. **Aucun template serveur n'intervient, donc aucun manifeste à lire côté back et aucune conditionnelle dev/prod dans un template.** Le motif des intégrations back de Vite (`vite_rails`, `django-vite`) ne s'applique pas ici : il n'existe que parce que le back rend la page.
- **Build sur le serveur** : une tâche Ansible de plus, à côté de celle qui existe. Les statiques produits sont recopiés dans le répertoire servi par nginx.
- **En développement** : serveur de dev Vite avec rechargement à chaud, et un **proxy `/api` vers le port d'igo**. Le navigateur voit tout en même origine, donc le cookie de session passe sans CORS.
- **Les URL d'API sont relatives** (`/api/...`). C'est ce qui permet au même `index.html` haché de fonctionner dans les six environnements sans être recompilé par environnement.

### Pourquoi les autres ont été écartées

- **Option 1** — c'est exactement le point de friction mesuré. Deux répertoires frères avec leurs dépendances propres ne cohabitent pas, ils se juxtaposent : le problème disparaît au lieu d'être géré.
- **Option 3** — elle règle la friction de build, mais introduit une discipline de version entre deux dépôts : quelle version du front est déployée avec quelle version de l'API. Le dépôt unique rend cette cohérence **gratuite** — un commit porte un front et un back cohérents.
- **Un dépôt front partagé entre projets** — il ferait monter les versions une fois au lieu de N, mais imposerait la montée à tous les clients en même temps, alors que chaque projet a son budget et son go. Il mettrait aussi à portée de main le paquet interne partagé que l'ADR [Système de design](systeme-de-design.md) a refusé.
- **Option B** — meilleure sur le fond, prématurée ici. Elle demande de décider où vit l'artefact et d'ajouter un maillon à la chaîne, pour un risque qui ne s'est pas encore matérialisé. *Pas de complexité pour rien.*

## Consequences

- Bon : **la cohérence front/back est structurelle**, pas procédurale. Un commit, un déploiement, un artefact — conforme au mode de livraison décidé.
- Bon : la friction de cohabitation des chaînes de build **disparaît**, sans rien construire pour l'éviter.
- Bon : le développement du front est celui de n'importe quel projet Vite. Rien de spécifique à igo à apprendre, sauf le proxy.
- Bon : **l'existant n'est pas touché.** La tâche webpack actuelle continue de tourner à l'identique.

- Neutre : six environnements, six builds. C'est déjà le régime actuel — pas de régression, pas d'amélioration.
- Neutre : le passage en CI reste ouvert et **peu coûteux** : c'est un déplacement de tâche, il ne remet aucune décision en cause.

- Mauvais : **le build reste sur la production.** Le pré-mortem avait soulevé le scénario du build qui échoue faute de mémoire et laisse l'application entre deux états. Ce risque est reconduit et **assumé**. Sortie identifiée : basculer en CI.
- Mauvais : un `index.html` construit à l'avance **ne peut rien recevoir du serveur**. Pas d'utilisateur pré-sérialisé, pas de jeton dans une balise `meta`. Le front démarre par un appel du type `/api/me`, avec l'état de chargement initial que ça implique. Acceptable ici — SEO et web perf non critiques — mais c'est une contrainte, pas un détail.

## Confirmation

Trois vérifications avant le premier déploiement en production :

1. **Ce que consomme le build Vite sur le serveur**, en mémoire et en temps, comparé au `webpack-prod` actuel. Si l'écart est significatif, l'option B se justifie tout de suite.
2. **Le proxy de développement face à la session d'igo** — que le cookie et les redirections d'authentification traversent bien.
3. **La configuration nginx du sous-espace front** : `try_files` doit retomber sur son `index.html` pour que le routage client fonctionne, et cet `index.html` **ne doit pas recevoir `expires max`** — les notes d'implémentation de l'ADR d'architecture le signalent déjà comme fatal.

## More Information

Cette décision met en œuvre [Architecture front de référence](architecture-front-de-reference.md) sans le contraindre : le choix du lieu de build est réversible dans les deux sens.

Le refus du dépôt front partagé prolonge l'arbitrage de [Système de design](systeme-de-design.md) — on copie, on possède, on accepte la divergence, plutôt que de reconstruire une couche maison partagée.

Le chiffre de la cohabitation des chaînes de build vient de l'atelier équipe du 19/08/2026.
52 changes: 52 additions & 0 deletions docs/adr/format-echange-front-back.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Format d'échange front/back

**Statut** : accepté
**Date** : 2026-08-20

## Context and Problem Statement

Aujourd'hui le front des applications igo échange avec le serveur par **soumission de formulaires** et réception de **HTML rendu**. Là où de l'Ajax a été écrit à la main, le serveur renvoie encore un fragment HTML injecté dans la page — par exemple `document-upload.js` dans ladom :

```js
success: function(html) { upload.find('.upload-content').html(html); window.refreshAll(); }
```

Ce modèle a deux défauts constatés. **Les plugins ne sont pas rebranchés** après injection, ce qui décourage de faire de l'Ajax et pousse à recharger la page entière. Et **la zone remplacée est plus étroite que la zone à mettre à jour** : c'est la cause racine du bouton « Transmettre » qui n'apparaît pas après un dépôt de pièce — sa visibilité dépend de la liste des documents, mais il vit en dehors du fragment renvoyé. Le défaut a été remonté du terrain et n'a reçu qu'un contournement partiel.

Un front à modèle de composants a besoin de **données**, pas de balisage : il rend lui-même.

## Considered Options

1. **JSON** — le serveur expose des routes `/api` renvoyant des données ; le front rend.
2. **Conserver les fragments HTML rendus par le serveur** et les injecter côté client.
3. **Modèle mixte** — HTML pour les zones existantes, JSON pour les écrans nouveaux.

## Decision Outcome

**Option 1 retenue : le serveur expose du JSON.**

- Les nouveaux échanges passent par des **routes `/api` renvoyant des données**, non du balisage.
- Les erreurs de validation sont renvoyées **structurées**, dans un format stable que le front affiche sans transformation.
- **Conséquence assumée** : l'actif « forms + validation » d'igo devient hors sujet sur les écrans concernés. Ce n'est pas une perte à compenser, c'est un changement de couche.
- **L'option 3 reste le régime transitoire de fait**, non par choix : les écrans non portés continuent de fonctionner en formulaires et HTML aussi longtemps qu'ils ne sont pas reprises. La cohabitation est durable — 1 669 templates dust ne seront pas réécrits.

### Pourquoi les autres ont été écartées

- **Option 2** — un modèle de composants qui reçoit du HTML étranger entre en conflit avec sa propre réconciliation du DOM, et le défaut de périmètre de la zone remplacée subsiste. Elle reconduirait la classe de bug qu'on cherche à éliminer.
- **Option 3 comme cible** — deux formats d'échange maintenus indéfiniment doublent les chemins de code et les modes de défaillance, sans bénéfice une fois le JSON en place. Acceptable en transition, pas comme état stable.

## Consequences

- Bon : le bug de la zone trop étroite **disparaît par construction** — la visibilité d'un élément se dérive de l'état, et il se rend où qu'il soit dans la page.
- Bon : ouvre l'inférence de types côté front et la dérivation d'un contrat, si un schéma isomorphe est retenu.

- Neutre : question ouverte soulevée par l'équipe — faut-il **générer les types TypeScript depuis un contrat OpenAPI** pour éviter la dérive back/front, ou les écrire à la main comme dans le POC ? À trancher séparément.

- Mauvais : **exige un mécanisme de validation d'API côté serveur** avant de pouvoir exposer du JSON sérieusement. igo n'a aucun outillage de contrat — OpenAPI, Swagger ou JSON-schema — à ce jour.
- Mauvais : les routes `/api` du POC ont été **dupliquées** depuis l'existant. À terme il faudra décider si les deux surfaces cohabitent ou si les vues serveur sont retirées écran par écran.

## More Information

Cette décision rend nécessaire [Stratégie de validation](strategie-de-validation.md) : en cessant d'échanger des formulaires, elle met hors jeu la validation orientée formulaire d'igo et oblige à statuer sur son remplacement. La dépendance est à sens unique — celle-ci se tient seule.

Le défaut de périmètre est constaté dans `ladom/js/document-upload.js`. La démonstration du modèle JSON est le POC React sur l'espace stagiaire de certigo, 20/08/2026.
Loading
Loading