@dewtech/dare-cli 3.3.0 → 3.4.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 (582) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +764 -764
  3. package/dist/__tests__/confidence.test.js +13 -13
  4. package/dist/__tests__/dag-converter.test.js +56 -56
  5. package/dist/__tests__/mcp-server/server.test.js +3 -16
  6. package/dist/__tests__/mcp-server/server.test.js.map +1 -1
  7. package/dist/__tests__/project-generator.test.js +2 -2
  8. package/dist/__tests__/project-generator.test.js.map +1 -1
  9. package/dist/__tests__/refine.test.js +49 -49
  10. package/dist/__tests__/reverse-collection.test.js +6 -6
  11. package/dist/__tests__/review.test.js +38 -38
  12. package/dist/__tests__/security-hardening.test.d.ts +2 -0
  13. package/dist/__tests__/security-hardening.test.d.ts.map +1 -0
  14. package/dist/__tests__/security-hardening.test.js +101 -0
  15. package/dist/__tests__/security-hardening.test.js.map +1 -0
  16. package/dist/__tests__/validate.test.js +65 -65
  17. package/dist/bin/dare.js +0 -0
  18. package/dist/commands/__tests__/init-validation.test.d.ts +2 -0
  19. package/dist/commands/__tests__/init-validation.test.d.ts.map +1 -0
  20. package/dist/commands/__tests__/init-validation.test.js +81 -0
  21. package/dist/commands/__tests__/init-validation.test.js.map +1 -0
  22. package/dist/commands/__tests__/init.integration.spec.js +6 -4
  23. package/dist/commands/__tests__/init.integration.spec.js.map +1 -1
  24. package/dist/commands/__tests__/init.spec.d.ts +2 -0
  25. package/dist/commands/__tests__/init.spec.d.ts.map +1 -0
  26. package/dist/commands/__tests__/init.spec.js +88 -0
  27. package/dist/commands/__tests__/init.spec.js.map +1 -0
  28. package/dist/commands/blueprint.js +122 -122
  29. package/dist/commands/design.js +20 -20
  30. package/dist/commands/init-validation.d.ts +22 -0
  31. package/dist/commands/init-validation.d.ts.map +1 -0
  32. package/dist/commands/init-validation.js +54 -0
  33. package/dist/commands/init-validation.js.map +1 -0
  34. package/dist/commands/init.d.ts.map +1 -1
  35. package/dist/commands/init.js +26 -10
  36. package/dist/commands/init.js.map +1 -1
  37. package/dist/graphrag/graph-rag.js +24 -24
  38. package/dist/mcp-server/__tests__/auth.test.d.ts +2 -0
  39. package/dist/mcp-server/__tests__/auth.test.d.ts.map +1 -0
  40. package/dist/mcp-server/__tests__/auth.test.js +72 -0
  41. package/dist/mcp-server/__tests__/auth.test.js.map +1 -0
  42. package/dist/mcp-server/__tests__/boot-config.test.d.ts +2 -0
  43. package/dist/mcp-server/__tests__/boot-config.test.d.ts.map +1 -0
  44. package/dist/mcp-server/__tests__/boot-config.test.js +29 -0
  45. package/dist/mcp-server/__tests__/boot-config.test.js.map +1 -0
  46. package/dist/mcp-server/__tests__/error-sanitize.test.d.ts +2 -0
  47. package/dist/mcp-server/__tests__/error-sanitize.test.d.ts.map +1 -0
  48. package/dist/mcp-server/__tests__/error-sanitize.test.js +66 -0
  49. package/dist/mcp-server/__tests__/error-sanitize.test.js.map +1 -0
  50. package/dist/mcp-server/__tests__/path-confinement.test.d.ts +2 -0
  51. package/dist/mcp-server/__tests__/path-confinement.test.d.ts.map +1 -0
  52. package/dist/mcp-server/__tests__/path-confinement.test.js +135 -0
  53. package/dist/mcp-server/__tests__/path-confinement.test.js.map +1 -0
  54. package/dist/mcp-server/bin/server.js +18 -6
  55. package/dist/mcp-server/bin/server.js.map +1 -1
  56. package/dist/mcp-server/boot-config.d.ts +6 -0
  57. package/dist/mcp-server/boot-config.d.ts.map +1 -0
  58. package/dist/mcp-server/boot-config.js +17 -0
  59. package/dist/mcp-server/boot-config.js.map +1 -0
  60. package/dist/mcp-server/middleware/auth.d.ts +10 -0
  61. package/dist/mcp-server/middleware/auth.d.ts.map +1 -0
  62. package/dist/mcp-server/middleware/auth.js +44 -0
  63. package/dist/mcp-server/middleware/auth.js.map +1 -0
  64. package/dist/mcp-server/middleware/cors.d.ts +6 -0
  65. package/dist/mcp-server/middleware/cors.d.ts.map +1 -0
  66. package/dist/mcp-server/middleware/cors.js +30 -0
  67. package/dist/mcp-server/middleware/cors.js.map +1 -0
  68. package/dist/mcp-server/middleware/error-handler.d.ts +11 -0
  69. package/dist/mcp-server/middleware/error-handler.d.ts.map +1 -0
  70. package/dist/mcp-server/middleware/error-handler.js +14 -0
  71. package/dist/mcp-server/middleware/error-handler.js.map +1 -0
  72. package/dist/mcp-server/server.d.ts +7 -2
  73. package/dist/mcp-server/server.d.ts.map +1 -1
  74. package/dist/mcp-server/server.js +185 -105
  75. package/dist/mcp-server/server.js.map +1 -1
  76. package/dist/skills/registry-mock.json +109 -109
  77. package/dist/skills/tests/manifest.spec.js +20 -20
  78. package/dist/stacks/__tests__/dna-emitter.spec.js +6 -6
  79. package/dist/stacks/dna-emitter.js +69 -69
  80. package/dist/stacks/ruby-rails-8/scaffold.js +15 -15
  81. package/dist/utils/project-generator.d.ts.map +1 -1
  82. package/dist/utils/project-generator.js +254 -252
  83. package/dist/utils/project-generator.js.map +1 -1
  84. package/dist/utils/stack-bootstrap.js +371 -371
  85. package/dist/utils/templates.js +394 -394
  86. package/dist/verification/__tests__/anti-tamper.test.js +13 -13
  87. package/package.json +96 -93
  88. package/templates/DARE-dag-example.yaml +280 -280
  89. package/templates/UPDATE-MANIFEST.json +68 -68
  90. package/templates/backend/node-nestjs/.env.example +9 -9
  91. package/templates/backend/node-nestjs/nest-cli.json +8 -8
  92. package/templates/backend/node-nestjs/package.json +50 -50
  93. package/templates/backend/node-nestjs/src/app.controller.ts +12 -12
  94. package/templates/backend/node-nestjs/src/app.module.ts +15 -15
  95. package/templates/backend/node-nestjs/src/app.service.ts +8 -8
  96. package/templates/backend/node-nestjs/src/main.ts +24 -24
  97. package/templates/backend/node-nestjs/tsconfig.json +21 -21
  98. package/templates/backend/php-laravel/.env.example +22 -22
  99. package/templates/backend/php-laravel/app/Http/Controllers/HealthController.php +15 -15
  100. package/templates/backend/php-laravel/composer.json +40 -40
  101. package/templates/backend/python-fastapi/.env.example +4 -4
  102. package/templates/backend/python-fastapi/app/api/router.py +8 -8
  103. package/templates/backend/python-fastapi/app/core/config.py +20 -20
  104. package/templates/backend/python-fastapi/main.py +35 -35
  105. package/templates/backend/python-fastapi/requirements.txt +13 -13
  106. package/templates/backend/rust-axum/.env.example +3 -3
  107. package/templates/backend/rust-axum/Cargo.toml +23 -23
  108. package/templates/backend/rust-axum/src/errors.rs +30 -30
  109. package/templates/backend/rust-axum/src/main.rs +32 -32
  110. package/templates/backend/rust-axum/src/routes.rs +6 -6
  111. package/templates/frontend/leptos-csr/.cargo/config.toml +2 -2
  112. package/templates/frontend/leptos-csr/Cargo.toml +16 -16
  113. package/templates/frontend/leptos-csr/Trunk.toml +10 -10
  114. package/templates/frontend/leptos-csr/index.html +11 -11
  115. package/templates/frontend/leptos-csr/src/lib.rs +20 -20
  116. package/templates/frontend/leptos-csr/style/main.scss +19 -19
  117. package/templates/frontend/leptos-fullstack/.cargo/config.toml +4 -4
  118. package/templates/frontend/leptos-fullstack/Cargo.toml +56 -56
  119. package/templates/frontend/leptos-fullstack/src/app.rs +49 -49
  120. package/templates/frontend/leptos-fullstack/src/lib.rs +9 -9
  121. package/templates/frontend/leptos-fullstack/src/main.rs +29 -29
  122. package/templates/frontend/leptos-fullstack/style/main.scss +19 -19
  123. package/templates/frontend/react/index.html +12 -12
  124. package/templates/frontend/react/package.json +35 -35
  125. package/templates/frontend/react/src/App.tsx +25 -25
  126. package/templates/frontend/react/src/main.tsx +9 -9
  127. package/templates/frontend/vue/package.json +32 -32
  128. package/templates/frontend/vue/src/App.vue +7 -7
  129. package/templates/frontend/vue/src/main.ts +10 -10
  130. package/templates/frontend/vue/src/router/index.ts +14 -14
  131. package/templates/frontend/vue/src/views/HomeView.vue +6 -6
  132. package/templates/hooks/pre-commit-dare-validate +24 -24
  133. package/templates/ide/antigravity/.agents/skills/dare-ax/SKILL.md +152 -152
  134. package/templates/ide/antigravity/.agents/skills/dare-bench/SKILL.md +21 -21
  135. package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +368 -368
  136. package/templates/ide/antigravity/.agents/skills/dare-bootstrap/SKILL.md +32 -32
  137. package/templates/ide/antigravity/.agents/skills/dare-bugfix-design/SKILL.md +76 -76
  138. package/templates/ide/antigravity/.agents/skills/dare-dag/SKILL.md +32 -32
  139. package/templates/ide/antigravity/.agents/skills/dare-dag-build/SKILL.md +154 -154
  140. package/templates/ide/antigravity/.agents/skills/dare-dag-run/SKILL.md +130 -130
  141. package/templates/ide/antigravity/.agents/skills/dare-dag-runner/SKILL.md +203 -203
  142. package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +180 -180
  143. package/templates/ide/antigravity/.agents/skills/dare-discover/SKILL.md +33 -33
  144. package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +63 -63
  145. package/templates/ide/antigravity/.agents/skills/dare-docker/SKILL.md +315 -315
  146. package/templates/ide/antigravity/.agents/skills/dare-execute/SKILL.md +264 -264
  147. package/templates/ide/antigravity/.agents/skills/dare-feature-design/SKILL.md +74 -74
  148. package/templates/ide/antigravity/.agents/skills/dare-frontend-design/SKILL.md +192 -192
  149. package/templates/ide/antigravity/.agents/skills/dare-graph/SKILL.md +35 -35
  150. package/templates/ide/antigravity/.agents/skills/dare-info/SKILL.md +31 -31
  151. package/templates/ide/antigravity/.agents/skills/dare-init/SKILL.md +35 -35
  152. package/templates/ide/antigravity/.agents/skills/dare-laravel-api/SKILL.md +337 -337
  153. package/templates/ide/antigravity/.agents/skills/dare-layered-design/SKILL.md +166 -166
  154. package/templates/ide/antigravity/.agents/skills/dare-llm-integration/SKILL.md +217 -217
  155. package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +61 -61
  156. package/templates/ide/antigravity/.agents/skills/dare-quality-telemetry/SKILL.md +187 -187
  157. package/templates/ide/antigravity/.agents/skills/dare-realtime/SKILL.md +217 -217
  158. package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +114 -114
  159. package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +108 -108
  160. package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +111 -111
  161. package/templates/ide/antigravity/.agents/skills/dare-rust-leptos/SKILL.md +263 -263
  162. package/templates/ide/antigravity/.agents/skills/dare-rust-workspace/SKILL.md +275 -275
  163. package/templates/ide/antigravity/.agents/skills/dare-security/SKILL.md +274 -274
  164. package/templates/ide/antigravity/.agents/skills/dare-skill/SKILL.md +35 -35
  165. package/templates/ide/antigravity/.agents/skills/dare-tasks/SKILL.md +265 -265
  166. package/templates/ide/antigravity/.agents/skills/dare-telemetry/SKILL.md +188 -188
  167. package/templates/ide/antigravity/.agents/skills/dare-update/SKILL.md +33 -33
  168. package/templates/ide/antigravity/.agents/skills/dare-validate/SKILL.md +33 -33
  169. package/templates/ide/antigravity/.agents/skills/dare-welcome/SKILL.md +30 -30
  170. package/templates/ide/antigravity/.agents/skills/skill-fastapi-api/SKILL.md +343 -343
  171. package/templates/ide/antigravity/.agents/skills/skill-go-gin-api/SKILL.md +377 -377
  172. package/templates/ide/antigravity/.agents/skills/skill-mcp-server/SKILL.md +382 -382
  173. package/templates/ide/antigravity/.agents/skills/skill-nestjs-api/SKILL.md +326 -326
  174. package/templates/ide/antigravity/.agents/skills/skill-rails-api/SKILL.md +393 -393
  175. package/templates/ide/antigravity/templates/BLUEPRINT-template.md +193 -193
  176. package/templates/ide/antigravity/templates/DESIGN-template.md +129 -129
  177. package/templates/ide/antigravity/templates/TASK-SPEC-template.md +141 -141
  178. package/templates/ide/antigravity/templates/TASKS-template.md +26 -26
  179. package/templates/ide/antigravity/templates/TELEMETRY-template.md +125 -125
  180. package/templates/ide/claude/.claude/commands/dare-ax.md +131 -131
  181. package/templates/ide/claude/.claude/commands/dare-bench.md +18 -18
  182. package/templates/ide/claude/.claude/commands/dare-blueprint.md +134 -134
  183. package/templates/ide/claude/.claude/commands/dare-bootstrap.md +27 -27
  184. package/templates/ide/claude/.claude/commands/dare-bugfix-design.md +119 -119
  185. package/templates/ide/claude/.claude/commands/dare-dag-build.md +151 -151
  186. package/templates/ide/claude/.claude/commands/dare-dag-run.md +109 -109
  187. package/templates/ide/claude/.claude/commands/dare-dag-runner.md +117 -117
  188. package/templates/ide/claude/.claude/commands/dare-dag-viz.md +197 -197
  189. package/templates/ide/claude/.claude/commands/dare-dag.md +27 -27
  190. package/templates/ide/claude/.claude/commands/dare-design.md +69 -69
  191. package/templates/ide/claude/.claude/commands/dare-discover.md +28 -28
  192. package/templates/ide/claude/.claude/commands/dare-dna.md +75 -75
  193. package/templates/ide/claude/.claude/commands/dare-docker.md +207 -207
  194. package/templates/ide/claude/.claude/commands/dare-execute.md +152 -152
  195. package/templates/ide/claude/.claude/commands/dare-feature-design.md +147 -147
  196. package/templates/ide/claude/.claude/commands/dare-frontend-design.md +149 -149
  197. package/templates/ide/claude/.claude/commands/dare-graph.md +30 -30
  198. package/templates/ide/claude/.claude/commands/dare-info.md +26 -26
  199. package/templates/ide/claude/.claude/commands/dare-init.md +30 -30
  200. package/templates/ide/claude/.claude/commands/dare-laravel-api.md +211 -211
  201. package/templates/ide/claude/.claude/commands/dare-layered-design.md +124 -124
  202. package/templates/ide/claude/.claude/commands/dare-llm-integration.md +148 -148
  203. package/templates/ide/claude/.claude/commands/dare-migrate.md +72 -72
  204. package/templates/ide/claude/.claude/commands/dare-quality-telemetry.md +166 -166
  205. package/templates/ide/claude/.claude/commands/dare-realtime.md +159 -159
  206. package/templates/ide/claude/.claude/commands/dare-refine.md +145 -145
  207. package/templates/ide/claude/.claude/commands/dare-reverse.md +139 -139
  208. package/templates/ide/claude/.claude/commands/dare-review.md +113 -113
  209. package/templates/ide/claude/.claude/commands/dare-rust-leptos.md +269 -269
  210. package/templates/ide/claude/.claude/commands/dare-rust-workspace.md +209 -209
  211. package/templates/ide/claude/.claude/commands/dare-security.md +232 -232
  212. package/templates/ide/claude/.claude/commands/dare-skill.md +30 -30
  213. package/templates/ide/claude/.claude/commands/dare-tasks.md +70 -70
  214. package/templates/ide/claude/.claude/commands/dare-telemetry.md +132 -132
  215. package/templates/ide/claude/.claude/commands/dare-update.md +28 -28
  216. package/templates/ide/claude/.claude/commands/dare-validate.md +28 -28
  217. package/templates/ide/claude/.claude/commands/dare-welcome.md +25 -25
  218. package/templates/ide/claude/.claude/commands/skill-fastapi-api.md +205 -205
  219. package/templates/ide/claude/.claude/commands/skill-go-gin-api.md +232 -232
  220. package/templates/ide/claude/.claude/commands/skill-mcp-server.md +228 -228
  221. package/templates/ide/claude/.claude/commands/skill-nestjs-api.md +210 -210
  222. package/templates/ide/claude/.claude/commands/skill-rails-api.md +236 -236
  223. package/templates/ide/claude/.claude/settings.example.json +35 -35
  224. package/templates/ide/claude/CLAUDE.md +146 -146
  225. package/templates/ide/claude/templates/BLUEPRINT-template.md +193 -193
  226. package/templates/ide/claude/templates/DESIGN-template.md +129 -129
  227. package/templates/ide/claude/templates/TASK-SPEC-template.md +141 -141
  228. package/templates/ide/claude/templates/TASKS-template.md +26 -26
  229. package/templates/ide/claude/templates/TELEMETRY-template.md +125 -125
  230. package/templates/ide/cursor/.cursor/commands/dare-bench.md +18 -18
  231. package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +86 -86
  232. package/templates/ide/cursor/.cursor/commands/dare-bootstrap.md +27 -27
  233. package/templates/ide/cursor/.cursor/commands/dare-bugfix-design.md +64 -64
  234. package/templates/ide/cursor/.cursor/commands/dare-dag-run.md +110 -110
  235. package/templates/ide/cursor/.cursor/commands/dare-dag-viz.md +139 -139
  236. package/templates/ide/cursor/.cursor/commands/dare-dag.md +27 -27
  237. package/templates/ide/cursor/.cursor/commands/dare-design.md +35 -35
  238. package/templates/ide/cursor/.cursor/commands/dare-discover.md +28 -28
  239. package/templates/ide/cursor/.cursor/commands/dare-dna.md +75 -75
  240. package/templates/ide/cursor/.cursor/commands/dare-docker-compose.md +18 -18
  241. package/templates/ide/cursor/.cursor/commands/dare-dockerfile.md +17 -17
  242. package/templates/ide/cursor/.cursor/commands/dare-execute.md +19 -19
  243. package/templates/ide/cursor/.cursor/commands/dare-feature-design.md +64 -64
  244. package/templates/ide/cursor/.cursor/commands/dare-graph.md +30 -30
  245. package/templates/ide/cursor/.cursor/commands/dare-info.md +26 -26
  246. package/templates/ide/cursor/.cursor/commands/dare-init.md +30 -30
  247. package/templates/ide/cursor/.cursor/commands/dare-migrate.md +72 -72
  248. package/templates/ide/cursor/.cursor/commands/dare-refine.md +107 -107
  249. package/templates/ide/cursor/.cursor/commands/dare-reverse.md +139 -139
  250. package/templates/ide/cursor/.cursor/commands/dare-review.md +91 -91
  251. package/templates/ide/cursor/.cursor/commands/dare-skill.md +30 -30
  252. package/templates/ide/cursor/.cursor/commands/dare-tasks.md +184 -184
  253. package/templates/ide/cursor/.cursor/commands/dare-telemetry.md +42 -42
  254. package/templates/ide/cursor/.cursor/commands/dare-update.md +28 -28
  255. package/templates/ide/cursor/.cursor/commands/dare-validate.md +28 -28
  256. package/templates/ide/cursor/.cursor/commands/dare-welcome.md +25 -25
  257. package/templates/ide/cursor/.cursor/rules/skill-ax.mdc +263 -263
  258. package/templates/ide/cursor/.cursor/rules/skill-bugfix-design.mdc +51 -51
  259. package/templates/ide/cursor/.cursor/rules/skill-dag-build.mdc +173 -173
  260. package/templates/ide/cursor/.cursor/rules/skill-dag-run.mdc +134 -134
  261. package/templates/ide/cursor/.cursor/rules/skill-dag-runner.mdc +221 -221
  262. package/templates/ide/cursor/.cursor/rules/skill-dna.mdc +63 -63
  263. package/templates/ide/cursor/.cursor/rules/skill-docker.mdc +33 -33
  264. package/templates/ide/cursor/.cursor/rules/skill-fastapi-api.mdc +352 -352
  265. package/templates/ide/cursor/.cursor/rules/skill-feature-design.mdc +43 -43
  266. package/templates/ide/cursor/.cursor/rules/skill-frontend-design.mdc +244 -244
  267. package/templates/ide/cursor/.cursor/rules/skill-go-gin-api.mdc +371 -371
  268. package/templates/ide/cursor/.cursor/rules/skill-laravel-api.mdc +44 -44
  269. package/templates/ide/cursor/.cursor/rules/skill-layered-design.mdc +266 -266
  270. package/templates/ide/cursor/.cursor/rules/skill-llm-integration.mdc +295 -295
  271. package/templates/ide/cursor/.cursor/rules/skill-mcp-server.mdc +367 -367
  272. package/templates/ide/cursor/.cursor/rules/skill-migrate.mdc +58 -58
  273. package/templates/ide/cursor/.cursor/rules/skill-nestjs-api.mdc +346 -346
  274. package/templates/ide/cursor/.cursor/rules/skill-quality-telemetry.mdc +248 -248
  275. package/templates/ide/cursor/.cursor/rules/skill-rails-api.mdc +400 -400
  276. package/templates/ide/cursor/.cursor/rules/skill-realtime.mdc +262 -262
  277. package/templates/ide/cursor/.cursor/rules/skill-reverse.mdc +107 -107
  278. package/templates/ide/cursor/.cursor/rules/skill-rust-leptos.mdc +281 -281
  279. package/templates/ide/cursor/.cursor/rules/skill-rust-workspace.mdc +312 -312
  280. package/templates/ide/cursor/.cursor/rules/skill-security.mdc +245 -245
  281. package/templates/ide/cursor/.cursor/rules/skill-telemetry.mdc +156 -156
  282. package/templates/ide/cursor/templates/BLUEPRINT-template.md +193 -193
  283. package/templates/ide/cursor/templates/DESIGN-template.md +129 -129
  284. package/templates/ide/cursor/templates/TASK-SPEC-template.md +141 -141
  285. package/templates/ide/cursor/templates/TASKS-template.md +26 -26
  286. package/templates/ide/cursor/templates/TELEMETRY-template.md +125 -125
  287. package/templates/shared/docker-compose.yml +41 -41
  288. package/templates/stacks/go-gin/.dare/skills.yml +11 -11
  289. package/templates/stacks/go-gin/.env.example +24 -24
  290. package/templates/stacks/go-gin/.github/workflows/dare-ci.yml +42 -42
  291. package/templates/stacks/go-gin/README.md.tpl +38 -38
  292. package/templates/stacks/go-gin/cmd/server/main.go.tpl +78 -78
  293. package/templates/stacks/go-gin/db/migrations/0001_create_users.down.sql +2 -2
  294. package/templates/stacks/go-gin/db/migrations/0001_create_users.up.sql +12 -12
  295. package/templates/stacks/go-gin/db/queries/users.sql +23 -23
  296. package/templates/stacks/go-gin/gitignore +7 -7
  297. package/templates/stacks/go-gin/go.mod.tpl +17 -17
  298. package/templates/stacks/go-gin/internal/config/config.go +41 -41
  299. package/templates/stacks/go-gin/internal/db/postgres.go.tpl +25 -25
  300. package/templates/stacks/go-gin/internal/handler/auth_handler.go.tpl +72 -72
  301. package/templates/stacks/go-gin/internal/handler/users_handler.go.tpl +72 -72
  302. package/templates/stacks/go-gin/internal/handler/ws_handler.go +37 -37
  303. package/templates/stacks/go-gin/internal/llm/dummy.go +14 -14
  304. package/templates/stacks/go-gin/internal/llm/provider.go +8 -8
  305. package/templates/stacks/go-gin/internal/middleware/jwt.go.tpl +58 -58
  306. package/templates/stacks/go-gin/internal/middleware/rate_limit.go +55 -55
  307. package/templates/stacks/go-gin/internal/model/user.go +17 -17
  308. package/templates/stacks/go-gin/internal/repository/users_repository.go.tpl +79 -79
  309. package/templates/stacks/go-gin/internal/service/auth_service.go.tpl +55 -55
  310. package/templates/stacks/go-gin/internal/service/users_service.go.tpl +53 -53
  311. package/templates/stacks/go-gin/llms.txt.tpl +54 -54
  312. package/templates/stacks/go-gin/openapi.json.tpl +46 -46
  313. package/templates/stacks/go-gin/sqlc.yaml +14 -14
  314. package/templates/stacks/go-gin/tests/smoke_test.go.tpl +22 -22
  315. package/templates/stacks/go-stdlib/.dare/skills.yml +11 -11
  316. package/templates/stacks/go-stdlib/.env.example +24 -24
  317. package/templates/stacks/go-stdlib/.github/workflows/dare-ci.yml +42 -42
  318. package/templates/stacks/go-stdlib/README.md.tpl +41 -41
  319. package/templates/stacks/go-stdlib/cmd/server/main.go.tpl +82 -82
  320. package/templates/stacks/go-stdlib/db/migrations/0001_create_users.down.sql +2 -2
  321. package/templates/stacks/go-stdlib/db/migrations/0001_create_users.up.sql +12 -12
  322. package/templates/stacks/go-stdlib/db/queries/users.sql +23 -23
  323. package/templates/stacks/go-stdlib/gitignore +6 -6
  324. package/templates/stacks/go-stdlib/go.mod.tpl +15 -15
  325. package/templates/stacks/go-stdlib/internal/config/config.go +41 -41
  326. package/templates/stacks/go-stdlib/internal/db/postgres.go.tpl +24 -24
  327. package/templates/stacks/go-stdlib/internal/handler/auth_handler.go.tpl +71 -71
  328. package/templates/stacks/go-stdlib/internal/handler/users_handler.go.tpl +84 -84
  329. package/templates/stacks/go-stdlib/internal/handler/ws_handler.go +36 -36
  330. package/templates/stacks/go-stdlib/internal/httpx/json.go +32 -32
  331. package/templates/stacks/go-stdlib/internal/llm/dummy.go +14 -14
  332. package/templates/stacks/go-stdlib/internal/llm/provider.go +8 -8
  333. package/templates/stacks/go-stdlib/internal/middleware/chain.go +21 -21
  334. package/templates/stacks/go-stdlib/internal/middleware/cors.go +27 -27
  335. package/templates/stacks/go-stdlib/internal/middleware/jwt.go.tpl +51 -51
  336. package/templates/stacks/go-stdlib/internal/middleware/rate_limit.go +81 -81
  337. package/templates/stacks/go-stdlib/internal/model/user.go +17 -17
  338. package/templates/stacks/go-stdlib/internal/repository/users_repository.go.tpl +75 -75
  339. package/templates/stacks/go-stdlib/internal/service/auth_service.go.tpl +55 -55
  340. package/templates/stacks/go-stdlib/internal/service/users_service.go.tpl +53 -53
  341. package/templates/stacks/go-stdlib/llms.txt.tpl +60 -60
  342. package/templates/stacks/go-stdlib/openapi.json.tpl +46 -46
  343. package/templates/stacks/go-stdlib/sqlc.yaml +14 -14
  344. package/templates/stacks/go-stdlib/tests/smoke_test.go.tpl +45 -45
  345. package/templates/stacks/mcp-go/.dare/skills.yml +8 -8
  346. package/templates/stacks/mcp-go/.env.example +14 -14
  347. package/templates/stacks/mcp-go/.github/workflows/dare-ci.yml +42 -42
  348. package/templates/stacks/mcp-go/README.md.tpl +50 -50
  349. package/templates/stacks/mcp-go/cmd/server/main.go.tpl +62 -62
  350. package/templates/stacks/mcp-go/gitignore +6 -6
  351. package/templates/stacks/mcp-go/go.mod.tpl +9 -9
  352. package/templates/stacks/mcp-go/internal/prompts/summarize.go +9 -9
  353. package/templates/stacks/mcp-go/internal/server/server.go.tpl +80 -80
  354. package/templates/stacks/mcp-go/internal/tools/echo.go +15 -15
  355. package/templates/stacks/mcp-go/internal/transports/http.go.tpl +21 -21
  356. package/templates/stacks/mcp-go/internal/transports/sse.go.tpl +17 -17
  357. package/templates/stacks/mcp-go/internal/transports/stdio.go.tpl +14 -14
  358. package/templates/stacks/mcp-go/llms.txt.tpl +60 -60
  359. package/templates/stacks/mcp-go/openapi.json.tpl +31 -31
  360. package/templates/stacks/mcp-go/tests/echo_test.go.tpl +37 -37
  361. package/templates/stacks/mcp-node-ts/.dare/skills.yml +8 -8
  362. package/templates/stacks/mcp-node-ts/.env.example +16 -16
  363. package/templates/stacks/mcp-node-ts/.github/workflows/dare-ci.yml +54 -54
  364. package/templates/stacks/mcp-node-ts/README.md.hbs +49 -49
  365. package/templates/stacks/mcp-node-ts/gitignore +7 -7
  366. package/templates/stacks/mcp-node-ts/llms.txt.hbs +61 -61
  367. package/templates/stacks/mcp-node-ts/openapi.json.hbs +39 -39
  368. package/templates/stacks/mcp-node-ts/package.json.hbs +35 -35
  369. package/templates/stacks/mcp-node-ts/src/cli.ts.hbs +71 -71
  370. package/templates/stacks/mcp-node-ts/src/prompts/index.ts +36 -36
  371. package/templates/stacks/mcp-node-ts/src/server.ts.hbs +45 -45
  372. package/templates/stacks/mcp-node-ts/src/tools/echo.ts +23 -23
  373. package/templates/stacks/mcp-node-ts/src/tools/index.ts +18 -18
  374. package/templates/stacks/mcp-node-ts/src/transports/http.ts +68 -68
  375. package/templates/stacks/mcp-node-ts/src/transports/sse.ts +58 -58
  376. package/templates/stacks/mcp-node-ts/src/transports/stdio.ts +5 -5
  377. package/templates/stacks/mcp-node-ts/tests/echo.test.ts +50 -50
  378. package/templates/stacks/mcp-node-ts/tsconfig.json +17 -17
  379. package/templates/stacks/mcp-python/.dare/skills.yml +8 -8
  380. package/templates/stacks/mcp-python/.env.example +14 -14
  381. package/templates/stacks/mcp-python/.github/workflows/dare-ci.yml +42 -42
  382. package/templates/stacks/mcp-python/README.md.j2 +49 -49
  383. package/templates/stacks/mcp-python/gitignore +12 -12
  384. package/templates/stacks/mcp-python/llms.txt.j2 +56 -56
  385. package/templates/stacks/mcp-python/openapi.json.j2 +33 -33
  386. package/templates/stacks/mcp-python/pyproject.toml.j2 +37 -37
  387. package/templates/stacks/mcp-python/src/cli.py.j2 +68 -68
  388. package/templates/stacks/mcp-python/src/prompts/summarize.py +10 -10
  389. package/templates/stacks/mcp-python/src/server.py.j2 +28 -28
  390. package/templates/stacks/mcp-python/src/tools/echo.py +12 -12
  391. package/templates/stacks/mcp-python/src/transports/http.py +12 -12
  392. package/templates/stacks/mcp-python/src/transports/sse.py +13 -13
  393. package/templates/stacks/mcp-python/src/transports/stdio.py +6 -6
  394. package/templates/stacks/mcp-python/tests/test_echo.py +28 -28
  395. package/templates/stacks/mcp-rust/.dare/skills.yml +8 -8
  396. package/templates/stacks/mcp-rust/.env.example +14 -14
  397. package/templates/stacks/mcp-rust/.github/workflows/dare-ci.yml +38 -38
  398. package/templates/stacks/mcp-rust/Cargo.toml.tera +35 -35
  399. package/templates/stacks/mcp-rust/README.md.tera +50 -50
  400. package/templates/stacks/mcp-rust/gitignore +5 -5
  401. package/templates/stacks/mcp-rust/llms.txt.tera +60 -60
  402. package/templates/stacks/mcp-rust/openapi.json.tera +31 -31
  403. package/templates/stacks/mcp-rust/src/cli.rs.tera +33 -33
  404. package/templates/stacks/mcp-rust/src/lib.rs +6 -6
  405. package/templates/stacks/mcp-rust/src/main.rs.tera +30 -30
  406. package/templates/stacks/mcp-rust/src/prompts/mod.rs +1 -1
  407. package/templates/stacks/mcp-rust/src/prompts/summarize.rs +5 -5
  408. package/templates/stacks/mcp-rust/src/server.rs.tera +38 -38
  409. package/templates/stacks/mcp-rust/src/tools/echo.rs +18 -18
  410. package/templates/stacks/mcp-rust/src/tools/mod.rs +22 -22
  411. package/templates/stacks/mcp-rust/src/transports/http.rs +27 -27
  412. package/templates/stacks/mcp-rust/src/transports/mod.rs +3 -3
  413. package/templates/stacks/mcp-rust/src/transports/sse.rs +33 -33
  414. package/templates/stacks/mcp-rust/src/transports/stdio.rs +14 -14
  415. package/templates/stacks/mcp-rust/tests/echo_test.rs.tera +27 -27
  416. package/templates/stacks/node-nestjs/.dare/skills.yml +11 -11
  417. package/templates/stacks/node-nestjs/.env.example +21 -21
  418. package/templates/stacks/node-nestjs/.github/workflows/dare-ci.yml +54 -54
  419. package/templates/stacks/node-nestjs/README.md.hbs +35 -35
  420. package/templates/stacks/node-nestjs/gitignore +7 -7
  421. package/templates/stacks/node-nestjs/llms.txt.hbs +47 -47
  422. package/templates/stacks/node-nestjs/nest-cli.json +16 -16
  423. package/templates/stacks/node-nestjs/openapi.json.hbs +75 -75
  424. package/templates/stacks/node-nestjs/package.json.hbs +57 -57
  425. package/templates/stacks/node-nestjs/prisma/schema.prisma +25 -25
  426. package/templates/stacks/node-nestjs/prisma/seed.ts.hbs +25 -25
  427. package/templates/stacks/node-nestjs/src/app.module.ts +39 -39
  428. package/templates/stacks/node-nestjs/src/auth/auth.controller.ts +29 -29
  429. package/templates/stacks/node-nestjs/src/auth/auth.module.ts +25 -25
  430. package/templates/stacks/node-nestjs/src/auth/auth.service.ts +36 -36
  431. package/templates/stacks/node-nestjs/src/auth/dto/login-response.dto.ts +9 -9
  432. package/templates/stacks/node-nestjs/src/auth/dto/login.dto.ts +17 -17
  433. package/templates/stacks/node-nestjs/src/auth/jwt.strategy.ts +25 -25
  434. package/templates/stacks/node-nestjs/src/common/filters/problem-details.filter.ts +38 -38
  435. package/templates/stacks/node-nestjs/src/common/interceptors/json-response.interceptor.ts +13 -13
  436. package/templates/stacks/node-nestjs/src/main.ts.hbs +44 -44
  437. package/templates/stacks/node-nestjs/src/prisma/prisma.module.ts +9 -9
  438. package/templates/stacks/node-nestjs/src/prisma/prisma.service.ts +9 -9
  439. package/templates/stacks/node-nestjs/src/users/dto/create-user.dto.ts +22 -22
  440. package/templates/stacks/node-nestjs/src/users/dto/user.dto.ts +15 -15
  441. package/templates/stacks/node-nestjs/src/users/users.controller.ts +41 -41
  442. package/templates/stacks/node-nestjs/src/users/users.module.ts +11 -11
  443. package/templates/stacks/node-nestjs/src/users/users.repository.ts +38 -38
  444. package/templates/stacks/node-nestjs/src/users/users.service.ts +38 -38
  445. package/templates/stacks/node-nestjs/tsconfig.build.json +4 -4
  446. package/templates/stacks/node-nestjs/tsconfig.json +28 -28
  447. package/templates/stacks/php-laravel/.dare/skills.yml +11 -11
  448. package/templates/stacks/php-laravel/.env.example +41 -41
  449. package/templates/stacks/php-laravel/.github/workflows/dare-ci.yml +43 -43
  450. package/templates/stacks/php-laravel/README.md.hbs +36 -36
  451. package/templates/stacks/php-laravel/app/Http/Controllers/Api/AuthController.php +36 -36
  452. package/templates/stacks/php-laravel/app/Http/Controllers/Api/UsersController.php +33 -33
  453. package/templates/stacks/php-laravel/app/Http/Requests/CreateUserRequest.php +26 -26
  454. package/templates/stacks/php-laravel/app/Http/Requests/LoginRequest.php +34 -34
  455. package/templates/stacks/php-laravel/app/Llm/Contracts/LlmProvider.php +12 -12
  456. package/templates/stacks/php-laravel/app/Llm/Providers/DummyProvider.php +13 -13
  457. package/templates/stacks/php-laravel/app/Llm/Providers/OpenAiProvider.php +33 -33
  458. package/templates/stacks/php-laravel/app/Models/User.php +44 -44
  459. package/templates/stacks/php-laravel/app/Repositories/UsersRepository.php +32 -32
  460. package/templates/stacks/php-laravel/app/Services/AuthService.php +37 -37
  461. package/templates/stacks/php-laravel/app/Services/UsersService.php +57 -57
  462. package/templates/stacks/php-laravel/artisan +12 -12
  463. package/templates/stacks/php-laravel/bootstrap/app.php +29 -29
  464. package/templates/stacks/php-laravel/bootstrap/providers.php +5 -5
  465. package/templates/stacks/php-laravel/composer.json.hbs +58 -58
  466. package/templates/stacks/php-laravel/config/l5-swagger.php +41 -41
  467. package/templates/stacks/php-laravel/config/reverb.php +34 -34
  468. package/templates/stacks/php-laravel/config/sanctum.php +15 -15
  469. package/templates/stacks/php-laravel/database/migrations/2026_06_01_000001_create_users_table.php +27 -27
  470. package/templates/stacks/php-laravel/database/seeders/DatabaseSeeder.php +21 -21
  471. package/templates/stacks/php-laravel/gitignore +23 -23
  472. package/templates/stacks/php-laravel/llms.txt.hbs +53 -53
  473. package/templates/stacks/php-laravel/openapi.json.hbs +43 -43
  474. package/templates/stacks/php-laravel/phpstan.neon +9 -9
  475. package/templates/stacks/php-laravel/routes/api.php +13 -13
  476. package/templates/stacks/php-laravel/routes/channels.php +7 -7
  477. package/templates/stacks/php-laravel/tests/Feature/AuthTest.php +35 -35
  478. package/templates/stacks/php-laravel/tests/Feature/UsersTest.php +30 -30
  479. package/templates/stacks/php-laravel/tests/Pest.php +5 -5
  480. package/templates/stacks/python-fastapi/.dare/skills.yml +11 -11
  481. package/templates/stacks/python-fastapi/.env.example +21 -21
  482. package/templates/stacks/python-fastapi/.github/workflows/dare-ci.yml +43 -43
  483. package/templates/stacks/python-fastapi/README.md.j2 +35 -35
  484. package/templates/stacks/python-fastapi/alembic/env.py +46 -46
  485. package/templates/stacks/python-fastapi/alembic/script.py.mako +26 -26
  486. package/templates/stacks/python-fastapi/alembic/versions/0001_create_users.py.j2 +37 -37
  487. package/templates/stacks/python-fastapi/alembic.ini.j2 +39 -39
  488. package/templates/stacks/python-fastapi/app/core/config.py +24 -24
  489. package/templates/stacks/python-fastapi/app/core/security.py +34 -34
  490. package/templates/stacks/python-fastapi/app/db/session.py +22 -22
  491. package/templates/stacks/python-fastapi/app/main.py.j2 +36 -36
  492. package/templates/stacks/python-fastapi/app/models/__init__.py +3 -3
  493. package/templates/stacks/python-fastapi/app/models/user.py +30 -30
  494. package/templates/stacks/python-fastapi/app/repositories/user_repository.py +34 -34
  495. package/templates/stacks/python-fastapi/app/routers/auth.py +37 -37
  496. package/templates/stacks/python-fastapi/app/routers/users.py +46 -46
  497. package/templates/stacks/python-fastapi/app/schemas/user.py +56 -56
  498. package/templates/stacks/python-fastapi/app/services/auth_service.py +22 -22
  499. package/templates/stacks/python-fastapi/app/services/user_service.py +31 -31
  500. package/templates/stacks/python-fastapi/gitignore +12 -12
  501. package/templates/stacks/python-fastapi/llms.txt.j2 +53 -53
  502. package/templates/stacks/python-fastapi/openapi.json.j2 +43 -43
  503. package/templates/stacks/python-fastapi/pyproject.toml.j2 +45 -45
  504. package/templates/stacks/python-fastapi/tests/test_auth.py +22 -22
  505. package/templates/stacks/ruby-rails-8/.dare/skills.yml +50 -50
  506. package/templates/stacks/ruby-rails-8/.env.example +20 -20
  507. package/templates/stacks/ruby-rails-8/.github/workflows/dare-ci.yml +112 -112
  508. package/templates/stacks/ruby-rails-8/Gemfile.erb +61 -61
  509. package/templates/stacks/ruby-rails-8/app/channels/application_cable/channel.rb +11 -11
  510. package/templates/stacks/ruby-rails-8/app/channels/application_cable/connection.rb +34 -34
  511. package/templates/stacks/ruby-rails-8/app/channels/dare_updates_channel.rb +18 -18
  512. package/templates/stacks/ruby-rails-8/app/channels/user_updates_channel.rb +23 -23
  513. package/templates/stacks/ruby-rails-8/app/controllers/application_controller.rb +44 -44
  514. package/templates/stacks/ruby-rails-8/app/controllers/concerns/problem_details.rb +93 -93
  515. package/templates/stacks/ruby-rails-8/app/handlers/summarize_handler.rb +33 -33
  516. package/templates/stacks/ruby-rails-8/app/handlers/users_handler.rb +68 -68
  517. package/templates/stacks/ruby-rails-8/app/llm/cache/llm_cache.rb +44 -44
  518. package/templates/stacks/ruby-rails-8/app/llm/prompts/prompt_loader.rb +54 -54
  519. package/templates/stacks/ruby-rails-8/app/llm/prompts/summarize_v1.jinja2 +12 -12
  520. package/templates/stacks/ruby-rails-8/app/llm/providers/dummy_provider.rb +35 -35
  521. package/templates/stacks/ruby-rails-8/app/llm/providers/llm_provider.rb +67 -67
  522. package/templates/stacks/ruby-rails-8/app/llm/providers/openai_provider.rb +62 -62
  523. package/templates/stacks/ruby-rails-8/app/llm/rate_limit/token_bucket.rb +82 -82
  524. package/templates/stacks/ruby-rails-8/app/llm/validators/summarize_output_schema.json +21 -21
  525. package/templates/stacks/ruby-rails-8/app/llm/validators/validator.rb +52 -52
  526. package/templates/stacks/ruby-rails-8/app/models/user.rb +36 -36
  527. package/templates/stacks/ruby-rails-8/app/presenters/user_presenter.rb +48 -48
  528. package/templates/stacks/ruby-rails-8/app/repositories/document_repository.rb +57 -57
  529. package/templates/stacks/ruby-rails-8/app/repositories/user_repository.rb +73 -73
  530. package/templates/stacks/ruby-rails-8/app/services/create_user_service.rb +67 -67
  531. package/templates/stacks/ruby-rails-8/app/services/realtime_service.rb +53 -53
  532. package/templates/stacks/ruby-rails-8/app/services/summarize_document_service.rb +57 -57
  533. package/templates/stacks/ruby-rails-8/config/dare.yml +42 -42
  534. package/templates/stacks/ruby-rails-8/config/initializers/dare.rb +31 -31
  535. package/templates/stacks/ruby-rails-8/config/initializers/rack_attack.rb +64 -64
  536. package/templates/stacks/ruby-rails-8/config/initializers/rswag_api.rb +12 -12
  537. package/templates/stacks/ruby-rails-8/lib/tasks/dare.rake +159 -159
  538. package/templates/stacks/ruby-rails-8/llms.txt.erb +69 -69
  539. package/templates/stacks/ruby-rails-8/spec/api/summarize_spec.rb +56 -56
  540. package/templates/stacks/ruby-rails-8/spec/api/users_spec.rb +72 -72
  541. package/templates/stacks/ruby-rails-8/spec/channels/dare_updates_channel_spec.rb +61 -61
  542. package/templates/stacks/ruby-rails-8/spec/channels/user_updates_channel_spec.rb +56 -56
  543. package/templates/stacks/ruby-rails-8/spec/factories/users.rb +27 -27
  544. package/templates/stacks/ruby-rails-8/spec/handlers/users_handler_spec.rb +88 -88
  545. package/templates/stacks/ruby-rails-8/spec/rails_helper.rb +31 -31
  546. package/templates/stacks/ruby-rails-8/spec/services/create_user_service_spec.rb +88 -88
  547. package/templates/stacks/ruby-rails-8/spec/services/summarize_document_service_spec.rb +142 -142
  548. package/templates/stacks/ruby-rails-8/spec/swagger_helper.rb +73 -73
  549. package/templates/stacks/rust-axum/.dare/skills.yml +11 -11
  550. package/templates/stacks/rust-axum/.env.example +26 -26
  551. package/templates/stacks/rust-axum/.github/workflows/dare-ci.yml +40 -40
  552. package/templates/stacks/rust-axum/Cargo.toml.tera +53 -53
  553. package/templates/stacks/rust-axum/README.md.tera +37 -37
  554. package/templates/stacks/rust-axum/gitignore +5 -5
  555. package/templates/stacks/rust-axum/llms.txt.tera +54 -54
  556. package/templates/stacks/rust-axum/migrations/0001_create_users.sql +13 -13
  557. package/templates/stacks/rust-axum/openapi.json.tera +46 -46
  558. package/templates/stacks/rust-axum/src/config.rs +45 -45
  559. package/templates/stacks/rust-axum/src/errors.rs +48 -48
  560. package/templates/stacks/rust-axum/src/handlers/auth.rs +48 -48
  561. package/templates/stacks/rust-axum/src/handlers/mod.rs +3 -3
  562. package/templates/stacks/rust-axum/src/handlers/users.rs +81 -81
  563. package/templates/stacks/rust-axum/src/handlers/ws.rs +24 -24
  564. package/templates/stacks/rust-axum/src/lib.rs +19 -19
  565. package/templates/stacks/rust-axum/src/llm/mod.rs +1 -1
  566. package/templates/stacks/rust-axum/src/llm/provider.rs +48 -48
  567. package/templates/stacks/rust-axum/src/main.rs.tera +64 -64
  568. package/templates/stacks/rust-axum/src/middleware/auth.rs +20 -20
  569. package/templates/stacks/rust-axum/src/middleware/mod.rs +2 -2
  570. package/templates/stacks/rust-axum/src/middleware/rate_limit.rs +27 -27
  571. package/templates/stacks/rust-axum/src/models/mod.rs +1 -1
  572. package/templates/stacks/rust-axum/src/models/user.rs +13 -13
  573. package/templates/stacks/rust-axum/src/repositories/mod.rs +1 -1
  574. package/templates/stacks/rust-axum/src/repositories/user_repository.rs +62 -62
  575. package/templates/stacks/rust-axum/src/services/auth_service.rs +50 -50
  576. package/templates/stacks/rust-axum/src/services/mod.rs +2 -2
  577. package/templates/stacks/rust-axum/src/services/user_service.rs +53 -53
  578. package/templates/stacks/rust-axum/tests/integration_test.rs.tera +13 -13
  579. package/dist/commands/new.d.ts +0 -16
  580. package/dist/commands/new.d.ts.map +0 -1
  581. package/dist/commands/new.js +0 -104
  582. package/dist/commands/new.js.map +0 -1
@@ -1,22 +1,22 @@
1
- """SQLAlchemy engine + session + declarative Base."""
2
- from collections.abc import Generator
3
-
4
- from sqlalchemy import create_engine
5
- from sqlalchemy.orm import DeclarativeBase, Session, sessionmaker
6
-
7
- from app.core.config import settings
8
-
9
- engine = create_engine(settings.database_url, pool_pre_ping=True)
10
- SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
11
-
12
-
13
- class Base(DeclarativeBase):
14
- """Declarative base for all ORM models."""
15
-
16
-
17
- def get_db() -> Generator[Session, None, None]:
18
- db = SessionLocal()
19
- try:
20
- yield db
21
- finally:
22
- db.close()
1
+ """SQLAlchemy engine + session + declarative Base."""
2
+ from collections.abc import Generator
3
+
4
+ from sqlalchemy import create_engine
5
+ from sqlalchemy.orm import DeclarativeBase, Session, sessionmaker
6
+
7
+ from app.core.config import settings
8
+
9
+ engine = create_engine(settings.database_url, pool_pre_ping=True)
10
+ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
11
+
12
+
13
+ class Base(DeclarativeBase):
14
+ """Declarative base for all ORM models."""
15
+
16
+
17
+ def get_db() -> Generator[Session, None, None]:
18
+ db = SessionLocal()
19
+ try:
20
+ yield db
21
+ finally:
22
+ db.close()
@@ -1,36 +1,36 @@
1
- """FastAPI app entrypoint."""
2
- from fastapi import FastAPI
3
- from fastapi.middleware.cors import CORSMiddleware
4
- from slowapi import Limiter, _rate_limit_exceeded_handler
5
- from slowapi.errors import RateLimitExceeded
6
- from slowapi.util import get_remote_address
7
-
8
- from app.core.config import settings
9
- from app.routers import auth, users
10
-
11
- limiter = Limiter(key_func=get_remote_address, default_limits=[f"{settings.rate_limit_per_min}/minute"])
12
-
13
- app = FastAPI(
14
- title="{{ projectName }}",
15
- version="0.1.0",
16
- description="DARE-shaped FastAPI API",
17
- )
18
-
19
- app.state.limiter = limiter
20
- app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
21
-
22
- app.add_middleware(
23
- CORSMiddleware,
24
- allow_origins=settings.cors_origins,
25
- allow_credentials=True,
26
- allow_methods=["*"],
27
- allow_headers=["*"],
28
- )
29
-
30
- app.include_router(auth.router, prefix="/auth", tags=["auth"])
31
- app.include_router(users.router, prefix="/users", tags=["users"])
32
-
33
-
34
- @app.get("/healthz", include_in_schema=False)
35
- def healthz() -> dict[str, str]:
36
- return {"status": "ok"}
1
+ """FastAPI app entrypoint."""
2
+ from fastapi import FastAPI
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from slowapi import Limiter, _rate_limit_exceeded_handler
5
+ from slowapi.errors import RateLimitExceeded
6
+ from slowapi.util import get_remote_address
7
+
8
+ from app.core.config import settings
9
+ from app.routers import auth, users
10
+
11
+ limiter = Limiter(key_func=get_remote_address, default_limits=[f"{settings.rate_limit_per_min}/minute"])
12
+
13
+ app = FastAPI(
14
+ title="{{ projectName }}",
15
+ version="0.1.0",
16
+ description="DARE-shaped FastAPI API",
17
+ )
18
+
19
+ app.state.limiter = limiter
20
+ app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
21
+
22
+ app.add_middleware(
23
+ CORSMiddleware,
24
+ allow_origins=settings.cors_origins,
25
+ allow_credentials=True,
26
+ allow_methods=["*"],
27
+ allow_headers=["*"],
28
+ )
29
+
30
+ app.include_router(auth.router, prefix="/auth", tags=["auth"])
31
+ app.include_router(users.router, prefix="/users", tags=["users"])
32
+
33
+
34
+ @app.get("/healthz", include_in_schema=False)
35
+ def healthz() -> dict[str, str]:
36
+ return {"status": "ok"}
@@ -1,3 +1,3 @@
1
- from app.models.user import User
2
-
3
- __all__ = ["User"]
1
+ from app.models.user import User
2
+
3
+ __all__ = ["User"]
@@ -1,30 +1,30 @@
1
- """User ORM model."""
2
- import uuid
3
- from datetime import datetime
4
- from enum import Enum
5
-
6
- from sqlalchemy import DateTime, Index, String, func
7
- from sqlalchemy.dialects.postgresql import UUID
8
- from sqlalchemy.orm import Mapped, mapped_column
9
-
10
- from app.db.session import Base
11
-
12
-
13
- class Role(str, Enum):
14
- USER = "USER"
15
- ADMIN = "ADMIN"
16
-
17
-
18
- class User(Base):
19
- __tablename__ = "users"
20
-
21
- id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
22
- email: Mapped[str] = mapped_column(String(254), unique=True, nullable=False)
23
- password: Mapped[str] = mapped_column(String(255), nullable=False)
24
- role: Mapped[str] = mapped_column(String(16), nullable=False, default=Role.USER.value)
25
- created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
26
- updated_at: Mapped[datetime] = mapped_column(
27
- DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
28
- )
29
-
30
- __table_args__ = (Index("ix_users_email", "email"),)
1
+ """User ORM model."""
2
+ import uuid
3
+ from datetime import datetime
4
+ from enum import Enum
5
+
6
+ from sqlalchemy import DateTime, Index, String, func
7
+ from sqlalchemy.dialects.postgresql import UUID
8
+ from sqlalchemy.orm import Mapped, mapped_column
9
+
10
+ from app.db.session import Base
11
+
12
+
13
+ class Role(str, Enum):
14
+ USER = "USER"
15
+ ADMIN = "ADMIN"
16
+
17
+
18
+ class User(Base):
19
+ __tablename__ = "users"
20
+
21
+ id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
22
+ email: Mapped[str] = mapped_column(String(254), unique=True, nullable=False)
23
+ password: Mapped[str] = mapped_column(String(255), nullable=False)
24
+ role: Mapped[str] = mapped_column(String(16), nullable=False, default=Role.USER.value)
25
+ created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
26
+ updated_at: Mapped[datetime] = mapped_column(
27
+ DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
28
+ )
29
+
30
+ __table_args__ = (Index("ix_users_email", "email"),)
@@ -1,34 +1,34 @@
1
- """User repository — encapsulates SQLAlchemy queries."""
2
- from sqlalchemy import func, select
3
- from sqlalchemy.orm import Session
4
-
5
- from app.models.user import User
6
-
7
-
8
- class UserRepository:
9
- def __init__(self, db: Session) -> None:
10
- self.db = db
11
-
12
- def find_by_email(self, email: str) -> User | None:
13
- return self.db.execute(select(User).where(User.email == email)).scalar_one_or_none()
14
-
15
- def page(self, page: int, limit: int) -> tuple[list[User], int]:
16
- page = max(1, page)
17
- limit = min(100, max(1, limit))
18
- offset = (page - 1) * limit
19
- items = list(
20
- self.db.execute(
21
- select(User).order_by(User.created_at.desc()).offset(offset).limit(limit)
22
- )
23
- .scalars()
24
- .all()
25
- )
26
- total = self.db.execute(select(func.count()).select_from(User)).scalar_one()
27
- return items, total
28
-
29
- def create(self, *, email: str, password: str, role: str) -> User:
30
- user = User(email=email, password=password, role=role)
31
- self.db.add(user)
32
- self.db.commit()
33
- self.db.refresh(user)
34
- return user
1
+ """User repository — encapsulates SQLAlchemy queries."""
2
+ from sqlalchemy import func, select
3
+ from sqlalchemy.orm import Session
4
+
5
+ from app.models.user import User
6
+
7
+
8
+ class UserRepository:
9
+ def __init__(self, db: Session) -> None:
10
+ self.db = db
11
+
12
+ def find_by_email(self, email: str) -> User | None:
13
+ return self.db.execute(select(User).where(User.email == email)).scalar_one_or_none()
14
+
15
+ def page(self, page: int, limit: int) -> tuple[list[User], int]:
16
+ page = max(1, page)
17
+ limit = min(100, max(1, limit))
18
+ offset = (page - 1) * limit
19
+ items = list(
20
+ self.db.execute(
21
+ select(User).order_by(User.created_at.desc()).offset(offset).limit(limit)
22
+ )
23
+ .scalars()
24
+ .all()
25
+ )
26
+ total = self.db.execute(select(func.count()).select_from(User)).scalar_one()
27
+ return items, total
28
+
29
+ def create(self, *, email: str, password: str, role: str) -> User:
30
+ user = User(email=email, password=password, role=role)
31
+ self.db.add(user)
32
+ self.db.commit()
33
+ self.db.refresh(user)
34
+ return user
@@ -1,37 +1,37 @@
1
- """Auth router: POST /auth/login, GET /auth/me."""
2
- from fastapi import APIRouter, Depends, HTTPException, status
3
- from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
4
- from sqlalchemy.orm import Session
5
-
6
- from app.core.security import decode_access_token
7
- from app.db.session import get_db
8
- from app.repositories.user_repository import UserRepository
9
- from app.schemas.user import LoginIn, LoginOut, UserOut
10
- from app.services.auth_service import AuthService, InvalidCredentials
11
-
12
- router = APIRouter()
13
- bearer = HTTPBearer(auto_error=True)
14
-
15
-
16
- @router.post("/login", response_model=LoginOut)
17
- def login(dto: LoginIn, db: Session = Depends(get_db)) -> LoginOut:
18
- service = AuthService(UserRepository(db))
19
- try:
20
- return service.login(dto)
21
- except InvalidCredentials as exc:
22
- raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid credentials") from exc
23
-
24
-
25
- @router.get("/me", response_model=UserOut)
26
- def me(
27
- creds: HTTPAuthorizationCredentials = Depends(bearer),
28
- db: Session = Depends(get_db),
29
- ) -> UserOut:
30
- payload = decode_access_token(creds.credentials)
31
- if not payload or "sub" not in payload:
32
- raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid token")
33
- repo = UserRepository(db)
34
- user = repo.find_by_email(payload.get("email", ""))
35
- if user is None:
36
- raise HTTPException(status.HTTP_401_UNAUTHORIZED, "User not found")
37
- return UserOut.model_validate(user)
1
+ """Auth router: POST /auth/login, GET /auth/me."""
2
+ from fastapi import APIRouter, Depends, HTTPException, status
3
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
4
+ from sqlalchemy.orm import Session
5
+
6
+ from app.core.security import decode_access_token
7
+ from app.db.session import get_db
8
+ from app.repositories.user_repository import UserRepository
9
+ from app.schemas.user import LoginIn, LoginOut, UserOut
10
+ from app.services.auth_service import AuthService, InvalidCredentials
11
+
12
+ router = APIRouter()
13
+ bearer = HTTPBearer(auto_error=True)
14
+
15
+
16
+ @router.post("/login", response_model=LoginOut)
17
+ def login(dto: LoginIn, db: Session = Depends(get_db)) -> LoginOut:
18
+ service = AuthService(UserRepository(db))
19
+ try:
20
+ return service.login(dto)
21
+ except InvalidCredentials as exc:
22
+ raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid credentials") from exc
23
+
24
+
25
+ @router.get("/me", response_model=UserOut)
26
+ def me(
27
+ creds: HTTPAuthorizationCredentials = Depends(bearer),
28
+ db: Session = Depends(get_db),
29
+ ) -> UserOut:
30
+ payload = decode_access_token(creds.credentials)
31
+ if not payload or "sub" not in payload:
32
+ raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid token")
33
+ repo = UserRepository(db)
34
+ user = repo.find_by_email(payload.get("email", ""))
35
+ if user is None:
36
+ raise HTTPException(status.HTTP_401_UNAUTHORIZED, "User not found")
37
+ return UserOut.model_validate(user)
@@ -1,46 +1,46 @@
1
- """Users router: GET /users, POST /users."""
2
- from fastapi import APIRouter, Depends, HTTPException, Query, status
3
- from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
4
- from sqlalchemy.orm import Session
5
-
6
- from app.core.security import decode_access_token
7
- from app.db.session import get_db
8
- from app.repositories.user_repository import UserRepository
9
- from app.schemas.user import UserCreate, UserOut, UserPage
10
- from app.services.user_service import EmailAlreadyInUse, UserService
11
-
12
- router = APIRouter()
13
- bearer = HTTPBearer(auto_error=True)
14
-
15
-
16
- def _require_admin(creds: HTTPAuthorizationCredentials) -> None:
17
- payload = decode_access_token(creds.credentials)
18
- if not payload or payload.get("role") != "ADMIN":
19
- raise HTTPException(status.HTTP_403_FORBIDDEN, "admin role required")
20
-
21
-
22
- @router.get("", response_model=UserPage)
23
- def list_users(
24
- page: int = Query(1, ge=1),
25
- limit: int = Query(20, ge=1, le=100),
26
- creds: HTTPAuthorizationCredentials = Depends(bearer),
27
- db: Session = Depends(get_db),
28
- ) -> UserPage:
29
- payload = decode_access_token(creds.credentials)
30
- if not payload:
31
- raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid token")
32
- return UserService(UserRepository(db)).list(page, limit)
33
-
34
-
35
- @router.post("", response_model=UserOut, status_code=status.HTTP_201_CREATED)
36
- def create_user(
37
- dto: UserCreate,
38
- creds: HTTPAuthorizationCredentials = Depends(bearer),
39
- db: Session = Depends(get_db),
40
- ) -> UserOut:
41
- _require_admin(creds)
42
- service = UserService(UserRepository(db))
43
- try:
44
- return service.create(dto)
45
- except EmailAlreadyInUse as exc:
46
- raise HTTPException(status.HTTP_409_CONFLICT, "email already in use") from exc
1
+ """Users router: GET /users, POST /users."""
2
+ from fastapi import APIRouter, Depends, HTTPException, Query, status
3
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
4
+ from sqlalchemy.orm import Session
5
+
6
+ from app.core.security import decode_access_token
7
+ from app.db.session import get_db
8
+ from app.repositories.user_repository import UserRepository
9
+ from app.schemas.user import UserCreate, UserOut, UserPage
10
+ from app.services.user_service import EmailAlreadyInUse, UserService
11
+
12
+ router = APIRouter()
13
+ bearer = HTTPBearer(auto_error=True)
14
+
15
+
16
+ def _require_admin(creds: HTTPAuthorizationCredentials) -> None:
17
+ payload = decode_access_token(creds.credentials)
18
+ if not payload or payload.get("role") != "ADMIN":
19
+ raise HTTPException(status.HTTP_403_FORBIDDEN, "admin role required")
20
+
21
+
22
+ @router.get("", response_model=UserPage)
23
+ def list_users(
24
+ page: int = Query(1, ge=1),
25
+ limit: int = Query(20, ge=1, le=100),
26
+ creds: HTTPAuthorizationCredentials = Depends(bearer),
27
+ db: Session = Depends(get_db),
28
+ ) -> UserPage:
29
+ payload = decode_access_token(creds.credentials)
30
+ if not payload:
31
+ raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid token")
32
+ return UserService(UserRepository(db)).list(page, limit)
33
+
34
+
35
+ @router.post("", response_model=UserOut, status_code=status.HTTP_201_CREATED)
36
+ def create_user(
37
+ dto: UserCreate,
38
+ creds: HTTPAuthorizationCredentials = Depends(bearer),
39
+ db: Session = Depends(get_db),
40
+ ) -> UserOut:
41
+ _require_admin(creds)
42
+ service = UserService(UserRepository(db))
43
+ try:
44
+ return service.create(dto)
45
+ except EmailAlreadyInUse as exc:
46
+ raise HTTPException(status.HTTP_409_CONFLICT, "email already in use") from exc
@@ -1,56 +1,56 @@
1
- """Pydantic IN/OUT schemas for user resource."""
2
- import re
3
- import uuid
4
- from datetime import datetime
5
- from typing import Annotated, Literal
6
-
7
- from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator
8
-
9
-
10
- class LoginIn(BaseModel):
11
- email: EmailStr
12
- password: Annotated[str, Field(min_length=8)]
13
-
14
- @field_validator("password")
15
- @classmethod
16
- def password_complexity(cls, v: str) -> str:
17
- if not re.search(r"[A-Z]", v):
18
- raise ValueError("password must contain an uppercase letter")
19
- if not re.search(r"\d", v):
20
- raise ValueError("password must contain a digit")
21
- return v
22
-
23
-
24
- class LoginOut(BaseModel):
25
- access_token: str
26
- expires_in: int
27
- token_type: Literal["bearer"] = "bearer"
28
-
29
-
30
- class UserOut(BaseModel):
31
- model_config = ConfigDict(from_attributes=True)
32
- id: uuid.UUID
33
- email: EmailStr
34
- role: str
35
- created_at: datetime
36
-
37
-
38
- class UserCreate(BaseModel):
39
- email: EmailStr
40
- password: Annotated[str, Field(min_length=8)]
41
- role: Literal["USER", "ADMIN"] = "USER"
42
-
43
- @field_validator("password")
44
- @classmethod
45
- def password_complexity(cls, v: str) -> str:
46
- if not re.search(r"[A-Z]", v):
47
- raise ValueError("password must contain an uppercase letter")
48
- if not re.search(r"\d", v):
49
- raise ValueError("password must contain a digit")
50
- return v
51
-
52
-
53
- class UserPage(BaseModel):
54
- items: list[UserOut]
55
- total: int
56
- page: int
1
+ """Pydantic IN/OUT schemas for user resource."""
2
+ import re
3
+ import uuid
4
+ from datetime import datetime
5
+ from typing import Annotated, Literal
6
+
7
+ from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator
8
+
9
+
10
+ class LoginIn(BaseModel):
11
+ email: EmailStr
12
+ password: Annotated[str, Field(min_length=8)]
13
+
14
+ @field_validator("password")
15
+ @classmethod
16
+ def password_complexity(cls, v: str) -> str:
17
+ if not re.search(r"[A-Z]", v):
18
+ raise ValueError("password must contain an uppercase letter")
19
+ if not re.search(r"\d", v):
20
+ raise ValueError("password must contain a digit")
21
+ return v
22
+
23
+
24
+ class LoginOut(BaseModel):
25
+ access_token: str
26
+ expires_in: int
27
+ token_type: Literal["bearer"] = "bearer"
28
+
29
+
30
+ class UserOut(BaseModel):
31
+ model_config = ConfigDict(from_attributes=True)
32
+ id: uuid.UUID
33
+ email: EmailStr
34
+ role: str
35
+ created_at: datetime
36
+
37
+
38
+ class UserCreate(BaseModel):
39
+ email: EmailStr
40
+ password: Annotated[str, Field(min_length=8)]
41
+ role: Literal["USER", "ADMIN"] = "USER"
42
+
43
+ @field_validator("password")
44
+ @classmethod
45
+ def password_complexity(cls, v: str) -> str:
46
+ if not re.search(r"[A-Z]", v):
47
+ raise ValueError("password must contain an uppercase letter")
48
+ if not re.search(r"\d", v):
49
+ raise ValueError("password must contain a digit")
50
+ return v
51
+
52
+
53
+ class UserPage(BaseModel):
54
+ items: list[UserOut]
55
+ total: int
56
+ page: int
@@ -1,22 +1,22 @@
1
- """Authentication service — login flow."""
2
- from app.core.security import create_access_token, verify_password
3
- from app.repositories.user_repository import UserRepository
4
- from app.schemas.user import LoginIn, LoginOut
5
-
6
-
7
- class InvalidCredentials(Exception):
8
- """Raised when email or password don't match."""
9
-
10
-
11
- class AuthService:
12
- def __init__(self, repo: UserRepository) -> None:
13
- self.repo = repo
14
-
15
- def login(self, dto: LoginIn) -> LoginOut:
16
- user = self.repo.find_by_email(dto.email.lower().strip())
17
- if user is None or not verify_password(dto.password, user.password):
18
- raise InvalidCredentials
19
- token, expires_in = create_access_token(
20
- str(user.id), claims={"email": user.email, "role": user.role}
21
- )
22
- return LoginOut(access_token=token, expires_in=expires_in)
1
+ """Authentication service — login flow."""
2
+ from app.core.security import create_access_token, verify_password
3
+ from app.repositories.user_repository import UserRepository
4
+ from app.schemas.user import LoginIn, LoginOut
5
+
6
+
7
+ class InvalidCredentials(Exception):
8
+ """Raised when email or password don't match."""
9
+
10
+
11
+ class AuthService:
12
+ def __init__(self, repo: UserRepository) -> None:
13
+ self.repo = repo
14
+
15
+ def login(self, dto: LoginIn) -> LoginOut:
16
+ user = self.repo.find_by_email(dto.email.lower().strip())
17
+ if user is None or not verify_password(dto.password, user.password):
18
+ raise InvalidCredentials
19
+ token, expires_in = create_access_token(
20
+ str(user.id), claims={"email": user.email, "role": user.role}
21
+ )
22
+ return LoginOut(access_token=token, expires_in=expires_in)
@@ -1,31 +1,31 @@
1
- """User service — create/list business logic."""
2
- from app.core.security import hash_password
3
- from app.repositories.user_repository import UserRepository
4
- from app.schemas.user import UserCreate, UserOut, UserPage
5
-
6
-
7
- class EmailAlreadyInUse(Exception):
8
- """Raised when a user with the same email already exists."""
9
-
10
-
11
- class UserService:
12
- def __init__(self, repo: UserRepository) -> None:
13
- self.repo = repo
14
-
15
- def list(self, page: int, limit: int) -> UserPage:
16
- items, total = self.repo.page(page, limit)
17
- return UserPage(
18
- items=[UserOut.model_validate(u) for u in items],
19
- total=total,
20
- page=max(1, page),
21
- )
22
-
23
- def create(self, dto: UserCreate) -> UserOut:
24
- if self.repo.find_by_email(dto.email.lower().strip()) is not None:
25
- raise EmailAlreadyInUse
26
- created = self.repo.create(
27
- email=dto.email.lower().strip(),
28
- password=hash_password(dto.password),
29
- role=dto.role,
30
- )
31
- return UserOut.model_validate(created)
1
+ """User service — create/list business logic."""
2
+ from app.core.security import hash_password
3
+ from app.repositories.user_repository import UserRepository
4
+ from app.schemas.user import UserCreate, UserOut, UserPage
5
+
6
+
7
+ class EmailAlreadyInUse(Exception):
8
+ """Raised when a user with the same email already exists."""
9
+
10
+
11
+ class UserService:
12
+ def __init__(self, repo: UserRepository) -> None:
13
+ self.repo = repo
14
+
15
+ def list(self, page: int, limit: int) -> UserPage:
16
+ items, total = self.repo.page(page, limit)
17
+ return UserPage(
18
+ items=[UserOut.model_validate(u) for u in items],
19
+ total=total,
20
+ page=max(1, page),
21
+ )
22
+
23
+ def create(self, dto: UserCreate) -> UserOut:
24
+ if self.repo.find_by_email(dto.email.lower().strip()) is not None:
25
+ raise EmailAlreadyInUse
26
+ created = self.repo.create(
27
+ email=dto.email.lower().strip(),
28
+ password=hash_password(dto.password),
29
+ role=dto.role,
30
+ )
31
+ return UserOut.model_validate(created)