agentic-dev 0.2.10 → 0.2.12

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 (603) hide show
  1. package/README.md +50 -29
  2. package/bin/agentic-dev.mjs +656 -124
  3. package/lib/scaffold.mjs +109 -6
  4. package/package.json +8 -22
  5. package/.agent/prd.json +0 -29
  6. package/.agent/progress.txt +0 -1
  7. package/.agent/prompt.md +0 -21
  8. package/.agent/ralph-loop-state.json +0 -13
  9. package/.agent/ralph-supervisor-state.json +0 -12
  10. package/.agent/ralph-supervisor.sh +0 -238
  11. package/.agent/ralph.sh +0 -305
  12. package/.agent/runs/README.md +0 -7
  13. package/.agent/sdd-build-ast-audit.json +0 -13
  14. package/.claude/CLAUDE.md +0 -44
  15. package/.claude/agentic-dev.json +0 -3
  16. package/.claude/agents/ai-dev.md +0 -27
  17. package/.claude/agents/backend-dev.md +0 -26
  18. package/.claude/agents/db-dev.md +0 -26
  19. package/.claude/agents/devops.md +0 -27
  20. package/.claude/agents/frontend-dev.md +0 -25
  21. package/.claude/agents/github-ops.md +0 -25
  22. package/.claude/agents/test-dev.md +0 -26
  23. package/.claude/agents/uiux-designer.md +0 -25
  24. package/.claude/settings.json +0 -49
  25. package/.claude/settings.local.json +0 -8
  26. package/.claude/skills/sdd/SKILL.md +0 -189
  27. package/.claude/skills/sdd/agents/openai.yaml +0 -4
  28. package/.claude/skills/sdd/references/section-map.md +0 -67
  29. package/.claude/workspace-config.json +0 -3
  30. package/.codex/agentic-dev.json +0 -3
  31. package/.codex/agents/README.md +0 -22
  32. package/.codex/agents/api.toml +0 -11
  33. package/.codex/agents/architecture.toml +0 -11
  34. package/.codex/agents/ci.toml +0 -11
  35. package/.codex/agents/gitops.toml +0 -11
  36. package/.codex/agents/orchestrator.toml +0 -11
  37. package/.codex/agents/quality.toml +0 -11
  38. package/.codex/agents/runtime.toml +0 -11
  39. package/.codex/agents/security.toml +0 -11
  40. package/.codex/agents/specs.toml +0 -11
  41. package/.codex/agents/ui.toml +0 -11
  42. package/.codex/config.toml +0 -46
  43. package/.codex/skills/SKILL.md +0 -13
  44. package/.codex/skills/sdd/SKILL.md +0 -189
  45. package/.codex/skills/sdd/agents/openai.yaml +0 -4
  46. package/.codex/skills/sdd/references/section-map.md +0 -67
  47. package/.dockerignore +0 -8
  48. package/.env.example +0 -50
  49. package/.gitignore +0 -16
  50. package/AGENTS.md +0 -86
  51. package/SDD_SKILL.md +0 -589
  52. package/client/admin/.dockerignore +0 -3
  53. package/client/admin/.env.example +0 -1
  54. package/client/admin/Dockerfile +0 -16
  55. package/client/admin/Dockerfile.dev +0 -18
  56. package/client/admin/README.md +0 -20
  57. package/client/admin/index.html +0 -12
  58. package/client/admin/package.json +0 -41
  59. package/client/admin/postcss.config.js +0 -6
  60. package/client/admin/scripts/ui-parity-admin-adapter.mjs +0 -65
  61. package/client/admin/src/api/alerts.ts +0 -33
  62. package/client/admin/src/api/client.ts +0 -71
  63. package/client/admin/src/api/orders.ts +0 -33
  64. package/client/admin/src/api/support.ts +0 -11
  65. package/client/admin/src/app/App.tsx +0 -23
  66. package/client/admin/src/auth/AuthProvider.tsx +0 -122
  67. package/client/admin/src/auth/ProtectedRoute.tsx +0 -22
  68. package/client/admin/src/auth/auth-client.ts +0 -38
  69. package/client/admin/src/auth/types.ts +0 -18
  70. package/client/admin/src/components/AdminNotificationsDrawer.tsx +0 -162
  71. package/client/admin/src/components/AdminShell.tsx +0 -76
  72. package/client/admin/src/components/ui/button.tsx +0 -34
  73. package/client/admin/src/components/ui/input.tsx +0 -21
  74. package/client/admin/src/lib/cn.ts +0 -6
  75. package/client/admin/src/lib/specRouteCatalog.json +0 -30
  76. package/client/admin/src/lib/specScreens.json +0 -22
  77. package/client/admin/src/main.tsx +0 -17
  78. package/client/admin/src/pages/AdminDashboardPage.tsx +0 -171
  79. package/client/admin/src/pages/AdminLoginPage.tsx +0 -75
  80. package/client/admin/src/pages/AdminQueuePage.tsx +0 -107
  81. package/client/admin/src/pages/AdminSupportPage.tsx +0 -61
  82. package/client/admin/src/styles/globals.css +0 -17
  83. package/client/admin/src/theme-vars.ts +0 -18
  84. package/client/admin/src/theme.ts +0 -25
  85. package/client/admin/src/vite-env.d.ts +0 -1
  86. package/client/admin/tailwind.config.js +0 -8
  87. package/client/admin/tsconfig.json +0 -25
  88. package/client/admin/vite.config.ts +0 -12
  89. package/client/landing/.dockerignore +0 -3
  90. package/client/landing/.env.example +0 -1
  91. package/client/landing/Dockerfile +0 -16
  92. package/client/landing/Dockerfile.dev +0 -18
  93. package/client/landing/README.md +0 -18
  94. package/client/landing/index.html +0 -12
  95. package/client/landing/package.json +0 -41
  96. package/client/landing/postcss.config.js +0 -6
  97. package/client/landing/scripts/ui-parity-landing-adapter.mjs +0 -65
  98. package/client/landing/src/App.tsx +0 -21
  99. package/client/landing/src/api/catalog.ts +0 -30
  100. package/client/landing/src/api/client.ts +0 -30
  101. package/client/landing/src/auth/AuthProvider.tsx +0 -122
  102. package/client/landing/src/auth/ProtectedRoute.tsx +0 -22
  103. package/client/landing/src/auth/auth-client.ts +0 -38
  104. package/client/landing/src/auth/types.ts +0 -18
  105. package/client/landing/src/components/LandingShell.tsx +0 -34
  106. package/client/landing/src/lib/specRouteCatalog.json +0 -23
  107. package/client/landing/src/lib/specScreens.json +0 -17
  108. package/client/landing/src/main.tsx +0 -17
  109. package/client/landing/src/pages/LandingHomePage.tsx +0 -215
  110. package/client/landing/src/pages/LandingLoginPage.tsx +0 -90
  111. package/client/landing/src/pages/LandingWorkspacePage.tsx +0 -126
  112. package/client/landing/src/styles/globals.css +0 -17
  113. package/client/landing/src/theme-vars.ts +0 -16
  114. package/client/landing/src/theme.ts +0 -21
  115. package/client/landing/src/vite-env.d.ts +0 -1
  116. package/client/landing/tailwind.config.js +0 -8
  117. package/client/landing/tsconfig.json +0 -25
  118. package/client/landing/vite.config.ts +0 -12
  119. package/client/mobile/.dockerignore +0 -2
  120. package/client/mobile/.env.example +0 -1
  121. package/client/mobile/Dockerfile +0 -16
  122. package/client/mobile/Dockerfile.dev +0 -18
  123. package/client/mobile/README.md +0 -19
  124. package/client/mobile/index.html +0 -12
  125. package/client/mobile/package.json +0 -42
  126. package/client/mobile/postcss.config.js +0 -6
  127. package/client/mobile/scripts/ui-parity-mobile-adapter.mjs +0 -67
  128. package/client/mobile/src/App.tsx +0 -1
  129. package/client/mobile/src/api/client.ts +0 -62
  130. package/client/mobile/src/api/fulfillment.ts +0 -55
  131. package/client/mobile/src/api/shipping.ts +0 -56
  132. package/client/mobile/src/app/App.tsx +0 -23
  133. package/client/mobile/src/auth/AuthProvider.tsx +0 -122
  134. package/client/mobile/src/auth/ProtectedRoute.tsx +0 -27
  135. package/client/mobile/src/auth/auth-client.ts +0 -38
  136. package/client/mobile/src/auth/types.ts +0 -18
  137. package/client/mobile/src/components/InShell.tsx +0 -74
  138. package/client/mobile/src/components/ui/button.tsx +0 -35
  139. package/client/mobile/src/components/ui/card.tsx +0 -15
  140. package/client/mobile/src/components/ui/input.tsx +0 -21
  141. package/client/mobile/src/lib/cn.ts +0 -6
  142. package/client/mobile/src/lib/specRouteCatalog.json +0 -26
  143. package/client/mobile/src/lib/specScreens.json +0 -22
  144. package/client/mobile/src/lib/useSpeechRecognitionInput.ts +0 -271
  145. package/client/mobile/src/main.tsx +0 -17
  146. package/client/mobile/src/pages/DashboardPage.tsx +0 -172
  147. package/client/mobile/src/pages/FulfillmentPage.tsx +0 -138
  148. package/client/mobile/src/pages/LoginPage.tsx +0 -74
  149. package/client/mobile/src/pages/ShippingPage.tsx +0 -338
  150. package/client/mobile/src/styles/globals.css +0 -23
  151. package/client/mobile/src/theme-vars.ts +0 -16
  152. package/client/mobile/src/theme.ts +0 -21
  153. package/client/mobile/src/vite-env.d.ts +0 -1
  154. package/client/mobile/tailwind.config.js +0 -8
  155. package/client/mobile/tsconfig.json +0 -25
  156. package/client/mobile/vite.config.ts +0 -12
  157. package/client/web/.dockerignore +0 -3
  158. package/client/web/.env.example +0 -1
  159. package/client/web/Dockerfile +0 -16
  160. package/client/web/Dockerfile.dev +0 -18
  161. package/client/web/README.md +0 -47
  162. package/client/web/index.html +0 -12
  163. package/client/web/package.json +0 -42
  164. package/client/web/postcss.config.js +0 -6
  165. package/client/web/scripts/ui-parity-web-adapter.mjs +0 -66
  166. package/client/web/src/api/client.ts +0 -30
  167. package/client/web/src/api/orders.ts +0 -42
  168. package/client/web/src/app/App.tsx +0 -21
  169. package/client/web/src/auth/AuthProvider.tsx +0 -122
  170. package/client/web/src/auth/ProtectedRoute.tsx +0 -22
  171. package/client/web/src/auth/auth-client.ts +0 -38
  172. package/client/web/src/auth/types.ts +0 -18
  173. package/client/web/src/components/AppShell.tsx +0 -59
  174. package/client/web/src/components/ui/button.tsx +0 -35
  175. package/client/web/src/components/ui/card.tsx +0 -7
  176. package/client/web/src/components/ui/input.tsx +0 -21
  177. package/client/web/src/lib/cn.ts +0 -6
  178. package/client/web/src/lib/specRouteCatalog.json +0 -23
  179. package/client/web/src/lib/specScreens.json +0 -17
  180. package/client/web/src/main.tsx +0 -17
  181. package/client/web/src/pages/DashboardPage.tsx +0 -158
  182. package/client/web/src/pages/LoginPage.tsx +0 -72
  183. package/client/web/src/pages/OrdersPage.tsx +0 -123
  184. package/client/web/src/styles/globals.css +0 -17
  185. package/client/web/src/theme-vars.ts +0 -18
  186. package/client/web/src/theme.ts +0 -25
  187. package/client/web/src/vite-env.d.ts +0 -1
  188. package/client/web/tailwind.config.js +0 -8
  189. package/client/web/tsconfig.json +0 -25
  190. package/client/web/vite.config.ts +0 -12
  191. package/compose.yml +0 -206
  192. package/infra/compose/.env.dev.example +0 -28
  193. package/infra/compose/.env.prod.example +0 -29
  194. package/infra/compose/README.md +0 -35
  195. package/infra/compose/dev.yml +0 -125
  196. package/infra/compose/prod.yml +0 -126
  197. package/infra/terraform/README.md +0 -34
  198. package/infra/terraform/aws/data/.terraform.lock.hcl +0 -25
  199. package/infra/terraform/aws/data/README.md +0 -18
  200. package/infra/terraform/aws/data/main.tf +0 -147
  201. package/infra/terraform/aws/data/outputs.tf +0 -14
  202. package/infra/terraform/aws/data/variables.tf +0 -57
  203. package/infra/terraform/aws/data/versions.tf +0 -10
  204. package/infra/terraform/aws/domain/.terraform.lock.hcl +0 -25
  205. package/infra/terraform/aws/domain/README.md +0 -20
  206. package/infra/terraform/aws/domain/env/dev.tfvars.example +0 -6
  207. package/infra/terraform/aws/domain/env/prod.tfvars.example +0 -7
  208. package/infra/terraform/aws/domain/main.tf +0 -149
  209. package/infra/terraform/aws/domain/outputs.tf +0 -29
  210. package/infra/terraform/aws/domain/variables.tf +0 -58
  211. package/infra/terraform/aws/domain/versions.tf +0 -10
  212. package/infra/terraform/openstack/README.md +0 -38
  213. package/infra/terraform/openstack/dev/.terraform.lock.hcl +0 -24
  214. package/infra/terraform/openstack/dev/README.md +0 -18
  215. package/infra/terraform/openstack/dev/main.tf +0 -49
  216. package/infra/terraform/openstack/dev/providers.tf +0 -15
  217. package/infra/terraform/openstack/dev/terraform.tfvars.example +0 -54
  218. package/infra/terraform/openstack/dev/variables.tf +0 -210
  219. package/infra/terraform/openstack/dev/versions.tf +0 -10
  220. package/infra/terraform/openstack/modules/environment_host/main.tf +0 -143
  221. package/infra/terraform/openstack/modules/environment_host/outputs.tf +0 -25
  222. package/infra/terraform/openstack/modules/environment_host/templates/docker-host-user-data.sh.tftpl +0 -40
  223. package/infra/terraform/openstack/modules/environment_host/variables.tf +0 -145
  224. package/infra/terraform/openstack/modules/environment_host/versions.tf +0 -7
  225. package/infra/terraform/openstack/prod/.terraform.lock.hcl +0 -24
  226. package/infra/terraform/openstack/prod/README.md +0 -18
  227. package/infra/terraform/openstack/prod/main.tf +0 -49
  228. package/infra/terraform/openstack/prod/providers.tf +0 -15
  229. package/infra/terraform/openstack/prod/terraform.tfvars.example +0 -55
  230. package/infra/terraform/openstack/prod/variables.tf +0 -210
  231. package/infra/terraform/openstack/prod/versions.tf +0 -10
  232. package/infra/terraform/openstack/server/.terraform.lock.hcl +0 -45
  233. package/infra/terraform/openstack/server/README.md +0 -47
  234. package/infra/terraform/openstack/server/main.tf +0 -161
  235. package/infra/terraform/openstack/server/outputs.tf +0 -30
  236. package/infra/terraform/openstack/server/providers.tf +0 -30
  237. package/infra/terraform/openstack/server/templates/server-user-data.sh.tftpl +0 -50
  238. package/infra/terraform/openstack/server/variables.tf +0 -233
  239. package/infra/terraform/openstack/server/zz_aspace.auto.tfvars.example.json +0 -29
  240. package/pnpm-workspace.yaml +0 -2
  241. package/scripts/dev/audit_sdd_build_ast.py +0 -277
  242. package/sdd/01_planning/01_feature/INDEX.md +0 -16
  243. package/sdd/01_planning/01_feature/README.md +0 -76
  244. package/sdd/01_planning/01_feature/alerts_feature_spec.md +0 -55
  245. package/sdd/01_planning/01_feature/auth_feature_spec.md +0 -57
  246. package/sdd/01_planning/01_feature/catalog_feature_spec.md +0 -61
  247. package/sdd/01_planning/01_feature/fulfillment_feature_spec.md +0 -58
  248. package/sdd/01_planning/01_feature/health_feature_spec.md +0 -52
  249. package/sdd/01_planning/01_feature/inventory_feature_spec.md +0 -60
  250. package/sdd/01_planning/01_feature/order_feature_spec.md +0 -63
  251. package/sdd/01_planning/01_feature/shipping_feature_spec.md +0 -55
  252. package/sdd/01_planning/01_feature/support_feature_spec.md +0 -53
  253. package/sdd/01_planning/01_feature/user_feature_spec.md +0 -54
  254. package/sdd/01_planning/02_screen/INDEX.md +0 -13
  255. package/sdd/01_planning/02_screen/README.md +0 -41
  256. package/sdd/01_planning/02_screen/admin_screen_spec.pdf +0 -0
  257. package/sdd/01_planning/02_screen/assets/README.md +0 -16
  258. package/sdd/01_planning/02_screen/assets/example/README.md +0 -13
  259. package/sdd/01_planning/02_screen/landing_screen_spec.pdf +0 -0
  260. package/sdd/01_planning/02_screen/mobile_screen_spec.pdf +0 -0
  261. package/sdd/01_planning/02_screen/web_screen_spec.pdf +0 -0
  262. package/sdd/01_planning/03_architecture/INDEX.md +0 -9
  263. package/sdd/01_planning/03_architecture/README.md +0 -25
  264. package/sdd/01_planning/03_architecture/architecture_document_structure.md +0 -77
  265. package/sdd/01_planning/03_architecture/backend/README.md +0 -10
  266. package/sdd/01_planning/03_architecture/frontend/README.md +0 -12
  267. package/sdd/01_planning/03_architecture/infra/README.md +0 -10
  268. package/sdd/01_planning/03_architecture/tech-research/README.md +0 -4
  269. package/sdd/01_planning/03_architecture/templates_system_architecture.md +0 -84
  270. package/sdd/01_planning/04_data/INDEX.md +0 -4
  271. package/sdd/01_planning/04_data/README.md +0 -10
  272. package/sdd/01_planning/04_data/templates_data_modeling.md +0 -119
  273. package/sdd/01_planning/05_api/README.md +0 -12
  274. package/sdd/01_planning/05_api/templates_api_contract.md +0 -90
  275. package/sdd/01_planning/06_iac/README.md +0 -11
  276. package/sdd/01_planning/06_iac/templates_runtime_and_cicd_baseline.md +0 -46
  277. package/sdd/01_planning/07_integration/README.md +0 -11
  278. package/sdd/01_planning/07_integration/templates_frontend_api_integration.md +0 -46
  279. package/sdd/01_planning/08_nonfunctional/README.md +0 -7
  280. package/sdd/01_planning/09_security/README.md +0 -7
  281. package/sdd/01_planning/10_test/README.md +0 -12
  282. package/sdd/01_planning/10_test/templates_test_strategy.md +0 -60
  283. package/sdd/01_planning/INDEX.md +0 -19
  284. package/sdd/01_planning/README.md +0 -17
  285. package/sdd/02_plan/01_feature/README.md +0 -34
  286. package/sdd/02_plan/01_feature/_feature_todo_template.md +0 -29
  287. package/sdd/02_plan/02_screen/INDEX.md +0 -19
  288. package/sdd/02_plan/02_screen/README.md +0 -39
  289. package/sdd/02_plan/02_screen/_screen_todo_template.md +0 -60
  290. package/sdd/02_plan/03_architecture/README.md +0 -23
  291. package/sdd/02_plan/03_architecture/architecture_document_governance.md +0 -40
  292. package/sdd/02_plan/03_architecture/build_ast_runtime_tree_governance.md +0 -53
  293. package/sdd/02_plan/03_architecture/repository_governance.md +0 -39
  294. package/sdd/02_plan/03_architecture/runtime_and_structure_governance.md +0 -38
  295. package/sdd/02_plan/03_architecture/templates-hexagonal-template-architecture.md +0 -9
  296. package/sdd/02_plan/03_architecture/toolchain_governance.md +0 -98
  297. package/sdd/02_plan/04_data/README.md +0 -5
  298. package/sdd/02_plan/05_api/README.md +0 -5
  299. package/sdd/02_plan/06_iac/README.md +0 -11
  300. package/sdd/02_plan/06_iac/dev_runtime_delivery.md +0 -36
  301. package/sdd/02_plan/06_iac/template_runtime_delivery.md +0 -50
  302. package/sdd/02_plan/07_integration/README.md +0 -5
  303. package/sdd/02_plan/07_integration/frontend_live_integration.md +0 -31
  304. package/sdd/02_plan/08_nonfunctional/README.md +0 -5
  305. package/sdd/02_plan/08_nonfunctional/repository_hygiene.md +0 -26
  306. package/sdd/02_plan/09_security/README.md +0 -5
  307. package/sdd/02_plan/10_test/README.md +0 -11
  308. package/sdd/02_plan/10_test/regression_verification.md +0 -39
  309. package/sdd/02_plan/10_test/templates/README.md +0 -8
  310. package/sdd/02_plan/10_test/templates/ui_parity_web_contract.template.yaml +0 -23
  311. package/sdd/02_plan/10_test/verification_strategy.md +0 -43
  312. package/sdd/02_plan/99_generated/from_planning/ui_parity/.gitkeep +0 -1
  313. package/sdd/02_plan/README.md +0 -40
  314. package/sdd/03_build/01_feature/README.md +0 -20
  315. package/sdd/03_build/01_feature/domain/README.md +0 -3
  316. package/sdd/03_build/01_feature/domain/account_and_access.md +0 -20
  317. package/sdd/03_build/01_feature/domain/catalog_and_inventory.md +0 -20
  318. package/sdd/03_build/01_feature/domain/ordering_and_fulfillment.md +0 -21
  319. package/sdd/03_build/01_feature/domain/support_and_observability.md +0 -21
  320. package/sdd/03_build/01_feature/domain_surfaces.md +0 -28
  321. package/sdd/03_build/01_feature/service/README.md +0 -3
  322. package/sdd/03_build/01_feature/service/admin_surface.md +0 -15
  323. package/sdd/03_build/01_feature/service/landing_surface.md +0 -13
  324. package/sdd/03_build/01_feature/service/mobile_surface.md +0 -14
  325. package/sdd/03_build/01_feature/service/web_surface.md +0 -14
  326. package/sdd/03_build/02_screen/README.md +0 -25
  327. package/sdd/03_build/02_screen/_screen_build_template.md +0 -26
  328. package/sdd/03_build/02_screen/admin/README.md +0 -5
  329. package/sdd/03_build/02_screen/landing/README.md +0 -5
  330. package/sdd/03_build/02_screen/mobile/README.md +0 -5
  331. package/sdd/03_build/02_screen/web/README.md +0 -5
  332. package/sdd/03_build/03_architecture/README.md +0 -10
  333. package/sdd/03_build/03_architecture/architecture_document_governance.md +0 -30
  334. package/sdd/03_build/03_architecture/build_ast_runtime_tree_governance.md +0 -24
  335. package/sdd/03_build/03_architecture/repository_governance.md +0 -18
  336. package/sdd/03_build/03_architecture/toolchain_governance.md +0 -36
  337. package/sdd/03_build/06_iac/README.md +0 -3
  338. package/sdd/03_build/06_iac/dev_runtime_delivery.md +0 -10
  339. package/sdd/03_build/06_iac/template_runtime_delivery.md +0 -49
  340. package/sdd/03_build/07_integration/README.md +0 -3
  341. package/sdd/03_build/07_integration/frontend_live_integration.md +0 -11
  342. package/sdd/03_build/08_nonfunctional/README.md +0 -3
  343. package/sdd/03_build/08_nonfunctional/repository_hygiene.md +0 -10
  344. package/sdd/03_build/10_test/README.md +0 -9
  345. package/sdd/03_build/10_test/regression_verification.md +0 -16
  346. package/sdd/03_build/10_test/verification_harness.md +0 -11
  347. package/sdd/03_build/README.md +0 -35
  348. package/sdd/03_verify/01_feature/README.md +0 -5
  349. package/sdd/03_verify/01_feature/domain_verification.md +0 -14
  350. package/sdd/03_verify/01_feature/service_verification.md +0 -22
  351. package/sdd/03_verify/02_screen/README.md +0 -6
  352. package/sdd/03_verify/02_screen/_screen_verify_template.md +0 -20
  353. package/sdd/03_verify/02_screen/admin/README.md +0 -4
  354. package/sdd/03_verify/02_screen/landing/README.md +0 -4
  355. package/sdd/03_verify/02_screen/mobile/README.md +0 -4
  356. package/sdd/03_verify/02_screen/web/README.md +0 -4
  357. package/sdd/03_verify/03_architecture/README.md +0 -10
  358. package/sdd/03_verify/03_architecture/architecture_document_governance.md +0 -15
  359. package/sdd/03_verify/03_architecture/build_ast_runtime_tree_governance.md +0 -28
  360. package/sdd/03_verify/03_architecture/repository_governance.md +0 -16
  361. package/sdd/03_verify/03_architecture/toolchain_governance.md +0 -58
  362. package/sdd/03_verify/06_iac/README.md +0 -3
  363. package/sdd/03_verify/06_iac/dev_runtime_delivery.md +0 -10
  364. package/sdd/03_verify/06_iac/template_runtime_delivery.md +0 -42
  365. package/sdd/03_verify/07_integration/README.md +0 -3
  366. package/sdd/03_verify/07_integration/frontend_live_integration.md +0 -16
  367. package/sdd/03_verify/08_nonfunctional/README.md +0 -3
  368. package/sdd/03_verify/08_nonfunctional/repository_hygiene.md +0 -14
  369. package/sdd/03_verify/10_test/README.md +0 -9
  370. package/sdd/03_verify/10_test/regression_verification.md +0 -16
  371. package/sdd/03_verify/10_test/ui_parity/README.md +0 -4
  372. package/sdd/03_verify/10_test/ui_parity/loop_runs/.gitkeep +0 -0
  373. package/sdd/03_verify/10_test/ui_parity/reference/.gitkeep +0 -0
  374. package/sdd/03_verify/10_test/ui_parity/staged_runs/.gitkeep +0 -0
  375. package/sdd/03_verify/10_test/verification_harness.md +0 -17
  376. package/sdd/03_verify/README.md +0 -22
  377. package/sdd/05_operate/01_runbooks/.gitkeep +0 -1
  378. package/sdd/05_operate/01_runbooks/README.md +0 -4
  379. package/sdd/05_operate/02_delivery_status/README.md +0 -4
  380. package/sdd/05_operate/02_delivery_status/service_status.md +0 -16
  381. package/sdd/05_operate/README.md +0 -12
  382. package/sdd/99_toolchain/01_automation/.gitkeep +0 -1
  383. package/sdd/99_toolchain/01_automation/README.md +0 -76
  384. package/sdd/99_toolchain/01_automation/agentic-dev/analyze_proof_results.py +0 -132
  385. package/sdd/99_toolchain/01_automation/agentic-dev/analyze_route_gap.py +0 -85
  386. package/sdd/99_toolchain/01_automation/agentic-dev/assets/repo-contract.template.json +0 -75
  387. package/sdd/99_toolchain/01_automation/agentic-dev/bootstrap_frontend_parity.sh +0 -84
  388. package/sdd/99_toolchain/01_automation/agentic-dev/init_frontend_parity.sh +0 -33
  389. package/sdd/99_toolchain/01_automation/agentic-dev/init_repo_contract.sh +0 -51
  390. package/sdd/99_toolchain/01_automation/agentic-dev/repo-contract.json +0 -76
  391. package/sdd/99_toolchain/01_automation/agentic-dev/resolve_frontend_target.py +0 -52
  392. package/sdd/99_toolchain/01_automation/agentic-dev/resolve_repo_contract.py +0 -56
  393. package/sdd/99_toolchain/01_automation/agentic-dev/run_frontend_target.sh +0 -100
  394. package/sdd/99_toolchain/01_automation/agentic-dev/run_repo_phase.sh +0 -140
  395. package/sdd/99_toolchain/01_automation/agentic-dev/validate_json_schema.py +0 -39
  396. package/sdd/99_toolchain/01_automation/agentic-parity-harness-design.md +0 -291
  397. package/sdd/99_toolchain/01_automation/assets/admin_screen_capture/dashboard.png +0 -0
  398. package/sdd/99_toolchain/01_automation/assets/admin_screen_capture/login.png +0 -0
  399. package/sdd/99_toolchain/01_automation/assets/admin_screen_capture/queue.png +0 -0
  400. package/sdd/99_toolchain/01_automation/assets/admin_screen_capture/support.png +0 -0
  401. package/sdd/99_toolchain/01_automation/assets/landing_screen_capture/home.png +0 -0
  402. package/sdd/99_toolchain/01_automation/assets/landing_screen_capture/login.png +0 -0
  403. package/sdd/99_toolchain/01_automation/assets/landing_screen_capture/workspace.png +0 -0
  404. package/sdd/99_toolchain/01_automation/assets/mobile_screen_capture/dashboard.png +0 -0
  405. package/sdd/99_toolchain/01_automation/assets/mobile_screen_capture/fulfillment.png +0 -0
  406. package/sdd/99_toolchain/01_automation/assets/mobile_screen_capture/login.png +0 -0
  407. package/sdd/99_toolchain/01_automation/assets/web_screen_capture/dashboard.png +0 -0
  408. package/sdd/99_toolchain/01_automation/assets/web_screen_capture/login.png +0 -0
  409. package/sdd/99_toolchain/01_automation/assets/web_screen_capture/orders.png +0 -0
  410. package/sdd/99_toolchain/01_automation/build_asset_recipes.py +0 -10
  411. package/sdd/99_toolchain/01_automation/build_screen_spec_pdf.py +0 -427
  412. package/sdd/99_toolchain/01_automation/capture_screen_assets.mjs +0 -148
  413. package/sdd/99_toolchain/01_automation/harness-layout.md +0 -34
  414. package/sdd/99_toolchain/01_automation/parity-execution-tooling-design.md +0 -319
  415. package/sdd/99_toolchain/01_automation/playwright_exactness_manifest.py +0 -21
  416. package/sdd/99_toolchain/01_automation/run_playwright_exactness.py +0 -87
  417. package/sdd/99_toolchain/01_automation/screen_spec_manifest.py +0 -321
  418. package/sdd/99_toolchain/01_automation/spec_asset_builder.py +0 -274
  419. package/sdd/99_toolchain/01_automation/ui-contract-projection.md +0 -79
  420. package/sdd/99_toolchain/01_automation/ui-parity/README.md +0 -60
  421. package/sdd/99_toolchain/01_automation/ui-parity/cli/extract-reference-pages.mjs +0 -2
  422. package/sdd/99_toolchain/01_automation/ui-parity/cli/materialize-reference-assets.mjs +0 -58
  423. package/sdd/99_toolchain/01_automation/ui-parity/cli/normalize-reference-assets.mjs +0 -2
  424. package/sdd/99_toolchain/01_automation/ui-parity/cli/route-gap-report.mjs +0 -187
  425. package/sdd/99_toolchain/01_automation/ui-parity/cli/run-proof.mjs +0 -50
  426. package/sdd/99_toolchain/01_automation/ui-parity/cli/scaffold-contract.mjs +0 -62
  427. package/sdd/99_toolchain/01_automation/ui-parity/cli/upload-parity1.mjs +0 -2
  428. package/sdd/99_toolchain/01_automation/ui-parity/contracts/collector-metadata.schema.json +0 -33
  429. package/sdd/99_toolchain/01_automation/ui-parity/contracts/proof-result.schema.json +0 -76
  430. package/sdd/99_toolchain/01_automation/ui-parity/contracts/route-gap-report.schema.json +0 -95
  431. package/sdd/99_toolchain/01_automation/ui-parity/core/capture-runner.mjs +0 -55
  432. package/sdd/99_toolchain/01_automation/ui-parity/core/load-adapter.mjs +0 -25
  433. package/sdd/99_toolchain/01_automation/ui-parity/core/load-contract.mjs +0 -81
  434. package/sdd/99_toolchain/01_automation/ui-parity/core/paths.mjs +0 -23
  435. package/sdd/99_toolchain/01_automation/ui-parity/core/proof-runner.mjs +0 -255
  436. package/sdd/99_toolchain/01_automation/ui-parity/interfaces/ui-parity-artifact-layout.md +0 -23
  437. package/sdd/99_toolchain/01_automation/ui-parity/interfaces/ui-parity-proof-interface.md +0 -60
  438. package/sdd/99_toolchain/01_automation/ui-parity/interfaces/ui-parity-route-gap-interface.md +0 -82
  439. package/sdd/99_toolchain/01_automation/ui-parity/runtime/playwright-runtime.mjs +0 -16
  440. package/sdd/99_toolchain/01_automation/ui-parity/runtime/static-runtime.mjs +0 -6
  441. package/sdd/99_toolchain/02_policies/.gitkeep +0 -1
  442. package/sdd/99_toolchain/02_policies/build-ast-governance-policy.md +0 -22
  443. package/sdd/99_toolchain/02_policies/compose-runtime-baseline-policy.md +0 -24
  444. package/sdd/99_toolchain/02_policies/convention-storage-policy.md +0 -26
  445. package/sdd/99_toolchain/02_policies/main-push-before-dev-deploy-policy.md +0 -27
  446. package/sdd/99_toolchain/02_policies/regression-verification-policy.md +0 -22
  447. package/sdd/99_toolchain/03_templates/.gitkeep +0 -1
  448. package/sdd/99_toolchain/03_templates/asset_recipe_manifest.example.py +0 -38
  449. package/sdd/99_toolchain/03_templates/generated_assets/README.md +0 -11
  450. package/sdd/99_toolchain/03_templates/generated_assets/example-brand-lockup.svg +0 -3
  451. package/sdd/99_toolchain/03_templates/generated_assets/example-brand-mark.svg +0 -3
  452. package/sdd/99_toolchain/03_templates/generated_assets/example-brand-wordmark.svg +0 -3
  453. package/sdd/99_toolchain/03_templates/playwright_exactness_manifest.example.py +0 -21
  454. package/sdd/99_toolchain/README.md +0 -23
  455. package/sdd/README.md +0 -21
  456. package/server/.dockerignore +0 -4
  457. package/server/.env.example +0 -19
  458. package/server/Dockerfile +0 -22
  459. package/server/Dockerfile.dev +0 -19
  460. package/server/README.md +0 -33
  461. package/server/__init__.py +0 -0
  462. package/server/api/__init__.py +0 -1
  463. package/server/api/http/__init__.py +0 -4
  464. package/server/api/http/app.py +0 -53
  465. package/server/api/http/router.py +0 -24
  466. package/server/config.py +0 -52
  467. package/server/contexts/__init__.py +0 -12
  468. package/server/contexts/alerts/__init__.py +0 -1
  469. package/server/contexts/alerts/application/__init__.py +0 -13
  470. package/server/contexts/alerts/application/services.py +0 -41
  471. package/server/contexts/alerts/contracts/__init__.py +0 -3
  472. package/server/contexts/alerts/contracts/http/__init__.py +0 -3
  473. package/server/contexts/alerts/contracts/http/router.py +0 -37
  474. package/server/contexts/alerts/domain/__init__.py +0 -15
  475. package/server/contexts/alerts/domain/models.py +0 -29
  476. package/server/contexts/alerts/infrastructure/__init__.py +0 -11
  477. package/server/contexts/alerts/infrastructure/repository.py +0 -41
  478. package/server/contexts/auth/__init__.py +0 -1
  479. package/server/contexts/auth/application/__init__.py +0 -3
  480. package/server/contexts/auth/application/ports.py +0 -10
  481. package/server/contexts/auth/application/services.py +0 -64
  482. package/server/contexts/auth/contracts/__init__.py +0 -4
  483. package/server/contexts/auth/contracts/http/__init__.py +0 -4
  484. package/server/contexts/auth/contracts/http/dependencies.py +0 -37
  485. package/server/contexts/auth/contracts/http/router.py +0 -19
  486. package/server/contexts/auth/domain/__init__.py +0 -3
  487. package/server/contexts/auth/domain/models.py +0 -24
  488. package/server/contexts/auth/infrastructure/__init__.py +0 -4
  489. package/server/contexts/auth/infrastructure/adapters/memory.py +0 -19
  490. package/server/contexts/auth/infrastructure/adapters/mongodb.py +0 -24
  491. package/server/contexts/auth/infrastructure/adapters/sqlalchemy.py +0 -74
  492. package/server/contexts/auth/infrastructure/repository.py +0 -28
  493. package/server/contexts/catalog/__init__.py +0 -1
  494. package/server/contexts/catalog/application/__init__.py +0 -28
  495. package/server/contexts/catalog/application/ports.py +0 -15
  496. package/server/contexts/catalog/application/services.py +0 -154
  497. package/server/contexts/catalog/contracts/__init__.py +0 -3
  498. package/server/contexts/catalog/contracts/http/__init__.py +0 -3
  499. package/server/contexts/catalog/contracts/http/router.py +0 -60
  500. package/server/contexts/catalog/domain/__init__.py +0 -45
  501. package/server/contexts/catalog/domain/models.py +0 -113
  502. package/server/contexts/catalog/infrastructure/__init__.py +0 -4
  503. package/server/contexts/catalog/infrastructure/adapters/memory.py +0 -62
  504. package/server/contexts/catalog/infrastructure/repository.py +0 -8
  505. package/server/contexts/fulfillment/__init__.py +0 -1
  506. package/server/contexts/fulfillment/application/__init__.py +0 -13
  507. package/server/contexts/fulfillment/application/ports.py +0 -20
  508. package/server/contexts/fulfillment/application/services.py +0 -85
  509. package/server/contexts/fulfillment/contracts/__init__.py +0 -3
  510. package/server/contexts/fulfillment/contracts/http/__init__.py +0 -3
  511. package/server/contexts/fulfillment/contracts/http/router.py +0 -40
  512. package/server/contexts/fulfillment/domain/__init__.py +0 -25
  513. package/server/contexts/fulfillment/domain/models.py +0 -73
  514. package/server/contexts/fulfillment/infrastructure/__init__.py +0 -13
  515. package/server/contexts/fulfillment/infrastructure/adapters/memory.py +0 -43
  516. package/server/contexts/fulfillment/infrastructure/repository.py +0 -97
  517. package/server/contexts/health/__init__.py +0 -1
  518. package/server/contexts/health/application/__init__.py +0 -3
  519. package/server/contexts/health/application/services.py +0 -2
  520. package/server/contexts/health/contracts/__init__.py +0 -3
  521. package/server/contexts/health/contracts/http/__init__.py +0 -3
  522. package/server/contexts/health/contracts/http/router.py +0 -10
  523. package/server/contexts/inventory/__init__.py +0 -1
  524. package/server/contexts/inventory/application/__init__.py +0 -28
  525. package/server/contexts/inventory/application/ports.py +0 -11
  526. package/server/contexts/inventory/application/services.py +0 -214
  527. package/server/contexts/inventory/contracts/__init__.py +0 -3
  528. package/server/contexts/inventory/contracts/http/__init__.py +0 -3
  529. package/server/contexts/inventory/contracts/http/router.py +0 -82
  530. package/server/contexts/inventory/domain/__init__.py +0 -33
  531. package/server/contexts/inventory/domain/models.py +0 -93
  532. package/server/contexts/inventory/infrastructure/__init__.py +0 -4
  533. package/server/contexts/inventory/infrastructure/adapters/memory.py +0 -24
  534. package/server/contexts/inventory/infrastructure/repository.py +0 -8
  535. package/server/contexts/orders/__init__.py +0 -1
  536. package/server/contexts/orders/application/__init__.py +0 -19
  537. package/server/contexts/orders/application/services.py +0 -127
  538. package/server/contexts/orders/contracts/__init__.py +0 -3
  539. package/server/contexts/orders/contracts/http/__init__.py +0 -3
  540. package/server/contexts/orders/contracts/http/router.py +0 -82
  541. package/server/contexts/orders/domain/__init__.py +0 -29
  542. package/server/contexts/orders/domain/models.py +0 -95
  543. package/server/contexts/orders/infrastructure/__init__.py +0 -7
  544. package/server/contexts/orders/infrastructure/repository.py +0 -104
  545. package/server/contexts/shipping/__init__.py +0 -1
  546. package/server/contexts/shipping/application/__init__.py +0 -13
  547. package/server/contexts/shipping/application/services.py +0 -92
  548. package/server/contexts/shipping/contracts/__init__.py +0 -3
  549. package/server/contexts/shipping/contracts/http/__init__.py +0 -3
  550. package/server/contexts/shipping/contracts/http/router.py +0 -40
  551. package/server/contexts/shipping/domain/__init__.py +0 -19
  552. package/server/contexts/shipping/domain/models.py +0 -48
  553. package/server/contexts/shipping/infrastructure/__init__.py +0 -9
  554. package/server/contexts/shipping/infrastructure/repository.py +0 -50
  555. package/server/contexts/support/__init__.py +0 -1
  556. package/server/contexts/support/application/__init__.py +0 -13
  557. package/server/contexts/support/application/services.py +0 -29
  558. package/server/contexts/support/contracts/__init__.py +0 -3
  559. package/server/contexts/support/contracts/http/__init__.py +0 -3
  560. package/server/contexts/support/contracts/http/router.py +0 -40
  561. package/server/contexts/support/domain/__init__.py +0 -13
  562. package/server/contexts/support/domain/models.py +0 -27
  563. package/server/contexts/support/infrastructure/__init__.py +0 -11
  564. package/server/contexts/support/infrastructure/repository.py +0 -70
  565. package/server/contexts/user/__init__.py +0 -1
  566. package/server/contexts/user/application/__init__.py +0 -3
  567. package/server/contexts/user/application/ports.py +0 -11
  568. package/server/contexts/user/application/services.py +0 -44
  569. package/server/contexts/user/contracts/__init__.py +0 -3
  570. package/server/contexts/user/contracts/http/__init__.py +0 -3
  571. package/server/contexts/user/contracts/http/router.py +0 -26
  572. package/server/contexts/user/domain/__init__.py +0 -3
  573. package/server/contexts/user/domain/models.py +0 -22
  574. package/server/contexts/user/infrastructure/__init__.py +0 -3
  575. package/server/contexts/user/infrastructure/adapters/memory.py +0 -27
  576. package/server/contexts/user/infrastructure/adapters/mongodb.py +0 -41
  577. package/server/contexts/user/infrastructure/adapters/sqlalchemy.py +0 -94
  578. package/server/contexts/user/infrastructure/factory.py +0 -28
  579. package/server/data/README.md +0 -24
  580. package/server/data/bootstrap/alerts.json +0 -38
  581. package/server/data/bootstrap/auth_accounts.json +0 -18
  582. package/server/data/bootstrap/catalog_products.json +0 -179
  583. package/server/data/bootstrap/fulfillment_events.json +0 -5
  584. package/server/data/bootstrap/fulfillment_notes.json +0 -5
  585. package/server/data/bootstrap/fulfillment_tasks.json +0 -50
  586. package/server/data/bootstrap/inventory_levels.json +0 -80
  587. package/server/data/bootstrap/orders.json +0 -62
  588. package/server/data/bootstrap/shipping_shipments.json +0 -50
  589. package/server/data/bootstrap/support_faqs.json +0 -26
  590. package/server/data/bootstrap/users.json +0 -20
  591. package/server/data/bootstrap_loader.py +0 -15
  592. package/server/docker-entrypoint.sh +0 -56
  593. package/server/main.py +0 -3
  594. package/server/pyproject.toml +0 -36
  595. package/server/shared/__init__.py +0 -1
  596. package/server/shared/application/__init__.py +0 -3
  597. package/server/shared/application/health.py +0 -2
  598. package/server/shared/infrastructure/__init__.py +0 -10
  599. package/server/shared/infrastructure/runtime.py +0 -6
  600. package/server/shared/infrastructure/security.py +0 -33
  601. package/server/tests/e2e/test_domain_feature_flows.py +0 -483
  602. package/server/tests/test_health.py +0 -49
  603. package/server/uv.lock +0 -1169
@@ -1,41 +0,0 @@
1
- from contexts.alerts.domain import AlertRecord
2
- from data.bootstrap_loader import load_bootstrap_json
3
-
4
- _alert_store: list[AlertRecord] | None = None
5
-
6
-
7
- def _get_alert_store() -> list[AlertRecord]:
8
- global _alert_store
9
- if _alert_store is None:
10
- _alert_store = [
11
- AlertRecord(**entry) for entry in load_bootstrap_json("alerts.json")
12
- ]
13
- return _alert_store
14
-
15
-
16
- def list_seed_alerts() -> list[AlertRecord]:
17
- return [record.model_copy(deep=True) for record in _get_alert_store()]
18
-
19
-
20
- def mark_seed_alert_read(alert_id: str) -> AlertRecord:
21
- records = _get_alert_store()
22
- for index, record in enumerate(records):
23
- if record.id != alert_id:
24
- continue
25
-
26
- updated_record = record.model_copy(update={"read": True})
27
- records[index] = updated_record
28
- return updated_record.model_copy(deep=True)
29
-
30
- raise LookupError(f"Alert {alert_id} not found")
31
-
32
-
33
- def mark_all_seed_alerts_read() -> int:
34
- records = _get_alert_store()
35
- updated_count = 0
36
- for index, record in enumerate(records):
37
- if record.read:
38
- continue
39
- records[index] = record.model_copy(update={"read": True})
40
- updated_count += 1
41
- return updated_count
@@ -1 +0,0 @@
1
- __all__ = ["contracts", "application", "domain", "infrastructure"]
@@ -1,3 +0,0 @@
1
- from .services import authenticate_user, prepare_auth_store, resolve_current_user
2
-
3
- __all__ = ["authenticate_user", "resolve_current_user", "prepare_auth_store"]
@@ -1,10 +0,0 @@
1
- from typing import Protocol
2
-
3
- from contexts.auth.domain import AuthAccountRecord
4
-
5
-
6
- class AuthAccountRepository(Protocol):
7
- def initialize(self) -> None: ...
8
- def seed_accounts(self, accounts: list[AuthAccountRecord]) -> None: ...
9
- def get_by_email(self, email: str) -> AuthAccountRecord | None: ...
10
- def get_by_id(self, user_id: str) -> AuthAccountRecord | None: ...
@@ -1,64 +0,0 @@
1
- from functools import lru_cache
2
-
3
- from fastapi import HTTPException, status
4
-
5
- from config import get_settings
6
- from contexts.auth.domain import AuthAccountRecord, AuthenticatedUser, AuthToken, LoginCommand
7
- from contexts.auth.infrastructure import (
8
- decode_access_token,
9
- get_auth_repository,
10
- issue_access_token,
11
- verify_password,
12
- )
13
- from data.bootstrap_loader import load_bootstrap_json
14
- from shared.infrastructure import hash_password
15
-
16
-
17
- def authenticate_user(command: LoginCommand) -> AuthToken:
18
- prepare_auth_store()
19
- repository = get_auth_repository()
20
- account = repository.get_by_email(str(command.email))
21
- if account is None or not verify_password(command.password, account.password_hash):
22
- raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")
23
-
24
- return AuthToken(access_token=issue_access_token(account.id), user_id=account.id)
25
-
26
-
27
- def resolve_current_user(bearer_token: str) -> AuthenticatedUser:
28
- prepare_auth_store()
29
- subject = decode_access_token(bearer_token)
30
- if subject is None:
31
- raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
32
-
33
- repository = get_auth_repository()
34
- account = repository.get_by_id(subject)
35
- if account is None:
36
- raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
37
- return AuthenticatedUser(**account.model_dump(exclude={"password_hash"}))
38
-
39
-
40
- def prepare_auth_store() -> None:
41
- _seed_auth_store()
42
-
43
-
44
- @lru_cache
45
- def _seed_auth_store() -> None:
46
- settings = get_settings()
47
- repository = get_auth_repository()
48
- repository.initialize()
49
- password_lookup = {
50
- "bootstrap_admin_password": settings.bootstrap_admin_password,
51
- "bootstrap_operator_password": settings.bootstrap_operator_password,
52
- }
53
- accounts = [
54
- AuthAccountRecord(
55
- id=entry["id"],
56
- name=entry["name"],
57
- email=entry["email"],
58
- role=entry["role"],
59
- status=entry["status"],
60
- password_hash=hash_password(password_lookup[entry["password_source"]]),
61
- )
62
- for entry in load_bootstrap_json("auth_accounts.json")
63
- ]
64
- repository.seed_accounts(accounts)
@@ -1,4 +0,0 @@
1
- from .http.dependencies import require_admin_user, require_authenticated_user
2
- from .http.router import router
3
-
4
- __all__ = ["require_admin_user", "require_authenticated_user", "router"]
@@ -1,4 +0,0 @@
1
- from .dependencies import require_admin_user, require_authenticated_user
2
- from .router import router
3
-
4
- __all__ = ["require_admin_user", "require_authenticated_user", "router"]
@@ -1,37 +0,0 @@
1
- from fastapi import Depends, Header, HTTPException, status
2
-
3
- from contexts.auth.application import resolve_current_user
4
- from contexts.auth.domain import AuthenticatedUser
5
-
6
-
7
- def _extract_bearer_token(authorization: str | None) -> str:
8
- if authorization is None:
9
- raise HTTPException(
10
- status_code=status.HTTP_401_UNAUTHORIZED,
11
- detail="Missing authorization header",
12
- )
13
-
14
- scheme, _, token = authorization.partition(" ")
15
- if scheme.casefold() != "bearer" or not token.strip():
16
- raise HTTPException(
17
- status_code=status.HTTP_401_UNAUTHORIZED,
18
- detail="Invalid authorization header",
19
- )
20
- return token.strip()
21
-
22
-
23
- def require_authenticated_user(
24
- authorization: str | None = Header(default=None),
25
- ) -> AuthenticatedUser:
26
- return resolve_current_user(_extract_bearer_token(authorization))
27
-
28
-
29
- def require_admin_user(
30
- current_user: AuthenticatedUser = Depends(require_authenticated_user),
31
- ) -> AuthenticatedUser:
32
- if current_user.role != "admin":
33
- raise HTTPException(
34
- status_code=status.HTTP_403_FORBIDDEN,
35
- detail="Admin access required",
36
- )
37
- return current_user
@@ -1,19 +0,0 @@
1
- from fastapi import APIRouter, Depends
2
-
3
- from contexts.auth.application import authenticate_user
4
- from contexts.auth.contracts.http.dependencies import require_authenticated_user
5
- from contexts.auth.domain import AuthToken, AuthenticatedUser, LoginCommand
6
-
7
- router = APIRouter(prefix="/auth", tags=["auth"])
8
-
9
-
10
- @router.post("/login", response_model=AuthToken)
11
- def login(command: LoginCommand) -> AuthToken:
12
- return authenticate_user(command)
13
-
14
-
15
- @router.get("/me", response_model=AuthenticatedUser)
16
- def me(
17
- current_user: AuthenticatedUser = Depends(require_authenticated_user),
18
- ) -> AuthenticatedUser:
19
- return current_user
@@ -1,3 +0,0 @@
1
- from .models import AuthAccountRecord, AuthenticatedUser, AuthToken, LoginCommand
2
-
3
- __all__ = ["AuthToken", "LoginCommand", "AuthenticatedUser", "AuthAccountRecord"]
@@ -1,24 +0,0 @@
1
- from pydantic import BaseModel, EmailStr
2
-
3
-
4
- class LoginCommand(BaseModel):
5
- email: EmailStr
6
- password: str
7
-
8
-
9
- class AuthToken(BaseModel):
10
- access_token: str
11
- token_type: str = "bearer"
12
- user_id: str
13
-
14
-
15
- class AuthenticatedUser(BaseModel):
16
- id: str
17
- name: str
18
- email: EmailStr
19
- role: str
20
- status: str
21
-
22
-
23
- class AuthAccountRecord(AuthenticatedUser):
24
- password_hash: str
@@ -1,4 +0,0 @@
1
- from .repository import get_auth_repository
2
- from shared.infrastructure import decode_access_token, issue_access_token, verify_password
3
-
4
- __all__ = ["decode_access_token", "get_auth_repository", "issue_access_token", "verify_password"]
@@ -1,19 +0,0 @@
1
- from contexts.auth.domain import AuthAccountRecord
2
-
3
-
4
- class MemoryAuthAccountRepository:
5
- def __init__(self) -> None:
6
- self._accounts: dict[str, AuthAccountRecord] = {}
7
-
8
- def initialize(self) -> None:
9
- return None
10
-
11
- def seed_accounts(self, accounts: list[AuthAccountRecord]) -> None:
12
- for account in accounts:
13
- self._accounts[account.id] = account
14
-
15
- def get_by_email(self, email: str) -> AuthAccountRecord | None:
16
- return next((account for account in self._accounts.values() if account.email == email), None)
17
-
18
- def get_by_id(self, user_id: str) -> AuthAccountRecord | None:
19
- return self._accounts.get(user_id)
@@ -1,24 +0,0 @@
1
- from pymongo import ASCENDING, MongoClient
2
-
3
- from contexts.auth.domain import AuthAccountRecord
4
-
5
-
6
- class MongoAuthAccountRepository:
7
- def __init__(self, mongodb_url: str, database_name: str) -> None:
8
- self.client = MongoClient(mongodb_url)
9
- self.collection = self.client[database_name]["auth_accounts"]
10
-
11
- def initialize(self) -> None:
12
- self.collection.create_index([("email", ASCENDING)], unique=True)
13
-
14
- def seed_accounts(self, accounts: list[AuthAccountRecord]) -> None:
15
- for account in accounts:
16
- self.collection.update_one({"id": account.id}, {"$set": account.model_dump()}, upsert=True)
17
-
18
- def get_by_email(self, email: str) -> AuthAccountRecord | None:
19
- record = self.collection.find_one({"email": email}, {"_id": 0})
20
- return AuthAccountRecord(**record) if record else None
21
-
22
- def get_by_id(self, user_id: str) -> AuthAccountRecord | None:
23
- record = self.collection.find_one({"id": user_id}, {"_id": 0})
24
- return AuthAccountRecord(**record) if record else None
@@ -1,74 +0,0 @@
1
- from sqlalchemy import String, create_engine, select
2
- from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, sessionmaker
3
-
4
- from contexts.auth.domain import AuthAccountRecord
5
-
6
-
7
- class Base(DeclarativeBase):
8
- pass
9
-
10
-
11
- class AuthAccountTable(Base):
12
- __tablename__ = "auth_accounts"
13
-
14
- id: Mapped[str] = mapped_column(String(64), primary_key=True)
15
- name: Mapped[str] = mapped_column(String(128))
16
- email: Mapped[str] = mapped_column(String(255), unique=True, index=True)
17
- role: Mapped[str] = mapped_column(String(64))
18
- status: Mapped[str] = mapped_column(String(32))
19
- password_hash: Mapped[str] = mapped_column(String(255))
20
-
21
-
22
- class SqlAlchemyAuthAccountRepository:
23
- def __init__(self, database_url: str) -> None:
24
- self.engine = create_engine(database_url, future=True)
25
- self.session_factory = sessionmaker(bind=self.engine, expire_on_commit=False)
26
-
27
- def initialize(self) -> None:
28
- Base.metadata.create_all(self.engine)
29
-
30
- def seed_accounts(self, accounts: list[AuthAccountRecord]) -> None:
31
- with self.session_factory() as session:
32
- for account in accounts:
33
- existing = session.get(AuthAccountTable, account.id)
34
- if existing is None:
35
- session.add(AuthAccountTable(**account.model_dump()))
36
- continue
37
- for field, value in account.model_dump().items():
38
- setattr(existing, field, value)
39
- session.commit()
40
-
41
- def get_by_email(self, email: str) -> AuthAccountRecord | None:
42
- with self.session_factory() as session:
43
- record = session.scalar(select(AuthAccountTable).where(AuthAccountTable.email == email))
44
- return self._to_record(record)
45
-
46
- def get_by_id(self, user_id: str) -> AuthAccountRecord | None:
47
- with self.session_factory() as session:
48
- record = session.get(AuthAccountTable, user_id)
49
- return self._to_record(record)
50
-
51
- @staticmethod
52
- def _to_record(record: AuthAccountTable | None) -> AuthAccountRecord | None:
53
- if record is None:
54
- return None
55
- return AuthAccountRecord(
56
- id=record.id,
57
- name=record.name,
58
- email=record.email,
59
- role=record.role,
60
- status=record.status,
61
- password_hash=record.password_hash,
62
- )
63
-
64
-
65
- class PostgresAuthAccountRepository(SqlAlchemyAuthAccountRepository):
66
- pass
67
-
68
-
69
- class MySqlAuthAccountRepository(SqlAlchemyAuthAccountRepository):
70
- pass
71
-
72
-
73
- class MariaDbAuthAccountRepository(SqlAlchemyAuthAccountRepository):
74
- pass
@@ -1,28 +0,0 @@
1
- from functools import lru_cache
2
- from typing import TYPE_CHECKING
3
-
4
- from config import get_settings
5
- from contexts.auth.infrastructure.adapters.memory import MemoryAuthAccountRepository
6
- from contexts.auth.infrastructure.adapters.mongodb import MongoAuthAccountRepository
7
- from contexts.auth.infrastructure.adapters.sqlalchemy import (
8
- MariaDbAuthAccountRepository,
9
- MySqlAuthAccountRepository,
10
- PostgresAuthAccountRepository,
11
- )
12
-
13
- if TYPE_CHECKING:
14
- from contexts.auth.application.ports import AuthAccountRepository
15
-
16
-
17
- @lru_cache
18
- def get_auth_repository() -> "AuthAccountRepository":
19
- settings = get_settings()
20
- if settings.database_backend == "postgres":
21
- return PostgresAuthAccountRepository(settings.postgres_url)
22
- if settings.database_backend == "mysql":
23
- return MySqlAuthAccountRepository(settings.mysql_url)
24
- if settings.database_backend == "mariadb":
25
- return MariaDbAuthAccountRepository(settings.mariadb_url)
26
- if settings.database_backend == "mongodb":
27
- return MongoAuthAccountRepository(settings.mongodb_url, settings.mongodb_database)
28
- return MemoryAuthAccountRepository()
@@ -1 +0,0 @@
1
- __all__ = ["application", "contracts", "domain", "infrastructure"]
@@ -1,28 +0,0 @@
1
- from .services import (
2
- create_product,
3
- get_product_or_404,
4
- list_product_summaries,
5
- prepare_catalog_store,
6
- update_product_or_404,
7
- update_product_status_or_404,
8
- )
9
-
10
- create_catalog_product = create_product
11
- get_catalog_product_or_404 = get_product_or_404
12
- list_catalog_products = list_product_summaries
13
- update_catalog_product = update_product_or_404
14
- update_catalog_product_status = update_product_status_or_404
15
-
16
- __all__ = [
17
- "create_catalog_product",
18
- "create_product",
19
- "get_catalog_product_or_404",
20
- "get_product_or_404",
21
- "list_catalog_products",
22
- "list_product_summaries",
23
- "prepare_catalog_store",
24
- "update_catalog_product",
25
- "update_catalog_product_status",
26
- "update_product_or_404",
27
- "update_product_status_or_404",
28
- ]
@@ -1,15 +0,0 @@
1
- from typing import Protocol
2
-
3
- from contexts.catalog.domain import ProductRecord, ProductStatus, ProductSummary
4
-
5
-
6
- class CatalogRepository(Protocol):
7
- def initialize(self) -> None: ...
8
- def seed_products(self, products: list[ProductRecord]) -> None: ...
9
- def list_products(self) -> list[ProductRecord]: ...
10
- def list_summaries(self) -> list[ProductSummary]: ...
11
- def get_by_id(self, product_id: str) -> ProductRecord | None: ...
12
- def get_by_slug(self, slug: str) -> ProductRecord | None: ...
13
- def create_product(self, product: ProductRecord) -> ProductRecord: ...
14
- def update_product(self, product: ProductRecord) -> ProductRecord: ...
15
- def update_status(self, product_id: str, status: ProductStatus) -> ProductRecord | None: ...
@@ -1,154 +0,0 @@
1
- from datetime import datetime, timezone
2
- from functools import lru_cache
3
-
4
- from fastapi import HTTPException, status as http_status
5
-
6
- from contexts.catalog.domain import (
7
- CreateProductCommand,
8
- ProductDetail,
9
- ProductRecord,
10
- ProductStatus,
11
- ProductSummary,
12
- UpdateProductCommand,
13
- UpdateProductStatusCommand,
14
- )
15
- from contexts.catalog.infrastructure import get_catalog_repository
16
- from data.bootstrap_loader import load_bootstrap_json
17
-
18
-
19
- def list_product_summaries(
20
- product_status: ProductStatus | None = None,
21
- category: str | None = None,
22
- search: str | None = None,
23
- ) -> list[ProductSummary]:
24
- prepare_catalog_store()
25
- repository = get_catalog_repository()
26
- products = repository.list_products()
27
-
28
- if product_status is not None:
29
- products = [product for product in products if product.status == product_status]
30
- if category is not None:
31
- normalized_category = category.strip().casefold()
32
- products = [product for product in products if product.category.casefold() == normalized_category]
33
- if search is not None:
34
- normalized_search = search.strip().casefold()
35
- products = [
36
- product
37
- for product in products
38
- if normalized_search
39
- in " ".join([product.name, product.brand, product.category, product.slug, *product.tags]).casefold()
40
- ]
41
-
42
- return [_to_summary(product) for product in products]
43
-
44
-
45
- def get_product_or_404(product_id: str) -> ProductDetail:
46
- prepare_catalog_store()
47
- repository = get_catalog_repository()
48
- product = repository.get_by_id(product_id)
49
- if product is None:
50
- raise HTTPException(status_code=http_status.HTTP_404_NOT_FOUND, detail="Catalog product not found")
51
- return ProductDetail(**product.model_dump())
52
-
53
-
54
- def create_product(command: CreateProductCommand) -> ProductDetail:
55
- prepare_catalog_store()
56
- repository = get_catalog_repository()
57
- if repository.get_by_slug(command.slug) is not None:
58
- raise HTTPException(status_code=http_status.HTTP_409_CONFLICT, detail="Catalog product slug already exists")
59
-
60
- next_id = _next_product_id(repository.list_products())
61
- timestamp = _now_iso()
62
- product = ProductRecord(
63
- id=next_id,
64
- slug=command.slug,
65
- name=command.name,
66
- brand=command.brand,
67
- category=command.category,
68
- status=command.status,
69
- short_description=command.short_description,
70
- description=command.description,
71
- hero_image=command.hero_image,
72
- gallery=command.gallery,
73
- price=command.price,
74
- compare_at_price=command.compare_at_price,
75
- tags=command.tags,
76
- attributes=command.attributes,
77
- variants=command.variants,
78
- created_at=timestamp,
79
- updated_at=timestamp,
80
- )
81
- return ProductDetail(**repository.create_product(product).model_dump())
82
-
83
-
84
- def update_product_or_404(product_id: str, command: UpdateProductCommand) -> ProductDetail:
85
- prepare_catalog_store()
86
- repository = get_catalog_repository()
87
- current = repository.get_by_id(product_id)
88
- if current is None:
89
- raise HTTPException(status_code=http_status.HTTP_404_NOT_FOUND, detail="Catalog product not found")
90
-
91
- updates = command.model_dump(exclude_none=True, exclude_unset=True)
92
- if not updates:
93
- raise HTTPException(status_code=http_status.HTTP_400_BAD_REQUEST, detail="No catalog product fields provided")
94
-
95
- if "slug" in updates:
96
- existing = repository.get_by_slug(updates["slug"])
97
- if existing is not None and existing.id != product_id:
98
- raise HTTPException(status_code=http_status.HTTP_409_CONFLICT, detail="Catalog product slug already exists")
99
-
100
- updated = current.model_copy(update={**updates, "updated_at": _now_iso()})
101
- return ProductDetail(**repository.update_product(updated).model_dump())
102
-
103
-
104
- def update_product_status_or_404(product_id: str, command: UpdateProductStatusCommand) -> ProductDetail:
105
- prepare_catalog_store()
106
- repository = get_catalog_repository()
107
- current = repository.get_by_id(product_id)
108
- if current is None:
109
- raise HTTPException(status_code=http_status.HTTP_404_NOT_FOUND, detail="Catalog product not found")
110
- updated = current.model_copy(update={"status": command.status, "updated_at": _now_iso()})
111
- return ProductDetail(**repository.update_product(updated).model_dump())
112
-
113
-
114
- def prepare_catalog_store() -> None:
115
- _seed_catalog_store()
116
-
117
-
118
- @lru_cache
119
- def _seed_catalog_store() -> None:
120
- repository = get_catalog_repository()
121
- repository.initialize()
122
- records = [ProductRecord(**entry) for entry in load_bootstrap_json("catalog_products.json")]
123
- repository.seed_products(records)
124
-
125
-
126
- def _to_summary(product: ProductRecord) -> ProductSummary:
127
- return ProductSummary(
128
- id=product.id,
129
- slug=product.slug,
130
- name=product.name,
131
- brand=product.brand,
132
- category=product.category,
133
- status=product.status,
134
- short_description=product.short_description,
135
- hero_image=product.hero_image,
136
- price=product.price,
137
- compare_at_price=product.compare_at_price,
138
- tags=product.tags,
139
- variant_count=len(product.variants),
140
- )
141
-
142
-
143
- def _next_product_id(products: list[ProductRecord]) -> str:
144
- max_sequence = 1000
145
- for product in products:
146
- try:
147
- max_sequence = max(max_sequence, int(product.id.split("-")[-1]))
148
- except ValueError:
149
- continue
150
- return f"prd-{max_sequence + 1}"
151
-
152
-
153
- def _now_iso() -> str:
154
- return datetime.now(timezone.utc).replace(microsecond=0).isoformat()
@@ -1,3 +0,0 @@
1
- from .http.router import router
2
-
3
- __all__ = ["router"]
@@ -1,3 +0,0 @@
1
- from .router import router
2
-
3
- __all__ = ["router"]
@@ -1,60 +0,0 @@
1
- from fastapi import APIRouter, Depends, Query, status
2
-
3
- from contexts.auth.contracts.http.dependencies import require_admin_user
4
- from contexts.catalog.application import (
5
- create_product,
6
- get_product_or_404,
7
- list_product_summaries,
8
- update_product_or_404,
9
- update_product_status_or_404,
10
- )
11
- from contexts.catalog.domain import (
12
- CreateProductCommand,
13
- ProductDetail,
14
- ProductStatus,
15
- ProductSummary,
16
- UpdateProductCommand,
17
- UpdateProductStatusCommand,
18
- )
19
-
20
- router = APIRouter(prefix="/catalog", tags=["catalog"])
21
-
22
-
23
- @router.get("/products", response_model=list[ProductSummary])
24
- def list_products(
25
- product_status: ProductStatus | None = Query(default=None, alias="status"),
26
- category: str | None = Query(default=None),
27
- search: str | None = Query(default=None, alias="q"),
28
- ) -> list[ProductSummary]:
29
- return list_product_summaries(product_status=product_status, category=category, search=search)
30
-
31
-
32
- @router.get("/products/{product_id}", response_model=ProductDetail)
33
- def get_product(product_id: str) -> ProductDetail:
34
- return get_product_or_404(product_id)
35
-
36
-
37
- @router.post("/products", response_model=ProductDetail, status_code=status.HTTP_201_CREATED)
38
- def post_product(
39
- command: CreateProductCommand,
40
- _: object = Depends(require_admin_user),
41
- ) -> ProductDetail:
42
- return create_product(command)
43
-
44
-
45
- @router.put("/products/{product_id}", response_model=ProductDetail)
46
- def put_product(
47
- product_id: str,
48
- command: UpdateProductCommand,
49
- _: object = Depends(require_admin_user),
50
- ) -> ProductDetail:
51
- return update_product_or_404(product_id, command)
52
-
53
-
54
- @router.patch("/products/{product_id}/status", response_model=ProductDetail)
55
- def patch_product_status(
56
- product_id: str,
57
- command: UpdateProductStatusCommand,
58
- _: object = Depends(require_admin_user),
59
- ) -> ProductDetail:
60
- return update_product_status_or_404(product_id, command)