@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,42 @@
1
+ ---
2
+ name: agile
3
+ description: "Agile — Scrum, Kanban, Shape Up, sprints, estimation, retros, amelioration continue. A charger quand on travaille en mode agile."
4
+ ---
5
+
6
+ # Agile
7
+
8
+ **Principe premier :** L'agilite n'est pas un framework (Scrum n'est pas l'agilite) — c'est un principe : livrer de la valeur en petits increments, inspecter le resultat, et adapter le plan. Le manifeste agile a 4 valeurs, et la premiere est "les individus et leurs interactions plus que les processus et les outils". Si ton processus agile est plus important que les personnes qui l'utilisent, tu as echoue l'agilite. Le but du process n'est pas d'etre suivi — c'est de rendre l'equipe plus efficace. Un processus qui ralentit l'equipe n'est pas agile, meme s'il suit Scrum a la lettre. Le meilleur indicateur d'agilite : combien de temps entre "j'ai une idee" et "c'est en production" ?
9
+
10
+ ## Checklist
11
+ - [ ] Les ceremonies sont cadrees : standup 15min, retro 1h, planning 1-2h — si plus long, le processus est casse
12
+ - [ ] Les tickets sont INVEST : Independent, Negotiable, Valuable, Estimable, Small, Testable
13
+ - [ ] Le WIP est limite (Kanban/Scrum avec capacite explicite) — pas plus de travail en cours que de capacite
14
+ - [ ] Les retros produisent des actions concretes (pas "on communiquera mieux") — max 2-3 actions par retro
15
+ - [ ] La velocite est utilisee pour le planning, pas pour le jugement de performance
16
+ - [ ] Le backlog est priorise par valeur business, pas par "c'est facile" ou "c'est urgent depuis 6 mois"
17
+ - [ ] Le cycle time (temps ticket ouvert → ferme) est mesure et s'ameliore — c'est le vrai KPI agile
18
+
19
+ ## Anti-patterns
20
+ ### Agile = Scrum = standups + sprints
21
+ **Ce qu'on voit :** l'equipe fait des standups, des sprints de 2 semaines, et un retro. "On est agile." Les stories sont estimees en story points. Les sprints sont bookes a 110%. Rien n'est livre en production a la fin du sprint.
22
+ **Pourquoi c'est dangereux :** c'est du theatre agile. Les ceremonies sont suivies mais l'objectif (livrer de la valeur rapidement) est manque. Le processus devient le produit. L'equipe est frustree ("l'agile c'est des reunions qui servent a rien") sans comprendre que le probleme n'est pas l'agilite, c'est l'imitation vide de l'agilite.
23
+ **Faire plutot :** se demander POURQUOI on fait chaque ceremonie. Si le standup est un compte-rendu au manager, c'est foutu — le standup est pour que l'equipe se synchronise. Si la retro ne produit jamais d'actions, l'arreter. Moins de processus, plus de livraison. Commencer par Kanban (pas de sprint, flux continu) et ajouter des ceremonies seulement si le besoin emerge.
24
+
25
+ ### Story points = mesure de performance
26
+ **Ce qu'on voit :** "tu as fait 8 points ce sprint, l'objectif est 13." Les story points deviennent un KPI individuel.
27
+ **Pourquoi c'est dangereux :** les story points mesurent la complexite relative, pas la productivite. Les utiliser comme KPI = l'equipe gonfle les estimations. 1 point devient 3. La velocite augmente mais rien n'est livre plus vite. Culture de la peur et du gaming du systeme.
28
+ **Faire plutot :** les story points servent UNIQUEMENT a la planification de sprint (combien de travail l'equipe peut absorber). La vraie metrique est le cycle time (combien de temps pour livrer) et le throughput (combien de tickets livres par semaine). Ces metriques ne sont pas gameables.
29
+
30
+ ### Retro = rituel vide
31
+ **Ce qu'on voit :** "Qu'est-ce qui s'est bien passe ? Qu'est-ce qui s'est mal passe ?" Memes reponses depuis 6 mois : "la communication" et "les specs pas claires". Zero action concrete.
32
+ **Pourquoi c'est dangereux :** une retro sans action est un signal que l'equipe est apprise a l'impuissance. Les problemes sont identifies mais jamais resolus. La retro devient une soupape ou on se plaint sans consequence — c'est pire que pas de retro car ca cree du cynisme.
33
+ **Faire plutot :** chaque retro produit 1-2 actions concretes, assignees, avec deadline. La retro suivante commence par "est-ce que les actions de la derniere retro sont faites ?" Si non, pourquoi ? Si une action n'est jamais faite, le probleme n'est pas l'equipe — c'est que le systeme empeche l'amelioration.
34
+
35
+ ## Patterns
36
+ ### Kanban pour commencer
37
+ **Quand :** equipe qui decouvre l'agilite ou qui a ete brulee par Scrum.
38
+ **Comment :** visualiser le flux (colonnes To Do / In Progress / Done), limiter le WIP (max 2 taches par personne en In Progress), mesurer le cycle time. Pas de sprint, pas d'estimation obligatoire, pas de ceremonies forcees. Ajouter un standup uniquement si la synchro est necessaire. Iterer sur le processus a partir de la.
39
+
40
+ ### Cycle time comme North Star
41
+ **Quand :** mesurer l'amelioration continue.
42
+ **Comment :** cycle time = temps entre "le ticket est pret a developper" et "en production". Mesurer le P50 et P85 (pas la moyenne — les outliers faussent). Objectif : reduire le cycle time sans sacrifier la qualite. Un cycle time qui diminue = l'equipe s'ameliore VRAIMENT.
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: alerting
3
+ description: "Alerting — SLO-based alerting, alert fatigue prevention, on-call, post-mortems, runbooks. A charger quand on configure des alertes."
4
+ ---
5
+
6
+ # Alerting
7
+
8
+ **Principe premier :** Une alerte qui ne declenche pas d'action n'est pas une alerte — c'est du bruit qui tue les vraies alertes. Chaque alerte doit etre : actionable (tu sais quoi faire), symptom-based (pas cause-based), et avoir un runbook. Si tu ne peux pas ecrire le runbook en < 5 etapes, ne cree pas l'alerte. Le but n'est pas d'etre notifie de tout — c'est d'etre notifie assez tot pour agir avant que les utilisateurs ne remarquent.
9
+
10
+ ## Checklist
11
+ - [ ] Les alertes sont sur les symptomes (P95 > 1s, error rate > 1%), pas sur les causes (CPU > 70%)
12
+ - [ ] Chaque alerte a un runbook — pas "on verra quand ca sonnera"
13
+ - [ ] Les regles d'alerte et la config AlertManager sont dans le repo (alerting as code) — pas creees a la main
14
+ - [ ] SLA de reponse defini : critical (page, < 5 min), high (page jour, < 30 min), medium (ticket, < 4h)
15
+ - [ ] Alertes groupees et de-dupliquees — pas 50 pages pour la meme cause racine
16
+ - [ ] On-call rotation documentee avec escalation — personne n'est on-call seul sans backup
17
+ - [ ] Post-mortem blameless apres chaque incident majeur + 5 Whys jusqu'a la cause racine
18
+
19
+ ## Anti-patterns
20
+ ### Alerter sur tout
21
+ **Ce qu'on voit :** "CPU > 70%", "memoire > 60%", "disque > 70%" — 200 alertes configurees. 15 pages par nuit. L'equipe a mute le canal.
22
+ **Pourquoi c'est dangereux :** alert fatigue. Chaque fausse alerte entraine la suivante vers l'ignore. Quand la vraie alerte critique arrive, personne ne la voit. Le canal d'alerte est devenu un flux de bruit ignore.
23
+ **Faire plutot :** alerter sur les symptomes utilisateur. "P95 latency > 1s pendant 5 min" (l'utilisateur ressent la lenteur). "Error rate > 1% pendant 5 min" (l'utilisateur voit des erreurs). Le CPU est une cause possible parmi 10, pas un symptome.
24
+
25
+ ### Alerte sans runbook
26
+ **Ce qu'on voit :** alerte "PaymentService is down". Pas de runbook. L'on-call Googlise "comment restart payment service" a 3h du matin.
27
+ **Pourquoi c'est dangereux :** MTTR explose. L'on-call stresse fait des erreurs. Le runbook est la difference entre "redemarrer en 2 minutes" et "aggraver l'incident en 30 minutes de debugging panique".
28
+ **Faire plutot :** runbook attache a chaque alerte. Etapes concretes. "1. Verifier les logs dans Loki avec {service=payment, level=error}. 2. Si OOM -> restart le pod. 3. Si DB timeout -> verifier les connexions pool. 4. Si rien -> escalader a l'equipe backend. 5. Post-mortem avec 5 Whys dans les 48h."
29
+
30
+ ### Aucun post-mortem
31
+ **Ce qu'on voit :** incident resolu -> "ouf, on passe a autre chose". Pas d'analyse. Le meme incident se reproduit 3 mois plus tard.
32
+ **Pourquoi c'est dangereux :** sans post-mortem, l'organisation n'apprend pas. Les memes erreurs se repetent. Le but du post-mortem n'est pas de trouver un coupable — c'est d'identifier les failles du SYSTEME qui ont permis l'incident.
33
+ **Faire plutot :** post-mortem blameless dans les 48h. Format : timeline, impact, 5 Whys jusqu'a la cause racine, what went well, what went wrong, action items. Les action items ont des owners et des deadlines.
34
+
35
+ ### Corriger le symptome, pas la cause racine
36
+ **Ce qu'on voit :** le disque est plein -> on supprime des logs. Le disque se remplit 3 jours plus tard. Meme incident, meme reponse. 5 iterations avant de se demander POURQUOI.
37
+ **Pourquoi c'est dangereux :** corriger le symptome sans trouver la cause racine garantit la recidive. Chaque recurrence erode la confiance. Le MTTR apparent est bas, le MTTR reel est infini (l'incident n'est jamais vraiment resolu).
38
+ **Faire plutot :** methode des 5 Whys. "Le disque est plein" -> Pourquoi ? "Les logs font 50 Go/jour" -> Pourquoi ? "Level DEBUG active en prod" -> Pourquoi ? "Le deploiement a ecrase la config" -> Pourquoi ? "La config n'est pas versionnee" -> Action racine : versionner la config + alerter si disque > 80%. Le bug est le niveau DEBUG. La cause racine est l'absence d'IaC pour la config. On corrige la cause, pas le symptome.
39
+
40
+ ## Patterns
41
+ ### AlertManager (routing + dedup + silence)
42
+ **Quand :** toute stack Prometheus en production.
43
+ **Comment :** Prometheus evalue les rules -> alertes -> AlertManager. AlertManager groupe les alertes (`group_by: [service, severity]`), deduplique (meme alerte = une notification), silencie la maintenance (`matchers: [env=staging]`). Routes par severite : critical -> PagerDuty/Opsgenie, warning -> Slack. Config dans `monitoring/alertmanager.yml`, versionne dans le repo.
44
+
45
+ ### Alerting as Code (regles dans le repo)
46
+ **Quand :** toute equipe de plus d'une personne.
47
+ **Comment :** regles Prometheus (`monitoring/rules.yml`), config AlertManager (`monitoring/alertmanager.yml`), dashboards Grafana (`monitoring/dashboards/`) — tout dans le repo, versionne, deploye via CI/CD. Pas de regle creee a la main dans l'UI Grafana. Une PR pour chaque changement d'alerte — le seuil, le runbook_url, la severite sont revus comme du code.
48
+
49
+ ### Runbook integre a l'alerte
50
+ **Quand :** chaque alerte creee.
51
+ **Comment :** `annotations: { runbook_url: "https://wiki.corp/runbooks/payment-latency" }`. Le runbook contient : (1) ce que signifie l'alerte, (2) comment verifier dans Grafana/Loki/Tempo, (3) actions de mitigation, (4) qui escalader, (5) comment faire un 5 Whys si la mitigation ne suffit pas.
52
+
53
+ ### Post-mortem blameless + 5 Whys
54
+ **Quand :** tout incident qui a declenche une alerte on-call.
55
+ **Comment :** document blameless dans les 48h. Sections : timeline, impact, 5 Whys jusqu'a la cause racine systemique, what went well, what went wrong, action items avec owners et deadlines. L'objectif est d'ameliorer le SYSTEME — pas de trouver un responsable. Action items prioritaires sur le prochain sprint.
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: api-design
3
+ description: "API Design — l'API comme contrat, REST/GraphQL/gRPC, pagination cursor-based, idempotency, structured errors, rate limiting. À charger quand on crée ou modifie des endpoints."
4
+ ---
5
+
6
+ # API Design
7
+
8
+ **Principe premier :** Une API est un contrat entre un client et un serveur qui évoluent à des rythmes différents. Le client peut être une app mobile qui se met à jour une fois par mois, le serveur peut être déployé 10× par jour. Le design d'API est l'art de faire évoluer le contrat sans le casser. Chaque champ que tu ajoutes est un engagement, chaque champ que tu changes est une rupture. La question n'est pas "est-ce que c'est RESTful ?" mais "est-ce que le client peut survivre à 6 mois de changements serveur sans mise à jour ?"
9
+
10
+ ## Checklist
11
+ - [ ] L'API est versionnée — dans l'URL (/v1/) ou le header (Accept-Version)
12
+ - [ ] Pagination cursor-based — stable, index-friendly, pas de doublon entre pages
13
+ - [ ] Les erreurs sont structurées : `{error: {code, message, details}}` — pas de `200 OK {success: false}`
14
+ - [ ] Les mutations POST/PUT/DELETE supportent l'idempotency key
15
+ - [ ] Rate limiting en place avec headers standards : `Retry-After`, `X-RateLimit-*`
16
+ - [ ] Le schéma est documenté (OpenAPI/GraphQL schema/gRPC proto) et la doc est le contrat, pas une suggestion
17
+ - [ ] Pas de breaking change sans nouvelle version ou deprecation window explicite
18
+
19
+ ## Anti-patterns
20
+ ### Breaking change silencieux
21
+ **Ce qu'on voit :** `{price: 10}` devient `{price: {amount: 10, currency: "EUR"}}` sur la même version d'API. Les clients mobiles qui n'ont pas été mis à jour crashent.
22
+ **Pourquoi c'est dangereux :** le client n'a aucun moyen de savoir que le contrat a changé. Il parse ce qu'il reçoit, ça casse. Le pire : ça peut arriver à 20% des utilisateurs seulement (ceux qui n'ont pas la dernière version de l'app). Le bug est invisible côté serveur.
23
+ **Faire plutôt :** nouvelle version (/v2/) avec le nouveau format. L'ancienne version (/v1/) est maintenue pendant une deprecation window (6-12 mois) avec un header `Deprecation: true` et `Sunset: <date>`. Les clients ont le temps de migrer.
24
+
25
+ ### `200 OK` avec erreur dedans
26
+ **Ce qu'on voit :** toutes les réponses sont HTTP 200. Le corps contient `{success: false, error: "quelque chose"}`. Même pour une erreur 500.
27
+ **Pourquoi c'est dangereux :** HTTP a un système de codes d'erreur pour une raison. Les CDN cachent les 200. Les load balancers comptent les 5xx. Les outils de monitoring alertent sur les taux d'erreur HTTP. En faisant tout en 200, tu rends ton API invisible à toute la chaîne d'infrastructure.
28
+ **Faire plutôt :** utiliser les codes HTTP comme prévu. 201 Created, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable, 429 Too Many Requests, 500 Internal. Le code HTTP est un signal machine-readable.
29
+
30
+ ### Offset pagination
31
+ **Ce qu'on voit :** `GET /orders?page=3&limit=50` → `LIMIT 50 OFFSET 100`. À la page 100, la DB scanne 5000 rows pour en retourner 50.
32
+ **Pourquoi c'est dangereux :** deux problèmes. Performance : OFFSET N oblige la DB à scanner N rows. Cohérence : si une row est insérée entre deux pages, toutes les rows suivantes sont décalées et l'utilisateur voit des doublons ou manque des entrées.
33
+ **Faire plutôt :** cursor-based : `GET /orders?cursor=xyz&limit=50` → `WHERE id > 'xyz' ORDER BY id LIMIT 50`. Index-friendly. Stable. Pas de doublon. Le cursor est opaque pour le client.
34
+
35
+ ## Patterns
36
+ ### Structured errors
37
+ **Quand :** toute API.
38
+ **Comment :** `{error: {code: "INSUFFICIENT_FUNDS", message: "Solde insuffisant", details: [{field: "amount", reason: "minimum 10 EUR"}]}}`. `code` : machine-readable (switch côté client). `message` : human-readable (debug). `details` : actionable (form validation).
39
+
40
+ ### Idempotency key
41
+ **Quand :** toute mutation où le double-submit est dangereux (paiements, créations).
42
+ **Comment :** header `Idempotency-Key: <uuid>`. Le serveur stocke la clé + le résultat. Même clé = même réponse, l'opération n'est exécutée qu'une fois. Stripe utilise ce pattern pour 100% de leurs mutations.
43
+
44
+ ### Rate limiting avec headers
45
+ **Quand :** tout endpoint public.
46
+ **Comment :** `429 Too Many Requests` + `Retry-After: 30` + `X-RateLimit-Limit: 100` + `X-RateLimit-Remaining: 0` + `X-RateLimit-Reset: 1716000000`. Le client sait exactement quand réessayer. Pas de backoff deviné.
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: appsec
3
+ description: "Application Security — OWASP Top 10, defense in depth, auth (OAuth2/OIDC), input validation, session security. À charger quand on sécurise une application."
4
+ ---
5
+
6
+ # Application Security
7
+
8
+ **Principe premier :** La sécurité applicative n'est pas une feature — c'est une propriété émergente d'un système où chaque couche suppose que celle d'avant a échoué. Si ton input validation compte sur le WAF, et que ton WAF compte sur le framework, personne ne valide vraiment. La défense en profondeur n'est pas "plusieurs couches" — c'est "chaque couche traite l'input comme hostile, même si une autre couche est censée l'avoir déjà nettoyé". Assume breach à chaque étage.
9
+
10
+ ## Checklist
11
+ - [ ] Toutes les entrées utilisateur sont validées à la frontière — type, longueur, charset, range
12
+ - [ ] Requêtes SQL/NoSQL paramétrées — jamais de concaténation (injection)
13
+ - [ ] Authentification via OAuth2/OIDC avec providers éprouvés — pas d'auth maison
14
+ - [ ] Sessions : HttpOnly, Secure, SameSite=Lax, rotation d'ID après login
15
+ - [ ] CSRF protégé sur toutes les mutations (SameSite + token si nécessaire)
16
+ - [ ] Rate limiting sur TOUS les endpoints sensibles (login, API, upload, reset password)
17
+ - [ ] Headers de sécurité : CSP, HSTS, X-Frame-Options, X-Content-Type-Options
18
+ - [ ] Mots de passe hashés avec argon2id (pas de SHA, pas de MD5)
19
+
20
+ ## Anti-patterns
21
+ ### Auth maison
22
+ **Ce qu'on voit :** `const token = jwt.sign({userId}, SECRET)` — JWT sans expiration, sans refresh, sans blacklist. Le token volé = accès permanent.
23
+ **Pourquoi c'est dangereux :** l'authentification est le problème de sécurité le plus résolu — et le plus mal implémenté. Un JWT mal configuré n'a pas de révocation possible. Si l'attaquant vole un token, il a un accès permanent. Construire son propre système d'auth est la cause #1 des failles critiques.
24
+ **Faire plutôt :** OAuth2/OIDC via un provider éprouvé (Auth0, Clerk, NextAuth, Keycloak). Access token courte durée (15 min), refresh token longue durée (7j) avec rotation. Blacklist côté serveur pour les tokens révoqués.
25
+
26
+ ### Validation "plus tard"
27
+ **Ce qu'on voit :** les données arrivent dans le controller, passent dans le service, arrivent dans la DB sans validation. "Le frontend valide". "L'ORM échappe".
28
+ **Pourquoi c'est dangereux :** le frontend est sous le contrôle de l'attaquant. Un simple `curl` contourne toute validation frontend. L'ORM échappe le SQL mais ne valide pas le type, la longueur, le charset, le business logic. Sans validation à la frontière, la DB reçoit n'importe quoi.
29
+ **Faire plutôt :** validation à l'entrée de l'API (middleware/guard). Schéma (Zod, JSON Schema, Pydantic). Rejeter tout ce qui ne matche PAS le schéma — ne pas essayer de "corriger". Whitelist, pas blacklist.
30
+
31
+ ### Rate limiting absent
32
+ **Ce qu'on voit :** `POST /login` sans rate limiting. Un attaquant brute-force 10 000 mots de passe par seconde.
33
+ **Pourquoi c'est dangereux :** le brute-force est l'attaque la plus simple et la plus efficace. Sans rate limiting, un mot de passe faible tombe en minutes. Le rate limiting n'est pas une feature — c'est la seule défense contre l'énumération.
34
+ **Faire plutôt :** rate limiting sur /login (5 tentatives/min/IP + compte), /api (100 req/s par clé), /reset-password (1 tentative/min/email). Retourner 429 avec `Retry-After`. Bloquer (pas juste ralentir) après N échecs.
35
+
36
+ ## Patterns
37
+ ### Defense in depth
38
+ **Quand :** toute application manipulant des données sensibles.
39
+ **Comment :** WAF → Input validation → Auth → Authorization → SQL paramétré → Output encoding → CSP → Encryption at rest. Chaque couche suppose que les précédentes ont failli. Exemple : même avec du SQL paramétré, valider le type de l'input avant. Même avec HTTPS, marquer les cookies Secure.
40
+
41
+ ### Structured security review (OWASP Top 10)
42
+ **Quand :** à chaque release ou changement majeur.
43
+ **Comment :** passer en revue le Top 10 OWASP pour CHAQUE endpoint critique. Injection, Broken Auth, Sensitive Data Exposure, XXE, Broken Access Control, Security Misconfiguration, XSS, Insecure Deserialization, Vulnerable Components, Insufficient Logging. Pas un audit annuel — une habitude de release.
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: architecture
3
+ description: "Architecture Logicielle — monolithe modulaire, microservices, ports/adapters, ADR, Strangler Fig, trade-offs. A charger quand on definit la structure d'un projet."
4
+ ---
5
+
6
+ # Architecture Logicielle
7
+
8
+ **Principe premier :** L'architecture n'est pas une collection de patterns — c'est la gestion explicite des dependances. La qualite d'une architecture se mesure a une chose : combien de modules dois-je toucher pour faire un changement metier ? Si la reponse est > 3, l'architecture est cassee, peu importe le pattern utilise. Le bon pattern depend du contexte (taille d'equipe, frequence de changement, exigences de scale), pas de la mode.
9
+
10
+ ## Checklist
11
+ - [ ] Le choix d'architecture est justifie par le contexte et documente (ADR)
12
+ - [ ] Les dependances pointent vers le domaine — jamais l'inverse (Domain <> Infrastructure)
13
+ - [ ] Les modules sont nommes par capacite metier (billing, shipping), pas par couche technique (controllers, services, utils)
14
+ - [ ] Chaque module a une interface explicite (contrat) — pas de couplage par import direct interne
15
+ - [ ] Demarrer simple (monolithe modulaire) — extraire en service UNIQUEMENT quand le besoin est prouve
16
+ - [ ] Le diagramme de contexte (C4 niveau 1-2) existe et est visible des nouveaux
17
+
18
+ ## Trade-offs : les 3 architectures
19
+
20
+ ### Monolithe simple vs Monolithe modulaire vs Microservices
21
+
22
+ | | Monolithe simple | Monolithe modulaire | Microservices |
23
+ |--|-----------------|-------------------|--------------|
24
+ | **Structure** | 1 codebase, pas de frontieres internes | 1 codebase, modules separes par domaine (billing/, orders/) | N codebases independantes |
25
+ | **Deploiement** | 1 artefact | 1 artefact | N artefacts |
26
+ | **Avantages** | Simple, rapide a demarrer | Deploiement simple, frontieres claires, peut extraire en service plus tard | Scale independant, equipes autonomes, isolation de pannes |
27
+ | **Desavantages** | Devient vite un "big ball of mud" | Modules peuvent se coupler par import direct si pas discipline | Cout reseau, latence, serialisation, deploiements coordonnes |
28
+ | **Quand choisir** | POC, equipe 1-3, court-terme | Equipe 4-20, projet long-terme | > 5 equipes, besoin de scale independant |
29
+ | **Piege** | "On modularisera plus tard" → jamais fait | Modules deviennent des services deguises (imports croises) | Microservices sans equipes autonomes = pire que monolithe |
30
+
31
+ **Regle :** commencer monolithe modulaire. Extraire en microservice quand : (1) l'equipe est trop grande pour une codebase (> 20), OU (2) un module a besoin de scale independant, OU (3) un module a un cycle de release different.
32
+
33
+ ## Anti-patterns
34
+ ### Microservices comme defaut
35
+ **Ce qu'on voit :** 12 services, 12 repos, 12 pipelines — pour 3 devs et 100 utilisateurs. Un changement simple touche 4 repos.
36
+ **Pourquoi c'est dangereux :** les microservices deplacent la complexite du code vers le reseau. Chaque service ajoute latence, serialisation, gestion d'erreur reseau. Le seuil n'est pas technologique, il est organisationnel : une equipe par service.
37
+ **Faire plutot :** monolithe modulaire. Domaines separes en modules, interfaces explicites, meme codebase. Un commit = un changement. Extraire un service quand l'equipe grandit (> 20) ou qu'un module a besoin de scale independant.
38
+
39
+ ### Architecture en couches videe
40
+ **Ce qu'on voit :** Controller → Service → Repository. Le Service fait 3 lignes : `return this.repository.findById(id)`. Le domaine n'existe pas — c'est un tuyau HTTP→DB.
41
+ **Pourquoi c'est dangereux :** les regles metier sont eparpillees dans les controllers, validateurs, middlewares. Changer une regle oblige a traquer la logique dans 6 fichiers.
42
+ **Faire plutot :** le domaine contient les regles. `order.approve()` verifie le statut, le credit, la dispo. Le service orchestre, le repository persiste, le controller traduit HTTP. Chaque couche a une VRAIE responsabilite.
43
+
44
+ ### Architecture decidee puis figee
45
+ **Ce qu'on voit :** un diagramme dessine il y a 3 ans. L'archi reelle a diverge. Personne ne l'a documente.
46
+ **Pourquoi c'est dangereux :** l'architecture documentee est un mensonge. Les nouveaux devs prennent des decisions sur une base fausse. La derive architecturale s'accelere.
47
+ **Faire plutot :** ADR (Architecture Decision Records) pour les decisions importantes. Diagrammes regeneres (C4 via structurizr ou PlantUML). L'architecture est vivante.
48
+
49
+ ## Patterns
50
+ ### Monolithe modulaire
51
+ **Quand :** debut de projet, equipe < 20, pas de besoin de scale independant.
52
+ **Comment :** modules par domaine (billing/, shipping/, auth/). Chaque module a son propre schema DB logique. Communication inter-module par interfaces explicites.
53
+ - **Avantages :** deploy simple, refactoring facile (un commit), pas de latence reseau
54
+ - **Desavantages :** scale tout-ou-rien, un module peut bloquer le deploiement
55
+ - **Mise en place :** (1) Creer un dossier par domaine (`src/billing/`, `src/shipping/`). (2) Chaque module expose une interface publique (`index.ts` avec exports explicites). (3) Les imports entre modules passent UNIQUEMENT par l'interface publique. (4) Chaque module a ses propres migrations DB. (5) Tester les modules isolement. (6) Si un module devient trop gros → Strangler Fig pour l'extraire.
56
+
57
+ ### Ports & Adapters (Hexagonale)
58
+ **Quand :** le domaine metier doit survivre aux changements d'infrastructure.
59
+ **Comment :** le domaine definit des interfaces (ports : `OrderRepository`, `PaymentGateway`). Les adapters implementent ces interfaces (PostgresAdapter, StripeAdapter). Le domaine ne depend de rien d'externe.
60
+ - **Avantages :** changer de DB ou de payment provider sans toucher le domaine. Testable sans infra.
61
+ - **Desavantages :** couche d'abstraction supplementaire. Plus de fichiers.
62
+ - **Mise en place :** (1) Definir les ports dans le domaine. (2) Implementer les adapters dans un dossier `infrastructure/`. (3) Injecter les adapters au runtime (constructor injection). (4) Tester le domaine avec des adapters in-memory. (5) Tester les vrais adapters en integration.
63
+
64
+ ### Strangler Fig (migration progressive)
65
+ **Quand :** migration d'un legacy vers une nouvelle architecture sans big bang.
66
+ **Comment :** router le trafic progressivement. Nouvelle fonctionnalite → nouveau systeme. Ancienne migree → proxy vers nouveau, puis suppression.
67
+ - **Avantages :** chaque etape est deployable et rollbackable. Zero downtime.
68
+ - **Desavantages :** plus lent qu'un big bang. Cout de maintenance du proxy et des deux systemes en parallele.
69
+ - **Mise en place :** (1) Placer un proxy/API Gateway devant le legacy. (2) Creer le nouveau service avec un sous-ensemble de fonctionnalites. (3) Router par endpoint : `GET /orders` → nouveau, le reste → legacy. (4) Migrer les endpoints un par un, valider chaque migration. (5) Migrer les donnees progressivement (dual-write puis backfill). (6) Quand tout le trafic est sur le nouveau → supprimer le legacy. (7) Supprimer le proxy. Chaque etape = une PR deployable.
70
+
71
+ ### ADR (Architecture Decision Record)
72
+ **Quand :** toute decision architecturale non triviale.
73
+ **Comment :** document leger (1-2 pages) dans `docs/adrs/NNNN-title.md`. Format : Titre, Statut (proposed/accepted/deprecated), Contexte, Decision, Alternatives, Consequences.
74
+ - **Mise en place :** (1) Creer `docs/adrs/`. (2) Template ADR. (3) Chaque decision significative → un ADR. (4) Les ADR sont revus en PR comme du code. (5) Les ADR obsoletes sont marques `deprecated` (pas supprimes — l'historique a de la valeur). Un nouveau membre lit les ADR dans l'ordre pour comprendre l'histoire de l'architecture.
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: backend
3
+ description: "Backend — graceful degradation, connection pooling, idempotency, error handling as contract, health checks. À charger quand on crée ou modifie des services backend."
4
+ ---
5
+
6
+ # Backend
7
+
8
+ **Principe premier :** Le backend n'est pas "la partie qui parle à la base de données" — c'est un composant dans un système distribué qui doit survivre à la défaillance de tout ce qui l'entoure. La DB tombe, le réseau coupe, le client timeout. Un backend bien conçu ne crash pas — il dégrade, il retry, il informe. La métrique n'est pas "uptime" mais "MTTR" — chaque seconde entre la panne et la récupération est du temps utilisateur perdu.
9
+
10
+ ## Checklist
11
+ - [ ] Chaque endpoint a un timeout explicite — pas de requête pendante infinie
12
+ - [ ] Graceful shutdown : SIGTERM → stop accepter → drainer les requêtes (max 30s) → close connexions → exit
13
+ - [ ] Health check exposé : liveness (suis-je vivant ?) ≠ readiness (puis-je servir ?)
14
+ - [ ] Connection pooling sur DB, Redis, et clients HTTP — pas de connexion unique
15
+ - [ ] Les erreurs sont structurées : `{code, message, details}` — jamais de stack trace en prod
16
+ - [ ] Rate limiting en place sur les endpoints publics — pas de "on verra plus tard"
17
+
18
+ ## Anti-patterns
19
+ ### Avaler les erreurs
20
+ **Ce qu'on voit :** `try { await db.query() } catch (e) { console.log(e) }`. Pas de rethrow, pas de fallback. L'erreur est loguée et oubliée.
21
+ **Pourquoi c'est dangereux :** l'appelant reçoit "success" mais rien n'a été fait. Le système continue dans un état incohérent. Les erreurs avalées sont impossibles à debugger — tu ne sais jamais quelles opérations ont réellement échoué.
22
+ **Faire plutôt :** soit gérer l'erreur (retry, fallback, compensation), soit la laisser remonter à un error handler global qui la transforme en réponse structurée. Ne jamais avaler silencieusement.
23
+
24
+ ### Graceful shutdown = process.exit(0)
25
+ **Ce qu'on voit :** `process.on('SIGTERM', () => process.exit(0))` — les 50 requêtes en cours sont coupées net. Le load balancer envoie encore du trafic vers une instance zombie.
26
+ **Pourquoi c'est dangereux :** perte de données, transactions incomplètes, expérience utilisateur dégradée. Le load balancer détecte la panne 30 secondes plus tard — pendant ce temps, toutes les requêtes échouent.
27
+ **Faire plutôt :** SIGTERM → le load balancer retire l'instance (health check fail) → l'instance arrête d'accepter les nouvelles requêtes → attend la fin des requêtes en cours (timeout 30s max) → close les connexions DB/Redis → exit. Kubernetes donne 30s par défaut (terminationGracePeriodSeconds).
28
+
29
+ ### Une connexion DB pour tout le monde
30
+ **Ce qu'on voit :** `const db = new Database(DATABASE_URL)` — un singleton connexion pour toute l'application. 100 requêtes simultanées = 99 en file d'attente.
31
+ **Pourquoi c'est dangereux :** la connexion unique est le bottleneck. Les requêtes s'empilent, la latence explose. Sous charge, l'app devient non-réactive. Une seule requête lente bloque tout le monde.
32
+ **Faire plutôt :** connection pool. min/max configurés selon la charge attendue (min: 2, max: 20). Monitorer les métriques du pool : waiting, idle, active. Si `waiting > 0` régulièrement, augmenter le max ou optimiser les requêtes.
33
+
34
+ ## Patterns
35
+ ### Middleware chain
36
+ **Quand :** logique transversale (auth, logging, rate limiting, CORS).
37
+ **Comment :** chaque middleware fait UNE chose. Ordre canonique : CORS → rate limit → auth → validation → handler → error handler. La requête traverse la chaîne dans l'ordre, l'erreur remonte dans l'ordre inverse.
38
+
39
+ ### Idempotency token
40
+ **Quand :** opérations mutantes (paiement, création de ressource) où le double-submit est dangereux.
41
+ **Comment :** le client génère un `Idempotency-Key: uuid`. Le serveur stocke la clé + le résultat de l'opération dans une transaction. Si la clé est déjà vue → retourner le résultat stocké sans ré-exécuter.
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: backup-recovery
3
+ description: "Backup & Recovery — RPO/RTO, PITR, disaster recovery, multi-region, test de restore. A charger quand on configure les sauvegardes."
4
+ ---
5
+
6
+ # Backup & Recovery
7
+
8
+ **Principe premier :** Une sauvegarde n'est pas une copie de donnees — c'est une police d'assurance, et comme toute assurance, tu ne sais pas si elle marche tant que tu n'as pas fait de sinistre. La question n'est pas "est-ce qu'on a des backups ?" (oui, tout le monde en a) — c'est "a quelle date etait le dernier test de restore ?" Un backup jamais teste n'est pas un backup, c'est un vœu pieux. Les deux metriques qui definissent ta strategie sont le RPO (Recovery Point Objective : combien de donnees tu acceptes de perdre, en temps) et le RTO (Recovery Time Objective : combien de temps pour restaurer le service). Tout le reste — outils, frequence, retention — decoule de ces deux nombres.
9
+
10
+ ## Checklist
11
+ - [ ] RPO (perte de donnees max acceptable) et RTO (temps de restore max acceptable) sont definis et documentes
12
+ - [ ] Les backups sont automatises — pas de "je fais un pg_dump le vendredi soir"
13
+ - [ ] Le restore est teste regulierement (minimum trimestriel) — sans test, pas de backup
14
+ - [ ] Les backups sont stockes dans une region/separee differente de la production (pas dans le meme datacenter)
15
+ - [ ] La retention est definie : journaux 30j, mensuels 12 mois, annuels 7 ans (selon conformite)
16
+ - [ ] Les backups sont chiffres au repos et en transit — une fuite de backup = fuite de toutes les donnees
17
+ - [ ] Le processus de restore est documente et testable par n'importe quel membre de l'equipe
18
+
19
+ ## Anti-patterns
20
+ ### Backup = dump periodique
21
+ **Ce qu'on voit :** `pg_dump` tous les jours a 3h du matin. "On a une sauvegarde." RPO = 24h. Restore = manuel, non teste.
22
+ **Pourquoi c'est dangereux :** un pg_dump quotidien = tu perds jusqu'a 24h de donnees. Le restore prend des heures (charger un dump complet). Pas de PITR (point-in-time recovery) — si la corruption est arrivee a 14h, tu ne peux pas restaurer a 13h59, seulement a 3h du matin.
23
+ **Faire plutot :** WAL archiving continu (PostgreSQL) ou binlog (MySQL) → PITR possible a la seconde pres. Backups complets hebdomadaires + incrementaux quotidiens ou continus. Restore PITR teste automatiquement.
24
+
25
+ ### Backup dans la meme region
26
+ **Ce qu'on voit :** backups dans le meme S3 bucket, meme region, meme compte. "C'est plus simple a gerer."
27
+ **Pourquoi c'est dangereux :** la region tombe (panne AWS, coupure electrique, catastrophe naturelle) → tous les backups sont inaccessibles. Un attaquant compromet le compte → il supprime tout, backups inclus. Le backup co-localise n'est pas un backup — c'est une copie.
28
+ **Faire plutot :** backups cross-region minimum. Idealement cross-cloud pour les donnees critiques. Les backups sont dans un compte separe avec acces minimal. Immutable backups (Object Lock, WORM) : meme l'admin ne peut pas supprimer avant la retention.
29
+
30
+ ### "Le restore a marche en staging il y a 6 mois"
31
+ **Ce qu'on voit :** le test de restore a ete fait une fois, lors de la mise en place. Depuis, le schema a change, les volumes ont triple, l'equipe a tourne.
32
+ **Pourquoi c'est dangereux :** un restore est un processus complexe : restaurer la DB, verifier l'integrite, re-configurer les connexions, re-chauffer les caches, valider les donnees. Chaque changement dans le schema, les dependances, ou l'infrastructure peut casser le restore. Un restore qui echoue le jour du sinistre = pas de restore du tout.
33
+ **Faire plutot :** restore automatise hebdomadaire dans un environnement isole. Tests d'integrite automatiques apres restore. L'alerte part si le restore echoue. Le test de restore fait partie de la sante operationnelle, comme un health check.
34
+
35
+ ## Patterns
36
+ ### Strategie 3-2-1
37
+ **Quand :** toute strategie de backup.
38
+ **Comment :** 3 copies des donnees, sur 2 types de media differents, dont 1 copie hors site (offsite). Exemple : backup local (rapide a restaurer) + backup cloud (region A) + backup cloud (region B, immuable). Une panne ou corruption sur un seul media ne detruit pas tout.
39
+
40
+ ### Point-in-time recovery (PITR)
41
+ **Quand :** base de donnees relationnelle (PostgreSQL, MySQL, SQL Server).
42
+ **Comment :** WAL archiving continu vers un stockage objet. Backup complet hebdomadaire. Restore : charger le dernier backup complet → appliquer les WAL jusqu'au timestamp desire. RPO effectif = secondes (le delai de replication du WAL), pas heures.
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: caching
3
+ description: "Caching — cache-aside/write-through, cache stampede protection, TTL strategy, invalidation as the hard problem. À charger quand on parle de performance ou de mise en cache."
4
+ ---
5
+
6
+ # Caching
7
+
8
+ **Principe premier :** Il y a deux problèmes difficiles en informatique : nommer les choses, l'invalidation de cache, et les off-by-one. Le cache est un mensonge délibéré — tu sers une version potentiellement périmée de la donnée en échange de latence réduite. La seule question qui compte est : "quelle est la péremption acceptable pour CE cas d'usage ?" Si la réponse est 0ms, pas de cache. Si la réponse est "5 minutes, c'est acceptable", tu as un budget d'incohérence. Nommer ce budget explicitement est le design du cache.
9
+
10
+ ## Checklist
11
+ - [ ] La stratégie est choisie selon le pattern d'accès : cache-aside (read-heavy), write-through (read-after-write), write-behind (write-heavy)
12
+ - [ ] Chaque entrée de cache a un TTL explicite et justifié — jamais de cache infini
13
+ - [ ] La protection anti-stampede est en place — 1000 miss simultanés ne déclenchent pas 1000 requêtes DB
14
+ - [ ] Le cache est monitoré : hit rate, miss rate, eviction rate, mémoire utilisée
15
+ - [ ] L'invalidation est événementielle ou par TTL — jamais "pense à vider le cache" en commentaire
16
+
17
+ ## Anti-patterns
18
+ ### Cache infini
19
+ **Ce qu'on voit :** `cache.set('user:' + id, userData)` sans TTL. Le cache ne sera vidé que quand Redis sera plein et fera une éviction arbitraire.
20
+ **Pourquoi c'est dangereux :** l'incohérence grandit avec le temps. L'utilisateur change son email dans la DB, le cache sert l'ancien pendant des jours. Le bug est intermittent (parfois cache hit, parfois miss) — le pire type de bug à debugger.
21
+ **Faire plutôt :** toujours un TTL. Court pour les données dynamiques (1-5 min). Long pour le statique (1-24h). Le TTL est un compromis entre fraîcheur et performance — le choisir consciemment.
22
+
23
+ ### Cache stampede
24
+ **Ce qu'on voit :** une clé chaude expire. 1000 requêtes simultanées arrivent. Toutes font un cache miss → toutes interrogent la DB. La DB reçoit 1000× la même requête.
25
+ **Pourquoi c'est dangereux :** le stampede transforme un cache miss en attaque DDoS auto-infligée. La DB qui allait bien voit soudainement 1000× la charge normale. Pire : elle génère 1000× la même réponse, et 999 réponses sont jetées.
26
+ **Faire plutôt :** probabilistic early recomputation (recalculer avec une probabilité croissante quand le TTL approche). Ou lock distribué temporaire — un seul worker recalcule, les autres attendent le résultat (SETNX).
27
+
28
+ ### Invalidation commentée
29
+ **Ce qu'on voit :** `// PENSE À VIDER LE CACHE QUAND TU MODIFIES CETTE TABLE` — dans un commentaire. Qui n'est pas lu. Par un dev qui ne savait pas. Le cache et la DB divergent silencieusement.
30
+ **Pourquoi c'est dangereux :** l'invalidation manuelle est une machine à bugs intermittents. Chaque écriture est une opportunité d'oubli. Le bug n'apparaît que dans le cas "cache hit après écriture" — difficile à reproduire.
31
+ **Faire plutôt :** invalidation automatique. Événement DB → event bus → cache invalidation. Ou TTL assez court pour que l'incohérence maximale soit acceptable. Jamais de "penser à" dans la conception d'un système.
32
+
33
+ ## Patterns
34
+ ### Cache-aside
35
+ **Quand :** lecture dominante, tolérance à la stale data.
36
+ **Comment :** (1) lire le cache, (2) si hit → retourner, (3) si miss → lire la DB, (4) écrire dans le cache, (5) retourner. L'application est responsable de la cohérence. Simple, mais attention au stampede.
37
+
38
+ ### Write-through
39
+ **Quand :** les données écrites sont presque toujours relues immédiatement.
40
+ **Comment :** écrire dans le cache ET dans la DB dans la même opération. Le cache est toujours chaud pour les lectures récentes. Coût : chaque écriture touche le cache, même si personne ne relit.
41
+
42
+ ### Probabilistic early recomputation
43
+ **Quand :** protéger une clé chaude du stampede.
44
+ **Comment :** avant que le TTL n'expire, le worker vérifie si `random() < 1 / (TTL_remaining_seconds * request_rate)`. Si oui, il recalcule de manière anticipée et met à jour le cache. Statistiquement, un seul worker le fait.
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: cdn
3
+ description: "CDN & Edge — cache geographique, TTL strategies, origin shield, edge computing, cache invalidation. A charger quand on configure un CDN ou optimise la livraison de contenu."
4
+ ---
5
+
6
+ # CDN & Edge
7
+
8
+ **Principe premier :** Un CDN n'est pas un "cache rapide" — c'est un reseau de distribution qui rapproche les donnees de l'utilisateur. La latence n'est pas une question de bande passante, c'est une question de distance (lumiere dans la fibre = ~5ms pour 1000km). Un CDN reduit la distance en placant les donnees dans 200+ points de presence. Mais un CDN est aussi un cache — et tout cache peut servir des donnees stale. La question centrale n'est pas "est-ce que le CDN est rapide ?" mais "quelle fraicheur est acceptable pour quel contenu ?"
9
+
10
+ ## Checklist
11
+ - [ ] Les assets statiques sont servis via CDN (pas depuis le serveur d'origine) avec Cache-Control explicite
12
+ - [ ] Les headers de cache sont differencies par type de contenu : immutable pour versionne, revalidation pour dynamique
13
+ - [ ] L'origin shield est configure — pas de 50 POPs qui frappent l'origine simultanement
14
+ - [ ] L'invalidation est ciblee (chemins specifiques, pas `/*`) et monitorisee
15
+ - [ ] Le TTL est defini selon la fraicheur acceptable : html 5min, assets versionnes 1 an
16
+ - [ ] Les tokens/query strings prives ne cassent pas le cache (strip, normalize, ou ignore)
17
+ - [ ] Le CDN est devant l'application entiere, pas juste les assets (DDoS protection, SSL termination)
18
+
19
+ ## Anti-patterns
20
+ ### Tout en `max-age=0, no-cache`
21
+ **Ce qu'on voit :** l'equipe a ete brulee par du contenu stale. Solution : tout revalider a chaque requete.
22
+ **Pourquoi c'est dangereux :** chaque requete frappe l'origine. Le CDN devient un proxy transparent inutile (cout + latence sans benefice). Le serveur d'origine encaisse 100% du trafic. Le CDN coute de l'argent pour rien.
23
+ **Faire plutot :** differencier par type de contenu. Assets versionnes → `max-age=31536000, immutable`. Pages HTML → `max-age=300, stale-while-revalidate=600`. API responses → `max-age=0, private` (pas de cache CDN pour les donnees privees).
24
+
25
+ ### Cache invalidation = `/*`
26
+ **Ce qu'on voit :** un deployement → invalidation de tout le cache (`/*`). 50000 requetes simultanees vers l'origine.
27
+ **Pourquoi c'est dangereux :** l'invalidation complete cree un "cache stampede" sur l'origine. Le serveur d'origine n'est pas dimensionne pour le trafic total. Chaque deployement = risque d'outage.
28
+ **Faire plutot :** invalider uniquement les chemins modifies. Utiliser des noms de fichiers versionnes (`main.a3f2b1c.js`) → jamais besoin d'invalider. Pour les SPA : invalider `index.html` seulement, le reste est immutable.
29
+
30
+ ### CDN = juste pour les images
31
+ **Ce qu'on voit :** seuls les assets statiques sont sur le CDN. L'API et les pages HTML passent directement au serveur.
32
+ **Pourquoi c'est dangereux :** le CDN offre la terminaison SSL, la protection DDoS, le WAF, l'optimisation d'images, le edge computing. Le mettre uniquement devant `/static/` gaspille sa capacite principale : absorber le trafic malveillant avant qu'il n'atteigne l'origine.
33
+ **Faire plutot :** CDN devant tout le domaine. L'origine est cachee derriere le CDN, pas exposee publiquement. Les regles de cache decident ce qui est servi depuis le edge vs l'origine.
34
+
35
+ ## Patterns
36
+ ### Cache hierarchies (origin shield)
37
+ **Quand :** trafic global avec beaucoup de POPs (200+).
38
+ **Comment :** un POP regional intermediaire (origin shield) consolide les requetes vers l'origine. Au lieu de 200 POPs qui frappent l'origine sur un cache miss, seul l'origin shield la contacte. Reduction de la charge origine de 100-200x.
39
+
40
+ ### Stale-while-revalidate
41
+ **Quand :** contenu qui peut etre legerement stales (pages HTML, reponses API publiques).
42
+ **Comment :** `Cache-Control: max-age=300, stale-while-revalidate=600`. Le CDN sert le contenu stales jusqu'a 15 minutes pendant qu'il revalide en arriere-plan. L'utilisateur ne voit jamais la latence de revalidation. Ideal pour les pages qui changent peu.
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: chaos
3
+ description: "Chaos Engineering — injection de pannes, Game Day, Chaos Monkey, experimentation, hypotheses de resilience. A charger quand on teste la resilience d'un systeme."
4
+ ---
5
+
6
+ # Chaos Engineering
7
+
8
+ **Principe premier :** Le chaos engineering n'est pas "casser des choses en production pour voir ce qui se passe" — c'est une discipline scientifique appliquee aux systemes distribues. Tu formules une hypothese de resilience ("si le service B tombe, le fallback degrade le mode"), tu injectes la panne de maniere controlee, et tu compares le comportement observe a l'hypothese. La valeur n'est pas dans le chaos — elle est dans la decouverte des comportements emergents que personne n'avait prevus. Un systeme sans chaos engineering n'est pas stable — il est non teste. La stabilite reelle se mesure en production, pas en staging.
9
+
10
+ ## Checklist
11
+ - [ ] Une hypothese de resilience est formulee avant chaque experience (pas "on va eteindre cette DB et voir")
12
+ - [ ] Le blast radius est controle : un petit pourcentage de trafic, un seul AZ/service
13
+ - [ ] L'experience a un arret d'urgence (kill switch) actionnable en < 10 secondes
14
+ - [ ] Les metriques sont en place AVANT l'experience (baseline + deviation en temps reel)
15
+ - [ ] Le Game Day est planifie avec un scenario et un runbook
16
+ - [ ] Les decouvertes sont documentees et transforment le systeme (pas "c'etait interessant, on fera mieux")
17
+
18
+ ## Anti-patterns
19
+ ### Chaos en production sans filet
20
+ **Ce qu'on voit :** "on va tester en production vendredi soir." Pas d'hypothese, pas de kill switch, pas de monitoring.
21
+ **Pourquoi c'est dangereux :** le chaos sans controle n'est pas une experience — c'est un incident provoque. Sans hypothese, tu ne sais pas si le comportement est normal ou anormal. Sans kill switch, tu ne peux pas arreter l'hemorragie.
22
+ **Faire plutot :** commencer en staging avec des pannes simples (kill un process, saturer un disque). Monter en puissance progressivement. En production : commencer par 1% de trafic, puis 5%, puis 10%. Toujours avec un kill switch.
23
+
24
+ ### Chaos = Chaos Monkey uniquement
25
+ **Ce qu'on voit :** l'equipe installe Chaos Monkey, kill des instances au hasard, et considere que le chaos engineering est fait.
26
+ **Pourquoi c'est dangereux :** Chaos Monkey teste UNE chose : que ton application survit a la mort d'une instance. Ca ne teste pas la latence reseau, la corruption de donnees, la saturation disque, les pannes DNS, les timeouts de circuit breaker. Le chaos engineering est une discipline large — Chaos Monkey en est un tout petit sous-ensemble.
27
+ **Faire plutot :** varier les injections : latence reseau, perte de paquets, defaillance DNS, saturation CPU/disque, coupure de dependance, corruption de reponse, expiration de certificat. Chaque type de panne revele une classe de vulnerabilites differente.
28
+
29
+ ### Pas de suivi des decouvertes
30
+ **Ce qu'on voit :** le Game Day est fun. Les decouvertes sont notees sur un post-it. Rien n'est corrige.
31
+ **Pourquoi c'est dangereux :** le chaos engineering sans correction est du theatre. Les memes vulnerabilites survivent au Game Day suivant. L'equipe apprend mais le systeme n'apprend pas.
32
+ **Faire plutot :** chaque decouverte = un ticket. Prioriser les corrections avant le prochain Game Day. Re-tester les memes pannes pour verifier que la correction fonctionne. Le chaos engineering est une boucle : injecter → mesurer → corriger → re-tester.
33
+
34
+ ## Patterns
35
+ ### Game Day
36
+ **Quand :** equipe qui n'a jamais teste son systeme en conditions de panne.
37
+ **Comment :** 2h-4h planifiees. 1 scenario defini a l'avance ("la DB primaire est inaccessible"). Roles : un orchestrateur, un observateur, un intervenant. Monitoring temps reel. Debrief immediat apres : qu'est-ce qui a casse ? qu'est-ce qui a tenu ? qu'est-ce qu'on corrige ?
38
+
39
+ ### Steady-state hypothesis
40
+ **Quand :** toute experience de chaos.
41
+ **Comment :** definir l'etat normal AVANT l'injection ("P95 latence < 500ms, taux d'erreur < 1%, pas d'alerte critique"). Injecter la panne. Comparer a l'etat normal. Si l'ecart est inattendu → vulnerabilite. Cette methode donne une definition objective de "le systeme a tenu".
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: cicd-pipeline
3
+ description: "CI/CD — feedback loops, DORA metrics, trunk-based dev, pipeline as constraint theory, matrix builds, OIDC, ephemeral runners. À charger quand on conçoit ou optimise un pipeline CI/CD."
4
+ ---
5
+
6
+ # CI/CD Pipeline
7
+
8
+ **Principe premier :** La CI/CD n'est pas "automatiser les builds". C'est réduire le temps entre un commit et le feedback de production. Chaque minute perdue entre "j'écris" et "je sais si ça marche" est du gaspillage. Les 4 métriques DORA (Lead Time, Deploy Frequency, MTTR, Change Failure Rate) mesurent cette performance. Tout le reste — caching, parallel builds, OIDC — est un moyen, pas une fin.
9
+
10
+ ## Checklist
11
+ - [ ] La pipeline donne du feedback en < 5 min (sinon les devs arrêtent de l'attendre)
12
+ - [ ] Le trunk-based development est la norme — branches ≤ 1 jour, pas de long-lived branches
13
+ - [ ] Les 4 DORA metrics sont mesurées et visibles (dashboard, pas dans un coin)
14
+ - [ ] Les secrets utilisent OIDC — zéro credential long-lived
15
+ - [ ] Les runners sont éphémères — rien ne survit entre deux builds
16
+ - [ ] Concurrency groups — pas deux pipelines en parallèle sur la même branche
17
+ - [ ] Le pipeline bloque sur flaky test detection (> 2% de flaky rate = quarantaine automatique)
18
+ - [ ] L'artefact de build est immutable et signé (hash + signature vérifiés au déploiement)
19
+
20
+ ## Anti-patterns
21
+ ### Branches longue durée
22
+ **Ce qu'on voit :** un dev travaille 2 semaines sur `feature/big-refactor`. Merge conflict de 200 fichiers. Tests jamais lancés ensemble.
23
+ **Pourquoi c'est dangereux :** le "I" de CI, c'est l'intégration. Si le code n'est pas intégré au trunk au moins 1×/jour, ce n'est pas de la CI. Le merge final est un événement traumatique — les bugs apparaissent tous en même temps, impossible de bisecter proprement.
24
+ **Faire plutôt :** trunk-based development. Branches ≤ 1 jour. Feature flags pour cacher le code incomplet. Petits commits fréquents — le diff est la meilleure défense contre les bugs.
25
+
26
+ ### Pipeline vu comme un checklist et non une contrainte
27
+ **Ce qu'on voit :** lint → test → build → deploy, séquentiel. Le pipeline met 20 min et personne ne se demande pourquoi c'est lent.
28
+ **Pourquoi c'est dangereux :** un pipeline lent n'est pas juste chiant — il tue la boucle de feedback. Les devs ne poussent plus, ils accumulent, les PRs grossissent, la CI devient un bottleneck systémique. C'est la théorie des contraintes : le pipeline EST la contrainte.
29
+ **Faire plutôt :** traiter le pipeline comme un système à optimiser. Paralléliser tout ce qui peut l'être. Investir dans le cache. Splitter les tests lents. CI < 5 min — si c'est pas possible, c'est que l'architecture de test a un problème.
30
+
31
+ ### Pipeline non versionné
32
+ **Ce qu'on voit :** le pipeline est configuré dans l'UI GitHub Actions, pas dans `.github/workflows/`. Ou pire : un Jenkins configuré à la main.
33
+ **Pourquoi c'est dangereux :** le pipeline n'est pas reproductible. Si le runner crashe, personne ne sait le reconstruire. Pas de code review sur les changements de pipeline. Le pipeline devient un snowflake.
34
+ **Faire plutôt :** pipeline as code — dans le repo, revu comme du code. Tout changement de pipeline passe par une PR. Le pipeline se teste lui-même (les changements de CI s'exécutent sur la PR qui les propose).
35
+
36
+ ### Flaky tests ignorés
37
+ **Ce qu'on voit :** "ah ce test faille parfois, relance le job". Le pipeline a un taux de succès de 70% et tout le monde rerun jusqu'à ce que ça passe.
38
+ **Pourquoi c'est dangereux :** un test flaky tue la confiance dans le pipeline. Quand le rouge ne veut plus dire "bug", les vrais bugs passent au travers. Les devs développent une tolérance à l'échec — c'est la mort lente de la CI.
39
+ **Faire plutôt :** quarantaine automatique. Un test qui faille > 2% du temps est isolé dans une suite "quarantaine". Le pipeline principal bloque sur vrai rouge. La quarantaine est traitée comme dette technique prioritaire.
40
+
41
+ ## Patterns
42
+ ### OIDC
43
+ **Quand :** tout pipeline qui parle à un cloud provider.
44
+ **Comment :** GitHub Actions → OIDC token → AWS IAM / GCP WIF → credentials temporaires (< 1h). Zéro secret stocké. Rotation automatique. Si le token fuit, il expire avant d'être utilisable.
45
+
46
+ ### Matrix build
47
+ **Quand :** bibliothèque ou outil utilisé sur plusieurs versions/OS.
48
+ **Comment :** `matrix: { node: [18, 20, 22], os: [ubuntu, macos] }`. Chaque combinaison est un job indépendant. Pas de "ça marche sur ma machine" quand la CI couvre 3 OS.
49
+
50
+ ### Concurrency groups
51
+ **Quand :** éviter les interférences entre runs.
52
+ **Comment :** `concurrency: { group: deploy-${{ github.ref }}, cancel-in-progress: true }`. Un seul déploiement à la fois par branche. Le nouveau run annule le précédent. Évite les race conditions de déploiement.
53
+
54
+ ### Flaky test quarantine
55
+ **Quand :** suite de tests avec > 100 tests.
56
+ **Comment :** chaque test a un compteur de flaky (fail suivi de pass sans changement de code). Si > 2% sur 100 runs → déplacé en `quarantine/`. Le pipeline principal ignore cette suite. La quarantaine est revue chaque sprint — chaque test est soit fixé, soit réécrit, soit supprimé.
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: ciel
3
+ description: Ciel v9 — thin shell. Understand before generating. Verify before claiming done.
4
+ ---
5
+
6
+ # Ciel v9
7
+
8
+ **Suis les instructions dans CLAUDE.md.** Ce skill ne duplique pas ce qui y est deja.
9
+
10
+ ## Specifique a l'invocation /ciel
11
+ - **Skills domaine** — evalue le contexte, invoque tous les skills pertinents avec `Skill()`. C'est la meme instruction que CLAUDE.md, rappelee ici.
12
+ - **VISIBILITE** — le pipeline est ta checklist mentale, pas un journal public. Pas de tableaux d'etapes, pas de "[CIEL]", pas de "DOCS termine". Sortie visible = resultats, pas la machinerie.
13
+ - **META** — a la fin de la tache, les 3 questions META (stop hook). Si la reponse a "qu'ai-je manque" est une vraie question pour l'utilisateur → pose-la. Si c'est une action logique → fais-la sans demander.
14
+ - **Memoire** — si une decouverte merite d'etre sauvegardee, ecris dans `.ciel/memory/` et rebuild l'index. Ne pas juste dire "je devrais sauvegarder" — sauvegarde.