@booklib/core 2.0.0

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 (374) hide show
  1. package/.cursor/rules/booklib-standards.mdc +40 -0
  2. package/.gemini/context.md +372 -0
  3. package/AGENTS.md +166 -0
  4. package/CHANGELOG.md +226 -0
  5. package/CLAUDE.md +81 -0
  6. package/CODE_OF_CONDUCT.md +31 -0
  7. package/CONTRIBUTING.md +304 -0
  8. package/LICENSE +21 -0
  9. package/PLAN.md +28 -0
  10. package/README.ja.md +198 -0
  11. package/README.ko.md +198 -0
  12. package/README.md +503 -0
  13. package/README.pt-BR.md +198 -0
  14. package/README.uk.md +241 -0
  15. package/README.zh-CN.md +198 -0
  16. package/SECURITY.md +9 -0
  17. package/agents/architecture-reviewer.md +136 -0
  18. package/agents/booklib-reviewer.md +90 -0
  19. package/agents/data-reviewer.md +107 -0
  20. package/agents/jvm-reviewer.md +146 -0
  21. package/agents/python-reviewer.md +128 -0
  22. package/agents/rust-reviewer.md +115 -0
  23. package/agents/ts-reviewer.md +110 -0
  24. package/agents/ui-reviewer.md +117 -0
  25. package/assets/logo.svg +36 -0
  26. package/bin/booklib-mcp.js +304 -0
  27. package/bin/booklib.js +1705 -0
  28. package/bin/skills.cjs +1292 -0
  29. package/booklib-router.mdc +36 -0
  30. package/booklib.config.json +19 -0
  31. package/commands/animation-at-work.md +10 -0
  32. package/commands/clean-code-reviewer.md +10 -0
  33. package/commands/data-intensive-patterns.md +10 -0
  34. package/commands/data-pipelines.md +10 -0
  35. package/commands/design-patterns.md +10 -0
  36. package/commands/domain-driven-design.md +10 -0
  37. package/commands/effective-java.md +10 -0
  38. package/commands/effective-kotlin.md +10 -0
  39. package/commands/effective-python.md +10 -0
  40. package/commands/effective-typescript.md +10 -0
  41. package/commands/kotlin-in-action.md +10 -0
  42. package/commands/lean-startup.md +10 -0
  43. package/commands/microservices-patterns.md +10 -0
  44. package/commands/programming-with-rust.md +10 -0
  45. package/commands/refactoring-ui.md +10 -0
  46. package/commands/rust-in-action.md +10 -0
  47. package/commands/skill-router.md +10 -0
  48. package/commands/spring-boot-in-action.md +10 -0
  49. package/commands/storytelling-with-data.md +10 -0
  50. package/commands/system-design-interview.md +10 -0
  51. package/commands/using-asyncio-python.md +10 -0
  52. package/commands/web-scraping-python.md +10 -0
  53. package/community/registry.json +1616 -0
  54. package/hooks/hooks.json +23 -0
  55. package/hooks/posttooluse-capture.mjs +67 -0
  56. package/hooks/suggest.js +153 -0
  57. package/lib/agent-behaviors.js +40 -0
  58. package/lib/agent-detector.js +96 -0
  59. package/lib/config-loader.js +39 -0
  60. package/lib/conflict-resolver.js +148 -0
  61. package/lib/context-builder.js +574 -0
  62. package/lib/discovery-engine.js +298 -0
  63. package/lib/doctor/hook-installer.js +83 -0
  64. package/lib/doctor/usage-tracker.js +87 -0
  65. package/lib/engine/ai-features.js +253 -0
  66. package/lib/engine/auditor.js +103 -0
  67. package/lib/engine/bm25-index.js +178 -0
  68. package/lib/engine/capture.js +120 -0
  69. package/lib/engine/corrections.js +198 -0
  70. package/lib/engine/doctor.js +195 -0
  71. package/lib/engine/graph-injector.js +137 -0
  72. package/lib/engine/graph.js +161 -0
  73. package/lib/engine/handoff.js +405 -0
  74. package/lib/engine/indexer.js +242 -0
  75. package/lib/engine/parser.js +53 -0
  76. package/lib/engine/query-expander.js +42 -0
  77. package/lib/engine/reranker.js +40 -0
  78. package/lib/engine/rrf.js +59 -0
  79. package/lib/engine/scanner.js +151 -0
  80. package/lib/engine/searcher.js +139 -0
  81. package/lib/engine/session-coordinator.js +306 -0
  82. package/lib/engine/session-manager.js +429 -0
  83. package/lib/engine/synthesizer.js +70 -0
  84. package/lib/installer.js +70 -0
  85. package/lib/instinct-block.js +33 -0
  86. package/lib/mcp-config-writer.js +88 -0
  87. package/lib/paths.js +57 -0
  88. package/lib/profiles/design.md +19 -0
  89. package/lib/profiles/general.md +16 -0
  90. package/lib/profiles/research-analysis.md +22 -0
  91. package/lib/profiles/software-development.md +23 -0
  92. package/lib/profiles/writing-content.md +19 -0
  93. package/lib/project-initializer.js +916 -0
  94. package/lib/registry/skills.js +102 -0
  95. package/lib/registry-searcher.js +99 -0
  96. package/lib/rules/rules-manager.js +169 -0
  97. package/lib/skill-fetcher.js +333 -0
  98. package/lib/well-known-builder.js +70 -0
  99. package/lib/wizard/index.js +404 -0
  100. package/lib/wizard/integration-detector.js +41 -0
  101. package/lib/wizard/project-detector.js +100 -0
  102. package/lib/wizard/prompt.js +156 -0
  103. package/lib/wizard/registry-embeddings.js +107 -0
  104. package/lib/wizard/skill-recommender.js +69 -0
  105. package/llms-full.txt +254 -0
  106. package/llms.txt +70 -0
  107. package/package.json +45 -0
  108. package/research-reports/2026-04-01-current-architecture.md +160 -0
  109. package/research-reports/IDEAS.md +93 -0
  110. package/rules/common/clean-code.md +42 -0
  111. package/rules/java/effective-java.md +42 -0
  112. package/rules/kotlin/effective-kotlin.md +37 -0
  113. package/rules/python/effective-python.md +38 -0
  114. package/rules/rust/rust.md +37 -0
  115. package/rules/typescript/effective-typescript.md +42 -0
  116. package/scripts/gen-llms-full.mjs +36 -0
  117. package/scripts/gen-og.mjs +142 -0
  118. package/scripts/validate-frontmatter.js +25 -0
  119. package/skills/animation-at-work/SKILL.md +270 -0
  120. package/skills/animation-at-work/assets/example_asset.txt +1 -0
  121. package/skills/animation-at-work/evals/evals.json +44 -0
  122. package/skills/animation-at-work/evals/results.json +13 -0
  123. package/skills/animation-at-work/examples/after.md +64 -0
  124. package/skills/animation-at-work/examples/before.md +35 -0
  125. package/skills/animation-at-work/references/api_reference.md +369 -0
  126. package/skills/animation-at-work/references/review-checklist.md +79 -0
  127. package/skills/animation-at-work/scripts/audit_animations.py +295 -0
  128. package/skills/animation-at-work/scripts/example.py +1 -0
  129. package/skills/clean-code-reviewer/SKILL.md +444 -0
  130. package/skills/clean-code-reviewer/audit.json +35 -0
  131. package/skills/clean-code-reviewer/evals/evals.json +185 -0
  132. package/skills/clean-code-reviewer/evals/results.json +13 -0
  133. package/skills/clean-code-reviewer/examples/after.md +48 -0
  134. package/skills/clean-code-reviewer/examples/before.md +33 -0
  135. package/skills/clean-code-reviewer/references/api_reference.md +158 -0
  136. package/skills/clean-code-reviewer/references/practices-catalog.md +282 -0
  137. package/skills/clean-code-reviewer/references/review-checklist.md +254 -0
  138. package/skills/clean-code-reviewer/scripts/pre-review.py +206 -0
  139. package/skills/data-intensive-patterns/SKILL.md +267 -0
  140. package/skills/data-intensive-patterns/assets/example_asset.txt +1 -0
  141. package/skills/data-intensive-patterns/evals/evals.json +54 -0
  142. package/skills/data-intensive-patterns/evals/results.json +13 -0
  143. package/skills/data-intensive-patterns/examples/after.md +61 -0
  144. package/skills/data-intensive-patterns/examples/before.md +38 -0
  145. package/skills/data-intensive-patterns/references/api_reference.md +34 -0
  146. package/skills/data-intensive-patterns/references/patterns-catalog.md +551 -0
  147. package/skills/data-intensive-patterns/references/review-checklist.md +193 -0
  148. package/skills/data-intensive-patterns/scripts/adr.py +213 -0
  149. package/skills/data-intensive-patterns/scripts/example.py +1 -0
  150. package/skills/data-pipelines/SKILL.md +259 -0
  151. package/skills/data-pipelines/assets/example_asset.txt +1 -0
  152. package/skills/data-pipelines/evals/evals.json +45 -0
  153. package/skills/data-pipelines/evals/results.json +13 -0
  154. package/skills/data-pipelines/examples/after.md +97 -0
  155. package/skills/data-pipelines/examples/before.md +37 -0
  156. package/skills/data-pipelines/references/api_reference.md +301 -0
  157. package/skills/data-pipelines/references/review-checklist.md +181 -0
  158. package/skills/data-pipelines/scripts/example.py +1 -0
  159. package/skills/data-pipelines/scripts/new_pipeline.py +444 -0
  160. package/skills/design-patterns/SKILL.md +271 -0
  161. package/skills/design-patterns/assets/example_asset.txt +1 -0
  162. package/skills/design-patterns/evals/evals.json +46 -0
  163. package/skills/design-patterns/evals/results.json +13 -0
  164. package/skills/design-patterns/examples/after.md +52 -0
  165. package/skills/design-patterns/examples/before.md +29 -0
  166. package/skills/design-patterns/references/api_reference.md +1 -0
  167. package/skills/design-patterns/references/patterns-catalog.md +726 -0
  168. package/skills/design-patterns/references/review-checklist.md +173 -0
  169. package/skills/design-patterns/scripts/example.py +1 -0
  170. package/skills/design-patterns/scripts/scaffold.py +807 -0
  171. package/skills/domain-driven-design/SKILL.md +142 -0
  172. package/skills/domain-driven-design/assets/example_asset.txt +1 -0
  173. package/skills/domain-driven-design/evals/evals.json +48 -0
  174. package/skills/domain-driven-design/evals/results.json +13 -0
  175. package/skills/domain-driven-design/examples/after.md +80 -0
  176. package/skills/domain-driven-design/examples/before.md +43 -0
  177. package/skills/domain-driven-design/references/api_reference.md +1 -0
  178. package/skills/domain-driven-design/references/patterns-catalog.md +545 -0
  179. package/skills/domain-driven-design/references/review-checklist.md +158 -0
  180. package/skills/domain-driven-design/scripts/example.py +1 -0
  181. package/skills/domain-driven-design/scripts/scaffold.py +421 -0
  182. package/skills/effective-java/SKILL.md +227 -0
  183. package/skills/effective-java/assets/example_asset.txt +1 -0
  184. package/skills/effective-java/evals/evals.json +46 -0
  185. package/skills/effective-java/evals/results.json +13 -0
  186. package/skills/effective-java/examples/after.md +83 -0
  187. package/skills/effective-java/examples/before.md +37 -0
  188. package/skills/effective-java/references/api_reference.md +1 -0
  189. package/skills/effective-java/references/items-catalog.md +955 -0
  190. package/skills/effective-java/references/review-checklist.md +216 -0
  191. package/skills/effective-java/scripts/checkstyle_setup.py +211 -0
  192. package/skills/effective-java/scripts/example.py +1 -0
  193. package/skills/effective-kotlin/SKILL.md +271 -0
  194. package/skills/effective-kotlin/assets/example_asset.txt +1 -0
  195. package/skills/effective-kotlin/audit.json +29 -0
  196. package/skills/effective-kotlin/evals/evals.json +45 -0
  197. package/skills/effective-kotlin/evals/results.json +13 -0
  198. package/skills/effective-kotlin/examples/after.md +36 -0
  199. package/skills/effective-kotlin/examples/before.md +38 -0
  200. package/skills/effective-kotlin/references/api_reference.md +1 -0
  201. package/skills/effective-kotlin/references/practices-catalog.md +1228 -0
  202. package/skills/effective-kotlin/references/review-checklist.md +126 -0
  203. package/skills/effective-kotlin/scripts/example.py +1 -0
  204. package/skills/effective-python/SKILL.md +441 -0
  205. package/skills/effective-python/evals/evals.json +44 -0
  206. package/skills/effective-python/evals/results.json +13 -0
  207. package/skills/effective-python/examples/after.md +56 -0
  208. package/skills/effective-python/examples/before.md +40 -0
  209. package/skills/effective-python/ref-01-pythonic-thinking.md +202 -0
  210. package/skills/effective-python/ref-02-lists-and-dicts.md +146 -0
  211. package/skills/effective-python/ref-03-functions.md +186 -0
  212. package/skills/effective-python/ref-04-comprehensions-generators.md +211 -0
  213. package/skills/effective-python/ref-05-classes-interfaces.md +188 -0
  214. package/skills/effective-python/ref-06-metaclasses-attributes.md +209 -0
  215. package/skills/effective-python/ref-07-concurrency.md +213 -0
  216. package/skills/effective-python/ref-08-robustness-performance.md +248 -0
  217. package/skills/effective-python/ref-09-testing-debugging.md +253 -0
  218. package/skills/effective-python/ref-10-collaboration.md +175 -0
  219. package/skills/effective-python/references/api_reference.md +218 -0
  220. package/skills/effective-python/references/practices-catalog.md +483 -0
  221. package/skills/effective-python/references/review-checklist.md +190 -0
  222. package/skills/effective-python/scripts/lint.py +173 -0
  223. package/skills/effective-typescript/SKILL.md +262 -0
  224. package/skills/effective-typescript/audit.json +29 -0
  225. package/skills/effective-typescript/evals/evals.json +37 -0
  226. package/skills/effective-typescript/evals/results.json +13 -0
  227. package/skills/effective-typescript/examples/after.md +70 -0
  228. package/skills/effective-typescript/examples/before.md +47 -0
  229. package/skills/effective-typescript/references/api_reference.md +118 -0
  230. package/skills/effective-typescript/references/practices-catalog.md +371 -0
  231. package/skills/effective-typescript/scripts/review.py +169 -0
  232. package/skills/kotlin-in-action/SKILL.md +261 -0
  233. package/skills/kotlin-in-action/assets/example_asset.txt +1 -0
  234. package/skills/kotlin-in-action/evals/evals.json +43 -0
  235. package/skills/kotlin-in-action/evals/results.json +13 -0
  236. package/skills/kotlin-in-action/examples/after.md +53 -0
  237. package/skills/kotlin-in-action/examples/before.md +39 -0
  238. package/skills/kotlin-in-action/references/api_reference.md +1 -0
  239. package/skills/kotlin-in-action/references/practices-catalog.md +436 -0
  240. package/skills/kotlin-in-action/references/review-checklist.md +204 -0
  241. package/skills/kotlin-in-action/scripts/example.py +1 -0
  242. package/skills/kotlin-in-action/scripts/setup_detekt.py +224 -0
  243. package/skills/lean-startup/SKILL.md +160 -0
  244. package/skills/lean-startup/assets/example_asset.txt +1 -0
  245. package/skills/lean-startup/evals/evals.json +43 -0
  246. package/skills/lean-startup/evals/results.json +13 -0
  247. package/skills/lean-startup/examples/after.md +80 -0
  248. package/skills/lean-startup/examples/before.md +34 -0
  249. package/skills/lean-startup/references/api_reference.md +319 -0
  250. package/skills/lean-startup/references/review-checklist.md +137 -0
  251. package/skills/lean-startup/scripts/example.py +1 -0
  252. package/skills/lean-startup/scripts/new_experiment.py +286 -0
  253. package/skills/microservices-patterns/SKILL.md +384 -0
  254. package/skills/microservices-patterns/evals/evals.json +45 -0
  255. package/skills/microservices-patterns/evals/results.json +13 -0
  256. package/skills/microservices-patterns/examples/after.md +69 -0
  257. package/skills/microservices-patterns/examples/before.md +40 -0
  258. package/skills/microservices-patterns/references/patterns-catalog.md +391 -0
  259. package/skills/microservices-patterns/references/review-checklist.md +169 -0
  260. package/skills/microservices-patterns/scripts/new_service.py +583 -0
  261. package/skills/programming-with-rust/SKILL.md +209 -0
  262. package/skills/programming-with-rust/evals/evals.json +37 -0
  263. package/skills/programming-with-rust/evals/results.json +13 -0
  264. package/skills/programming-with-rust/examples/after.md +107 -0
  265. package/skills/programming-with-rust/examples/before.md +59 -0
  266. package/skills/programming-with-rust/references/api_reference.md +152 -0
  267. package/skills/programming-with-rust/references/practices-catalog.md +335 -0
  268. package/skills/programming-with-rust/scripts/review.py +142 -0
  269. package/skills/refactoring-ui/SKILL.md +362 -0
  270. package/skills/refactoring-ui/assets/example_asset.txt +1 -0
  271. package/skills/refactoring-ui/evals/evals.json +45 -0
  272. package/skills/refactoring-ui/evals/results.json +13 -0
  273. package/skills/refactoring-ui/examples/after.md +85 -0
  274. package/skills/refactoring-ui/examples/before.md +58 -0
  275. package/skills/refactoring-ui/references/api_reference.md +355 -0
  276. package/skills/refactoring-ui/references/review-checklist.md +114 -0
  277. package/skills/refactoring-ui/scripts/audit_css.py +250 -0
  278. package/skills/refactoring-ui/scripts/example.py +1 -0
  279. package/skills/rust-in-action/SKILL.md +350 -0
  280. package/skills/rust-in-action/evals/evals.json +38 -0
  281. package/skills/rust-in-action/evals/results.json +13 -0
  282. package/skills/rust-in-action/examples/after.md +156 -0
  283. package/skills/rust-in-action/examples/before.md +56 -0
  284. package/skills/rust-in-action/references/practices-catalog.md +346 -0
  285. package/skills/rust-in-action/scripts/review.py +147 -0
  286. package/skills/skill-router/SKILL.md +186 -0
  287. package/skills/skill-router/evals/evals.json +38 -0
  288. package/skills/skill-router/evals/results.json +13 -0
  289. package/skills/skill-router/examples/after.md +63 -0
  290. package/skills/skill-router/examples/before.md +39 -0
  291. package/skills/skill-router/references/api_reference.md +24 -0
  292. package/skills/skill-router/references/routing-heuristics.md +89 -0
  293. package/skills/skill-router/references/skill-catalog.md +174 -0
  294. package/skills/skill-router/scripts/route.py +266 -0
  295. package/skills/spring-boot-in-action/SKILL.md +340 -0
  296. package/skills/spring-boot-in-action/evals/evals.json +39 -0
  297. package/skills/spring-boot-in-action/evals/results.json +13 -0
  298. package/skills/spring-boot-in-action/examples/after.md +185 -0
  299. package/skills/spring-boot-in-action/examples/before.md +84 -0
  300. package/skills/spring-boot-in-action/references/practices-catalog.md +403 -0
  301. package/skills/spring-boot-in-action/scripts/review.py +184 -0
  302. package/skills/storytelling-with-data/SKILL.md +241 -0
  303. package/skills/storytelling-with-data/assets/example_asset.txt +1 -0
  304. package/skills/storytelling-with-data/evals/evals.json +47 -0
  305. package/skills/storytelling-with-data/evals/results.json +13 -0
  306. package/skills/storytelling-with-data/examples/after.md +50 -0
  307. package/skills/storytelling-with-data/examples/before.md +33 -0
  308. package/skills/storytelling-with-data/references/api_reference.md +379 -0
  309. package/skills/storytelling-with-data/references/review-checklist.md +111 -0
  310. package/skills/storytelling-with-data/scripts/chart_review.py +301 -0
  311. package/skills/storytelling-with-data/scripts/example.py +1 -0
  312. package/skills/system-design-interview/SKILL.md +233 -0
  313. package/skills/system-design-interview/assets/example_asset.txt +1 -0
  314. package/skills/system-design-interview/evals/evals.json +46 -0
  315. package/skills/system-design-interview/evals/results.json +13 -0
  316. package/skills/system-design-interview/examples/after.md +94 -0
  317. package/skills/system-design-interview/examples/before.md +27 -0
  318. package/skills/system-design-interview/references/api_reference.md +582 -0
  319. package/skills/system-design-interview/references/review-checklist.md +201 -0
  320. package/skills/system-design-interview/scripts/example.py +1 -0
  321. package/skills/system-design-interview/scripts/new_design.py +421 -0
  322. package/skills/using-asyncio-python/SKILL.md +290 -0
  323. package/skills/using-asyncio-python/assets/example_asset.txt +1 -0
  324. package/skills/using-asyncio-python/evals/evals.json +43 -0
  325. package/skills/using-asyncio-python/evals/results.json +13 -0
  326. package/skills/using-asyncio-python/examples/after.md +68 -0
  327. package/skills/using-asyncio-python/examples/before.md +39 -0
  328. package/skills/using-asyncio-python/references/api_reference.md +267 -0
  329. package/skills/using-asyncio-python/references/review-checklist.md +149 -0
  330. package/skills/using-asyncio-python/scripts/check_blocking.py +270 -0
  331. package/skills/using-asyncio-python/scripts/example.py +1 -0
  332. package/skills/web-scraping-python/SKILL.md +280 -0
  333. package/skills/web-scraping-python/assets/example_asset.txt +1 -0
  334. package/skills/web-scraping-python/evals/evals.json +46 -0
  335. package/skills/web-scraping-python/evals/results.json +13 -0
  336. package/skills/web-scraping-python/examples/after.md +109 -0
  337. package/skills/web-scraping-python/examples/before.md +40 -0
  338. package/skills/web-scraping-python/references/api_reference.md +393 -0
  339. package/skills/web-scraping-python/references/review-checklist.md +163 -0
  340. package/skills/web-scraping-python/scripts/example.py +1 -0
  341. package/skills/web-scraping-python/scripts/new_scraper.py +231 -0
  342. package/skills/writing-plans/audit.json +34 -0
  343. package/tests/agent-detector.test.js +83 -0
  344. package/tests/corrections.test.js +245 -0
  345. package/tests/doctor/hook-installer.test.js +72 -0
  346. package/tests/doctor/usage-tracker.test.js +140 -0
  347. package/tests/engine/benchmark-eval.test.js +31 -0
  348. package/tests/engine/bm25-index.test.js +85 -0
  349. package/tests/engine/capture-command.test.js +35 -0
  350. package/tests/engine/capture.test.js +17 -0
  351. package/tests/engine/graph-augmented-search.test.js +107 -0
  352. package/tests/engine/graph-injector.test.js +44 -0
  353. package/tests/engine/graph.test.js +216 -0
  354. package/tests/engine/hybrid-searcher.test.js +74 -0
  355. package/tests/engine/indexer-bm25.test.js +37 -0
  356. package/tests/engine/mcp-tools.test.js +73 -0
  357. package/tests/engine/project-initializer-mcp.test.js +99 -0
  358. package/tests/engine/query-expander.test.js +36 -0
  359. package/tests/engine/reranker.test.js +51 -0
  360. package/tests/engine/rrf.test.js +49 -0
  361. package/tests/engine/srag-prefix.test.js +47 -0
  362. package/tests/instinct-block.test.js +23 -0
  363. package/tests/mcp-config-writer.test.js +60 -0
  364. package/tests/project-initializer-new-agents.test.js +48 -0
  365. package/tests/rules/rules-manager.test.js +230 -0
  366. package/tests/well-known-builder.test.js +40 -0
  367. package/tests/wizard/integration-detector.test.js +31 -0
  368. package/tests/wizard/project-detector.test.js +51 -0
  369. package/tests/wizard/prompt-session.test.js +61 -0
  370. package/tests/wizard/prompt.test.js +16 -0
  371. package/tests/wizard/registry-embeddings.test.js +35 -0
  372. package/tests/wizard/skill-recommender.test.js +34 -0
  373. package/tests/wizard/slot-count.test.js +25 -0
  374. package/vercel.json +21 -0
@@ -0,0 +1,45 @@
1
+ {
2
+ "evals": [
3
+ {
4
+ "id": "eval-01-distributed-transaction-no-saga",
5
+ "prompt": "Review this microservices code for an e-commerce checkout flow:\n\n```java\n// OrderService — orchestrates the entire checkout in one HTTP transaction\n@RestController\npublic class CheckoutController {\n private final OrderRepository orderRepository;\n private final InventoryServiceClient inventoryClient;\n private final PaymentServiceClient paymentClient;\n private final ShippingServiceClient shippingClient;\n private final NotificationServiceClient notificationClient;\n \n @PostMapping(\"/checkout\")\n @Transactional // <-- spans the entire method\n public OrderConfirmation checkout(@RequestBody CheckoutRequest request) {\n // Step 1: Reserve inventory\n inventoryClient.reserveItems(request.getItems());\n \n // Step 2: Create order in our DB\n Order order = orderRepository.save(new Order(request));\n \n // Step 3: Charge payment\n PaymentResult payment = paymentClient.charge(request.getPaymentInfo(), order.getTotal());\n \n // Step 4: Create shipping label\n ShippingLabel label = shippingClient.createLabel(order.getId(), request.getAddress());\n \n // Step 5: Send confirmation email\n notificationClient.sendConfirmation(request.getEmail(), order.getId());\n \n order.setShippingLabel(label.getTrackingNumber());\n order.setStatus(\"CONFIRMED\");\n return new OrderConfirmation(order.getId(), label.getTrackingNumber());\n }\n}\n```",
6
+ "expectations": [
7
+ "Identifies the core anti-pattern: a distributed transaction where @Transactional spans HTTP calls to 3 external services — this does not work as intended",
8
+ "Explains why @Transactional cannot span HTTP calls: the ACID transaction boundary is the local database only; remote service calls are not rolled back if a later step fails",
9
+ "Identifies the failure scenario: if shippingClient.createLabel() throws after paymentClient.charge() succeeds, the customer is charged but never gets a shipping label — and inventory is reserved but no rollback occurs",
10
+ "Names the pattern that is needed: the Saga pattern (orchestration-based) to handle this cross-service workflow",
11
+ "Explains compensating transactions: each step needs a corresponding undo — if shipping fails, a ReversePaymentSaga step should issue a refund and a ReleaseInventory step should free reserved stock",
12
+ "Notes the synchronous chain anti-pattern: OrderService → Inventory → Payment → Shipping → Notification is a fragile chain — if Notification is slow or down, the entire checkout hangs",
13
+ "Recommends making notifications asynchronous via a message queue (fire-and-forget)",
14
+ "Suggests using Saga orchestration with explicit saga states (PENDING_INVENTORY, PENDING_PAYMENT, PENDING_SHIPPING, CONFIRMED, FAILED) stored durably"
15
+ ]
16
+ },
17
+ {
18
+ "id": "eval-02-shared-database",
19
+ "prompt": "Review this microservices architecture:\n\n```java\n// ProductService — manages product catalog\n@Service\npublic class ProductService {\n @Autowired\n private JdbcTemplate jdbc; // Connects to: jdbc:postgresql://shared-db:5432/platform\n \n public Product getProduct(Long id) {\n return jdbc.queryForObject(\n \"SELECT * FROM products WHERE id = ?\",\n new ProductRowMapper(), id);\n }\n \n public void updatePrice(Long productId, BigDecimal newPrice) {\n jdbc.update(\"UPDATE products SET price = ?, updated_at = NOW() WHERE id = ?\",\n newPrice, productId);\n }\n}\n\n// OrderService — in a SEPARATE deployable service/process\n@Service\npublic class OrderService {\n @Autowired\n private JdbcTemplate jdbc; // ALSO connects to: jdbc:postgresql://shared-db:5432/platform\n \n public Order createOrder(CreateOrderRequest req) {\n // Directly reads from products table owned by ProductService\n BigDecimal price = jdbc.queryForObject(\n \"SELECT price FROM products WHERE id = ?\",\n BigDecimal.class, req.getProductId());\n \n // Directly joins across service boundaries\n List<OrderLine> lines = jdbc.query(\n \"SELECT o.*, p.name, p.sku FROM orders o JOIN products p ON o.product_id = p.id WHERE o.customer_id = ?\",\n new OrderLineRowMapper(), req.getCustomerId());\n \n jdbc.update(\"INSERT INTO orders (product_id, customer_id, price) VALUES (?, ?, ?)\",\n req.getProductId(), req.getCustomerId(), price);\n return buildOrder(lines);\n }\n}\n```",
20
+ "expectations": [
21
+ "Identifies the Shared Database anti-pattern: both ProductService and OrderService connect to the same database and directly access each other's tables",
22
+ "Explains why this is problematic: ProductService cannot change its products table schema without coordinating with OrderService — the services are coupled at the data layer despite being separate deployables",
23
+ "Flags that OrderService reads from products — meaning ProductService's internal data model is now OrderService's public API; any rename or restructure breaks OrderService",
24
+ "Flags the cross-service JOIN in SQL: joins across service boundaries are a strong indicator of incorrect service decomposition or a shared database violation",
25
+ "Explains the correct pattern: each service owns its own database/schema; OrderService should get product information by calling ProductService's API (synchronous) or by maintaining a local read model via events (CQRS)",
26
+ "Recommends that OrderService should store the price at order-creation time (denormalized) rather than joining live to the products table — price at time of purchase is correct business behavior",
27
+ "Notes that this architecture makes independent deployment impossible: upgrading ProductService's database schema requires a coordinated deployment with OrderService"
28
+ ]
29
+ },
30
+ {
31
+ "id": "eval-03-event-driven-saga",
32
+ "prompt": "Review this saga implementation for a ride-sharing trip booking:\n\n```java\n// TripSaga — orchestrator (Spring Saga / Axon-style pseudocode)\n@Saga\npublic class BookTripSaga {\n private String tripId;\n private String driverId;\n private String paymentAuthId;\n \n @StartSaga\n @SagaEventHandler(associationProperty = \"tripId\")\n public void on(TripRequestedEvent event) {\n this.tripId = event.getTripId();\n commandGateway.send(new FindAvailableDriverCommand(event.getTripId(), event.getLocation()));\n }\n \n @SagaEventHandler(associationProperty = \"tripId\")\n public void on(DriverAssignedEvent event) {\n this.driverId = event.getDriverId();\n commandGateway.send(new AuthorizePaymentCommand(event.getTripId(), event.getEstimatedFare()));\n }\n \n @SagaEventHandler(associationProperty = \"tripId\")\n public void on(PaymentAuthorizedEvent event) {\n this.paymentAuthId = event.getAuthorizationId();\n commandGateway.send(new ConfirmTripCommand(tripId, driverId));\n }\n \n @SagaEventHandler(associationProperty = \"tripId\")\n public void on(NoDriverAvailableEvent event) {\n commandGateway.send(new CancelTripCommand(tripId, \"No drivers available\"));\n SagaLifecycle.end();\n }\n \n @SagaEventHandler(associationProperty = \"tripId\")\n public void on(PaymentDeclinedEvent event) {\n // Compensate: release the reserved driver\n commandGateway.send(new ReleaseDriverCommand(driverId, tripId));\n commandGateway.send(new CancelTripCommand(tripId, \"Payment declined\"));\n SagaLifecycle.end();\n }\n \n @EndSaga\n @SagaEventHandler(associationProperty = \"tripId\")\n public void on(TripConfirmedEvent event) {\n // Saga complete — trip is live\n }\n}\n```",
33
+ "expectations": [
34
+ "Recognizes this as a well-designed orchestration-based saga and says so explicitly",
35
+ "Praises the compensating transactions: PaymentDeclinedEvent triggers both ReleaseDriverCommand and CancelTripCommand — each forward step has a corresponding undo",
36
+ "Praises that the saga stores intermediate state (driverId, paymentAuthId) to enable compensation — the saga has the information it needs to undo each step",
37
+ "Praises that the saga is event-driven: each step reacts to an event rather than making synchronous calls — this decouples the booking flow from service availability",
38
+ "Praises explicit saga lifecycle management: SagaLifecycle.end() on failure paths and @EndSaga on success ensure the saga doesn't leak memory",
39
+ "Praises modeling failure paths as first-class events (NoDriverAvailableEvent, PaymentDeclinedEvent) — not exceptions, but domain events the saga handles explicitly",
40
+ "Does NOT manufacture fake issues just to have something to say",
41
+ "May offer optional suggestions (timeout handling if DriverAssignedEvent never arrives, idempotent command handlers) but frames them as additional robustness, not defects in the current design"
42
+ ]
43
+ }
44
+ ]
45
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "pass_rate": 1,
3
+ "passed": 23,
4
+ "total": 23,
5
+ "baseline_pass_rate": 0.696,
6
+ "baseline_passed": 16,
7
+ "baseline_total": 23,
8
+ "delta": 0.304,
9
+ "model": "default",
10
+ "evals_run": 3,
11
+ "date": "2026-03-28",
12
+ "non_standard_provider": true
13
+ }
@@ -0,0 +1,69 @@
1
+ # After
2
+
3
+ `InventoryService` owns its own read model, populated by consuming `OrderLineItemAdded` domain events published by the Order Service — no shared database access.
4
+
5
+ ```java
6
+ // --- Order Service publishes domain events (its own codebase) ---
7
+
8
+ @DomainEvent
9
+ public record OrderLineItemAdded(
10
+ String orderId,
11
+ String productId,
12
+ int quantity,
13
+ Instant occurredAt
14
+ ) {}
15
+
16
+ // Order Service publishes this event after saving the order aggregate
17
+ orderEventPublisher.publish(new OrderLineItemAdded(
18
+ order.getId(), line.getProductId(), line.getQuantity(), Instant.now()
19
+ ));
20
+
21
+
22
+ // --- Inventory Service: owns its own read model, no shared DB ---
23
+
24
+ // Private denormalized table — owned exclusively by Inventory Service
25
+ @Entity @Table(name = "product_weekly_sales")
26
+ public class ProductWeeklySales {
27
+ @Id private String productId;
28
+ private int unitsSoldLast7Days;
29
+ private Instant lastUpdated;
30
+ }
31
+
32
+ @Component
33
+ public class OrderLineItemAddedConsumer {
34
+
35
+ @KafkaListener(topics = "order.events", groupId = "inventory-service")
36
+ public void handle(OrderLineItemAdded event) {
37
+ // Idempotent: uses event's occurredAt to filter stale events
38
+ if (event.occurredAt().isBefore(Instant.now().minus(7, DAYS))) return;
39
+
40
+ weeklySalesRepository.incrementUnitsSold(event.productId(), event.quantity());
41
+ }
42
+ }
43
+
44
+ @RestController @RequestMapping("/inventory")
45
+ public class InventoryController {
46
+
47
+ @GetMapping("/reorder-candidates")
48
+ public List<ReorderItem> getReorderCandidates() {
49
+ // Queries Inventory Service's OWN database — no cross-service DB access
50
+ return weeklySalesRepository.findAll().stream()
51
+ .filter(sales -> {
52
+ int stockLevel = stockRepository.getLevel(sales.getProductId());
53
+ return stockLevel < sales.getUnitsSoldLast7Days() * 2;
54
+ })
55
+ .map(sales -> new ReorderItem(
56
+ sales.getProductId(),
57
+ sales.getUnitsSoldLast7Days() * 3 - stockRepository.getLevel(sales.getProductId())
58
+ ))
59
+ .toList();
60
+ }
61
+ }
62
+ ```
63
+
64
+ Key improvements:
65
+ - Each service owns its database — `InventoryService` never touches the `orders` schema (Database per Service pattern)
66
+ - `OrderLineItemAdded` domain event decouples the services; Order Service does not know Inventory Service exists
67
+ - `ProductWeeklySales` is a denormalized read model maintained by consuming events — a lightweight CQRS view
68
+ - The Kafka consumer is idempotent: events outside the 7-day window are skipped, making re-delivery safe
69
+ - Deleting the coupling to `sharedDataSource` eliminates the risk that a schema change in Order Service breaks Inventory Service at runtime
@@ -0,0 +1,40 @@
1
+ # Before
2
+
3
+ An `InventoryService` that directly queries the `orders` database table owned by another service, creating tight coupling and a shared-database anti-pattern.
4
+
5
+ ```java
6
+ @RestController
7
+ @RequestMapping("/inventory")
8
+ public class InventoryController {
9
+
10
+ @Autowired
11
+ private DataSource sharedDataSource; // connected to the orders DB
12
+
13
+ @GetMapping("/reorder-candidates")
14
+ public List<ReorderItem> getReorderCandidates() {
15
+ List<ReorderItem> candidates = new ArrayList<>();
16
+
17
+ // Directly querying the Order Service's database table
18
+ try (Connection conn = sharedDataSource.getConnection();
19
+ PreparedStatement ps = conn.prepareStatement(
20
+ "SELECT product_id, SUM(quantity) as sold_qty " +
21
+ "FROM orders.order_lines " +
22
+ "WHERE created_at > NOW() - INTERVAL 7 DAY " +
23
+ "GROUP BY product_id")) {
24
+
25
+ ResultSet rs = ps.executeQuery();
26
+ while (rs.next()) {
27
+ String productId = rs.getString("product_id");
28
+ int soldQty = rs.getInt("sold_qty");
29
+ int stockLevel = getStockLevel(productId);
30
+ if (stockLevel < soldQty * 2) {
31
+ candidates.add(new ReorderItem(productId, soldQty * 3 - stockLevel));
32
+ }
33
+ }
34
+ } catch (SQLException e) {
35
+ throw new RuntimeException(e);
36
+ }
37
+ return candidates;
38
+ }
39
+ }
40
+ ```
@@ -0,0 +1,391 @@
1
+ # Microservices Patterns Catalog
2
+
3
+ Comprehensive reference of patterns from Chris Richardson's *Microservices Patterns*.
4
+ Organized by problem category. Read the section relevant to the code you're generating.
5
+
6
+ ---
7
+
8
+ ## Table of Contents
9
+
10
+ 1. [Decomposition Patterns](#decomposition-patterns)
11
+ 2. [Communication Patterns](#communication-patterns)
12
+ 3. [API Gateway Patterns](#api-gateway-patterns)
13
+ 4. [Transaction Management — Sagas](#transaction-management--sagas)
14
+ 5. [Business Logic Patterns](#business-logic-patterns)
15
+ 6. [Event Sourcing](#event-sourcing)
16
+ 7. [Query Patterns](#query-patterns)
17
+ 8. [Testing Patterns](#testing-patterns)
18
+ 9. [Deployment Patterns](#deployment-patterns)
19
+ 10. [Observability Patterns](#observability-patterns)
20
+
21
+ ---
22
+
23
+ ## Decomposition Patterns
24
+
25
+ ### Decompose by Business Capability
26
+
27
+ Map services to what the organization *does*. Business capabilities are stable
28
+ over time even as org structure changes.
29
+
30
+ - Identify top-level capabilities (Order Management, Delivery, Billing, etc.)
31
+ - Each capability becomes a candidate service
32
+ - Services own the data for their capability
33
+
34
+ **When to use**: Starting a new microservices project or breaking up a monolith.
35
+
36
+ ### Decompose by Subdomain (DDD)
37
+
38
+ Use Domain-Driven Design to identify bounded contexts. Each bounded context
39
+ becomes a service.
40
+
41
+ - Core subdomains: the competitive advantage (invest the most here)
42
+ - Supporting subdomains: necessary but not differentiating
43
+ - Generic subdomains: solved problems (use off-the-shelf solutions)
44
+
45
+ **When to use**: Complex domain where business capability mapping isn't granular enough.
46
+
47
+ ### Strangler Fig Pattern
48
+
49
+ Incrementally migrate from monolith to microservices by building new functionality
50
+ as services and gradually routing traffic away from the monolith.
51
+
52
+ - Stand up new service alongside monolith
53
+ - Route specific requests to new service
54
+ - Gradually migrate functionality
55
+ - Eventually decommission monolith component
56
+
57
+ **When to use**: Migrating an existing monolith without a big-bang rewrite.
58
+
59
+ ---
60
+
61
+ ## Communication Patterns
62
+
63
+ ### Synchronous — REST
64
+
65
+ - Use for simple request/response interactions
66
+ - Design APIs using the Richardson Maturity Model (ideally Level 2+)
67
+ - Define IDL: OpenAPI/Swagger for REST
68
+ - Handle partial failure: timeouts, retries, circuit breakers
69
+
70
+ ### Synchronous — gRPC
71
+
72
+ - Binary protocol, strongly typed via Protocol Buffers
73
+ - More efficient than REST for inter-service calls
74
+ - Supports streaming (server, client, bidirectional)
75
+ - Good for polyglot environments (code generation for many languages)
76
+
77
+ ### Asynchronous — Messaging
78
+
79
+ - Services communicate via message broker (Kafka, RabbitMQ, etc.)
80
+ - Message types: **Document** (carries data), **Command** (request action), **Event** (notification of change)
81
+ - Channels: **Point-to-point** (one consumer) or **Publish-subscribe** (many consumers)
82
+
83
+ Key implementation concerns:
84
+
85
+ - **Message ordering**: Use partitioned channels (e.g., Kafka partitions keyed by aggregate ID)
86
+ - **Duplicate handling**: Make consumers idempotent (track processed message IDs, or make operations naturally idempotent)
87
+ - **Transactional outbox**: Write events to an OUTBOX table in the same transaction as business data, then relay to broker — ensures atomicity without distributed transactions
88
+ - **Polling publisher or Transaction log tailing**: Two strategies for relaying outbox messages to the broker
89
+
90
+ ### Circuit Breaker
91
+
92
+ Wrap remote calls in a circuit breaker to handle downstream failures gracefully:
93
+
94
+ - **Closed**: Requests pass through normally
95
+ - **Open**: Requests fail immediately (after failure threshold exceeded)
96
+ - **Half-open**: Periodically try a request; if it succeeds, close the circuit
97
+
98
+ Use libraries like Resilience4j (Java) or Polly (.NET).
99
+
100
+ ### Service Discovery
101
+
102
+ Services need to locate each other. Two approaches:
103
+
104
+ - **Client-side discovery**: Client queries a registry (e.g., Eureka) and load-balances
105
+ - **Server-side discovery**: Client calls a router/load balancer that queries the registry (e.g., Kubernetes services, AWS ELB)
106
+
107
+ ---
108
+
109
+ ## API Gateway Patterns
110
+
111
+ ### API Gateway
112
+
113
+ Single entry point for external clients. Responsibilities:
114
+
115
+ - Request routing to appropriate microservice
116
+ - API composition (aggregate responses from multiple services)
117
+ - Protocol translation (external REST to internal gRPC/messaging)
118
+ - Authentication and rate limiting
119
+ - Edge functions (caching, monitoring, etc.)
120
+
121
+ ### Backend for Frontend (BFF)
122
+
123
+ Separate API gateway per client type (web, mobile, third-party). Each BFF:
124
+
125
+ - Tailors the API to its client's needs
126
+ - Handles client-specific data aggregation
127
+ - Is owned by the client team
128
+ - Reduces coupling between client and backend service evolution
129
+
130
+ **When to use BFF over single gateway**: When different clients have significantly different API needs.
131
+
132
+ ---
133
+
134
+ ## Transaction Management — Sagas
135
+
136
+ ### The Problem
137
+
138
+ Microservices use Database per Service, so you cannot use ACID transactions
139
+ across services. Sagas maintain data consistency using a sequence of local
140
+ transactions with compensating transactions for rollback.
141
+
142
+ ### Choreography-based Saga
143
+
144
+ Services publish events and subscribe to each other's events:
145
+
146
+ ```
147
+ OrderService -> OrderCreated event
148
+ -> PaymentService listens, processes payment, publishes PaymentAuthorized
149
+ -> KitchenService listens, creates ticket, publishes TicketCreated
150
+ -> OrderService listens, approves order
151
+ ```
152
+
153
+ - Pros: Simple, no central coordinator, loose coupling
154
+ - Cons: Hard to understand the flow, cyclic dependencies possible
155
+
156
+ ### Orchestration-based Saga
157
+
158
+ A central saga orchestrator tells participants what to do:
159
+
160
+ ```
161
+ CreateOrderSaga:
162
+ 1. OrderService.createOrder(PENDING)
163
+ 2. PaymentService.authorize() -> fail? -> OrderService.rejectOrder()
164
+ 3. KitchenService.createTicket() -> fail? -> PaymentService.reverseAuth(), OrderService.rejectOrder()
165
+ 4. OrderService.approveOrder()
166
+ ```
167
+
168
+ - Pros: Clear flow, easy to understand, avoids cyclic dependencies
169
+ - Cons: Risk of centralizing too much logic in orchestrator
170
+
171
+ ### Saga Design Rules
172
+
173
+ - Each saga step modifies one aggregate in one service
174
+ - Every forward step needs a compensating transaction (undo/rollback action)
175
+ - Compensating transactions must be idempotent (safe to retry)
176
+ - Use semantic locks — mark records as "pending" during saga execution
177
+ - Countermeasures for lack of isolation: semantic locks, commutative updates, pessimistic/optimistic views, re-reading values
178
+
179
+ ---
180
+
181
+ ## Business Logic Patterns
182
+
183
+ ### Aggregate Pattern (DDD)
184
+
185
+ An aggregate is a cluster of domain objects treated as a unit for data changes.
186
+
187
+ - **Aggregate root**: Top-level entity through which all external access occurs
188
+ - **Invariants**: Business rules enforced within the aggregate
189
+ - **Transaction boundary**: One transaction = one aggregate update
190
+ - **References between aggregates**: Use IDs, not object references
191
+
192
+ Design rules:
193
+ - Keep aggregates small — reference other aggregates by identity
194
+ - Business logic lives in the aggregate, not in service classes
195
+ - Aggregates publish domain events when their state changes
196
+
197
+ ### Domain Events
198
+
199
+ Events represent something meaningful that happened in the domain:
200
+
201
+ - Named in past tense: OrderCreated, PaymentAuthorized, TicketAccepted
202
+ - Contain relevant data (IDs, state at time of event)
203
+ - Published by aggregates after state changes
204
+ - Consumed by other services for integration
205
+
206
+ ### Domain Event Publishing
207
+
208
+ Two approaches to reliably publish events:
209
+
210
+ 1. **Transactional outbox**: Store events in an outbox table in the same DB transaction as business data, then asynchronously publish to message broker
211
+ 2. **Event sourcing**: Events are the primary store (see below)
212
+
213
+ ---
214
+
215
+ ## Event Sourcing
216
+
217
+ Instead of storing current state, store a sequence of state-changing events.
218
+ Reconstruct current state by replaying events.
219
+
220
+ ### How It Works
221
+
222
+ - Each aggregate stored as a sequence of events in an event store
223
+ - To load: fetch all events, replay to reconstruct state
224
+ - To save: append new events to the store
225
+ - Event store is append-only (never update, never delete)
226
+
227
+ ### Benefits
228
+
229
+ - Reliable event publishing (events ARE the data — no outbox needed)
230
+ - Complete audit trail
231
+ - Temporal queries (reconstruct state at any point in time)
232
+ - Enables CQRS naturally
233
+
234
+ ### Challenges
235
+
236
+ - Learning curve; different way of thinking
237
+ - Querying the event store is hard (need CQRS for queries)
238
+ - Event schema evolution — events are immutable, so versioning matters
239
+ - Deleting data (e.g., GDPR) requires special handling like encryption with deletable keys
240
+
241
+ ### Snapshots
242
+
243
+ For aggregates with many events, periodically save a snapshot of current state
244
+ to avoid replaying the entire history. Load: last snapshot + events after snapshot.
245
+
246
+ ---
247
+
248
+ ## Query Patterns
249
+
250
+ ### API Composition
251
+
252
+ For queries spanning multiple services, an API composer calls each service
253
+ and combines results in memory.
254
+
255
+ ```
256
+ API Composer (or API Gateway):
257
+ 1. Call OrderService.getOrders(customerId)
258
+ 2. Call DeliveryService.getDeliveries(orderIds)
259
+ 3. Call RestaurantService.getRestaurants(restaurantIds)
260
+ 4. Join results in memory, return to client
261
+ ```
262
+
263
+ - Pros: Simple to implement
264
+ - Cons: Increased latency, no efficient join/filter across services, reduced availability
265
+
266
+ **When to use**: Simple queries where data from 2-3 services needs combining.
267
+
268
+ ### CQRS (Command Query Responsibility Segregation)
269
+
270
+ Separate the write model (commands) from the read model (queries):
271
+
272
+ - **Command side**: Services handle commands, publish domain events
273
+ - **Query side**: A separate view service subscribes to events and maintains denormalized read-optimized database
274
+
275
+ ```
276
+ OrderService publishes OrderCreated ->
277
+ DeliveryService publishes DeliveryStatusUpdated ->
278
+ OrderHistoryViewService subscribes to both,
279
+ maintains denormalized OrderHistoryView table,
280
+ serves GET /order-history queries
281
+ ```
282
+
283
+ - Pros: Efficient queries, scales reads independently, supports complex cross-service queries
284
+ - Cons: Extra complexity, eventual consistency, additional infrastructure
285
+
286
+ **When to use**: Complex queries spanning many services, or when read performance is critical.
287
+
288
+ ---
289
+
290
+ ## Testing Patterns
291
+
292
+ ### Consumer-Driven Contract Testing
293
+
294
+ Each consumer defines a contract: "I expect your API to behave like X."
295
+ Provider runs these contracts as tests to ensure compatibility.
296
+
297
+ - Tools: Spring Cloud Contract, Pact
298
+ - Catches breaking changes before deployment
299
+
300
+ ### Service Component Testing
301
+
302
+ Test a service in isolation by stubbing its dependencies:
303
+
304
+ - In-memory stubs for downstream services
305
+ - In-memory or containerized database
306
+ - Verify behavior end-to-end through the service's API
307
+
308
+ ### Integration Testing
309
+
310
+ Test interaction between a service and its infrastructure:
311
+
312
+ - Database integration tests (verify SQL, schema migrations)
313
+ - Messaging integration tests (verify event publishing/consuming)
314
+ - REST client integration tests (verify HTTP calls)
315
+ - Use Docker (Testcontainers) for realistic infrastructure
316
+
317
+ ### Testing Pyramid for Microservices
318
+
319
+ From bottom (fast, many) to top (slow, few):
320
+
321
+ 1. Unit tests — domain logic, aggregates, sagas
322
+ 2. Integration tests — persistence, messaging, REST clients
323
+ 3. Component tests — single service end-to-end with stubs
324
+ 4. Contract tests — API compatibility between consumer and provider
325
+ 5. End-to-end tests — full system (keep these minimal)
326
+
327
+ ---
328
+
329
+ ## Deployment Patterns
330
+
331
+ ### Service per Container
332
+
333
+ Package each service as a Docker container image:
334
+
335
+ - Encapsulates service and dependencies
336
+ - Consistent across environments
337
+ - Use multi-stage builds to keep images small
338
+
339
+ ### Kubernetes Orchestration
340
+
341
+ - Deployment: Manages replicas and rolling updates
342
+ - Service: Stable network endpoint for service discovery
343
+ - ConfigMap/Secret: Externalized configuration
344
+ - Probes: Liveness and readiness health checks
345
+
346
+ ### Service Mesh
347
+
348
+ Infrastructure layer handling service-to-service communication:
349
+
350
+ - Automatic mTLS between services
351
+ - Traffic management (retries, timeouts, circuit breaking)
352
+ - Observability (distributed tracing, metrics)
353
+ - Tools: Istio, Linkerd
354
+
355
+ ### Externalized Configuration
356
+
357
+ - Environment variables, config servers (Spring Cloud Config), Kubernetes ConfigMaps
358
+ - Secrets managed separately (Vault, Kubernetes Secrets)
359
+ - Same artifact runs in different environments
360
+
361
+ ---
362
+
363
+ ## Observability Patterns
364
+
365
+ ### Health Check API
366
+
367
+ Every service exposes a health endpoint (GET /health) reporting:
368
+ - Service status (UP/DOWN)
369
+ - Dependency status (database, message broker)
370
+ - Used by orchestrators and load balancers
371
+
372
+ ### Distributed Tracing
373
+
374
+ Assign unique trace ID to each external request, propagate through all service calls.
375
+ - Tools: Zipkin, Jaeger, AWS X-Ray
376
+ - Instrument with OpenTelemetry
377
+
378
+ ### Log Aggregation
379
+
380
+ Centralize logs from all services:
381
+ - Include trace IDs for correlation
382
+ - Structured logging (JSON format)
383
+ - Tools: ELK Stack, Fluentd, Datadog
384
+
385
+ ### Application Metrics
386
+
387
+ Collect and expose metrics from each service:
388
+ - Request rate, latency, error rate (RED method)
389
+ - Resource utilization
390
+ - Business metrics
391
+ - Tools: Prometheus + Grafana, Datadog, CloudWatch