@yss123/cage-cli 0.1.0 → 0.3.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 (734) hide show
  1. package/README.md +69 -3
  2. package/bin/cage.js +5 -0
  3. package/bin/create-cage-app.js +5 -0
  4. package/dist/analyze.d.ts +16 -0
  5. package/dist/analyze.js +20 -2
  6. package/dist/analyze.js.map +1 -1
  7. package/dist/baseline.d.ts +8 -0
  8. package/dist/baseline.js +13 -0
  9. package/dist/baseline.js.map +1 -1
  10. package/dist/bootstrap.d.ts +20 -0
  11. package/dist/bootstrap.js +75 -0
  12. package/dist/bootstrap.js.map +1 -0
  13. package/dist/budget.d.ts +7 -0
  14. package/dist/budget.js +49 -5
  15. package/dist/budget.js.map +1 -1
  16. package/dist/capabilities.d.ts +38 -0
  17. package/dist/capabilities.js +133 -0
  18. package/dist/capabilities.js.map +1 -0
  19. package/dist/config.d.ts +33 -4
  20. package/dist/config.js +22 -1
  21. package/dist/config.js.map +1 -1
  22. package/dist/context.d.ts +86 -0
  23. package/dist/context.js +235 -0
  24. package/dist/context.js.map +1 -0
  25. package/dist/create-prompt.d.ts +12 -0
  26. package/dist/create-prompt.js +62 -0
  27. package/dist/create-prompt.js.map +1 -0
  28. package/dist/create.d.ts +38 -1
  29. package/dist/create.js +52 -13
  30. package/dist/create.js.map +1 -1
  31. package/dist/derive.d.ts +23 -0
  32. package/dist/derive.js +40 -0
  33. package/dist/derive.js.map +1 -1
  34. package/dist/dev.d.ts +6 -0
  35. package/dist/dev.js +23 -51
  36. package/dist/dev.js.map +1 -1
  37. package/dist/doctor.d.ts +98 -0
  38. package/dist/doctor.js +93 -0
  39. package/dist/doctor.js.map +1 -0
  40. package/dist/env.d.ts +6 -0
  41. package/dist/env.js +11 -0
  42. package/dist/env.js.map +1 -1
  43. package/dist/findings.d.ts +27 -0
  44. package/dist/findings.js +20 -0
  45. package/dist/findings.js.map +1 -1
  46. package/dist/gen/contracts.d.ts +28 -0
  47. package/dist/gen/contracts.js +81 -20
  48. package/dist/gen/contracts.js.map +1 -1
  49. package/dist/gen/index.d.ts +26 -0
  50. package/dist/gen/index.js +112 -4
  51. package/dist/gen/index.js.map +1 -1
  52. package/dist/gen/zod-code.d.ts +43 -1
  53. package/dist/gen/zod-code.js +180 -16
  54. package/dist/gen/zod-code.js.map +1 -1
  55. package/dist/graph-approvals.d.ts +60 -0
  56. package/dist/graph-approvals.js +80 -0
  57. package/dist/graph-approvals.js.map +1 -0
  58. package/dist/graph-business.d.ts +135 -0
  59. package/dist/graph-business.js +404 -0
  60. package/dist/graph-business.js.map +1 -0
  61. package/dist/graph-command.d.ts +28 -0
  62. package/dist/graph-command.js +88 -0
  63. package/dist/graph-command.js.map +1 -0
  64. package/dist/graph-model.d.ts +65 -0
  65. package/dist/graph-model.js +134 -0
  66. package/dist/graph-model.js.map +1 -0
  67. package/dist/graph-presentation.d.ts +27 -0
  68. package/dist/graph-presentation.js +34 -0
  69. package/dist/graph-presentation.js.map +1 -0
  70. package/dist/graph-query.d.ts +266 -0
  71. package/dist/graph-query.js +304 -0
  72. package/dist/graph-query.js.map +1 -0
  73. package/dist/graph-relations.d.ts +34 -0
  74. package/dist/graph-relations.js +172 -0
  75. package/dist/graph-relations.js.map +1 -0
  76. package/dist/graph-search.d.ts +56 -0
  77. package/dist/graph-search.js +99 -0
  78. package/dist/graph-search.js.map +1 -0
  79. package/dist/graph-snapshot.d.ts +28 -4
  80. package/dist/graph-snapshot.js +32 -20
  81. package/dist/graph-snapshot.js.map +1 -1
  82. package/dist/graph.d.ts +13 -2
  83. package/dist/graph.js +78 -5
  84. package/dist/graph.js.map +1 -1
  85. package/dist/impact.d.ts +56 -0
  86. package/dist/impact.js +90 -18
  87. package/dist/impact.js.map +1 -1
  88. package/dist/index.d.ts +15 -1
  89. package/dist/index.js +15 -1
  90. package/dist/index.js.map +1 -1
  91. package/dist/init.d.ts +18 -0
  92. package/dist/init.js +146 -0
  93. package/dist/init.js.map +1 -0
  94. package/dist/load.d.ts +10 -0
  95. package/dist/load.js +15 -0
  96. package/dist/load.js.map +1 -1
  97. package/dist/main.d.ts +6 -0
  98. package/dist/main.js +170 -37
  99. package/dist/main.js.map +1 -1
  100. package/dist/migrate.d.ts +15 -6
  101. package/dist/migrate.js +31 -53
  102. package/dist/migrate.js.map +1 -1
  103. package/dist/ontology.d.ts +69 -2
  104. package/dist/ontology.js +101 -4
  105. package/dist/ontology.js.map +1 -1
  106. package/dist/process-rules.d.ts +21 -0
  107. package/dist/process-rules.js +100 -0
  108. package/dist/process-rules.js.map +1 -0
  109. package/dist/process.d.ts +32 -0
  110. package/dist/process.js +32 -0
  111. package/dist/process.js.map +1 -1
  112. package/dist/project-structure.d.ts +13 -0
  113. package/dist/project-structure.js +104 -0
  114. package/dist/project-structure.js.map +1 -0
  115. package/dist/registration.d.ts +16 -0
  116. package/dist/registration.js +56 -0
  117. package/dist/registration.js.map +1 -0
  118. package/dist/rules.d.ts +52 -0
  119. package/dist/rules.js +58 -0
  120. package/dist/rules.js.map +1 -1
  121. package/dist/runtime-diagnostics.d.ts +27 -0
  122. package/dist/runtime-diagnostics.js +60 -0
  123. package/dist/runtime-diagnostics.js.map +1 -0
  124. package/dist/snapshots.d.ts +40 -0
  125. package/dist/snapshots.js +62 -0
  126. package/dist/snapshots.js.map +1 -0
  127. package/dist/static-check.d.ts +33 -0
  128. package/dist/static-check.js +38 -5
  129. package/dist/static-check.js.map +1 -1
  130. package/dist/sync.d.ts +11 -0
  131. package/dist/sync.js +139 -10
  132. package/dist/sync.js.map +1 -1
  133. package/dist/upgrade.d.ts +16 -0
  134. package/dist/upgrade.js +21 -0
  135. package/dist/upgrade.js.map +1 -1
  136. package/dist/verify.d.ts +14 -0
  137. package/dist/verify.js +19 -0
  138. package/dist/verify.js.map +1 -1
  139. package/dist/version.js +5 -0
  140. package/dist/version.js.map +1 -1
  141. package/graph-ui/app.js +367 -35
  142. package/graph-ui/approval-flow.js +165 -0
  143. package/graph-ui/business.css +985 -0
  144. package/graph-ui/business.js +549 -0
  145. package/graph-ui/flowchart-interaction.js +177 -0
  146. package/graph-ui/flowchart.js +1059 -0
  147. package/graph-ui/graph-approvals.js +79 -0
  148. package/graph-ui/graph-business.js +403 -0
  149. package/graph-ui/graph-model.js +133 -0
  150. package/graph-ui/graph-relations.js +171 -0
  151. package/graph-ui/graph-search.js +98 -0
  152. package/graph-ui/index.html +26 -12
  153. package/graph-ui/model.js +47 -77
  154. package/graph-ui/relations.js +6 -125
  155. package/graph-ui/structure.js +48 -1
  156. package/graph-ui/style.css +33 -0
  157. package/package.json +10 -8
  158. package/templates/app/.dockerignore +2 -0
  159. package/templates/app/.env.example +68 -14
  160. package/templates/app/AGENTS.md +135 -12
  161. package/templates/app/Dockerfile +2 -0
  162. package/templates/app/README.md +49 -16
  163. package/templates/app/_gitignore +9 -0
  164. package/templates/app/apps/api/package.json +2 -2
  165. package/templates/app/apps/api/src/main.ts +5 -1
  166. package/templates/app/apps/api/src/worker.ts +3 -0
  167. package/templates/app/apps/web/index.html +1 -0
  168. package/templates/app/apps/web/package.json +7 -3
  169. package/templates/app/apps/web/src/app/app.tsx +128 -0
  170. package/templates/app/apps/web/src/{style.css → app/styles/global.css} +88 -8
  171. package/templates/app/apps/web/src/app/use-session.ts +43 -0
  172. package/templates/app/apps/web/src/app/workspace-layout.tsx +109 -0
  173. package/templates/app/apps/web/src/main.tsx +9 -543
  174. package/templates/app/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +31 -0
  175. package/templates/app/apps/web/src/modules/approval/index.ts +6 -0
  176. package/templates/app/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +73 -0
  177. package/templates/app/apps/web/src/modules/auth/index.ts +5 -0
  178. package/templates/app/apps/web/src/modules/auth/pages/login-page.tsx +71 -0
  179. package/templates/app/apps/web/src/modules/inventory/index.ts +5 -0
  180. package/templates/app/apps/web/src/modules/inventory/pages/inventory-page.tsx +102 -0
  181. package/templates/app/apps/web/src/modules/purchase/components/approval-history.tsx +32 -0
  182. package/templates/app/apps/web/src/modules/purchase/components/order-attachments.tsx +29 -0
  183. package/templates/app/apps/web/src/modules/purchase/components/purchase-assistant-context.tsx +17 -0
  184. package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.css +6 -0
  185. package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.tsx +82 -0
  186. package/templates/app/apps/web/src/modules/purchase/index.ts +7 -0
  187. package/templates/app/apps/web/src/modules/purchase/lib/presentation.ts +20 -0
  188. package/templates/app/apps/web/src/modules/purchase/pages/purchase-intelligence.css +15 -0
  189. package/templates/app/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +154 -0
  190. package/templates/app/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +240 -0
  191. package/templates/app/apps/web/src/modules/workspace/index.ts +5 -0
  192. package/templates/app/apps/web/src/modules/workspace/pages/home-page.tsx +44 -0
  193. package/templates/app/apps/web/src/shared/hooks/use-command.ts +42 -0
  194. package/templates/app/apps/web/src/shared/lib/error-message.ts +24 -0
  195. package/templates/app/apps/web/src/shared/lib/navigation.ts +21 -0
  196. package/templates/app/apps/web/src/shared/ui/assistant-markdown.tsx +19 -0
  197. package/templates/app/apps/web/src/shared/ui/assistant-panel.css +134 -0
  198. package/templates/app/apps/web/src/shared/ui/assistant-panel.tsx +200 -0
  199. package/templates/app/apps/web/src/shared/ui/assistant-scope.tsx +72 -0
  200. package/templates/app/apps/web/src/shared/ui/attachment-upload.css +28 -0
  201. package/templates/app/apps/web/src/shared/ui/attachment-upload.tsx +163 -0
  202. package/templates/app/apps/web/src/shared/ui/notice.tsx +20 -0
  203. package/templates/app/apps/web/src/shared/ui/page-heading.tsx +35 -0
  204. package/templates/app/apps/web/src/shared/ui/page-state.css +47 -0
  205. package/templates/app/apps/web/src/shared/ui/page-state.tsx +76 -0
  206. package/templates/app/apps/web/src/shared/ui/require-capability.tsx +34 -0
  207. package/templates/app/apps/web/vite.config.ts +8 -0
  208. package/templates/app/cage.config.json +10 -1
  209. package/templates/app/db/migrations/0002_draft.sql +12 -0
  210. package/templates/app/db/migrations/0003_draft.sql +8 -0
  211. package/templates/app/deploy/nginx.conf +52 -0
  212. package/templates/app/docs/ai/README.md +98 -0
  213. package/templates/app/docs/ai/architecture.md +148 -0
  214. package/templates/app/docs/ai/commenting.md +203 -0
  215. package/templates/app/docs/ai/diagnostics.md +80 -0
  216. package/templates/app/docs/ai/files.md +93 -0
  217. package/templates/app/docs/ai/intelligence.md +348 -0
  218. package/templates/app/docs/ai/ontology-context.md +172 -0
  219. package/templates/app/docs/ai/primitives.md +282 -0
  220. package/templates/app/docs/ai/project-structure.md +128 -0
  221. package/templates/app/docs/ai/purchase-example.md +111 -0
  222. package/templates/app/docs/ai/recipes.md +89 -0
  223. package/templates/app/docs/ai/relations.md +160 -0
  224. package/templates/app/docs/ai/routing.md +86 -0
  225. package/templates/app/docs/ai/transfers.md +92 -0
  226. package/templates/app/docs/ai/troubleshooting.md +65 -0
  227. package/templates/app/docs/ai/workflow.md +152 -0
  228. package/templates/app/docs/errors/CAGE-AI-001.md +61 -0
  229. package/templates/app/docs/errors/CAGE-APPR-001.md +48 -0
  230. package/templates/app/docs/errors/CAGE-APPR-002.md +47 -0
  231. package/templates/app/docs/errors/CAGE-APPR-003.md +47 -0
  232. package/templates/app/docs/errors/CAGE-APPR-004.md +47 -0
  233. package/templates/app/docs/errors/CAGE-APPR-005.md +47 -0
  234. package/templates/app/docs/errors/CAGE-APPR-006.md +53 -0
  235. package/templates/app/docs/errors/CAGE-APPR-007.md +50 -0
  236. package/templates/app/docs/errors/CAGE-APPR-010.md +48 -0
  237. package/templates/app/docs/errors/CAGE-AUDIT-001.md +53 -0
  238. package/templates/app/docs/errors/CAGE-AUTH-001.md +47 -0
  239. package/templates/app/docs/errors/CAGE-BIZ-001.md +51 -0
  240. package/templates/app/docs/errors/CAGE-BIZ-002.md +49 -0
  241. package/templates/app/docs/errors/CAGE-BUDGET-001.md +47 -0
  242. package/templates/app/docs/errors/CAGE-BUDGET-002.md +47 -0
  243. package/templates/app/docs/errors/CAGE-BUDGET-003.md +47 -0
  244. package/templates/app/docs/errors/CAGE-CMD-002.md +47 -0
  245. package/templates/app/docs/errors/CAGE-CMD-003.md +47 -0
  246. package/templates/app/docs/errors/CAGE-CONN-001.md +47 -0
  247. package/templates/app/docs/errors/CAGE-CONN-002.md +47 -0
  248. package/templates/app/docs/errors/CAGE-CONN-003.md +47 -0
  249. package/templates/app/docs/errors/CAGE-CONN-004.md +47 -0
  250. package/templates/app/docs/errors/CAGE-CONN-005.md +47 -0
  251. package/templates/app/docs/errors/CAGE-CONN-006.md +47 -0
  252. package/templates/app/docs/errors/CAGE-CONN-007.md +47 -0
  253. package/templates/app/docs/errors/CAGE-CONN-008.md +47 -0
  254. package/templates/app/docs/errors/CAGE-CONN-009.md +47 -0
  255. package/templates/app/docs/errors/CAGE-CONN-010.md +47 -0
  256. package/templates/app/docs/errors/CAGE-CONN-011.md +47 -0
  257. package/templates/app/docs/errors/CAGE-CONN-012.md +47 -0
  258. package/templates/app/docs/errors/CAGE-CONN-013.md +49 -0
  259. package/templates/app/docs/errors/CAGE-CONN-014.md +48 -0
  260. package/templates/app/docs/errors/CAGE-CONN-015.md +49 -0
  261. package/templates/app/docs/errors/CAGE-CREATE-001.md +53 -0
  262. package/templates/app/docs/errors/CAGE-DECL-001.md +48 -0
  263. package/templates/app/docs/errors/CAGE-DECL-002.md +48 -0
  264. package/templates/app/docs/errors/CAGE-DECL-003.md +47 -0
  265. package/templates/app/docs/errors/CAGE-DECL-004.md +47 -0
  266. package/templates/app/docs/errors/CAGE-DEP-001.md +48 -0
  267. package/templates/app/docs/errors/CAGE-DEP-002.md +47 -0
  268. package/templates/app/docs/errors/CAGE-DEP-003.md +47 -0
  269. package/templates/app/docs/errors/CAGE-DEP-004.md +47 -0
  270. package/templates/app/docs/errors/CAGE-DEP-005.md +47 -0
  271. package/templates/app/docs/errors/CAGE-DIAG-001.md +53 -0
  272. package/templates/app/docs/errors/CAGE-DLQ-001.md +48 -0
  273. package/templates/app/docs/errors/CAGE-ENV-001.md +52 -0
  274. package/templates/app/docs/errors/CAGE-ENV-002.md +51 -0
  275. package/templates/app/docs/errors/CAGE-ENV-003.md +48 -0
  276. package/templates/app/docs/errors/CAGE-EVENT-001.md +47 -0
  277. package/templates/app/docs/errors/CAGE-EVENT-002.md +50 -0
  278. package/templates/app/docs/errors/CAGE-FIELD-001.md +47 -0
  279. package/templates/app/docs/errors/CAGE-FIELD-002.md +47 -0
  280. package/templates/app/docs/errors/CAGE-FIELD-003.md +47 -0
  281. package/templates/app/docs/errors/CAGE-FIELD-004.md +47 -0
  282. package/templates/app/docs/errors/CAGE-FILE-001.md +56 -0
  283. package/templates/app/docs/errors/CAGE-GEN-001.md +48 -0
  284. package/templates/app/docs/errors/CAGE-GEN-002.md +47 -0
  285. package/templates/app/docs/errors/CAGE-GEN-003.md +53 -0
  286. package/templates/app/docs/errors/CAGE-GRANT-001.md +49 -0
  287. package/templates/app/docs/errors/CAGE-GRANT-002.md +48 -0
  288. package/templates/app/docs/errors/CAGE-GRANT-003.md +48 -0
  289. package/templates/app/docs/errors/CAGE-IMPACT-001.md +48 -0
  290. package/templates/app/docs/errors/CAGE-IMPACT-002.md +52 -0
  291. package/templates/app/docs/errors/CAGE-INIT-001.md +47 -0
  292. package/templates/app/docs/errors/CAGE-INIT-002.md +49 -0
  293. package/templates/app/docs/errors/CAGE-INIT-003.md +48 -0
  294. package/templates/app/docs/errors/CAGE-INIT-004.md +48 -0
  295. package/templates/app/docs/errors/CAGE-INIT-005.md +52 -0
  296. package/templates/app/docs/errors/CAGE-JOB-001.md +47 -0
  297. package/templates/app/docs/errors/CAGE-JOB-002.md +47 -0
  298. package/templates/app/docs/errors/CAGE-JOB-003.md +47 -0
  299. package/templates/app/docs/errors/CAGE-LINT-001.md +47 -0
  300. package/templates/app/docs/errors/CAGE-MIG-001.md +47 -0
  301. package/templates/app/docs/errors/CAGE-MIG-002.md +47 -0
  302. package/templates/app/docs/errors/CAGE-MIG-003.md +5 -0
  303. package/templates/app/docs/errors/CAGE-MIG-004.md +5 -0
  304. package/templates/app/docs/errors/CAGE-MIG-005.md +47 -0
  305. package/templates/app/docs/errors/CAGE-NAME-001.md +47 -0
  306. package/templates/app/docs/errors/CAGE-NAME-002.md +47 -0
  307. package/templates/app/docs/errors/CAGE-NAME-003.md +47 -0
  308. package/templates/app/docs/errors/CAGE-NAME-004.md +47 -0
  309. package/templates/app/docs/errors/CAGE-NAME-005.md +47 -0
  310. package/templates/app/docs/errors/CAGE-NAME-006.md +47 -0
  311. package/templates/app/docs/errors/CAGE-ORG-001.md +50 -0
  312. package/templates/app/docs/errors/CAGE-PAIR-002.md +51 -0
  313. package/templates/app/docs/errors/CAGE-QUERY-001.md +47 -0
  314. package/templates/app/docs/errors/CAGE-QUERY-002.md +47 -0
  315. package/templates/app/docs/errors/CAGE-QUERY-003.md +50 -0
  316. package/templates/app/docs/errors/CAGE-REACT-001.md +47 -0
  317. package/templates/app/docs/errors/CAGE-REACT-002.md +47 -0
  318. package/templates/app/docs/errors/CAGE-REACT-003.md +50 -0
  319. package/templates/app/docs/errors/CAGE-READS-001.md +50 -0
  320. package/templates/app/docs/errors/CAGE-REG-001.md +54 -0
  321. package/templates/app/docs/errors/CAGE-REG-002.md +49 -0
  322. package/templates/app/docs/errors/CAGE-REG-003.md +47 -0
  323. package/templates/app/docs/errors/CAGE-REL-001.md +64 -0
  324. package/templates/app/docs/errors/CAGE-ROUTE-001.md +48 -0
  325. package/templates/app/docs/errors/CAGE-SCOPE-001.md +47 -0
  326. package/templates/app/docs/errors/CAGE-SCOPE-002.md +47 -0
  327. package/templates/app/docs/errors/CAGE-SECRET-001.md +48 -0
  328. package/templates/app/docs/errors/CAGE-SECRET-002.md +47 -0
  329. package/templates/app/docs/errors/CAGE-SENS-001.md +48 -0
  330. package/templates/app/docs/errors/CAGE-SQL-001.md +47 -0
  331. package/templates/app/docs/errors/CAGE-SQL-002.md +47 -0
  332. package/templates/app/docs/errors/CAGE-STATE-001.md +49 -0
  333. package/templates/app/docs/errors/CAGE-STATE-002.md +47 -0
  334. package/templates/app/docs/errors/CAGE-STATE-003.md +47 -0
  335. package/templates/app/docs/errors/CAGE-STATE-004.md +47 -0
  336. package/templates/app/docs/errors/CAGE-STATE-005.md +49 -0
  337. package/templates/app/docs/errors/CAGE-STATE-010.md +48 -0
  338. package/templates/app/docs/errors/CAGE-STATE-011.md +48 -0
  339. package/templates/app/docs/errors/CAGE-STRUCT-001.md +51 -0
  340. package/templates/app/docs/errors/CAGE-STRUCT-002.md +51 -0
  341. package/templates/app/docs/errors/CAGE-SYNC-001.md +49 -0
  342. package/templates/app/docs/errors/CAGE-TEST-001.md +47 -0
  343. package/templates/app/docs/errors/CAGE-TEST-002.md +50 -0
  344. package/templates/app/docs/errors/CAGE-TEST-003.md +52 -0
  345. package/templates/app/docs/errors/CAGE-UNSAFE-001.md +49 -0
  346. package/templates/app/docs/errors/CAGE-UPGRADE-001.md +48 -0
  347. package/templates/app/docs/errors/CAGE-WORKER-001.md +48 -0
  348. package/templates/app/docs/errors/CAGE-WORKER-002.md +50 -0
  349. package/templates/app/docs/errors/CAGE-WORKER-003.md +48 -0
  350. package/templates/app/docs/errors/README.md +357 -0
  351. package/templates/app/docs/errors/runtime.md +50 -0
  352. package/templates/app/package.json +4 -7
  353. package/templates/app/packages/contracts/package.json +1 -1
  354. package/templates/app/packages/contracts/src/{dept.ts → aggregates/dept/index.ts} +11 -11
  355. package/templates/app/packages/contracts/src/{inventory.ts → aggregates/inventory/index.ts} +6 -6
  356. package/templates/app/packages/contracts/src/{inventory-lock.ts → aggregates/inventory-lock/index.ts} +5 -5
  357. package/templates/app/packages/contracts/src/aggregates/purchase-order/index.ts +86 -0
  358. package/templates/app/packages/contracts/src/{role.ts → aggregates/role/index.ts} +16 -16
  359. package/templates/app/packages/contracts/src/aggregates/user/index.ts +89 -0
  360. package/templates/app/packages/contracts/src/index.ts +20 -14
  361. package/templates/app/packages/contracts/src/{queries.ts → queries/index.ts} +2 -2
  362. package/templates/app/packages/domain/package.json +5 -4
  363. package/templates/app/packages/domain/src/index.ts +8 -7
  364. package/templates/app/packages/domain/src/{erp.ts → integrations/erp.ts} +16 -1
  365. package/templates/app/packages/domain/src/integrations/intelligence.ts +20 -0
  366. package/templates/app/packages/domain/src/modules/inventory/index.ts +3 -0
  367. package/templates/app/packages/domain/src/{inventory.ts → modules/inventory/inventory.ts} +12 -0
  368. package/templates/app/packages/domain/src/modules/purchase/approvals.ts +39 -0
  369. package/templates/app/packages/domain/src/modules/purchase/index.ts +7 -0
  370. package/templates/app/packages/domain/src/modules/purchase/intelligence.test.ts +62 -0
  371. package/templates/app/packages/domain/src/{jobs.ts → modules/purchase/jobs.ts} +5 -0
  372. package/templates/app/packages/domain/src/{purchase-order.test.ts → modules/purchase/purchase-order.test.ts} +11 -2
  373. package/templates/app/packages/domain/src/modules/purchase/purchase-order.ts +192 -0
  374. package/templates/app/packages/domain/src/{queries.ts → modules/purchase/queries.ts} +5 -0
  375. package/templates/app/packages/domain/src/{reactions.ts → workflows/purchase-inventory.ts} +8 -2
  376. package/templates/app/packages/domain/src/workflows/purchase-process.ts +42 -0
  377. package/templates/blank/.dockerignore +12 -0
  378. package/templates/blank/.env.example +71 -0
  379. package/templates/blank/.github/workflows/cage.yml +44 -0
  380. package/templates/blank/AGENTS.md +136 -0
  381. package/templates/blank/Dockerfile +25 -0
  382. package/templates/blank/README.md +40 -0
  383. package/templates/blank/_gitignore +9 -0
  384. package/templates/blank/apps/api/package.json +15 -0
  385. package/templates/blank/apps/api/src/main.ts +14 -0
  386. package/templates/blank/apps/api/src/worker.ts +10 -0
  387. package/templates/blank/apps/api/tsconfig.json +5 -0
  388. package/templates/blank/apps/web/index.html +14 -0
  389. package/templates/blank/apps/web/package.json +26 -0
  390. package/templates/blank/apps/web/src/app/app.tsx +106 -0
  391. package/templates/blank/apps/web/src/app/styles/global.css +606 -0
  392. package/templates/blank/apps/web/src/app/use-session.ts +43 -0
  393. package/templates/blank/apps/web/src/app/workspace-layout.tsx +95 -0
  394. package/templates/blank/apps/web/src/main.tsx +18 -0
  395. package/templates/blank/apps/web/src/modules/auth/index.ts +5 -0
  396. package/templates/blank/apps/web/src/modules/auth/pages/login-page.tsx +104 -0
  397. package/templates/blank/apps/web/src/modules/directory/index.ts +7 -0
  398. package/templates/blank/apps/web/src/modules/directory/pages/user-detail-page.tsx +78 -0
  399. package/templates/blank/apps/web/src/modules/directory/pages/users-page.tsx +93 -0
  400. package/templates/blank/apps/web/src/modules/workspace/index.ts +5 -0
  401. package/templates/blank/apps/web/src/modules/workspace/pages/home-page.tsx +62 -0
  402. package/templates/blank/apps/web/src/shared/lib/error-message.ts +22 -0
  403. package/templates/blank/apps/web/src/shared/lib/navigation.ts +21 -0
  404. package/templates/blank/apps/web/src/shared/ui/brand.tsx +19 -0
  405. package/templates/blank/apps/web/src/shared/ui/page-state.css +47 -0
  406. package/templates/blank/apps/web/src/shared/ui/page-state.tsx +76 -0
  407. package/templates/blank/apps/web/src/shared/ui/require-capability.tsx +34 -0
  408. package/templates/blank/apps/web/tsconfig.json +11 -0
  409. package/templates/blank/apps/web/vite.config.ts +24 -0
  410. package/templates/blank/cage.config.json +14 -0
  411. package/templates/blank/db/migrations/0001_init.sql +63 -0
  412. package/templates/blank/deploy/nginx.conf +52 -0
  413. package/templates/blank/docs/ai/README.md +98 -0
  414. package/templates/blank/docs/ai/architecture.md +148 -0
  415. package/templates/blank/docs/ai/commenting.md +203 -0
  416. package/templates/blank/docs/ai/diagnostics.md +80 -0
  417. package/templates/blank/docs/ai/files.md +93 -0
  418. package/templates/blank/docs/ai/intelligence.md +348 -0
  419. package/templates/blank/docs/ai/ontology-context.md +172 -0
  420. package/templates/blank/docs/ai/primitives.md +282 -0
  421. package/templates/blank/docs/ai/project-structure.md +128 -0
  422. package/templates/blank/docs/ai/purchase-example.md +111 -0
  423. package/templates/blank/docs/ai/recipes.md +89 -0
  424. package/templates/blank/docs/ai/relations.md +160 -0
  425. package/templates/blank/docs/ai/routing.md +86 -0
  426. package/templates/blank/docs/ai/transfers.md +92 -0
  427. package/templates/blank/docs/ai/troubleshooting.md +65 -0
  428. package/templates/blank/docs/ai/workflow.md +152 -0
  429. package/templates/blank/docs/errors/CAGE-AI-001.md +61 -0
  430. package/templates/blank/docs/errors/CAGE-APPR-001.md +48 -0
  431. package/templates/blank/docs/errors/CAGE-APPR-002.md +47 -0
  432. package/templates/blank/docs/errors/CAGE-APPR-003.md +47 -0
  433. package/templates/blank/docs/errors/CAGE-APPR-004.md +47 -0
  434. package/templates/blank/docs/errors/CAGE-APPR-005.md +47 -0
  435. package/templates/blank/docs/errors/CAGE-APPR-006.md +53 -0
  436. package/templates/blank/docs/errors/CAGE-APPR-007.md +50 -0
  437. package/templates/blank/docs/errors/CAGE-APPR-010.md +48 -0
  438. package/templates/blank/docs/errors/CAGE-AUDIT-001.md +53 -0
  439. package/templates/blank/docs/errors/CAGE-AUTH-001.md +47 -0
  440. package/templates/blank/docs/errors/CAGE-BIZ-001.md +51 -0
  441. package/templates/blank/docs/errors/CAGE-BIZ-002.md +49 -0
  442. package/templates/blank/docs/errors/CAGE-BUDGET-001.md +47 -0
  443. package/templates/blank/docs/errors/CAGE-BUDGET-002.md +47 -0
  444. package/templates/blank/docs/errors/CAGE-BUDGET-003.md +47 -0
  445. package/templates/blank/docs/errors/CAGE-CMD-002.md +47 -0
  446. package/templates/blank/docs/errors/CAGE-CMD-003.md +47 -0
  447. package/templates/blank/docs/errors/CAGE-CONN-001.md +47 -0
  448. package/templates/blank/docs/errors/CAGE-CONN-002.md +47 -0
  449. package/templates/blank/docs/errors/CAGE-CONN-003.md +47 -0
  450. package/templates/blank/docs/errors/CAGE-CONN-004.md +47 -0
  451. package/templates/blank/docs/errors/CAGE-CONN-005.md +47 -0
  452. package/templates/blank/docs/errors/CAGE-CONN-006.md +47 -0
  453. package/templates/blank/docs/errors/CAGE-CONN-007.md +47 -0
  454. package/templates/blank/docs/errors/CAGE-CONN-008.md +47 -0
  455. package/templates/blank/docs/errors/CAGE-CONN-009.md +47 -0
  456. package/templates/blank/docs/errors/CAGE-CONN-010.md +47 -0
  457. package/templates/blank/docs/errors/CAGE-CONN-011.md +47 -0
  458. package/templates/blank/docs/errors/CAGE-CONN-012.md +47 -0
  459. package/templates/blank/docs/errors/CAGE-CONN-013.md +49 -0
  460. package/templates/blank/docs/errors/CAGE-CONN-014.md +48 -0
  461. package/templates/blank/docs/errors/CAGE-CONN-015.md +49 -0
  462. package/templates/blank/docs/errors/CAGE-CREATE-001.md +53 -0
  463. package/templates/blank/docs/errors/CAGE-DECL-001.md +48 -0
  464. package/templates/blank/docs/errors/CAGE-DECL-002.md +48 -0
  465. package/templates/blank/docs/errors/CAGE-DECL-003.md +47 -0
  466. package/templates/blank/docs/errors/CAGE-DECL-004.md +47 -0
  467. package/templates/blank/docs/errors/CAGE-DEP-001.md +48 -0
  468. package/templates/blank/docs/errors/CAGE-DEP-002.md +47 -0
  469. package/templates/blank/docs/errors/CAGE-DEP-003.md +47 -0
  470. package/templates/blank/docs/errors/CAGE-DEP-004.md +47 -0
  471. package/templates/blank/docs/errors/CAGE-DEP-005.md +47 -0
  472. package/templates/blank/docs/errors/CAGE-DIAG-001.md +53 -0
  473. package/templates/blank/docs/errors/CAGE-DLQ-001.md +48 -0
  474. package/templates/blank/docs/errors/CAGE-ENV-001.md +52 -0
  475. package/templates/blank/docs/errors/CAGE-ENV-002.md +51 -0
  476. package/templates/blank/docs/errors/CAGE-ENV-003.md +48 -0
  477. package/templates/blank/docs/errors/CAGE-EVENT-001.md +47 -0
  478. package/templates/blank/docs/errors/CAGE-EVENT-002.md +50 -0
  479. package/templates/blank/docs/errors/CAGE-FIELD-001.md +47 -0
  480. package/templates/blank/docs/errors/CAGE-FIELD-002.md +47 -0
  481. package/templates/blank/docs/errors/CAGE-FIELD-003.md +47 -0
  482. package/templates/blank/docs/errors/CAGE-FIELD-004.md +47 -0
  483. package/templates/blank/docs/errors/CAGE-FILE-001.md +56 -0
  484. package/templates/blank/docs/errors/CAGE-GEN-001.md +48 -0
  485. package/templates/blank/docs/errors/CAGE-GEN-002.md +47 -0
  486. package/templates/blank/docs/errors/CAGE-GEN-003.md +53 -0
  487. package/templates/blank/docs/errors/CAGE-GRANT-001.md +49 -0
  488. package/templates/blank/docs/errors/CAGE-GRANT-002.md +48 -0
  489. package/templates/blank/docs/errors/CAGE-GRANT-003.md +48 -0
  490. package/templates/blank/docs/errors/CAGE-IMPACT-001.md +48 -0
  491. package/templates/blank/docs/errors/CAGE-IMPACT-002.md +52 -0
  492. package/templates/blank/docs/errors/CAGE-INIT-001.md +47 -0
  493. package/templates/blank/docs/errors/CAGE-INIT-002.md +49 -0
  494. package/templates/blank/docs/errors/CAGE-INIT-003.md +48 -0
  495. package/templates/blank/docs/errors/CAGE-INIT-004.md +48 -0
  496. package/templates/blank/docs/errors/CAGE-INIT-005.md +52 -0
  497. package/templates/blank/docs/errors/CAGE-JOB-001.md +47 -0
  498. package/templates/blank/docs/errors/CAGE-JOB-002.md +47 -0
  499. package/templates/blank/docs/errors/CAGE-JOB-003.md +47 -0
  500. package/templates/blank/docs/errors/CAGE-LINT-001.md +47 -0
  501. package/templates/blank/docs/errors/CAGE-MIG-001.md +47 -0
  502. package/templates/blank/docs/errors/CAGE-MIG-002.md +47 -0
  503. package/templates/blank/docs/errors/CAGE-MIG-003.md +5 -0
  504. package/templates/blank/docs/errors/CAGE-MIG-004.md +5 -0
  505. package/templates/blank/docs/errors/CAGE-MIG-005.md +47 -0
  506. package/templates/blank/docs/errors/CAGE-NAME-001.md +47 -0
  507. package/templates/blank/docs/errors/CAGE-NAME-002.md +47 -0
  508. package/templates/blank/docs/errors/CAGE-NAME-003.md +47 -0
  509. package/templates/blank/docs/errors/CAGE-NAME-004.md +47 -0
  510. package/templates/blank/docs/errors/CAGE-NAME-005.md +47 -0
  511. package/templates/blank/docs/errors/CAGE-NAME-006.md +47 -0
  512. package/templates/blank/docs/errors/CAGE-ORG-001.md +50 -0
  513. package/templates/blank/docs/errors/CAGE-PAIR-002.md +51 -0
  514. package/templates/blank/docs/errors/CAGE-QUERY-001.md +47 -0
  515. package/templates/blank/docs/errors/CAGE-QUERY-002.md +47 -0
  516. package/templates/blank/docs/errors/CAGE-QUERY-003.md +50 -0
  517. package/templates/blank/docs/errors/CAGE-REACT-001.md +47 -0
  518. package/templates/blank/docs/errors/CAGE-REACT-002.md +47 -0
  519. package/templates/blank/docs/errors/CAGE-REACT-003.md +50 -0
  520. package/templates/blank/docs/errors/CAGE-READS-001.md +50 -0
  521. package/templates/blank/docs/errors/CAGE-REG-001.md +54 -0
  522. package/templates/blank/docs/errors/CAGE-REG-002.md +49 -0
  523. package/templates/blank/docs/errors/CAGE-REG-003.md +47 -0
  524. package/templates/blank/docs/errors/CAGE-REL-001.md +64 -0
  525. package/templates/blank/docs/errors/CAGE-ROUTE-001.md +48 -0
  526. package/templates/blank/docs/errors/CAGE-SCOPE-001.md +47 -0
  527. package/templates/blank/docs/errors/CAGE-SCOPE-002.md +47 -0
  528. package/templates/blank/docs/errors/CAGE-SECRET-001.md +48 -0
  529. package/templates/blank/docs/errors/CAGE-SECRET-002.md +47 -0
  530. package/templates/blank/docs/errors/CAGE-SENS-001.md +48 -0
  531. package/templates/blank/docs/errors/CAGE-SQL-001.md +47 -0
  532. package/templates/blank/docs/errors/CAGE-SQL-002.md +47 -0
  533. package/templates/blank/docs/errors/CAGE-STATE-001.md +49 -0
  534. package/templates/blank/docs/errors/CAGE-STATE-002.md +47 -0
  535. package/templates/blank/docs/errors/CAGE-STATE-003.md +47 -0
  536. package/templates/blank/docs/errors/CAGE-STATE-004.md +47 -0
  537. package/templates/blank/docs/errors/CAGE-STATE-005.md +49 -0
  538. package/templates/blank/docs/errors/CAGE-STATE-010.md +48 -0
  539. package/templates/blank/docs/errors/CAGE-STATE-011.md +48 -0
  540. package/templates/blank/docs/errors/CAGE-STRUCT-001.md +51 -0
  541. package/templates/blank/docs/errors/CAGE-STRUCT-002.md +51 -0
  542. package/templates/blank/docs/errors/CAGE-SYNC-001.md +49 -0
  543. package/templates/blank/docs/errors/CAGE-TEST-001.md +47 -0
  544. package/templates/blank/docs/errors/CAGE-TEST-002.md +50 -0
  545. package/templates/blank/docs/errors/CAGE-TEST-003.md +52 -0
  546. package/templates/blank/docs/errors/CAGE-UNSAFE-001.md +49 -0
  547. package/templates/blank/docs/errors/CAGE-UPGRADE-001.md +48 -0
  548. package/templates/blank/docs/errors/CAGE-WORKER-001.md +48 -0
  549. package/templates/blank/docs/errors/CAGE-WORKER-002.md +50 -0
  550. package/templates/blank/docs/errors/CAGE-WORKER-003.md +48 -0
  551. package/templates/blank/docs/errors/README.md +357 -0
  552. package/templates/blank/docs/errors/runtime.md +50 -0
  553. package/templates/blank/docs/examples/purchase-admin/README.md +5 -0
  554. package/templates/blank/docs/examples/purchase-admin/apps/api/src/main.ts +14 -0
  555. package/templates/blank/docs/examples/purchase-admin/apps/api/src/worker.ts +17 -0
  556. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/app.tsx +128 -0
  557. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/styles/global.css +743 -0
  558. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/use-session.ts +43 -0
  559. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/workspace-layout.tsx +109 -0
  560. package/templates/blank/docs/examples/purchase-admin/apps/web/src/main.tsx +18 -0
  561. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +31 -0
  562. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/index.ts +6 -0
  563. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +73 -0
  564. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/index.ts +5 -0
  565. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/pages/login-page.tsx +71 -0
  566. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/index.ts +5 -0
  567. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/pages/inventory-page.tsx +102 -0
  568. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/approval-history.tsx +32 -0
  569. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/order-attachments.tsx +29 -0
  570. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-assistant-context.tsx +17 -0
  571. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.css +6 -0
  572. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.tsx +82 -0
  573. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/index.ts +7 -0
  574. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/lib/presentation.ts +20 -0
  575. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-intelligence.css +15 -0
  576. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +154 -0
  577. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +240 -0
  578. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/workspace/index.ts +5 -0
  579. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/workspace/pages/home-page.tsx +44 -0
  580. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/hooks/use-command.ts +42 -0
  581. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/error-message.ts +24 -0
  582. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/navigation.ts +21 -0
  583. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-markdown.tsx +19 -0
  584. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-panel.css +134 -0
  585. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-panel.tsx +200 -0
  586. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-scope.tsx +72 -0
  587. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/attachment-upload.css +28 -0
  588. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/attachment-upload.tsx +163 -0
  589. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/notice.tsx +20 -0
  590. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-heading.tsx +35 -0
  591. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-state.css +47 -0
  592. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-state.tsx +76 -0
  593. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/require-capability.tsx +34 -0
  594. package/templates/blank/docs/examples/purchase-admin/cage.config.json +123 -0
  595. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/dept/index.ts +74 -0
  596. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory/index.ts +57 -0
  597. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory-lock/index.ts +52 -0
  598. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/purchase-order/index.ts +86 -0
  599. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/role/index.ts +85 -0
  600. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/user/index.ts +89 -0
  601. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/index.ts +87 -0
  602. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/queries/index.ts +17 -0
  603. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/index.ts +10 -0
  604. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/erp.ts +51 -0
  605. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/intelligence.ts +20 -0
  606. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/index.ts +3 -0
  607. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/inventory.ts +55 -0
  608. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/approvals.ts +39 -0
  609. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/index.ts +7 -0
  610. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/intelligence.test.ts +62 -0
  611. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/jobs.ts +18 -0
  612. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.test.ts +146 -0
  613. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.ts +192 -0
  614. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/queries.ts +15 -0
  615. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-inventory.ts +30 -0
  616. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-process.ts +42 -0
  617. package/templates/blank/package.json +22 -0
  618. package/templates/blank/packages/contracts/package.json +16 -0
  619. package/templates/blank/packages/contracts/src/aggregates/dept/index.ts +74 -0
  620. package/templates/blank/packages/contracts/src/aggregates/role/index.ts +85 -0
  621. package/templates/blank/packages/contracts/src/aggregates/user/index.ts +89 -0
  622. package/templates/blank/packages/contracts/src/index.ts +55 -0
  623. package/templates/blank/packages/contracts/src/queries/index.ts +13 -0
  624. package/templates/blank/packages/contracts/tsconfig.json +5 -0
  625. package/templates/blank/packages/domain/package.json +24 -0
  626. package/templates/blank/packages/domain/src/index.ts +5 -0
  627. package/templates/blank/packages/domain/tsconfig.json +5 -0
  628. package/templates/blank/pnpm-workspace.yaml +10 -0
  629. package/templates/blank/renovate.json +5 -0
  630. package/templates/blank/tsconfig.base.json +8 -0
  631. package/dist/database.d.ts +0 -5
  632. package/dist/database.js +0 -70
  633. package/dist/database.js.map +0 -1
  634. package/managed/errors/CAGE-APPR-001.md +0 -32
  635. package/managed/errors/CAGE-APPR-002.md +0 -32
  636. package/managed/errors/CAGE-APPR-003.md +0 -32
  637. package/managed/errors/CAGE-APPR-004.md +0 -32
  638. package/managed/errors/CAGE-APPR-005.md +0 -32
  639. package/managed/errors/CAGE-APPR-006.md +0 -32
  640. package/managed/errors/CAGE-APPR-007.md +0 -32
  641. package/managed/errors/CAGE-APPR-010.md +0 -32
  642. package/managed/errors/CAGE-AUTH-001.md +0 -32
  643. package/managed/errors/CAGE-BUDGET-001.md +0 -32
  644. package/managed/errors/CAGE-BUDGET-002.md +0 -32
  645. package/managed/errors/CAGE-BUDGET-003.md +0 -32
  646. package/managed/errors/CAGE-CMD-002.md +0 -32
  647. package/managed/errors/CAGE-CMD-003.md +0 -34
  648. package/managed/errors/CAGE-CONN-001.md +0 -32
  649. package/managed/errors/CAGE-CONN-002.md +0 -32
  650. package/managed/errors/CAGE-CONN-003.md +0 -32
  651. package/managed/errors/CAGE-CONN-004.md +0 -32
  652. package/managed/errors/CAGE-CONN-005.md +0 -32
  653. package/managed/errors/CAGE-CONN-006.md +0 -32
  654. package/managed/errors/CAGE-CONN-007.md +0 -32
  655. package/managed/errors/CAGE-CONN-008.md +0 -32
  656. package/managed/errors/CAGE-CONN-009.md +0 -32
  657. package/managed/errors/CAGE-CONN-010.md +0 -32
  658. package/managed/errors/CAGE-CONN-011.md +0 -32
  659. package/managed/errors/CAGE-CONN-012.md +0 -32
  660. package/managed/errors/CAGE-CREATE-001.md +0 -32
  661. package/managed/errors/CAGE-DECL-001.md +0 -34
  662. package/managed/errors/CAGE-DECL-002.md +0 -34
  663. package/managed/errors/CAGE-DECL-003.md +0 -34
  664. package/managed/errors/CAGE-DECL-004.md +0 -34
  665. package/managed/errors/CAGE-DEP-001.md +0 -34
  666. package/managed/errors/CAGE-DEP-002.md +0 -34
  667. package/managed/errors/CAGE-DEP-003.md +0 -34
  668. package/managed/errors/CAGE-DEP-004.md +0 -34
  669. package/managed/errors/CAGE-DEP-005.md +0 -34
  670. package/managed/errors/CAGE-DLQ-001.md +0 -32
  671. package/managed/errors/CAGE-ENV-001.md +0 -32
  672. package/managed/errors/CAGE-EVENT-001.md +0 -32
  673. package/managed/errors/CAGE-EVENT-002.md +0 -32
  674. package/managed/errors/CAGE-FIELD-001.md +0 -32
  675. package/managed/errors/CAGE-FIELD-002.md +0 -32
  676. package/managed/errors/CAGE-FIELD-003.md +0 -32
  677. package/managed/errors/CAGE-FIELD-004.md +0 -32
  678. package/managed/errors/CAGE-GEN-001.md +0 -33
  679. package/managed/errors/CAGE-GEN-002.md +0 -33
  680. package/managed/errors/CAGE-GRANT-001.md +0 -32
  681. package/managed/errors/CAGE-GRANT-002.md +0 -32
  682. package/managed/errors/CAGE-GRANT-003.md +0 -32
  683. package/managed/errors/CAGE-IMPACT-001.md +0 -32
  684. package/managed/errors/CAGE-JOB-001.md +0 -32
  685. package/managed/errors/CAGE-JOB-002.md +0 -32
  686. package/managed/errors/CAGE-JOB-003.md +0 -32
  687. package/managed/errors/CAGE-LINT-001.md +0 -32
  688. package/managed/errors/CAGE-MIG-001.md +0 -32
  689. package/managed/errors/CAGE-MIG-002.md +0 -32
  690. package/managed/errors/CAGE-MIG-003.md +0 -32
  691. package/managed/errors/CAGE-MIG-004.md +0 -32
  692. package/managed/errors/CAGE-MIG-005.md +0 -32
  693. package/managed/errors/CAGE-NAME-001.md +0 -32
  694. package/managed/errors/CAGE-NAME-002.md +0 -32
  695. package/managed/errors/CAGE-NAME-003.md +0 -32
  696. package/managed/errors/CAGE-NAME-004.md +0 -32
  697. package/managed/errors/CAGE-NAME-005.md +0 -32
  698. package/managed/errors/CAGE-NAME-006.md +0 -32
  699. package/managed/errors/CAGE-ORG-001.md +0 -32
  700. package/managed/errors/CAGE-PAIR-002.md +0 -33
  701. package/managed/errors/CAGE-QUERY-001.md +0 -32
  702. package/managed/errors/CAGE-QUERY-002.md +0 -32
  703. package/managed/errors/CAGE-QUERY-003.md +0 -32
  704. package/managed/errors/CAGE-REACT-001.md +0 -32
  705. package/managed/errors/CAGE-REACT-002.md +0 -32
  706. package/managed/errors/CAGE-READS-001.md +0 -32
  707. package/managed/errors/CAGE-REG-001.md +0 -32
  708. package/managed/errors/CAGE-REG-002.md +0 -32
  709. package/managed/errors/CAGE-REG-003.md +0 -32
  710. package/managed/errors/CAGE-ROUTE-001.md +0 -32
  711. package/managed/errors/CAGE-SCOPE-001.md +0 -32
  712. package/managed/errors/CAGE-SCOPE-002.md +0 -32
  713. package/managed/errors/CAGE-SECRET-001.md +0 -32
  714. package/managed/errors/CAGE-SECRET-002.md +0 -32
  715. package/managed/errors/CAGE-SENS-001.md +0 -32
  716. package/managed/errors/CAGE-SQL-001.md +0 -32
  717. package/managed/errors/CAGE-SQL-002.md +0 -32
  718. package/managed/errors/CAGE-STATE-001.md +0 -32
  719. package/managed/errors/CAGE-STATE-002.md +0 -32
  720. package/managed/errors/CAGE-STATE-003.md +0 -32
  721. package/managed/errors/CAGE-STATE-004.md +0 -32
  722. package/managed/errors/CAGE-STATE-005.md +0 -32
  723. package/managed/errors/CAGE-STATE-010.md +0 -32
  724. package/managed/errors/CAGE-STATE-011.md +0 -32
  725. package/managed/errors/CAGE-SYNC-001.md +0 -35
  726. package/managed/errors/CAGE-TEST-001.md +0 -33
  727. package/managed/errors/CAGE-UNSAFE-001.md +0 -32
  728. package/managed/errors/CAGE-UPGRADE-001.md +0 -32
  729. package/managed/errors/README.md +0 -99
  730. package/templates/app/compose.yaml +0 -39
  731. package/templates/app/packages/contracts/src/purchase-order.ts +0 -72
  732. package/templates/app/packages/contracts/src/user.ts +0 -89
  733. package/templates/app/packages/domain/src/approvals.ts +0 -18
  734. package/templates/app/packages/domain/src/purchase-order.ts +0 -122
@@ -16,6 +16,8 @@ FROM node:24-bookworm-slim AS runtime
16
16
  WORKDIR /app
17
17
  COPY --from=build --chown=node:node /out/api /app
18
18
  COPY --from=build --chown=node:node /app/apps/web/dist /app/web
19
+ # 系统管理与图谱共享中文显示配置;运行时工作目录同样保持为 /app。
20
+ COPY --from=build --chown=node:node /app/cage.config.json /app/cage.config.json
19
21
  ENV NODE_ENV=production PORT=3000 WEB_DIR=/app/web
20
22
  USER node
21
23
  EXPOSE 3000
@@ -1,30 +1,61 @@
1
- # 采购工作台
1
+ # Cage 业务应用(含采购示例)
2
2
 
3
3
  这是可启动的标准范例:组织管理、采购单、审批待办、库存台账、库存锁生命周期和 ERP 出入站映射。
4
4
 
5
+ ## 让 AI 在本项目开发业务
6
+
7
+ 把本目录交给 Codex 等编程工具时,先让它读 [AGENTS.md](AGENTS.md),再按[业务开发指南](docs/ai/README.md)和[任务配方](docs/ai/recipes.md)实现需求。普通业务不需要修改框架源码。
8
+
9
+ [采购全链路导读](docs/ai/purchase-example.md)说明每个文件和异步步骤;[原语与最小业务](docs/ai/primitives.md)提供可添加的普通管理对象;[错误码册](docs/errors/README.md)用于按码修复。脚手架会将这些资料放入生成项目本地的 `docs/ai` 与 `docs/errors`,无需再次克隆框架。
10
+
5
11
  ## 启动
6
12
 
7
- 在框架仓库根目录执行 `pnpm install`、`pnpm build`,然后进入本目录。独立模板项目先执行 `pnpm install`、`pnpm build:app`、`pnpm cage gen`。
13
+ 在本项目根目录执行 `pnpm install`、`pnpm build:app`;无需克隆或构建框架仓库。
8
14
 
9
15
  ```powershell
10
- pnpm cage db setup
11
- pnpm cage db up
12
- # 仅首次初始化独立新集群时执行;已有库随后用 cage migrate。
13
- pnpm cage db init
16
+ # 首次配置时复制,已有 .env 时直接编辑原文件。
17
+ Copy-Item .env.example .env
18
+ # 编辑 .env,只填写 CAGE_ADMIN_DATABASE_URL,连接已经存在的数据库。
19
+ pnpm exec cage init
20
+ # init 自动创建账号、生成密码和 Cookie 密钥,并写回 .env。
21
+ pnpm gen
22
+ # 审查 db/migrations 后执行表结构迁移。
23
+ pnpm migrate
24
+ pnpm exec cage bootstrap --credentials-file .cage/admin-credentials.json
14
25
  pnpm dev
15
26
  ```
16
27
 
17
- 连接池、事务、数据库初始化和凭证生成均由框架提供,项目不写连接或建库脚本。`cage db setup` 生成随机密码和本地 `.env`,重复运行保留已有配置。开发库位于 `127.0.0.1:54329/cage_dev`,测试库位于独立容器的 54330 端口。`cage db down` 停止容器但保留开发数据卷;`cage db up` 再次启动。package.json 中的 `db:*` 是相同命令的简写。
28
+ 数据库配置位于本项目根目录的 `.env`,与 `package.json`、`cage.config.json` 同级。[`.env.example`](.env.example) 为每项提供中文注释、填写格式和是否必填。连接池和事务由框架提供,项目只需配置连接。
29
+
30
+ | 配置项 | 用途 |
31
+ | --- | --- |
32
+ | `CAGE_APP_DATABASE_URL` | `cage_app` 账号:API/worker 业务读写 |
33
+ | `CAGE_READ_DATABASE_URL` | `cage_read` 账号:仅查询安全视图 |
34
+ | `CAGE_MIGRATE_DATABASE_URL` | `cage_migrate` 账号:手动执行表结构迁移 |
35
+
36
+ 三个连接由 `cage init` 自动生成,指向**同一个已经存在的数据库**,主机、端口和库名一致。CLI 自动读取 `.env`,部署环境中的同名变量优先。修改后重启 `dev`。`migrate` 在下次执行时读取配置。
37
+
38
+ `pnpm migrate` 更新该库中的表、视图和索引;迁移历史记录在 `sys.schema_migrations`。`pnpm dev` 连接该库并启动 API、worker 和 Web,domain 变化后仅重新生成文件;表结构变更需审查迁移后手动执行。框架不创建数据库、不安装 PostgreSQL、不管理 Docker。
18
39
 
19
- CLI 自动读取项目 `.env`,部署环境变量优先。`CAGE_APP_DATABASE_URL`、`CAGE_READ_DATABASE_URL`、`CAGE_MIGRATE_DATABASE_URL` 分别连接写入、只读和迁移账号。超级用户仅用于初始化,API/worker 不接收其凭证。
40
+ ### 首次只提供管理员连接
41
+
42
+ 在 `.env` 中填写 `CAGE_ADMIN_DATABASE_URL=postgresql://postgres:管理员密码@主机:端口/已有数据库名`。PostgreSQL 管理员通常叫 `postgres`,已有管理员叫 `root` 时使用实际账号名;连接串中的密码特殊字符需要 URL 编码。
43
+
44
+ 执行 `pnpm exec cage init` 会创建框架账号和授权,生成三个独立随机密码及 Cookie 密钥,自动填写 `.env`,成功后移除文件中的管理员连接。业务端口、自定义配置和已有 Cookie 密钥会保留;失败会回滚数据库并保留原 `.env`。日常启动不需要管理员连接。
45
+
46
+ 重复 `init` 会验证并复用已保存的三个账号,不更改密码。若集群已有 Cage 账号但本项目没有原连接,请先复用原凭证再运行 `init`;命令不会为了新项目重置其他项目的账号。部署时也可由平台直接提供三个账号连接,无需执行本地初始化。
47
+
48
+ 数据库除三个登录账号外,还有不允许登录的 `cage_view_owner`,由 `init` 一并创建,用于持有安全视图,无需填写密码。角色名属于整个 PostgreSQL 集群,不能为另一个项目随意重置密码。业务表及系统表由后续 `pnpm migrate` 创建,`init` 只准备角色、schema 和授权。连接现有数据库不表示框架会自动识别、接管其中任意历史业务表;接入历史表需另行映射和审查迁移。
20
49
 
21
50
  测试环境会初始化集群级角色,因此 `CAGE_TEST_DATABASE_URL` 必须指向独立测试集群。运行 `pnpm cage verify` 验证示例;框架仓库根目录的 `pnpm test:docker` 验证全部框架测试。
22
51
 
23
- 浏览器打开 <http://localhost:5173>。初始管理员凭证在 API 终端显示一次。
24
- 如果 Windows Docker/Hyper-V 保留了该端口,在 `.env` 设置 `CAGE_WEB_PORT=15173`;终端会打印实际地址。`PORT` 控制 API 端口,Vite 代理同步使用它。未配置数据库连接串时才使用原有内嵌 PostgreSQL。
52
+ 浏览器打开终端打印的 Web 地址;配置示例使用 <http://localhost:15173>。管理员凭证由显式 bootstrap 交付到新的受限文件,交付后移除。初始化仅授予系统管理能力,采购能力需要管理员明确配置。
53
+ `CAGE_WEB_PORT` 控制 Web 端口,`PORT` 控制 API 端口,Vite 代理同步使用它。缺少数据库配置时会给出错误,需填写 `.env` 后重新启动。
25
54
 
26
55
  ## 体验完整采购流程
27
56
 
57
+ 前端使用 React Router:工作台 `/workspace`,采购列表 `/procurement/orders`,单据详情 `/procurement/orders/:id`,审批 `/approvals`,库存 `/inventory`,登录 `/login`。单号和审批待办可直接打开详情;刷新、前进后退和登录回跳保留页面地址。新增页面与部署按[路由和浏览器验收指南](docs/ai/routing.md)执行;Nginx 示例见 [deploy/nginx.conf](deploy/nginx.conf)。
58
+
28
59
  1. 管理员在“库存台账”登记 `A-01` 等物料。
29
60
  2. 进入 `/admin/` 创建采购员、经理,分别分配采购命令和审批能力;经理的 `PurchaseOrder.approve` 参数配置 `ceiling`。
30
61
  3. 把经理设为采购员所在部门的负责人。提单人与审批人必须不同。
@@ -47,12 +78,14 @@ CLI 自动读取项目 `.env`,部署环境变量优先。`CAGE_APP_DATABASE_UR
47
78
 
48
79
  图谱主标题显示中文业务名称,下面保留英文代码标识。框架会读取声明现有的 `description`;本项目在 `cage.config.json` 的 `graph.labels` 中补充状态、字段等名称,也可覆盖较长描述。例如 `"command:PurchaseOrder.approve": "通过审批"`。键为 `节点类型:本体节点 ID`,可从节点详情复制 ID;中文标题只用于显示,不改变命令、权限标识或数据库。新增业务声明时同时补上需要的名称,然后在图谱中点击“重新抽取”。
49
80
 
50
- - `packages/domain/src/inventory.ts`:最简聚合和库存锁。
51
- - `purchase-order.ts`:状态、命令、约束和事件。
52
- - `reactions.ts`:同事务建锁与异步释放,包含资源配对标记。
53
- - `approvals.ts`、`erp.ts`:封闭审批路由、出站和入站映射。
54
- - `queries.ts`、`jobs.ts`:安全视图查询及过期草稿清理。
81
+ - `packages/domain/src/modules/inventory`:最简聚合和库存锁。
82
+ - `packages/domain/src/modules/purchase`:采购状态、命令、约束、事件、审批、查询和任务。
83
+ - `packages/domain/src/workflows/purchase-inventory.ts`:同事务建锁与异步释放,包含资源配对标记。
84
+ - `packages/domain/src/integrations/erp.ts`:出站、入站映射和验签。
85
+ - `packages/contracts/src/aggregates/<聚合>`:生成的 SDK;页面统一从 `@app/contracts` 引入。
55
86
  - `apps/api/src`:API 和 worker 的薄启动入口。
56
- - `apps/web/src`:仅依赖生成契约的 React 界面。
87
+ - `apps/web/src/app`、`modules`、`shared`:应用组合、业务页面、共享基础组件;`main.tsx` 只挂载。
88
+
89
+ 新增业务先读[工程目录与代码组织](docs/ai/project-structure.md),不要继续在 src 根目录平铺文件。模板已启用模块目录门禁,`cage check` 和 `verify` 会指出目录与依赖越界。
57
90
 
58
91
  先运行 `pnpm cage gen` 再提交契约和迁移草稿;`pnpm cage verify` 检查完整工具链。派生测试遇到无法推断的业务输入会显示跳过,`purchase-order.test.ts` 另外准备真实业务数据覆盖成功审批和约束反例。
@@ -0,0 +1,9 @@
1
+ node_modules/
2
+ dist/
3
+ .cage/
4
+ .cage-files/
5
+ generated/
6
+ .env
7
+ .env.*
8
+ !.env.example
9
+ *.log
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@app/domain": "workspace:*",
13
- "@yss123/cage-http": "0.1.0",
14
- "@yss123/cage-connectors": "0.1.0"
13
+ "@yss123/cage-http": "0.3.0",
14
+ "@yss123/cage-connectors": "0.3.0"
15
15
  }
16
16
  }
@@ -1,9 +1,13 @@
1
1
  // 启动入口只装配框架:认证、业务路由和 /admin 都由 createServer 提供。
2
2
  // WEB_DIR 在部署镜像中指向 Vite 构建产物;本地由 Vite 独立提供前端。
3
+ // 进程启动只建立服务,不迁移结构、不初始化账号;这些操作由受控 CLI 流程提前完成。
4
+ // 声明中启用的 AI、审批与文件接口由框架挂载,后台事件消费仍需要独立 worker 进程。
3
5
  import { createServer } from '@yss123/cage-http';
4
6
  import * as domain from '@app/domain';
5
7
 
6
- const server = createServer({ domain, webDir: process.env.WEB_DIR, title: 'Cage 采购工作台' });
8
+ // 默认不接受转发头;部署在代理后时,仅在这里填写实际可信代理的地址或网段。
9
+ const server = createServer({ domain, webDir: process.env.WEB_DIR, title: 'Cage 采购工作台', trustProxy: false });
10
+ // listen 先等待路由、扩展与授权通知初始化;失败直接拒绝顶层启动,不伪装为已就绪。
7
11
  await server.listen();
8
12
  // 退出时释放数据库池及 LISTEN 连接,部署滚动替换时不会留下旧连接。
9
13
  process.once('SIGINT', () => void server.close());
@@ -1,4 +1,5 @@
1
1
  // API 与 worker 使用相同声明。worker 专门处理审批启动、异步反应和 ERP 推送。
2
+ // 两个进程部署同一版本,消费者依据声明发现工作;事件提交成功不等于这些后台动作已经完成。
2
3
  import { startWorker } from '@yss123/cage-http/worker';
3
4
  import { fakeConnector, stage } from '@yss123/cage-connectors';
4
5
  import * as domain from '@app/domain';
@@ -9,6 +10,8 @@ if (stage() === 'fake') {
9
10
  pushOrder: (request) => ({ erpNo: `DEMO-${request.externalId.slice(0, 8)}` }),
10
11
  });
11
12
  }
13
+ // 框架拥有轮询、重试、调度和连接生命周期;应用只注册本地 fake,不另建数据库池或业务重试循环。
12
14
  const worker = await startWorker({ domain });
15
+ // 停止句柄等待框架在途工作收尾并释放连接,避免进程退出时留下仍在续租的消费者。
13
16
  process.once('SIGINT', () => void worker.stop());
14
17
  process.once('SIGTERM', () => void worker.stop());
@@ -1,4 +1,5 @@
1
1
  <!doctype html>
2
+ <!-- 浏览器文档外壳:提供 React 挂载节点与模块入口;业务路由、会话及数据加载由 src/main.tsx 装配的应用处理。 -->
2
3
  <html lang="zh-CN">
3
4
  <head>
4
5
  <meta charset="UTF-8" />
@@ -10,13 +10,17 @@
10
10
  "dependencies": {
11
11
  "@app/contracts": "workspace:*",
12
12
  "@tanstack/react-query": "^5.87.1",
13
+ "@yss123/cage-client": "0.3.0",
13
14
  "react": "^19.1.1",
14
- "react-dom": "^19.1.1"
15
+ "react-dom": "^19.1.1",
16
+ "react-markdown": "^10.1.0",
17
+ "react-router-dom": "^7.18.5",
18
+ "remark-gfm": "^4.0.1"
15
19
  },
16
20
  "devDependencies": {
17
21
  "@types/react": "^19.1.13",
18
22
  "@types/react-dom": "^19.1.9",
19
- "vite": "^7.1.4",
20
- "typescript": "~5.9.3"
23
+ "typescript": "~5.9.3",
24
+ "vite": "^7.1.4"
21
25
  }
22
26
  }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * 采购应用的路由组合层,集中连接认证、工作台、采购、库存和审批模块的公开入口。
3
+ * 会话先恢复,再决定展示页面、跳转登录或保留原地址提示网络故障。
4
+ * 页面身份来自 URL,模块间导航通过 app 注入;前端能力守卫不能代替服务端授权。
5
+ */
6
+ // URL 是页面身份;应用壳只组合路由、会话与模块,不用组件状态模拟多页面导航。
7
+ import { BrowserRouter, Navigate, Route, Routes, useLocation } from 'react-router-dom';
8
+ import { LoginPage } from '../modules/auth';
9
+ import { HomePage } from '../modules/workspace';
10
+ import { PurchaseOrdersPage, PurchaseOrderDetailPage } from '../modules/purchase';
11
+ import { InventoryPage } from '../modules/inventory';
12
+ import { ApprovalTasksPage, useApprovalTasks } from '../modules/approval';
13
+ import { PageState } from '../shared/ui/page-state';
14
+ import { RequireCapability } from '../shared/ui/require-capability';
15
+ import { loginReturnTo } from '../shared/lib/navigation';
16
+ import { useSession } from './use-session';
17
+ import { WorkspaceLayout } from './workspace-layout';
18
+
19
+ const home = '/workspace';
20
+
21
+ /**
22
+ * 安装 BrowserRouter 并渲染路由树。部署方需为业务深链接提供 SPA 回退,/api 和 /admin 由各自服务处理。
23
+ */
24
+ export function App() {
25
+ return (
26
+ <BrowserRouter>
27
+ <AppRoutes />
28
+ </BrowserRouter>
29
+ );
30
+ }
31
+
32
+ /**
33
+ * 在组合层读取审批待办数量并传给采购列表,使采购模块不依赖审批页面的内部实现。
34
+ * 待办尚未加载或失败时允许数量缺省,页面显示未知而不伪造零。
35
+ */
36
+ function OrdersRoute() {
37
+ const tasks = useApprovalTasks();
38
+ return <PurchaseOrdersPage pendingTasks={tasks.data?.length} />;
39
+ }
40
+
41
+ /**
42
+ * 根据 useSession 的 loading/guest/ready/error 状态组装路由。
43
+ * guest 使用完整路径、查询参数和 hash 构造 returnTo;ready 经 loginReturnTo 校验后回跳。
44
+ * 网络错误保持当前地址以便重试;未知业务地址展示 404 页面,记录读取错误由各页面处理。
45
+ */
46
+ function AppRoutes() {
47
+ const { session, restore, onLogin, onLogout } = useSession();
48
+ const location = useLocation();
49
+ if (session === 'loading')
50
+ return (
51
+ <div className="loading" role="status">
52
+ 正在连接工作台…
53
+ </div>
54
+ );
55
+ if (session === 'error')
56
+ return (
57
+ <PageState
58
+ title="暂时无法连接工作台"
59
+ description="请检查网络和 API 服务,重试后继续访问当前地址。"
60
+ to={home}
61
+ label="返回工作台"
62
+ >
63
+ <button onClick={restore}>重新连接</button>
64
+ </PageState>
65
+ );
66
+ const login = `/login?returnTo=${encodeURIComponent(location.pathname + location.search + location.hash)}`;
67
+ return (
68
+ <Routes>
69
+ <Route
70
+ path="/login"
71
+ element={
72
+ session === 'ready' ? (
73
+ <Navigate to={loginReturnTo(location.search, home)} replace />
74
+ ) : (
75
+ <LoginPage onLogin={onLogin} />
76
+ )
77
+ }
78
+ />
79
+ <Route
80
+ element={
81
+ session === 'ready' ? <WorkspaceLayout onLogout={onLogout} /> : <Navigate to={login} replace />
82
+ }
83
+ >
84
+ <Route index element={<Navigate to={home} replace />} />
85
+ <Route path="workspace" element={<HomePage />} />
86
+ <Route
87
+ path="procurement/orders"
88
+ element={
89
+ <RequireCapability capability="PurchaseOrder.read" home={home}>
90
+ <OrdersRoute />
91
+ </RequireCapability>
92
+ }
93
+ />
94
+ <Route
95
+ path="procurement/orders/:id"
96
+ element={
97
+ <RequireCapability capability="PurchaseOrder.read" home={home}>
98
+ <PurchaseOrderDetailPage />
99
+ </RequireCapability>
100
+ }
101
+ />
102
+ <Route
103
+ path="inventory"
104
+ element={
105
+ <RequireCapability capability="Inventory.read" home={home}>
106
+ <InventoryPage />
107
+ </RequireCapability>
108
+ }
109
+ />
110
+ <Route
111
+ path="approvals"
112
+ element={<ApprovalTasksPage orderUrl={(id) => `/procurement/orders/${encodeURIComponent(id)}`} />}
113
+ />
114
+ <Route
115
+ path="*"
116
+ element={
117
+ <PageState
118
+ title="页面不存在"
119
+ description="请检查地址,或从工作台导航进入已有页面。"
120
+ to={home}
121
+ label="返回工作台"
122
+ />
123
+ }
124
+ />
125
+ </Route>
126
+ </Routes>
127
+ );
128
+ }
@@ -1,3 +1,7 @@
1
+ /**
2
+ * 采购应用的全局视觉与布局基础,随浏览器入口加载;依次定义主题、工作台、业务表格、表单及登录页。
3
+ * 模块专用样式在模块附近维护。状态类只映射已有 UI 状态,不承担权限、审批或数据计算。
4
+ */
1
5
  /* 暖白纸面配墨绿导航;用边线、字重和留白建立信息层次,避免装饰压过业务数据。 */
2
6
  :root {
3
7
  font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
@@ -83,6 +87,9 @@ h3 {
83
87
  font-family: Consolas, 'Courier New', monospace;
84
88
  font-size: 12px;
85
89
  }
90
+ /**
91
+ * 固定侧栏与主内容区的桌面组合;窄屏规则在文件后部覆盖布局,保留导航可达性。
92
+ */
86
93
  .workspace {
87
94
  display: flex;
88
95
  min-height: 100vh;
@@ -124,7 +131,7 @@ nav {
124
131
  display: grid;
125
132
  gap: 7px;
126
133
  }
127
- nav button {
134
+ nav a {
128
135
  display: flex;
129
136
  align-items: center;
130
137
  gap: 16px;
@@ -134,22 +141,22 @@ nav button {
134
141
  text-align: left;
135
142
  padding: 14px 13px;
136
143
  }
137
- nav button span {
144
+ nav a span {
138
145
  font-size: 10px;
139
146
  opacity: 0.6;
140
147
  }
141
- nav button b {
148
+ nav a b {
142
149
  margin-left: auto;
143
150
  font-size: 11px;
144
151
  }
145
- nav button.selected {
152
+ nav a.selected {
146
153
  background: var(--accent);
147
154
  color: var(--green);
148
155
  }
149
- nav button:hover {
156
+ nav a:hover {
150
157
  background: #31594e;
151
158
  }
152
- nav button.selected:hover {
159
+ nav a.selected:hover {
153
160
  background: #d9efa9;
154
161
  }
155
162
  .aside-bottom {
@@ -301,6 +308,9 @@ header {
301
308
  .toolbar > button {
302
309
  font-size: 11px;
303
310
  }
311
+ /**
312
+ * 宽表格在容器中横向滚动,避免列内容把页面宽度撑出视口。
313
+ */
304
314
  .table-wrap {
305
315
  overflow: auto;
306
316
  }
@@ -470,6 +480,9 @@ input {
470
480
  input:focus {
471
481
  outline: 2px solid #b2cb8b;
472
482
  }
483
+ /**
484
+ * 创建弹窗的遮罩与居中层;具体采购弹窗高度及内部滚动由模块样式补充。
485
+ */
473
486
  .modal-backdrop {
474
487
  position: fixed;
475
488
  inset: 0;
@@ -560,6 +573,9 @@ input:focus {
560
573
  color: var(--muted);
561
574
  }
562
575
  /* 窄屏将导航转成横向工具栏,表格保留横向滚动,操作列不会挤成不可点击的小按钮。 */
576
+ /**
577
+ * 在九百像素及以下调整导航与表单布局,减少桌面侧栏对内容宽度的挤占。
578
+ */
563
579
  @media (max-width: 900px) {
564
580
  aside {
565
581
  position: static;
@@ -581,11 +597,11 @@ input:focus {
581
597
  display: flex;
582
598
  margin-top: 20px;
583
599
  }
584
- nav button {
600
+ nav a {
585
601
  flex: 1;
586
602
  padding: 10px;
587
603
  }
588
- nav button span {
604
+ nav a span {
589
605
  display: none;
590
606
  }
591
607
  .aside-bottom {
@@ -656,8 +672,72 @@ input:focus {
656
672
  padding: 10px;
657
673
  }
658
674
  }
675
+ /**
676
+ * 尊重系统减少动画偏好,避免将过渡效果作为理解操作反馈的唯一依据。
677
+ */
659
678
  @media (prefers-reduced-motion: reduce) {
660
679
  * {
661
680
  transition: none !important;
662
681
  }
663
682
  }
683
+
684
+ /* 链接保持原生导航语义,单据编号可复制地址或在新标签页打开。 */
685
+ .record-link {
686
+ color: var(--green);
687
+ font-weight: 600;
688
+ text-decoration: underline;
689
+ text-decoration-color: #c6d5b5;
690
+ text-underline-offset: 4px;
691
+ }
692
+ .record-link:hover {
693
+ text-decoration-color: var(--green);
694
+ }
695
+ .record-facts {
696
+ display: grid;
697
+ grid-template-columns: repeat(2, minmax(0, 1fr));
698
+ margin: 0;
699
+ padding: 8px 24px;
700
+ gap: 0 36px;
701
+ }
702
+ .record-facts > div {
703
+ padding: 22px 0;
704
+ border-bottom: 1px solid var(--line);
705
+ }
706
+ .record-facts dt {
707
+ color: var(--muted);
708
+ font-size: 11px;
709
+ margin-bottom: 11px;
710
+ }
711
+ .record-facts dd {
712
+ margin: 0;
713
+ font-size: 14px;
714
+ overflow-wrap: anywhere;
715
+ }
716
+ .entry-grid {
717
+ display: grid;
718
+ grid-template-columns: repeat(3, 1fr);
719
+ gap: 18px;
720
+ }
721
+ .entry-grid > a {
722
+ padding: 30px 25px;
723
+ background: #fff;
724
+ border: 1px solid var(--line);
725
+ border-radius: 6px;
726
+ }
727
+ .entry-grid > a:hover {
728
+ border-color: #99b47f;
729
+ background: #fafdf6;
730
+ }
731
+ .entry-grid small {
732
+ color: var(--muted);
733
+ font-size: 10px;
734
+ letter-spacing: 1px;
735
+ }
736
+ .entry-grid h2 {
737
+ margin: 24px 0 14px;
738
+ }
739
+ .entry-grid p {
740
+ font-size: 12px;
741
+ color: var(--muted);
742
+ line-height: 1.8;
743
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 应用会话生命周期:首次加载 /me,并把 SDK 的账号退出或失效通知同步到路由状态。
3
+ * 与 URL 路由分离,网络故障不会被误判成未登录;查询缓存不能跨账号继续使用。
4
+ */
5
+ // 应用会话与 URL 导航分别管理:401 才进入登录,网络故障保留原地址并允许重试。
6
+ import { useCallback, useEffect, useState } from 'react';
7
+ import { useQueryClient } from '@tanstack/react-query';
8
+ import { client, loadMe } from '@app/contracts';
9
+
10
+ /**
11
+ * 在 QueryClientProvider 内使用。挂载时恢复用户,卸载时解除 SDK 订阅。
12
+ * 返回 session:loading 为恢复中,guest 为未认证,ready 为已加载身份,error 为其他恢复失败。
13
+ * restore 可重试恢复;onLogin/onLogout 由已完成认证动作的页面调用,只更新应用状态。
14
+ * 账号失效时发起取消查询并清空缓存;这里不负责服务端退出操作,也不保证取消已提交的业务命令。
15
+ */
16
+ export function useSession() {
17
+ const [session, setSession] = useState<'loading' | 'guest' | 'ready' | 'error'>('loading');
18
+ const cache = useQueryClient();
19
+ /**
20
+ * 每次恢复先显示 loading,再按 loadMe 的明确结果分类;只有 UNAUTHENTICATED 进入 guest。
21
+ */
22
+ const restore = useCallback(async () => {
23
+ setSession('loading');
24
+ const result = await loadMe();
25
+ setSession(result.ok ? 'ready' : result.code === 'UNAUTHENTICATED' ? 'guest' : 'error');
26
+ }, []);
27
+
28
+ useEffect(() => {
29
+ const unsubscribe = client.subscribe((_snapshot, reason) => {
30
+ if (reason === 'loaded') return;
31
+ // 先取消在途查询,再清除上一账号的缓存;路由守卫保留 URL 并决定登录回跳。
32
+ void cache.cancelQueries();
33
+ cache.clear();
34
+ setSession('guest');
35
+ });
36
+ void restore();
37
+ return () => {
38
+ unsubscribe();
39
+ };
40
+ }, [cache, restore]);
41
+
42
+ return { session, restore, onLogin: () => setSession('ready'), onLogout: () => setSession('guest') };
43
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * 已登录工作台的公共外壳:导航、当前账号、退出登录、Outlet 和唯一的业务助理。
3
+ * 业务页面经路由模块入口进入 Outlet;系统管理使用独立链接。
4
+ * 助理随页面更新语义快照,账号退出成功后清空查询缓存。
5
+ */
6
+ // 应用壳组合模块公开入口,只持有导航和会话;表单、筛选、命令留在各业务模块。
7
+ import { useState } from 'react';
8
+ import { Link, NavLink, Outlet, useLocation } from 'react-router-dom';
9
+ import { useQueryClient } from '@tanstack/react-query';
10
+ import { client, currentUser } from '@app/contracts';
11
+ import { useApprovalTasks } from '../modules/approval';
12
+ import { errorMessage } from '../shared/lib/error-message';
13
+ import { AssistantScope } from '../shared/ui/assistant-scope';
14
+
15
+ /**
16
+ * 渲染工作台公共区域并把子路由放入内容区。
17
+ * @param onLogout SDK 退出成功后通知 app 切换会话状态的回调。
18
+ * 本壳提供固定导航入口;目标路由和服务端分别处理页面访问与真实请求的权限。
19
+ * location.key 标识一次页面导航,用于防止新页面沿用上一张单据的助理上下文。
20
+ */
21
+ export function WorkspaceLayout({ onLogout }: { onLogout: () => void }) {
22
+ const [error, setError] = useState('');
23
+ const [busy, setBusy] = useState(false);
24
+ const location = useLocation();
25
+ const page = location.pathname.startsWith('/procurement/orders/')
26
+ ? '采购单详情'
27
+ : location.pathname === '/procurement/orders'
28
+ ? '采购单'
29
+ : location.pathname === '/approvals'
30
+ ? '审批待办'
31
+ : location.pathname === '/inventory'
32
+ ? '库存台账'
33
+ : location.pathname === '/workspace'
34
+ ? '工作台'
35
+ : '页面';
36
+ const tasks = useApprovalTasks();
37
+ const cache = useQueryClient();
38
+ return (
39
+ <AssistantScope pageKey={location.key} fallback={{
40
+ context: { page: { id: 'workspace-page', title: page, kind: 'custom', route: location.pathname + location.search } },
41
+ suggestions: ['我在当前页面可以做什么?', '帮我查看待处理的审批'],
42
+ }}>
43
+ <div className="workspace">
44
+ <aside>
45
+ <Link className="brand" to="/workspace">
46
+ cage<span>采购工作台</span>
47
+ </Link>
48
+ <span className="nav-caption">工作空间</span>
49
+ <nav>
50
+ {(
51
+ [
52
+ ['/workspace', '00', '工作台'],
53
+ ['/procurement/orders', '01', '采购单'],
54
+ ['/approvals', '02', '审批待办'],
55
+ ['/inventory', '03', '库存台账'],
56
+ ] as const
57
+ ).map(([key, no, label]) => (
58
+ <NavLink key={key} to={key} className={({ isActive }) => (isActive ? 'selected' : '')}>
59
+ <span>{no}</span>
60
+ {label}
61
+ {key === '/approvals' && <b>{tasks.data?.length ?? 0}</b>}
62
+ </NavLink>
63
+ ))}
64
+ </nav>
65
+ <div className="aside-bottom">
66
+ <a href="/admin/">系统管理 ↗</a>
67
+ <div className="user">
68
+ <span className="avatar">{currentUser()?.name?.slice(0, 1) ?? '用'}</span>
69
+ <div>
70
+ {currentUser()?.name}
71
+ <small>已登录</small>
72
+ </div>
73
+ </div>
74
+ <button
75
+ className="logout"
76
+ disabled={busy}
77
+ onClick={async () => {
78
+ setBusy(true);
79
+ const result = await client.logout();
80
+ setBusy(false);
81
+ if (result.ok) {
82
+ cache.clear();
83
+ onLogout();
84
+ } else setError(errorMessage(result));
85
+ }}
86
+ >
87
+ 退出登录
88
+ </button>
89
+ </div>
90
+ </aside>
91
+ <main className="content">
92
+ <header>
93
+ <span>采购管理 / {page}</span>
94
+ <span className="live-dot">团队工作空间</span>
95
+ </header>
96
+ {error && (
97
+ <p className="error" role="alert">
98
+ {error}
99
+ </p>
100
+ )}
101
+ <Outlet />
102
+ <div className="page-footer">
103
+ CAGE / PROCUREMENT WORKSPACE<span>业务操作均受权限与数据范围约束</span>
104
+ </div>
105
+ </main>
106
+ </div>
107
+ </AssistantScope>
108
+ );
109
+ }