@neikyun/ciel 6.14.0 → 6.14.2

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 (101) hide show
  1. package/assets/.claude/hooks/check-dispatch-gate.sh +14 -41
  2. package/assets/.claude/hooks/memory-engine.py +66 -5
  3. package/assets/.claude/hooks/pre-tool-write.sh +17 -52
  4. package/assets/.claude/hooks/session-start.sh +15 -128
  5. package/assets/.claude/hooks/stop.sh +10 -85
  6. package/assets/.claude/hooks/user-prompt-submit.sh +17 -110
  7. package/assets/.claude/rules/api-design.md +23 -0
  8. package/assets/.claude/rules/backend.md +22 -0
  9. package/assets/.claude/rules/cicd-pipeline.md +23 -0
  10. package/assets/.claude/rules/containers.md +23 -0
  11. package/assets/.claude/rules/database-design.md +22 -0
  12. package/assets/.claude/rules/environments.md +27 -0
  13. package/assets/.claude/rules/frontend.md +25 -0
  14. package/assets/.claude/rules/github.md +22 -0
  15. package/assets/.claude/rules/logging.md +23 -0
  16. package/assets/.claude/rules/monitoring.md +25 -0
  17. package/assets/.claude/rules/research.md +20 -0
  18. package/assets/.claude/settings.json +2 -58
  19. package/assets/.claude/skills/agile/SKILL.md +42 -0
  20. package/assets/.claude/skills/alerting/SKILL.md +55 -0
  21. package/assets/.claude/skills/api-design/SKILL.md +46 -0
  22. package/assets/.claude/skills/appsec/SKILL.md +43 -0
  23. package/assets/.claude/skills/architecture/SKILL.md +74 -0
  24. package/assets/.claude/skills/backend/SKILL.md +41 -0
  25. package/assets/.claude/skills/backup-recovery/SKILL.md +42 -0
  26. package/assets/.claude/skills/caching/SKILL.md +44 -0
  27. package/assets/.claude/skills/cdn/SKILL.md +42 -0
  28. package/assets/.claude/skills/chaos/SKILL.md +41 -0
  29. package/assets/.claude/skills/cicd-pipeline/SKILL.md +56 -0
  30. package/assets/.claude/skills/ciel/SKILL.md +14 -0
  31. package/assets/.claude/skills/ciel/reference.md +171 -0
  32. package/assets/.claude/skills/cloud/SKILL.md +42 -0
  33. package/assets/.claude/skills/code-quality/SKILL.md +42 -0
  34. package/assets/.claude/skills/code-review/SKILL.md +41 -0
  35. package/assets/.claude/skills/communication/SKILL.md +42 -0
  36. package/assets/.claude/skills/containers/SKILL.md +42 -0
  37. package/assets/.claude/skills/cqrs/SKILL.md +41 -0
  38. package/assets/.claude/skills/crypto/SKILL.md +46 -0
  39. package/assets/.claude/skills/data-engineering/SKILL.md +42 -0
  40. package/assets/.claude/skills/database-design/SKILL.md +46 -0
  41. package/assets/.claude/skills/ddd/SKILL.md +45 -0
  42. package/assets/.claude/skills/deployment-strategies/SKILL.md +51 -0
  43. package/assets/.claude/skills/desktop/SKILL.md +42 -0
  44. package/assets/.claude/skills/devsecops/SKILL.md +43 -0
  45. package/assets/.claude/skills/environments/SKILL.md +66 -0
  46. package/assets/.claude/skills/event-driven/SKILL.md +46 -0
  47. package/assets/.claude/skills/frontend/SKILL.md +41 -0
  48. package/assets/.claude/skills/functional/SKILL.md +42 -0
  49. package/assets/.claude/skills/github/SKILL.md +61 -0
  50. package/assets/.claude/skills/high-availability/SKILL.md +42 -0
  51. package/assets/.claude/skills/iac/SKILL.md +46 -0
  52. package/assets/.claude/skills/logging/SKILL.md +46 -0
  53. package/assets/.claude/skills/ml-engineering/SKILL.md +42 -0
  54. package/assets/.claude/skills/mobile/SKILL.md +42 -0
  55. package/assets/.claude/skills/monitoring/SKILL.md +54 -0
  56. package/assets/.claude/skills/networking/SKILL.md +42 -0
  57. package/assets/.claude/skills/nosql/SKILL.md +41 -0
  58. package/assets/.claude/skills/oop-solid/SKILL.md +42 -0
  59. package/assets/.claude/skills/performance/SKILL.md +41 -0
  60. package/assets/.claude/skills/reactive/SKILL.md +42 -0
  61. package/assets/.claude/skills/release-management/SKILL.md +51 -0
  62. package/assets/.claude/skills/research/SKILL.md +69 -0
  63. package/assets/.claude/skills/resilience/SKILL.md +41 -0
  64. package/assets/.claude/skills/serverless/SKILL.md +42 -0
  65. package/assets/.claude/skills/servers/SKILL.md +41 -0
  66. package/assets/.claude/skills/sql/SKILL.md +45 -0
  67. package/assets/.claude/skills/supply-chain/SKILL.md +41 -0
  68. package/assets/.claude/skills/system-design/SKILL.md +91 -0
  69. package/assets/.claude/skills/tech-leadership/SKILL.md +46 -0
  70. package/assets/.claude/skills/testing/SKILL.md +41 -0
  71. package/assets/.claude/skills/tracing/SKILL.md +36 -0
  72. package/assets/CLAUDE.md +31 -122
  73. package/assets/commands/{ciel-memory-bootstrap.md → ciel-memory-init.md} +3 -3
  74. package/assets/commands/ciel-memory.md +210 -0
  75. package/assets/platforms/opencode/.opencode/commands/{ciel-memory-bootstrap.md → ciel-memory-init.md} +3 -3
  76. package/assets/skills/ciel/SKILL.md +8 -97
  77. package/bin/ciel.js +1 -1
  78. package/dist/cli/check.d.ts.map +1 -1
  79. package/dist/cli/check.js +5 -11
  80. package/dist/cli/check.js.map +1 -1
  81. package/dist/cli/claude.d.ts.map +1 -1
  82. package/dist/cli/claude.js +42 -4
  83. package/dist/cli/claude.js.map +1 -1
  84. package/dist/cli/doctor.d.ts +16 -0
  85. package/dist/cli/doctor.d.ts.map +1 -0
  86. package/dist/cli/doctor.js +168 -0
  87. package/dist/cli/doctor.js.map +1 -0
  88. package/dist/cli/index.js +76 -0
  89. package/dist/cli/index.js.map +1 -1
  90. package/dist/cli/init.d.ts.map +1 -1
  91. package/dist/cli/init.js +23 -4
  92. package/dist/cli/init.js.map +1 -1
  93. package/dist/cli/memory.d.ts +18 -0
  94. package/dist/cli/memory.d.ts.map +1 -0
  95. package/dist/cli/memory.js +304 -0
  96. package/dist/cli/memory.js.map +1 -0
  97. package/dist/cli/opencode.js +1 -1
  98. package/dist/cli/opencode.js.map +1 -1
  99. package/package.json +2 -2
  100. /package/assets/{rules → .claude/rules}/security.md +0 -0
  101. /package/assets/{rules → .claude/rules}/testing.md +0 -0
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: ddd
3
+ description: "Domain-Driven Design — Bounded Contexts, Ubiquitous Language, Aggregates, Domain Events, Strategic Design. À charger quand on modélise un domaine métier complexe."
4
+ ---
5
+
6
+ # Domain-Driven Design
7
+
8
+ **Principe premier :** DDD n'est pas un pattern technique — c'est une discipline de modélisation. Le but n'est pas d'utiliser Entities, Value Objects et Aggregates. Le but est de faire en sorte que le code parle le même langage que le métier. Si un expert métier lit ton code et ne reconnaît pas son domaine, tu as échoué, peu importe la qualité technique des patterns. Le Ubiquitous Language est le livrable principal — tout le reste en découle.
9
+
10
+ ## Checklist
11
+ - [ ] Le Ubiquitous Language est le même dans le code ET dans les conversations avec le métier
12
+ - [ ] Les Bounded Contexts sont identifiés et leurs frontières sont explicites
13
+ - [ ] Chaque Aggregate a une racine qui protège ses invariants
14
+ - [ ] Les Value Objects sont immutables et validés à la construction
15
+ - [ ] La logique métier est dans le domaine — pas dans les services, pas dans les controllers
16
+ - [ ] Les Repositories sont des interfaces dans le domaine, implémentées dans l'infrastructure
17
+
18
+ ## Anti-patterns
19
+ ### Anemic Domain Model
20
+ **Ce qu'on voit :** `class Order { id, status, total, getters, setters }` — le domaine est un sac de données. Toute la logique est dans `OrderService.process()`, `OrderService.approve()`, etc.
21
+ **Pourquoi c'est dangereux :** le modèle ne protège rien. N'importe quel code peut faire `order.status = "shipped"` sans vérifier le paiement. Les règles métier sont dupliquées. Le code ment sur ce qui est possible.
22
+ **Faire plutôt :** le domaine est le gardien. `order.approve()` vérifie le statut, le stock, le crédit. `order.ship()` vérifie que la commande est approuvée. Les setters publics n'existent pas sur les propriétés qui ont des règles.
23
+
24
+ ### Bounded Context unique
25
+ **Ce qu'on voit :** une table `users` partagée par l'auth, le billing, le shipping, le marketing. Une entité `Order` unique pour tout le système.
26
+ **Pourquoi c'est dangereux :** "Client" ne veut pas dire la même chose pour le support (historique de tickets) et pour la facturation (adresse, TVA). Forcer un modèle unique crée des compromis qui ne satisfont personne et couplent tous les modules ensemble.
27
+ **Faire plutôt :** chaque contexte a sa propre représentation. `SalesContext.Order` a les items et le prix. `ShippingContext.Shipment` a l'adresse et le tracking. Ils communiquent par événements (`OrderPlaced` → le shipping crée son Shipment).
28
+
29
+ ### Tactical sans strategic
30
+ **Ce qu'on voit :** l'équipe utilise Entities, Value Objects, Aggregates, Repositories — mais n'a jamais défini les Bounded Contexts ni le Ubiquitous Language.
31
+ **Pourquoi c'est dangereux :** les patterns tactiques sans design stratégique, c'est comme des murs sans plan d'architecte. Tu construis proprement, mais peut-être au mauvais endroit. Les Bounded Contexts définissent CE QUI va ensemble — sans ça, les Aggregates sont arbitraires.
32
+ **Faire plutôt :** commencer par le strategic design : Event Storming, Context Mapping, Ubiquitous Language. Les patterns tactiques viennent APRÈS, pour implémenter ce qui a été modélisé.
33
+
34
+ ## Patterns
35
+ ### Bounded Context
36
+ **Quand :** le domaine a des significations différentes pour le même terme. "Client" pour le support ≠ "Client" pour la facturation.
37
+ **Comment :** frontière explicite. Chaque contexte a son propre modèle, son propre langage, sa propre persistence. Communication inter-contexte par Domain Events ou API bien définies. Pas de jointure SQL entre contextes.
38
+
39
+ ### Aggregate Root
40
+ **Quand :** un groupe d'objets doit rester cohérent (invariants). Ex: Order + OrderItems. Le total doit toujours = somme des items.
41
+ **Comment :** une entité racine protège l'accès. Toute modification passe par la racine : `order.addItem()`, jamais `orderItem.setPrice()`. Les objets externes ne référencent jamais l'intérieur d'un aggregate — ils passent par la racine.
42
+
43
+ ### Domain Events
44
+ **Quand :** un changement dans un contexte doit être connu d'un autre.
45
+ **Comment :** l'aggregate émet un événement : `OrderPlaced { orderId, customerId, total }`. Les autres contextes s'abonnent. L'événement est un fait passé (past tense), immuable, et contient tout ce dont le consommateur a besoin (pas de référence à l'aggregate).
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: deployment-strategies
3
+ description: "Deployment Strategies — deploy small/deploy often, blue-green, canary, DB migration coordination, feature flags as decoupling, rollback as first-class. À charger quand on planifie ou améliore un déploiement."
4
+ ---
5
+
6
+ # Deployment Strategies
7
+
8
+ **Principe premier :** La CD n'est pas "déployer vite" — c'est déployer PETIT. On ne fait pas de déploiement continu avec des PRs de 2000 lignes. La confiance vient de la taille du diff : un diff de 50 lignes est trivial à debug, un diff de 5000 lignes est un incident en attente. Blue-green, canary, feature flags — toutes ces stratégies sont des filets de sécurité, pas des enablers. Le vrai enabler, c'est la capacité à découper le travail en incréments déployables indépendamment.
9
+
10
+ ## Checklist
11
+ - [ ] La taille du diff est le premier indicateur de risque — si > 500 lignes, découper
12
+ - [ ] DB migration ET rollback de migration testés AVANT le déploiement du code
13
+ - [ ] Health checks définis (liveness ≠ readiness ≠ startup) — basculer le trafic uniquement sur readiness OK
14
+ - [ ] Rollback = un clic ou un revert automatisé (pas de procédure manuelle de 10 étapes)
15
+ - [ ] Feature flags pour tout changement de comportement — dissociation déploiement / activation
16
+ - [ ] Smoke tests automatiques post-déploiement (endpoints critiques, pas toute la suite E2E)
17
+ - [ ] Observabilité du déploiement : dashboards de comparaison avant/après (erreurs, latence, throughput)
18
+
19
+ ## Anti-patterns
20
+ ### Déploiement = événement stressant
21
+ **Ce qu'on voit :** le déploiement est planifié, annoncé, tout le monde est en war room. On prie. Si ça casse, c'est la panique.
22
+ **Pourquoi c'est dangereux :** si déployer fait peur, c'est que la confiance est absente. La peur pousse à déployer moins souvent → les diffs grossissent → encore plus peur → spirale de la mort. Une équipe qui fait vraiment de la CD déploie 10×/jour sans y penser.
23
+ **Faire plutôt :** rendre le déploiement ennuyeux. Automatiser tout ce qui peut l'être. Si le déploiement est stressant, investir dans la confiance (tests, health checks, rollback automatique) plutôt que dans le processus.
24
+
25
+ ### Déploiement et migration DB couplés
26
+ **Ce qu'on voit :** le déploiement inclut une migration DB `ALTER TABLE... NOT NULL`. Le rollback du code est facile, le rollback de la migration est impossible.
27
+ **Pourquoi c'est dangereux :** le couplage code/schema crée des déploiements irréversibles. Si le code est buggé, tu peux rollback le code mais pas la DB → le vieux code casse sur le nouveau schema. C'est la cause #1 des incidents de déploiement qui durent > 1h.
28
+ **Faire plutôt :** règle d'or — la migration DB doit être compatible avec l'ancien ET le nouveau code (expand/contract). Ajouter une colonne sans contrainte, déployer le code qui l'utilise, puis ajouter la contrainte. Chaque étape est réversible. Les migrations sont testées avec le rollback dans la CI.
29
+
30
+ ### Feature flags sans plan de cleanup
31
+ **Ce qu'on voit :** `if (featureFlags.isEnabled("new-checkout-v2"))` partout. Après 6 mois, v1, v2, v3 coexistent. Le code est incompréhensible.
32
+ **Pourquoi c'est dangereux :** les feature flags sont une dette technique à intérêt composé. Chaque flag ajoute une branche, et les branches se multiplient (2^n combinaisons). Sans cleanup, le système devient intestable.
33
+ **Faire plutôt :** chaque flag a une date d'expiration. Une tâche de cleanup est créée au moment où le flag est introduit. Après 100% de rollout, le flag est supprimé dans les 2 semaines. Si un flag existe depuis > 1 mois, il devient une urgence tech.
34
+
35
+ ### Canary sans critère de succès
36
+ **Ce qu'on voit :** "on envoie 5% du trafic au nouveau code et on voit bien". Pas de métrique, pas de seuil, pas de rollback automatique.
37
+ **Pourquoi c'est dangereux :** sans critère objectif, le canary est du théâtre. Personne ne sait à quel moment dire "le canary a échoué". Résultat : le canary "passe" toujours, jusqu'au déploiement complet où le bug explose à 100%.
38
+ **Faire plutôt :** canary avec critères automatiques. "Si P95 latency > +20% OU error rate > +50% pendant 5 min → rollback automatique. Si OK pendant 15 min → 30% → 50% → 100%." La décision est algorithmique, pas humaine.
39
+
40
+ ## Patterns
41
+ ### Expand/Contract pour les migrations DB
42
+ **Quand :** toute modification de schema en production.
43
+ **Comment :** Phase 1 (expand) : ajouter les nouvelles colonnes/tables, le code lit l'ancien et écrit les deux. Phase 2 (migrate) : backfill les données existantes par batches. Phase 3 (contract) : le code ne lit que le nouveau, supprimer l'ancien. Chaque phase est une PR séparée, déployable et rollbackable indépendamment.
44
+
45
+ ### Blue-Green
46
+ **Quand :** zero downtime requis, rollback immédiat nécessaire.
47
+ **Comment :** 2 environnements identiques. Le live (blue) tourne. On déploie sur green, on smoke-test green, on bascule le trafic. Blue reste chaud 24h. Si incident → rebascule sur blue (10 secondes, pas 10 minutes). Le vrai coût est l'infra doublée — à réserver pour les services critiques.
48
+
49
+ ### Feature flags comme architecture
50
+ **Quand :** toute fonctionnalité qui change le comportement utilisateur.
51
+ **Comment :** le flag ne cache pas juste un `if` — il est injecté, testable, avec un fallback explicite. `if (flags.isEnabled("new-checkout", { default: false }))`. Chaque flag est testé avec les deux valeurs dans la CI. Le flag est un contrat temporaire, pas un état permanent.
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: desktop
3
+ description: "Desktop — Electron/Tauri/WPF/Qt, auto-update, code signing, distribution, OS integration. A charger quand on developpe une application desktop."
4
+ ---
5
+
6
+ # Desktop
7
+
8
+ **Principe premier :** Une application desktop n'est pas un site web dans une fenetre — c'est un citoyen de l'OS. L'utilisateur attend des raccourcis clavier, un menu contextuel, des notifications systeme, un comportement au focus/blur, une integration avec le fichier systeme. Si ton app ne respecte pas les conventions de l'OS, l'utilisateur la percoit comme "pas finie" meme si elle fonctionne. Le deuxieme defi est la distribution : contrairement au web ou tu deployes sur un serveur, chaque utilisateur a une copie de ton binaire. Si tu ne peux pas le mettre a jour automatiquement, la version buggee reste en circulation indefiniment.
9
+
10
+ ## Checklist
11
+ - [ ] Auto-update fonctionnel et teste (ancienne version → nouvelle version, rollback si echec)
12
+ - [ ] Code signing en place (Apple notarization + Windows Authenticode) — pas de "telecharger depuis parametres"
13
+ - [ ] L'app respecte les conventions de l'OS : menu natif, raccourcis clavier, drag & drop, notifications
14
+ - [ ] Le bundle est minimal : pas de dependances inutiles, pas de fichiers de dev dans le package final
15
+ - [ ] Les chemins de fichiers utilisent les API OS (appData, documents, temp) — pas de chemins hardcodes Unix/Windows
16
+ - [ ] L'app gere le cycle de vie : focus/blur, sleep/wake, quit/relancer, ouverture de fichier par l'OS
17
+ - [ ] Les permissions sont demandees au moment de l'usage, pas au lancement (caméra, mic, fichiers)
18
+
19
+ ## Anti-patterns
20
+ ### Electron = 500MB pour "Hello World"
21
+ **Ce qu'on voit :** une app Electron qui pese 200MB, utilise 500MB de RAM pour afficher un formulaire. "C'est plus facile a developper."
22
+ **Pourquoi c'est dangereux :** l'utilisateur compare avec les apps natives (Slack = electron, VS Code = electron... mais eux ont des equipes d'optimisation dediees). Une app Electron non optimisee est percue comme "lente" et de trop. Les utilisateurs desinstallent.
23
+ **Faire plutot :** si l'app est simple → Tauri (backend Rust, frontend web, binaire < 5MB). Si Electron : tree-shaking, lazy loading, pas de `nodeIntegration`, pas de `remote` module. Mesurer la RAM et le temps de demarrage a chaque release.
24
+
25
+ ### Pas d'auto-update
26
+ **Ce qu'on voit :** l'utilisateur telecharge l'app sur le site web. Version 1.0. Nouvelle version 1.1 → email aux utilisateurs "telechargez la nouvelle version".
27
+ **Pourquoi c'est dangereux :** 90% des utilisateurs ne mettront jamais a jour manuellement. Les bugs de la v1.0 restent en circulation pendant des annees. Le support recoit des tickets sur des bugs deja corriges. La fragmentation des versions est un cauchemar.
28
+ **Faire plutot :** auto-update integre des le jour 1 (electron-updater, Sparkle pour Mac, Squirrel pour Windows). L'app verifie au demarrage et telecharge en arriere-plan. Mise a jour silencieuse pour les patchs, notification pour les features.
29
+
30
+ ### Ignorer les conventions OS
31
+ **Ce qu'on voit :** CTRL+C ne copie pas. CMD+Q ne quitte pas. Le menu est custom et ne ressemble a rien. Les dialogues de fichier sont du HTML custom.
32
+ **Pourquoi c'est dangereux :** les utilisateurs ont des annees de memoire musculaire. Chaque violation de convention = friction cognitive. L'utilisateur ne se dit pas "cette app a un design original" — il se dit "cette app est buggee" et retourne a l'alternative native.
33
+ **Faire plutot :** utiliser les composants natifs quand ils existent (menu, file dialog, notifications). Les raccourcis clavier standard doivent fonctionner. Tester sur Mac et Windows — les conventions sont differentes.
34
+
35
+ ## Patterns
36
+ ### Distribution multi-plateforme
37
+ **Quand :** app qui cible Windows + Mac + Linux.
38
+ **Comment :** CI qui build les 3 plateformes en parallele. Code signing specifique par plateforme (Mac : notarization via `gon`/`electron-notarize`, Windows : Authenticode via Azure Key Vault). Auto-update specifique par plateforme (Sparkle pour Mac, Squirrel.Windows pour Windows, AppImage pour Linux).
39
+
40
+ ### Minimiser la surface d'attaque Electron
41
+ **Quand :** toute app Electron.
42
+ **Comment :** `contextIsolation: true`, `nodeIntegration: false`, `sandbox: true`. IPC pour la communication main-renderer (pas de `remote`). Preload script minimal : exposer uniquement les API necessaires via `contextBridge`. La renderer process est non fiable — traiter chaque message comme du user input.
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: devsecops
3
+ description: "DevSecOps — shift-left security, supply chain integrity, SLSA, attestation, SBOM, CVE triage. À charger quand on intègre la sécurité dans le SDLC."
4
+ ---
5
+
6
+ # DevSecOps
7
+
8
+ **Principe premier :** La sécurité n'est pas une étape dans le pipeline — c'est une propriété émergente du système de développement. Le vrai objectif n'est pas "trouver des vulnérabilités" mais "réduire le temps entre l'introduction d'une vulnérabilité et sa détection". Plus ce délai est court, moins la vulnérabilité a de valeur pour un attaquant. Shift-left n'est pas un slogan : chaque heure gagnée réduit la fenêtre d'exposition.
9
+
10
+ ## Checklist
11
+ - [ ] SAST bloque sur les vulnérabilités critiques — le pipeline ne passe pas, point
12
+ - [ ] Les dépendances sont scannées automatiquement (Snyk/Renovate) avec politique de blocage claire (critique = block, haute = warn + SLA 72h, medium/low = log)
13
+ - [ ] Secret scanning au commit (pre-commit hook) ET dans l'historique (push hook, scheduled scan)
14
+ - [ ] Les images container sont signées (Sigstore/Cosign) et scannées (Trivy/Grype) — signature ET scan, pas l'un sans l'autre
15
+ - [ ] SLSA niveau 2 minimum : provenance attestée, build reproductible, artefacts signés
16
+ - [ ] SBOM généré à chaque build (SPDX ou CycloneDX) — consommable par les clients
17
+ - [ ] Les IaC et policies sont scannés (Checkov, OPA/Kyverno) — pas juste le code applicatif
18
+ - [ ] Les SLA de correction sont mesurés et visibles (critique < 24h, haute < 72h, medium < 30j)
19
+
20
+ ## Anti-patterns
21
+ ### Sécurité à la fin
22
+ **Ce qu'on voit :** SAST lancé une semaine avant la release. 50 CVEs critiques. Release bloquée.
23
+ **Pourquoi c'est dangereux :** plus une vulnérabilité est trouvée tard, plus elle coûte cher à corriger — c'est exponentiel. Une CVE trouvée au commit coûte 10 min, trouvée en staging coûte 2h, trouvée en prod coûte 2 jours + incident. Le coût n'est pas le scan — c'est le délai.
24
+ **Faire plutôt :** sécurité à chaque commit. SAST dans la CI de la PR. Dependency scan automatique hebdomadaire. Le but : détecter dans les minutes, pas dans les semaines.
25
+
26
+ ### Scanner sans bloquer
27
+ **Ce qu'on voit :** Trivy/Dependabot trouvent des CVE, le pipeline reste vert. Les alertes s'accumulent dans une inbox que personne ne lit.
28
+ **Pourquoi c'est dangereux :** un scan qui ne bloque pas n'existe pas. Il produit du bruit, et le bruit tue la vigilance. En 6 mois, l'équipe a appris que "rouge" ne veut rien dire — c'est le pire état possible pour un système de sécurité.
29
+ **Faire plutôt :** politique de blocage stricte et explicite. Critique = pipeline rouge, merge impossible. Haute = avertissement visible + ticket automatique + SLA. Le seuil monte avec le temps (on commence à medium, puis on resserre).
30
+
31
+ ### SBOM comme case à cocher
32
+ **Ce qu'on voit :** un SBOM est généré "parce qu'il faut" mais personne ne le lit, ne le vérifie, ni ne l'utilise en cas d'incident.
33
+ **Pourquoi c'est dangereux :** un SBOM non testé est pire que pas de SBOM — il donne une fausse confiance. Le jour où Log4Shell 2.0 sort, tu ne sais pas quels services sont affectés en < 1h. Le SBOM doit être utilisable en incident.
34
+ **Faire plutôt :** SBOM versionné avec le build, stocké dans un registre requêtable. Test d'audit trimestriel : "Simule une CVE sur le package X. En combien de temps identifies-tu tous les services affectés ?" Si > 10 min, le SBOM n'est pas opérationnel.
35
+
36
+ ## Patterns
37
+ ### Shift-left par étapes
38
+ **Quand :** organiser la sécurité sans tout casser.
39
+ **Comment :** 3 niveaux de maturité. Niveau 1 : secret scan au push, lint de sécurité en CI. Niveau 2 : SAST + dependency scan bloquants, OIDC. Niveau 3 : SLSA build attestation, SBOM signé, policy-as-code en déploiement. On monte d'un niveau par trimestre — pas tout d'un coup.
40
+
41
+ ### Security Champions
42
+ **Quand :** équipe sans security engineer dédié.
43
+ **Comment :** 1 dev par équipe formé à la sécurité (OWASP, threat modeling, revue de dépendances). Ce n'est pas un rôle full-time — c'est un point de contact. Le champion fait la review de sécurité des PRs de son équipe, escalade à l'équipe sécurité centrale pour les cas complexes. La connaissance se diffuse — en 1 an, toute l'équipe monte en compétence.
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: environments
3
+ description: "Environments — dev/staging/prod separation, GitHub Environments, CI/CD promotion gates, secrets per env, infra isolation. À charger quand on configure des environnements de déploiement."
4
+ ---
5
+
6
+ # Environments
7
+
8
+ **Principe premier :** Un bug en dev coûte 5 minutes. Un bug en staging coûte une réunion. Un bug en production coûte de l'argent, de la réputation, ou pire. La séparation des environnements n'est pas un luxe d'entreprise — c'est le filet de sécurité qui attrape les erreurs avant qu'elles n'atteignent les utilisateurs. Le but n'est pas d'avoir 3 environnements identiques, c'est d'avoir 3 chances de détecter un problème avant qu'il soit critique. Chaque environnement est un filtre : dev filtre les erreurs de code, staging filtre les erreurs d'intégration, production est le dernier rempart.
9
+
10
+ ## Checklist
11
+ - [ ] Au moins 2 environnements : un pour tester (staging/preview) et un pour la production
12
+ - [ ] Les environnements sont isolés — comptes/projets séparés (Vercel, Render, AWS), pas juste des dossiers ou des branches
13
+ - [ ] Les secrets sont par environnement — `DB_URL` en staging ≠ `DB_URL` en production, jamais partagés
14
+ - [ ] Le déploiement en production a une gate d'approbation humaine (pas de push-to-deploy direct sur prod)
15
+ - [ ] Staging est le jumeau de production — même stack, même config, juste les données et l'échelle qui diffèrent
16
+ - [ ] La promotion se fait dans un seul sens : dev → staging → prod. Jamais l'inverse (pas de "je fix en prod et je backport")
17
+ - [ ] Les logs et métriques sont centralisés par environnement avec un tag `env:` (staging/production)
18
+ - [ ] L'accès à la production est restreint — moins de monde peut déployer/modifier la production que le staging
19
+
20
+ ## Anti-patterns
21
+ ### Un seul environnement pour tout
22
+ **Ce qu'on voit :** le projet a un seul déploiement. Les features sont testées "en local" puis mergées sur main et déployées. Pas de staging.
23
+ **Pourquoi c'est dangereux :** chaque merge est un pari. "Ça marchait sur ma machine" n'est pas une vérification. Sans staging, la première fois que le code rencontre une vraie DB, un vrai réseau, une vraie config — c'est en production. Les bugs d'intégration sont découverts par les utilisateurs.
24
+ **Faire plutôt :** minimum 2 environnements. Un staging/preview qui est déployé automatiquement à chaque PR. La production qui est déployée après merge + validation sur staging. Pour un projet solo sans budget : une preview branch (Vercel/Render/Netlify la donnent gratuitement) + la production.
25
+
26
+ ### Secrets partagés entre environnements
27
+ **Ce qu'on voit :** `.env` avec `DATABASE_URL=postgres://...` — le même fichier copié en staging et en production. Ou pire : `.env` commité.
28
+ **Pourquoi c'est dangereux :** un secret de staging qui fuit donne accès à la DB de staging (pas grave). Un secret de production qui fuit donne accès à la DB de production (catastrophique). Si c'est le même secret, le staging devient un vecteur d'attaque vers la production. Le staging est moins sécurisé par nature (plus de gens y accèdent, logs plus verbeux, debugging actif).
29
+ **Faire plutôt :** secrets distincts par environnement. GitHub Environments → `DB_URL` configuré séparément pour `staging` et `production`. En local : `.env` dans `.gitignore`, jamais commité. Les clés API de production sont générées séparément, avec des permissions plus restrictives.
30
+
31
+ ### Promotion inversée (prod → staging)
32
+ **Ce qu'on voit :** un bug en production, on fix directement sur le serveur, et "on backportera plus tard". Le code de production diverge du code source. Personne ne sait exactement ce qui tourne.
33
+ **Pourquoi c'est dangereux :** le git n'est plus la source de vérité. Le prochain déploiement écrase le fix. Impossible de reproduire l'état de production en local. L'écart entre le code source et la production s'accumule jusqu'à ce qu'un déploiement casse tout.
34
+ **Faire plutôt :** le flux est toujours dev → staging → prod. Si un fix urgent est nécessaire : créer une branche `fix/...`, déployer en staging, valider, merger, déployer en production. Le cycle normal, juste accéléré. La production est toujours le reflet exact de main.
35
+
36
+ ### Staging ≠ production
37
+ **Ce qu'on voit :** staging tourne sur SQLite, production sur PostgreSQL. Staging a 10 rows, production en a 10M. Staging n'a pas de Redis, production en a un cluster. "C'est plus simple pour tester".
38
+ **Pourquoi c'est dangereux :** les bugs les plus dangereux sont ceux qui n'apparaissent QUE dans l'environnement de production. Une requête qui scanne 10 rows en 1ms peut scanner 10M rows en 30 secondes. Un index qui existe en production mais pas en staging. Un timeout réseau qui n'arrive jamais en local. Staging doit être le jumeau de production — différences = angles morts.
39
+ **Faire plutôt :** même stack, même versions, même configuration (hors secrets et scale). La DB de staging peut être plus petite mais doit utiliser le même moteur. Idéalement : staging est une copie anonymisée de la DB de production, rafraîchie régulièrement. Le coût : un deuxième déploiement. Le bénéfice : les bugs sont découverts avant les utilisateurs.
40
+
41
+ ### Déploiement production sans gate humaine
42
+ **Ce qu'on voit :** push sur main → CI passe → déploiement automatique en production. Personne n'a validé. "La CI est verte, c'est bon".
43
+ **Pourquoi c'est dangereux :** la CI ne teste pas tout. Elle ne teste pas l'UX, la performance perçue, l'impact sur les utilisateurs. Sans gate humaine, un vendredi 17h un dev merge une PR "refactor rapide" et part en weekend — le déploiement automatique casse la production, personne ne voit l'alerte.
44
+ **Faire plutôt :** déploiement automatique en staging. Déploiement en production avec une gate d'approbation. GitHub Environments → `production` → Required reviewers: 1. La gate peut être un clic dans l'UI GitHub ("Review deployments"), pas un processus lourd. Pour un projet solo : au minimum, le déploiement en production est déclenché manuellement ou après un délai (30 min après le merge, le temps de vérifier staging).
45
+
46
+ ## Patterns
47
+ ### GitHub Environments (sans org)
48
+ **Quand :** tout projet GitHub avec au moins un déploiement.
49
+ **Comment :** Settings → Environments → `staging` et `production`. Chaque environnement a ses propres secrets (`DB_URL`, `API_KEY`), ses propres rules (required reviewers, wait timer, deployment branches), et ses propres variables d'environnement. Les workflows référencent l'environnement : `environment: staging` dans le job. GitHub suit l'historique des déploiements par environnement. Fonctionne sur les repos personnels — pas besoin d'une organisation.
50
+
51
+ ### Promotion pipeline
52
+ **Quand :** tout projet avec staging + production.
53
+ **Comment :** 3 jobs dans le workflow CI/CD :
54
+ 1. `test` — lint + tests unitaires + intégration (toutes les branches)
55
+ 2. `deploy-staging` — déploie sur staging après merge sur main, automatique
56
+ 3. `deploy-production` — déploie sur production, manuel ou après approbation, avec `environment: production`
57
+
58
+ Le job production ne peut pas s'exécuter si le job staging a échoué. La promotion est linéaire et vérifiable.
59
+
60
+ ### Infrastructure isolation sans budget
61
+ **Quand :** projet solo ou petite équipe, pas de budget pour des comptes cloud séparés.
62
+ **Comment :** utiliser les fonctionnalités gratuites des plateformes. Vercel : preview deployments (par branche) + production. Render : PR previews + production. Netlify : deploy previews + production. Pour les DB : une DB de dev locale (Docker), une DB de staging (instance gratuite ou partagée), une DB de production (instance dédiée). Les clés API ont des permissions restreintes : la clé de staging ne peut pas envoyer d'emails réels, la clé de production oui.
63
+
64
+ ### Secrets rotation par environnement
65
+ **Quand :** tout projet avec des secrets.
66
+ **Comment :** chaque environnement a ses propres credentials, générés indépendamment. Si un secret de staging fuit : rotation sur staging uniquement, production inchangée. Les secrets ne sont jamais transmis entre environnements — pas de "copier-coller le .env de staging vers production". Pour les clés API tierces (Stripe, SendGrid) : utiliser leurs clés de test en staging/dev, leurs clés de production uniquement en production.
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: event-driven
3
+ description: "Event-Driven Architecture — pub/sub, idempotence, dead letter queues, ordering, outbox pattern. À charger quand on a des services qui doivent communiquer sans couplage direct."
4
+ ---
5
+
6
+ # Event-Driven Architecture
7
+
8
+ **Principe premier :** L'event-driven architecture n'est pas un pattern d'intégration — c'est une stratégie de découplage temporel. Le producer n'attend pas le consumer. Le consumer n'a pas besoin que le producer soit vivant. Cette indépendance temporelle est la vraie valeur, pas le "pub/sub". Mais elle a un prix : tu perds la consistence immédiate. Tu ne sais pas QUAND le consumer traitera l'événement. Assumer ce trade-off explicitement, c'est ça faire de l'event-driven.
9
+
10
+ ## Checklist
11
+ - [ ] Chaque événement est un fait passé (past tense : `PaymentReceived`, pas `ReceivePayment`)
12
+ - [ ] Chaque consumer est idempotent — même événement reçu 2× = même résultat (pas de double charge)
13
+ - [ ] Dead Letter Queue configurée avec alerte — un message qui échoue > N fois ne bloque pas les autres
14
+ - [ ] L'ordre est géré explicitement quand il est nécessaire (partition key, ordering key)
15
+ - [ ] Les timeouts sont explicites — pas de consumer bloqué à l'infini sur un appel externe
16
+ - [ ] Outbox pattern pour les opérations DB + événement atomiques
17
+ - [ ] Métriques sur chaque file : lag, retry rate, DLQ size, processing time
18
+
19
+ ## Anti-patterns
20
+ ### Chaîne HTTP synchrone déguisée en événementielle
21
+ **Ce qu'on voit :** Service A publie un événement, attend la réponse de B via un autre événement. B attend C, qui attend D. Timeout à 30s.
22
+ **Pourquoi c'est dangereux :** c'est du HTTP synchrone avec plus d'étapes et de points de défaillance. Si D est lent, toute la chaîne timeout. Tu as ajouté la complexité de l'event-driven sans le bénéfice (découplage temporel).
23
+ **Faire plutôt :** si tu as besoin d'une réponse synchrone, fais du HTTP. L'event-driven est pour le "fire and forget" — le producer émet et continue sa vie, le consommateur traite quand il peut.
24
+
25
+ ### Consumer non-idempotent
26
+ **Ce qu'on voit :** le consumer insère en DB sans vérifier si l'événement a déjà été traité. Un retry → double insertion.
27
+ **Pourquoi c'est dangereux :** en event-driven, at-least-once est la règle, pas l'exception. Les retries arrivent. Si ton consumer n'est pas idempotent, chaque retry corrompt les données. Un client débité 2×, un email envoyé 3×.
28
+ **Faire plutôt :** stocker l'event_id traité (dans la même transaction que le traitement). `INSERT ON CONFLICT (event_id) DO NOTHING`. Si l'event_id existe déjà, ACK sans traiter.
29
+
30
+ ### Pas de DLQ
31
+ **Ce qu'on voit :** un message mal formé bloque le consumer. Retry infini. Tous les messages suivants sont bloqués derrière le message poison.
32
+ **Pourquoi c'est dangereux :** un seul message invalide paralyse tout le pipeline d'événements. Le lag s'accumule. Quand le consumer est débloqué, il a 100 000 messages de retard — et certains sont périmés.
33
+ **Faire plutôt :** DLQ après N retries (3-5). Alerte immédiate sur DLQ non vide. Mécanisme de replay depuis la DLQ après correction. Ne jamais ignorer silencieusement la DLQ.
34
+
35
+ ## Patterns
36
+ ### Outbox Pattern
37
+ **Quand :** une opération doit écrire en DB ET publier un événement de manière atomique.
38
+ **Comment :** écrire l'événement dans une table `outbox` dans la MÊME transaction DB que l'écriture métier. Un worker lit l'outbox et publie. Si le publish échoue, il retry. Si le worker crashe, l'événement est dans l'outbox. Garantit at-least-once sans 2PC.
39
+
40
+ ### Idempotency Key
41
+ **Quand :** une opération doit être exécutée exactement une fois.
42
+ **Comment :** le producer génère une clé unique (`idempotency-key`). Le consumer stocke la clé + le résultat. Si la clé est déjà connue → retourner le résultat stocké, ne pas ré-exécuter. Stripe utilise ce pattern pour les paiements.
43
+
44
+ ### Schema evolution
45
+ **Quand :** le format des événements change avec le temps.
46
+ **Comment :** chaque événement a un champ `version` et un `type`. Les upcasters transforment les anciens événements vers le nouveau format au replay. Ne jamais modifier un type d'événement existant — en créer un nouveau (ex: `OrderPlacedV2`).
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: frontend
3
+ description: "Frontend — state management as complexity spectrum, rendering strategy (SSR/CSR/SSG), bundle as UX metric, optimistic UI. À charger quand on touche à du code frontend."
4
+ ---
5
+
6
+ # Frontend
7
+
8
+ **Principe premier :** Le frontend n'est pas "afficher des données HTML" — c'est gérer la complexité d'état sur un appareil qu'on ne contrôle pas. La seule métrique qui compte vraiment est le temps jusqu'à l'interaction (TTI). Tout le reste — state management, code splitting, SSR — est un moyen de réduire le TTI. Si ta stack "moderne" produit un TTI de 5 secondes, elle est moins performante qu'un site HTML vanilla de 2005. L'utilisateur ne voit pas ta stack, il voit le temps de chargement.
9
+
10
+ ## Checklist
11
+ - [ ] Le state management est proportionnel à la complexité : useState → Context → Zustand → Redux (pas l'inverse)
12
+ - [ ] La stratégie de rendu est délibérée : SSR pour SEO, CSR pour apps interactives, SSG pour contenu statique
13
+ - [ ] Le bundle est surveillé : JS < 200KB, lazy loading au-dessus du fold, code splitting par route
14
+ - [ ] Lighthouse ≥ 90 sur perf + a11y + best practices — mesuré dans la CI
15
+ - [ ] Les formulaires gèrent TOUS les états : idle, loading, success, error, validation
16
+ - [ ] L'accessibilité de base est non-négociable : labels, keyboard nav, contrast minimum, ARIA sur les composants interactifs
17
+
18
+ ## Anti-patterns
19
+ ### State management comme religion
20
+ **Ce qu'on voit :** Redux installé pour un formulaire de contact. Store, reducers, actions, selectors, middleware — 50 fichiers pour stocker `{email, message}`.
21
+ **Pourquoi c'est dangereux :** le state management a un coût cognitif. Chaque couche ajoute de l'indirection. Pour un state local à un formulaire, useState suffit. Le bon outil est celui qui résout le problème avec le moins de code — pas celui qui est "le standard de l'industrie".
22
+ **Faire plutôt :** spectre de complexité. useState pour le state local. Context pour le state partagé par < 5 composants. Zustand pour le state global simple. Redux uniquement si tu as besoin de devtools, middleware, et normalisation de state complexes.
23
+
24
+ ### useEffect comme solution à tout
25
+ **Ce qu'on voit :** des chaînes de `useEffect` qui se déclenchent les unes les autres. `useEffect(() => setB(a), [a]); useEffect(() => setC(b), [b])`. Props → state → render → effect → state → render → effect...
26
+ **Pourquoi c'est dangereux :** c'est du state management par effets de bord. Chaque render supplémentaire est une opportunité de bug. Les cascades d'effets créent des états intermédiaires incohérents visibles par l'utilisateur.
27
+ **Faire plutôt :** dériver pendant le rendu. `const derived = computeExpensive(data)` sans useEffect — React le recalcule au bon moment. `useMemo` pour les calculs coûteux, pas pour contourner un problème d'architecture.
28
+
29
+ ### Bundle obèse
30
+ **Ce qu'on voit :** `import { debounce } from "lodash"` → toute la librairie lodash (70KB) dans le bundle pour une fonction de 10 lignes.
31
+ **Pourquoi c'est dangereux :** le bundle est le premier facteur du TTI. 2 Mo de JS sur une connexion 3G = 20 secondes avant que l'utilisateur puisse interagir. La moitié des utilisateurs abandonnent après 3 secondes.
32
+ **Faire plutôt :** `import debounce from "lodash/debounce"`. Bundle analyzer dans la CI (`vite-bundle-visualizer`, `next-bundle-analyzer`). Budget de bundle : si la PR dépasse +50KB, bloquer et justifier.
33
+
34
+ ## Patterns
35
+ ### Suspense boundaries
36
+ **Quand :** chargement asynchrone de données ou de code.
37
+ **Comment :** `<Suspense fallback={<Skeleton />}>` autour du composant asynchrone. Le composant ne gère pas son propre état de chargement — le parent le fait. Permet de composer le chargement (tout chargé → afficher, plutôt que chaque widget avec son spinner).
38
+
39
+ ### Optimistic update
40
+ **Quand :** l'interface doit être perçue comme instantanée.
41
+ **Comment :** mettre à jour l'UI immédiatement comme si l'opération avait réussi. Envoyer la requête au serveur. Si succès → rien à faire. Si échec → rollback + notification d'erreur. L'utilisateur ne voit la latence que si l'opération échoue.
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: functional
3
+ description: "Programmation Fonctionnelle — immutabilite, fonctions pures, composition, Result/Option, pattern matching. A charger quand on utilise un style fonctionnel."
4
+ ---
5
+
6
+ # Programmation Fonctionnelle
7
+
8
+ **Principe premier :** La programmation fonctionnelle n'est pas "utiliser `map` et `filter`" — c'est un contrat avec toi-meme : tu ne modifieras pas l'etat existant. Ce contrat elimine une classe entiere de bugs (les mutations surprises, les races conditions sur l'etat mutable, les effets de bord caches). Une fonction pure est un sous-programme qui ne depend QUE de ses parametres et ne produit QUE sa valeur de retour. Pas de `this`, pas de variable globale, pas d'appel DB cache. Le prix a payer : tout copier est plus lent, et certains algorithmes sont plus naturels en imperatif. Le benefice : une fonction pure est testable, parallelisable, et raisonnable isolement — pas besoin de lire 10 fichiers pour comprendre ce qu'elle fait.
9
+
10
+ ## Checklist
11
+ - [ ] Les fonctions sont pures : meme entree → meme sortie, pas d'effet de bord (DB, HTTP, file)
12
+ - [ ] Les donnees sont immutables — pas de `push`, `splice`, `delete`, `sort()` in-place
13
+ - [ ] Les erreurs sont modelisees comme des valeurs (Result<T, E>, Option<T>) — pas d'exceptions non gerees
14
+ - [ ] La composition remplace l'heritage : `compose(f, g)(x)` plutot que `class B extends A`
15
+ - [ ] Les effets de bord sont pousses aux bords du systeme (entree/sortie) — le cœur est pur
16
+ - [ ] Le pattern matching est utilise pour les unions discriminantes — pas de `if (type === "...")` en chaine
17
+ - [ ] Pas de `null` — utiliser `Option<T>` (Some/None) pour les valeurs optionnelles
18
+
19
+ ## Anti-patterns
20
+ ### FP = utiliser des callbacks
21
+ **Ce qu'on voit :** `array.map(x => x * 2).filter(x => x > 5)` et l'equipe pense "on fait de la FP". Mais tout le reste est mutable et impur.
22
+ **Pourquoi c'est dangereux :** la FP n'est pas une liste d'operations sur tableau — c'est une discipline sur l'etat et les effets de bord. Utiliser `map` sans immutabilite, c'est mettre un autocollant "functional" sur du code imperatif. Les vrais bugs sont toujours dans les mutations partagees.
23
+ **Faire plutot :** commencer par l'immutabilite (c'est le plus gros gain). Ensuite pousser les effets de bord aux bords. Enfin, modeliser les erreurs comme valeurs. Les `map`/`filter`/`reduce` viendront naturellement.
24
+
25
+ ### Exception pour le flux de controle
26
+ **Ce qu'on voit :** `throw new UserNotFoundError()` dans un service, `catch (e) { if (e instanceof UserNotFoundError)... }` 3 couches plus haut.
27
+ **Pourquoi c'est dangereux :** l'exception casse le contrat de la fonction. La signature dit `User → UserProfile` mais en realite la fonction peut throw. Le compilateur ne verifie pas les exceptions (dans la plupart des langages). Le flux de controle devient implicite et non type.
28
+ **Faire plutot :** retourner `Result<UserProfile, UserNotFoundError>`. L'appelant est force de gerer les deux cas. Le flux de controle est explicite et type. Pattern matching : `match result { Ok(profile) => ..., Err(UserNotFound) => ... }`.
29
+
30
+ ### Immutabilite = tout copier naivement
31
+ **Ce qu'on voit :** `return { ...state, items: [...state.items, newItem] }` dans un reducer Redux avec 10000 items. Chaque update copie tout le tableau.
32
+ **Pourquoi c'est dangereux :** l'immutabilite naive est O(n) en memoire et en temps. Pour une liste de 100000 elements, 100 updates/s = 10 millions de copies = memoire explose. L'equipe conclut "la FP c'est lent" alors que c'est juste l'implementation.
33
+ **Faire plutot :** structures de donnees persistantes (Immutable.js, Immer avec structural sharing). Elles partagent la memoire entre les versions. O(log n) ou O(1) pour la plupart des operations. L'immutabilite n'est pas lente — la copie naive l'est.
34
+
35
+ ## Patterns
36
+ ### Result/Either type
37
+ **Quand :** toute operation qui peut echouer pour une raison connue (validation, lookup, parsing).
38
+ **Comment :** `type Result<T, E> = Ok<T> | Err<E>`. L'appelant pattern-match sur le resultat. Tous les chemins sont types et verifies. Pas de `try/catch` pour le flux normal. Les erreurs font partie du contrat de la fonction.
39
+
40
+ ### Sandwitch fonctionnel (IO sandwich)
41
+ **Quand :** une operation qui doit lire des donnees, les transformer, et ecrire le resultat.
42
+ **Comment :** (1) Lire toutes les donnees necessaires (IO, impur), (2) transformation pure en memoire (cœur, pur), (3) ecrire le resultat (IO, impur). Les entrees/sorties sont aux bords, le cœur est pur et testable sans mocks.
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: github
3
+ description: "GitHub — issues, projets, branches, commits conventionnels, PR templates, CI/CD Actions, releases, code review. À charger quand on interagit avec GitHub (issues, PRs, branches, workflows)."
4
+ ---
5
+
6
+ # GitHub
7
+
8
+ **Principe premier :** GitHub n'est pas juste un hébergeur de code — c'est la plateforme de collaboration qui relie le code, les issues, les PRs, la CI et les releases. Chaque élément (issue, branche, commit, PR, release) est un nœud dans un graphe lié. La valeur vient des liens : une PR sans issue liée est orpheline, un commit sans contexte est illisible, une release sans changelog est opaque. Bien utiliser GitHub, c'est maximiser la traçabilité entre ces nœuds.
9
+
10
+ ## Checklist
11
+ - [ ] Les commits suivent Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`, `test:`, `refactor:`) — machine-readable, génère le changelog automatiquement
12
+ - [ ] Chaque PR est liée à une issue (Closes #N) et fait moins de 400 lignes modifiées
13
+ - [ ] Le repo a des templates d'issue (bug, feature) dans `.github/ISSUE_TEMPLATE/`
14
+ - [ ] Le repo a un template de PR dans `.github/pull_request_template.md`
15
+ - [ ] Les branches suivent une convention : `feat/`, `fix/`, `chore/`, `docs/` — et vivent ≤ 1 jour
16
+ - [ ] Les branches sont protégées sur main/master : review obligatoire, CI verte, pas de force-push
17
+ - [ ] Les GitHub Actions utilisent OIDC pour les credentials cloud — zéro secret long-lived
18
+ - [ ] Les releases sont taggées (semver) avec des release notes générées depuis les conventional commits
19
+ - [ ] Les milestones et labels sont utilisés pour grouper le travail par version/thème
20
+
21
+ ## Anti-patterns
22
+ ### PR monstre sans issue
23
+ **Ce qu'on voit :** PR de 2000 lignes, titre "Fix stuff", pas d'issue liée, description vide ou "see commits".
24
+ **Pourquoi c'est dangereux :** le reviewer n'a aucun contexte. Pourquoi ce changement ? Quel problème ça résout ? Impossible de reviewer correctement — le reviewer va soit tout accepter sans comprendre, soit bloquer par peur. La PR devient un événement politique au lieu d'un échange technique.
25
+ **Faire plutôt :** PR < 400 lignes, liée à une issue qui décrit le problème (PAS la solution), description qui explique le WHY et le HOW. Le diff est petit → la review est rapide → le feedback est court → la vélocité augmente.
26
+
27
+ ### Commit messages vagues
28
+ **Ce qu'on voit :** "update", "fix bug", "wip", "changes", "typo". Le git log est un cimetière de messages inutiles.
29
+ **Pourquoi c'est dangereux :** `git blame` devient inutile. Le changelog est impossible à générer. Bisecter un bug nécessite de lire chaque diff. Le message de commit est le SEUL artefact qui survit au code (le code change, le message reste). Un mauvais message est une dette permanente.
30
+ **Faire plutôt :** Conventional Commits. `feat(auth): add OIDC token refresh` ou `fix(api): handle null user in GET /profile`. Le type (feat/fix/chore) est machine-readable. Le scope (auth/api) localise. Le sujet dit ce qui change. Le corps (optionnel) dit pourquoi.
31
+
32
+ ### Secrets dans les workflows
33
+ **Ce qu'on voit :** `env: API_KEY: ${{ secrets.API_KEY }}` puis `curl -H "Authorization: $API_KEY"` — le secret transite par une variable d'environnement accessible à tout le workflow.
34
+ **Pourquoi c'est dangereux :** les variables d'environnement sont visibles par tous les steps du job, y compris les actions tierces. Une action compromise lit `process.env` et exfiltre les secrets. Même sans action tierce, un script de build modifié peut les exposer.
35
+ **Faire plutôt :** OIDC (OpenID Connect) : le workflow obtient un token temporaire (< 1h) du cloud provider sans stocker de secret. Pour les secrets inévitables : les passer directement au step qui en a besoin, pas en env global. Utiliser `secrets: inherit` avec parcimonie.
36
+
37
+ ### Branch protection absente
38
+ **Ce qu'on voit :** pas de ruleset sur main. N'importe qui peut push direct. Pas de review obligatoire. La CI passe mais personne ne la regarde.
39
+ **Pourquoi c'est dangereux :** main est la branche de production. Un push direct sans review = un deploy non vérifié. Sans protection, un `git push --force` accidentel peut écraser l'historique. La branch protection est le dernier rempart entre une erreur humaine et la production.
40
+ **Faire plutôt :** ruleset sur main : require pull request (min 1 approval), require status checks (CI verte), block force push, require conversation resolution. Pour les hotfixes urgentes : une procédure d'override documentée, pas une désactivation de la règle.
41
+
42
+ ## Patterns
43
+ ### Conventional Commits
44
+ **Quand :** tout commit, sans exception.
45
+ **Comment :** `<type>(<scope>): <subject>` — type = feat|fix|chore|docs|test|refactor|ci|perf. Scope = le module/domaine. Subject = impératif présent, < 72 chars. Le corps après une ligne vide, en phrases complètes. Les breaking changes ajoutent `!` après le type ou `BREAKING CHANGE:` dans le footer.
46
+
47
+ ### Issue template
48
+ **Quand :** tout repo avec plus d'un contributeur.
49
+ **Comment :** `.github/ISSUE_TEMPLATE/bug.yml` avec les champs : version, steps to reproduce, expected vs actual behavior, logs, environment. `.github/ISSUE_TEMPLATE/feature.yml` avec : problème actuel, solution proposée, alternatives considérées. Les templates YAML supportent les dropdowns, textareas, et la validation — bien supérieur au markdown simple.
50
+
51
+ ### PR template
52
+ **Quand :** tout repo où le code est revu.
53
+ **Comment :** `.github/pull_request_template.md` avec : Summary (1-3 bullet points), Test plan (checklist), Screenshots/recordings (si UI), Breaking changes (oui/non + description). Pas de "What" et "Why" vagues — des sections qui incitent à l'action concrète.
54
+
55
+ ### Branch naming + protection
56
+ **Quand :** tout repo en équipe.
57
+ **Comment :** `feat/<slug>`, `fix/<slug>`, `chore/<slug>` — slug court en kebab-case depuis le titre de l'issue. Protection sur main : require PR + 1 approval + CI + no force push. Pour les repos solo : au minimum require CI et no force push.
58
+
59
+ ### GitHub Actions OIDC
60
+ **Quand :** tout workflow qui déploie sur un cloud.
61
+ **Comment :** `permissions: id-token: write` + configure le provider OIDC côté cloud (AWS IAM, GCP WIF). Le workflow reçoit un token temporaire automatiquement. Zéro secret stocké dans GitHub Secrets. Le token expire avant qu'un attaquant puisse l'utiliser même s'il est intercepté.
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: high-availability
3
+ description: "Haute Disponibilite — clustering, failover, multi-region, quorum, split-brain, replication, SLA 9s. A charger quand on concoit un systeme haute disponibilite."
4
+ ---
5
+
6
+ # Haute Disponibilite
7
+
8
+ **Principe premier :** La haute disponibilite n'est pas "avoir des serveurs de backup" — c'est concevoir pour la defaillance comme cas nominal. Tout composant va tomber un jour. La question n'est pas "est-ce que ca va tomber ?" mais "quand ca tombe, est-ce que le systeme continue ?". Le SLA (99.9%, 99.99%, 99.999%) n'est pas un objectif de disponibilite — c'est un budget de panne. 99.9% = 8h46min d'indisponibilite par an. 99.99% = 52min. 99.999% = 5min. Chaque 9 supplementaire coute un ordre de grandeur en complexite et en argent. Le vrai defi de la HA n'est pas technique — c'est economique : jusqu'ou vas-tu pour 9 de plus ?
9
+
10
+ ## Checklist
11
+ - [ ] Le SLA cible est defini (99.9%, 99.99%, 99.999%) et connu de l'equipe + budget de panne annuel calcule
12
+ - [ ] Le failover est automatise (pas de bascule manuelle a 3h du mat) — detection + basculement < SLA
13
+ - [ ] Chaque composant est deploye sur au moins 2 zones de disponibilite (ou 2 regions) — pas de SPOF
14
+ - [ ] Le quorum est configure correctement (3 ou 5 nœuds, jamais 2) pour eviter le split-brain
15
+ - [ ] La replication est monitorisee (lag en secondes) — alerter si lag > seuil
16
+ - [ ] Les tests de failover sont executes regulierement (trimestriel) — sans test, la HA est une croyance
17
+ - [ ] Le load balancer fait du health checking actif (endpoint applicatif, pas juste TCP connect)
18
+
19
+ ## Anti-patterns
20
+ ### Cluster a 2 nœuds
21
+ **Ce qu'on voit :** 2 serveurs en cluster. Le reseau entre eux coupe. Chacun pense que l'autre est mort et devient primaire → deux primaires → corruption de donnees.
22
+ **Pourquoi c'est dangereux :** avec 2 nœuds, aucun quorum n'est possible (majorite = 2/2). En cas de partition reseau, chaque nœud a 50% de chances — pas de majorite. Le split-brain est inevitable. C'est la configuration la plus dangereuse.
23
+ **Faire plutot :** minimum 3 nœuds pour un cluster. La majorite est 2/3 → un seul cote de la partition peut avoir le quorum. Pour les systemes a 2 nœuds, utiliser un témoin externe (witness, quorum disk) qui donne la majorite a UN des deux.
24
+
25
+ ### HA = juste dupliquer les serveurs
26
+ **Ce qu'on voit :** 2 serveurs d'application derriere un load balancer. "On est HA." La base de donnees est un seul RDS sans Multi-AZ.
27
+ **Pourquoi c'est dangereux :** la HA est aussi forte que ton maillon le plus faible. Serveurs app HA + DB single point of failure = la DB tombe, tout tombe. Les utilisateurs voient "error 500", pas "la DB est down". La HA est une propriete du systeme entier, pas d'un composant.
28
+ **Faire plutot :** analyser le chemin critique complet. Load balancer (redondant), serveurs app (≥2, multi-AZ), DB (multi-AZ ou cluster), cache (cluster Redis), file d'attente (cluster). Chaque composant doit survivre a la perte d'un nœud. Le test de resilience verifie le systeme entier.
29
+
30
+ ### Pas de test de failover
31
+ **Ce qu'on voit :** Multi-AZ configure. Le failover est "automatique". Personne ne l'a jamais declenche volontairement.
32
+ **Pourquoi c'est dangereux :** le failover automatique est un systeme complexe : detection de panne, election d'un nouveau primaire, reconfiguration DNS/proxy, reconnection des clients. Chaque etape peut echouer. La premiere fois que le failover est teste ne doit pas etre le jour de la panne reelle.
33
+ **Faire plutot :** Game Day trimestriel : on coupe le primaire et on observe le failover. Mesurer le temps de bascule. Verifier que les clients se reconnectent. Verifier que les donnees sont intactes. Documenter ce qui a mal tourne. Le failover non teste = pas de failover.
34
+
35
+ ## Patterns
36
+ ### Active-Passive avec health check
37
+ **Quand :** service avec etat (DB, file system).
38
+ **Comment :** un seul nœud actif (ecritures). Un ou plusieurs nœuds passifs (lecture seule ou standby). Health check continu sur l'actif. Si l'actif ne repond plus → promotion du standby le plus a jour via leader election (quorum). Les clients sont redirigés vers le nouveau primaire.
39
+
40
+ ### Multi-AZ stateless
41
+ **Quand :** services sans etat (API, workers).
42
+ **Comment :** deployer N instances reparties sur ≥2 zones de disponibilite. Load balancer repartit le trafic. Si une AZ tombe, le load balancer envoie tout le trafic vers les autres AZ. Aucune intervention humaine. Le nombre d'instances doit absorber la perte d'une AZ entiere sans saturation.
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: iac
3
+ description: "IaC — l'infrastructure comme code, pas comme clics. State management, drift detection, modules, immutabilite. A charger quand on definit ou modifie l'infrastructure."
4
+ ---
5
+
6
+ # Infrastructure as Code
7
+
8
+ **Principe premier :** L'infrastructure n'est pas une liste de ressources a creer — c'est un programme dont le state est la verite. La console est un outil de debugging, pas de gestion. Chaque clic est une dette qui sera oubliee et qui cassera au pire moment. Le vrai benefice de l'IaC n'est pas la vitesse de creation (la console est plus rapide pour 1 instance) — c'est la repetabilite : meme code → meme infra, dans 6 mois, par un autre humain, sans surprise. Le state file est ton inventaire physique — si tu le perds, tu reconstruis ou tu importes, mais tu ne devines pas.
9
+
10
+ ## Checklist
11
+ - [ ] Toute l'infrastructure est dans le code — zero ressource creee a la main (verifie avec drift detection)
12
+ - [ ] Le state est stocke dans un backend securise (S3 + DynamoDB lock, Terraform Cloud, Pulumi SaaS) — jamais en local
13
+ - [ ] Les modules sont versionnes (tag git, pas `source = "../common"`)
14
+ - [ ] Les ressources sont immutables — on remplace, on ne modifie pas en place
15
+ - [ ] Les secrets sont referencees depuis un secret manager, pas en clair dans le code
16
+ - [ ] Le plan est toujours sauvegarde (`terraform plan -out=plan.out`) et applique depuis le meme fichier
17
+ - [ ] Drift detection tourne regulierement (hebdomadaire ou dans la CI) — alerter si ecart
18
+
19
+ ## Anti-patterns
20
+ ### Console comme outil principal
21
+ **Ce qu'on voit :** l'equipe cree les ressources a la main "parce que c'est plus rapide". 6 mois plus tard, 200 ressources non trackees, configuration inconnue.
22
+ **Pourquoi c'est dangereux :** la console ne laisse pas de trace. Pas de review possible. Pas de rollback. Impossible de reproduire l'environnement. Le disaster recovery devient un puzzle.
23
+ **Faire plutot :** toute ressource est definie dans le code. Si une ressource existe deja, l'importer (`terraform import`) puis la gerer en code. La console est en read-only.
24
+
25
+ ### State local
26
+ **Ce qu'on voit :** `terraform.tfstate` dans le repo ou sur le laptop du dev. "C'est bon, je l'ai en local."
27
+ **Pourquoi c'est dangereux :** le laptop meurt, le state est perdu. Deux devs appliquent en parallele → corruption. Le state contient des donnees sensibles (passwords, private keys) → fuite.
28
+ **Faire plutot :** backend distant avec locking (S3 + DynamoDB). Chaque `apply` verifie le lock. Le state est chiffre. Les secrets sont marques `sensitive` dans le code, pas extraits du state.
29
+
30
+ ### Module monolithe
31
+ **Ce qu'on voit :** un seul module `main.tf` de 2000 lignes qui gere tout : reseau, compute, DB, DNS, IAM. Chaque changement fait peur.
32
+ **Pourquoi c'est dangereux :** blast radius maximal. Un changement de DNS peut detruire la DB si le state est corrompu. La revue est impossible. Le `terraform plan` prend 10 minutes.
33
+ **Faire plutot :** infrastructure decomposee en modules independants. Reseau dans un state, compute dans un autre, DB dans un autre. Chaque module a son propre cycle de vie. Les dependances sont explicites (data sources, remote state).
34
+
35
+ ## Patterns
36
+ ### Immutabilite
37
+ **Quand :** toute ressource modifiable (instances, conteneurs, lambdas).
38
+ **Comment :** `create_before_destroy = true`. On cree la nouvelle ressource, on valide, puis on detruit l'ancienne. Pas de modification en place. Le code est la verite — si le code change, la ressource est remplacee.
39
+
40
+ ### Drift detection
41
+ **Quand :** toute equipe de plus d'une personne.
42
+ **Comment :** `terraform plan -detailed-exitcode` ou `pulumi refresh --diff` dans la CI chaque semaine. Si drift → ticket automatique. Corriger la cause (console ? script maison ?) pas juste l'effet.
43
+
44
+ ### GitOps
45
+ **Quand :** deploiement continu de l'infrastructure.
46
+ **Comment :** le repo git est la source de verite. Un merge sur main declenche le plan, puis l'apply. Pas de `terraform apply` depuis un laptop. Le pipeline a les permissions IAM minimales (OIDC).