create-wakii-stack 0.0.0-stage → 0.1.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 (998) hide show
  1. package/README.md +66 -2
  2. package/dist/chunk-7XGW4UJ5.js +75 -0
  3. package/dist/chunk-AKPWS7FJ.js +76 -0
  4. package/dist/chunk-ELM6GGC5.js +50 -0
  5. package/dist/chunk-ON2WTGZH.js +77 -0
  6. package/dist/index.js +385 -0
  7. package/dist/manifest-2JVLRMDB.js +10 -0
  8. package/dist/manifest-O35TPW73.js +10 -0
  9. package/dist/manifest-TXTY67BF.js +10 -0
  10. package/dist/manifest-XWHR7Y3F.js +10 -0
  11. package/package.json +23 -4
  12. package/stack-template/.changeset/config.json +15 -0
  13. package/stack-template/.changeset/vu53-ui-redesign.md +11 -0
  14. package/stack-template/.claude/agents/be-dev.md +56 -0
  15. package/stack-template/.claude/agents/contracts-keeper.md +51 -0
  16. package/stack-template/.claude/agents/e2e-runner.md +61 -0
  17. package/stack-template/.claude/agents/fe-dev.md +53 -0
  18. package/stack-template/.claude/settings.json +77 -0
  19. package/stack-template/.claude/settings.local.json +9 -0
  20. package/stack-template/.claude/skills/add-service/SKILL.md +81 -0
  21. package/stack-template/.claude/skills/sync-contracts/SKILL.md +74 -0
  22. package/stack-template/.editorconfig +21 -0
  23. package/stack-template/.gitattributes +10 -0
  24. package/stack-template/.github/pull_request_template.md +26 -0
  25. package/stack-template/.github/workflow-templates/services-ci.yml.example +69 -0
  26. package/stack-template/.github/workflows/contracts.yml +133 -0
  27. package/stack-template/.github/workflows/convergence.yml +209 -0
  28. package/stack-template/.github/workflows/git-guard.yml +44 -0
  29. package/stack-template/.github/workflows/publish-uikit.yml +96 -0
  30. package/stack-template/.github/workflows/remotes-activity.yml +82 -0
  31. package/stack-template/.github/workflows/remotes-tasks.yml +82 -0
  32. package/stack-template/.github/workflows/services-auth-svc.yml +153 -0
  33. package/stack-template/.github/workflows/services-go-svc.yml +281 -0
  34. package/stack-template/.github/workflows/services-node-svc.yml +173 -0
  35. package/stack-template/.github/workflows/services-spring-svc.yml +132 -0
  36. package/stack-template/.github/workflows/shell.yml +78 -0
  37. package/stack-template/.github/workflows/ui-kit.yml +51 -0
  38. package/stack-template/.husky/commit-msg +14 -0
  39. package/stack-template/.husky/pre-push +51 -0
  40. package/stack-template/.spectral.yaml +17 -0
  41. package/stack-template/AGENTS.md +197 -0
  42. package/stack-template/CLAUDE.md +114 -0
  43. package/stack-template/README.md +172 -0
  44. package/stack-template/app/admin/index.html +12 -0
  45. package/stack-template/app/admin/package.json +40 -0
  46. package/stack-template/app/admin/scripts/verify-chart.mjs +49 -0
  47. package/stack-template/app/admin/src/App.test.tsx +70 -0
  48. package/stack-template/app/admin/src/App.tsx +33 -0
  49. package/stack-template/app/admin/src/data/users.ts +47 -0
  50. package/stack-template/app/admin/src/layout/AdminLayout.tsx +212 -0
  51. package/stack-template/app/admin/src/main.tsx +17 -0
  52. package/stack-template/app/admin/src/pages/ComponentsDemo.tsx +138 -0
  53. package/stack-template/app/admin/src/pages/Dashboard.tsx +182 -0
  54. package/stack-template/app/admin/src/pages/HooksDemo.tsx +153 -0
  55. package/stack-template/app/admin/src/pages/Settings.tsx +156 -0
  56. package/stack-template/app/admin/src/pages/UploadPage.tsx +34 -0
  57. package/stack-template/app/admin/src/pages/Users.test.tsx +66 -0
  58. package/stack-template/app/admin/src/pages/Users.tsx +245 -0
  59. package/stack-template/app/admin/src/styles.css +9 -0
  60. package/stack-template/app/admin/src/tests/setup.ts +15 -0
  61. package/stack-template/app/admin/tsconfig.json +18 -0
  62. package/stack-template/app/admin/vite.config.ts +11 -0
  63. package/stack-template/app/admin/vitest.config.ts +14 -0
  64. package/stack-template/app/create-wakii-app/README.md +71 -0
  65. package/stack-template/app/create-wakii-app/package.json +27 -0
  66. package/stack-template/app/create-wakii-app/scripts/publish-npm.sh +38 -0
  67. package/stack-template/app/create-wakii-app/src/index.ts +127 -0
  68. package/stack-template/app/create-wakii-app/src/options.test.ts +80 -0
  69. package/stack-template/app/create-wakii-app/src/options.ts +117 -0
  70. package/stack-template/app/create-wakii-app/src/scaffold.test.ts +143 -0
  71. package/stack-template/app/create-wakii-app/src/scaffold.ts +194 -0
  72. package/stack-template/app/create-wakii-app/tsconfig.json +17 -0
  73. package/stack-template/app/create-wakii-app/vitest.config.ts +9 -0
  74. package/stack-template/app/create-wakii-stack/package.json +27 -0
  75. package/stack-template/app/create-wakii-stack/src/manifest.ts +101 -0
  76. package/stack-template/app/create-wakii-stack/src/options.ts +106 -0
  77. package/stack-template/app/create-wakii-stack/src/scaffold.ts +315 -0
  78. package/stack-template/app/create-wakii-stack/tsconfig.json +17 -0
  79. package/stack-template/app/create-wakii-stack/vitest.config.ts +9 -0
  80. package/stack-template/app/remotes/activity/Dockerfile +36 -0
  81. package/stack-template/app/remotes/activity/README.md +59 -0
  82. package/stack-template/app/remotes/activity/index.html +11 -0
  83. package/stack-template/app/remotes/activity/nginx.conf +35 -0
  84. package/stack-template/app/remotes/activity/package.json +40 -0
  85. package/stack-template/app/remotes/activity/rspack.config.mjs +152 -0
  86. package/stack-template/app/remotes/activity/src/ActivityPage.tsx +139 -0
  87. package/stack-template/app/remotes/activity/src/api.ts +63 -0
  88. package/stack-template/app/remotes/activity/src/app.css +7 -0
  89. package/stack-template/app/remotes/activity/src/components/FeedItem.tsx +39 -0
  90. package/stack-template/app/remotes/activity/src/components/StatTile.tsx +24 -0
  91. package/stack-template/app/remotes/activity/src/components/Timeline.tsx +53 -0
  92. package/stack-template/app/remotes/activity/src/components/time.ts +30 -0
  93. package/stack-template/app/remotes/activity/src/env.d.ts +5 -0
  94. package/stack-template/app/remotes/activity/src/index.tsx +12 -0
  95. package/stack-template/app/remotes/activity/src/standalone.tsx +36 -0
  96. package/stack-template/app/remotes/activity/tests/ActivityPage.test.tsx +260 -0
  97. package/stack-template/app/remotes/activity/tests/api.test.ts +61 -0
  98. package/stack-template/app/remotes/activity/tests/setup.ts +1 -0
  99. package/stack-template/app/remotes/activity/tests/test-utils.tsx +16 -0
  100. package/stack-template/app/remotes/activity/tsconfig.json +26 -0
  101. package/stack-template/app/remotes/activity/vitest.config.ts +38 -0
  102. package/stack-template/app/remotes/tasks/Dockerfile +36 -0
  103. package/stack-template/app/remotes/tasks/README.md +59 -0
  104. package/stack-template/app/remotes/tasks/index.html +11 -0
  105. package/stack-template/app/remotes/tasks/nginx.conf +35 -0
  106. package/stack-template/app/remotes/tasks/package.json +41 -0
  107. package/stack-template/app/remotes/tasks/rspack.config.mjs +153 -0
  108. package/stack-template/app/remotes/tasks/src/TasksPage.tsx +284 -0
  109. package/stack-template/app/remotes/tasks/src/api.ts +109 -0
  110. package/stack-template/app/remotes/tasks/src/app.css +7 -0
  111. package/stack-template/app/remotes/tasks/src/components/StatusBadge.tsx +20 -0
  112. package/stack-template/app/remotes/tasks/src/components/StatusSelect.tsx +27 -0
  113. package/stack-template/app/remotes/tasks/src/components/TaskForm.tsx +74 -0
  114. package/stack-template/app/remotes/tasks/src/components/TaskItem.tsx +199 -0
  115. package/stack-template/app/remotes/tasks/src/components/TaskList.tsx +60 -0
  116. package/stack-template/app/remotes/tasks/src/components/status.ts +23 -0
  117. package/stack-template/app/remotes/tasks/src/env.d.ts +5 -0
  118. package/stack-template/app/remotes/tasks/src/index.tsx +12 -0
  119. package/stack-template/app/remotes/tasks/src/standalone.tsx +38 -0
  120. package/stack-template/app/remotes/tasks/tests/TasksPage.test.tsx +445 -0
  121. package/stack-template/app/remotes/tasks/tests/api.test.ts +159 -0
  122. package/stack-template/app/remotes/tasks/tests/setup.ts +1 -0
  123. package/stack-template/app/remotes/tasks/tests/test-utils.tsx +16 -0
  124. package/stack-template/app/remotes/tasks/tsconfig.json +26 -0
  125. package/stack-template/app/remotes/tasks/vitest.config.ts +34 -0
  126. package/stack-template/app/shared/README.md +21 -0
  127. package/stack-template/app/shared/package.json +37 -0
  128. package/stack-template/app/shared/src/api-client.ts +66 -0
  129. package/stack-template/app/shared/src/error-envelope.ts +38 -0
  130. package/stack-template/app/shared/src/index.ts +21 -0
  131. package/stack-template/app/shared/src/mf-bootstrap.ts +89 -0
  132. package/stack-template/app/shared/src/refresh-client.ts +170 -0
  133. package/stack-template/app/shared/src/token-storage.ts +57 -0
  134. package/stack-template/app/shell/Dockerfile +37 -0
  135. package/stack-template/app/shell/README.md +79 -0
  136. package/stack-template/app/shell/index.html +11 -0
  137. package/stack-template/app/shell/nginx.conf +23 -0
  138. package/stack-template/app/shell/package.json +43 -0
  139. package/stack-template/app/shell/rspack.config.mjs +147 -0
  140. package/stack-template/app/shell/src/App.tsx +57 -0
  141. package/stack-template/app/shell/src/api.ts +36 -0
  142. package/stack-template/app/shell/src/app.css +11 -0
  143. package/stack-template/app/shell/src/bootstrap.tsx +24 -0
  144. package/stack-template/app/shell/src/components/Layout.tsx +35 -0
  145. package/stack-template/app/shell/src/components/NavBar.tsx +118 -0
  146. package/stack-template/app/shell/src/components/RemoteSlot.tsx +82 -0
  147. package/stack-template/app/shell/src/components/RequireAuth.tsx +14 -0
  148. package/stack-template/app/shell/src/env.d.ts +7 -0
  149. package/stack-template/app/shell/src/index.tsx +3 -0
  150. package/stack-template/app/shell/src/pages/HomePage.tsx +70 -0
  151. package/stack-template/app/shell/src/pages/LoginPage.tsx +217 -0
  152. package/stack-template/app/shell/src/remote-urls.ts +18 -0
  153. package/stack-template/app/shell/tests/a11y.test.tsx +53 -0
  154. package/stack-template/app/shell/tests/api-timeout.test.ts +43 -0
  155. package/stack-template/app/shell/tests/integration.test.tsx +93 -0
  156. package/stack-template/app/shell/tests/login.test.tsx +227 -0
  157. package/stack-template/app/shell/tests/mf-retry.test.ts +76 -0
  158. package/stack-template/app/shell/tests/refresh-client.test.ts +301 -0
  159. package/stack-template/app/shell/tests/remote-slot.test.tsx +109 -0
  160. package/stack-template/app/shell/tests/remote-urls.test.ts +26 -0
  161. package/stack-template/app/shell/tests/setup.ts +15 -0
  162. package/stack-template/app/shell/tests/shell-chrome.test.tsx +126 -0
  163. package/stack-template/app/shell/tsconfig.json +26 -0
  164. package/stack-template/app/shell/vitest.config.ts +42 -0
  165. package/stack-template/app/spike/README.md +35 -0
  166. package/stack-template/app/spike/host/index.html +11 -0
  167. package/stack-template/app/spike/host/package.json +17 -0
  168. package/stack-template/app/spike/host/rspack.config.mjs +34 -0
  169. package/stack-template/app/spike/host/src/bootstrap.jsx +26 -0
  170. package/stack-template/app/spike/host/src/index.jsx +3 -0
  171. package/stack-template/app/spike/remote/package.json +17 -0
  172. package/stack-template/app/spike/remote/rspack.config.mjs +36 -0
  173. package/stack-template/app/spike/remote/src/Hello.jsx +7 -0
  174. package/stack-template/app/spike/remote/src/index.js +2 -0
  175. package/stack-template/app/spike/serve.mjs +31 -0
  176. package/stack-template/app/starter-templates/template-feats/extras/carousel/src/DemoCarousel.tsx +99 -0
  177. package/stack-template/app/starter-templates/template-feats/extras/chart/src/DemoChart.tsx +84 -0
  178. package/stack-template/app/starter-templates/template-feats/extras/editor/src/DemoEditor.tsx +110 -0
  179. package/stack-template/app/starter-templates/template-feats/extras/schedule/src/DemoSchedule.tsx +81 -0
  180. package/stack-template/app/starter-templates/template-feats/router/src/App.tsx +332 -0
  181. package/stack-template/app/starter-templates/template-feats/router/src/main.tsx +14 -0
  182. package/stack-template/app/starter-templates/vite-js/README.md +72 -0
  183. package/stack-template/app/starter-templates/vite-js/index.html +12 -0
  184. package/stack-template/app/starter-templates/vite-js/jsconfig.json +10 -0
  185. package/stack-template/app/starter-templates/vite-js/package.json +22 -0
  186. package/stack-template/app/starter-templates/vite-js/src/App.jsx +158 -0
  187. package/stack-template/app/starter-templates/vite-js/src/main.jsx +10 -0
  188. package/stack-template/app/starter-templates/vite-js/src/styles.css +15 -0
  189. package/stack-template/app/starter-templates/vite-js/src/theme.js +21 -0
  190. package/stack-template/app/starter-templates/vite-js/vite.config.mjs +8 -0
  191. package/stack-template/app/starter-templates/vite-ts/README.md +53 -0
  192. package/stack-template/app/starter-templates/vite-ts/index.html +12 -0
  193. package/stack-template/app/starter-templates/vite-ts/package.json +29 -0
  194. package/stack-template/app/starter-templates/vite-ts/src/App.tsx +181 -0
  195. package/stack-template/app/starter-templates/vite-ts/src/main.tsx +12 -0
  196. package/stack-template/app/starter-templates/vite-ts/src/styles.css +21 -0
  197. package/stack-template/app/starter-templates/vite-ts/src/theme.ts +16 -0
  198. package/stack-template/app/starter-templates/vite-ts/tsconfig.json +25 -0
  199. package/stack-template/app/starter-templates/vite-ts/tsconfig.node.json +11 -0
  200. package/stack-template/app/starter-templates/vite-ts/vite.config.ts +10 -0
  201. package/stack-template/app/ui-kit/.storybook/main.ts +29 -0
  202. package/stack-template/app/ui-kit/.storybook/manager-head.html +97 -0
  203. package/stack-template/app/ui-kit/.storybook/manager.ts +138 -0
  204. package/stack-template/app/ui-kit/.storybook/preview-head.html +57 -0
  205. package/stack-template/app/ui-kit/.storybook/preview.ts +62 -0
  206. package/stack-template/app/ui-kit/.storybook/tailwind-preview.css +3 -0
  207. package/stack-template/app/ui-kit/.storybook/test-runner.config.ts +20 -0
  208. package/stack-template/app/ui-kit/CHANGELOG.md +137 -0
  209. package/stack-template/app/ui-kit/LICENSE +21 -0
  210. package/stack-template/app/ui-kit/MIGRATION.md +84 -0
  211. package/stack-template/app/ui-kit/README.md +173 -0
  212. package/stack-template/app/ui-kit/RELEASE.md +77 -0
  213. package/stack-template/app/ui-kit/USAGE.md +380 -0
  214. package/stack-template/app/ui-kit/eslint.config.js +47 -0
  215. package/stack-template/app/ui-kit/package.json +166 -0
  216. package/stack-template/app/ui-kit/scripts/publish-github.sh +39 -0
  217. package/stack-template/app/ui-kit/scripts/publish-npm.sh +76 -0
  218. package/stack-template/app/ui-kit/scripts/stamp-build.cjs +13 -0
  219. package/stack-template/app/ui-kit/src/KitchenSink.stories.tsx +576 -0
  220. package/stack-template/app/ui-kit/src/Tokens.stories.tsx +193 -0
  221. package/stack-template/app/ui-kit/src/entries/carousel.ts +7 -0
  222. package/stack-template/app/ui-kit/src/entries/chart.ts +4 -0
  223. package/stack-template/app/ui-kit/src/entries/editor.ts +4 -0
  224. package/stack-template/app/ui-kit/src/entries/experience3d.ts +5 -0
  225. package/stack-template/app/ui-kit/src/entries/schedule.ts +5 -0
  226. package/stack-template/app/ui-kit/src/env.d.ts +3 -0
  227. package/stack-template/app/ui-kit/src/hooks/form.stories.tsx +80 -0
  228. package/stack-template/app/ui-kit/src/hooks/hooks-new.stories.tsx +392 -0
  229. package/stack-template/app/ui-kit/src/hooks/hooks.stories.tsx +167 -0
  230. package/stack-template/app/ui-kit/src/hooks/useClickAway.test.tsx +63 -0
  231. package/stack-template/app/ui-kit/src/hooks/useClickAway.ts +30 -0
  232. package/stack-template/app/ui-kit/src/hooks/useControllableState.test.ts +36 -0
  233. package/stack-template/app/ui-kit/src/hooks/useControllableState.ts +41 -0
  234. package/stack-template/app/ui-kit/src/hooks/useCopyToClipboard.test.ts +89 -0
  235. package/stack-template/app/ui-kit/src/hooks/useCopyToClipboard.ts +20 -0
  236. package/stack-template/app/ui-kit/src/hooks/useCountdown.test.ts +88 -0
  237. package/stack-template/app/ui-kit/src/hooks/useCountdown.ts +38 -0
  238. package/stack-template/app/ui-kit/src/hooks/useDebounce.test.ts +71 -0
  239. package/stack-template/app/ui-kit/src/hooks/useDebounce.ts +14 -0
  240. package/stack-template/app/ui-kit/src/hooks/useDefault.test.ts +37 -0
  241. package/stack-template/app/ui-kit/src/hooks/useDefault.ts +15 -0
  242. package/stack-template/app/ui-kit/src/hooks/useEventListener.test.ts +47 -0
  243. package/stack-template/app/ui-kit/src/hooks/useEventListener.ts +28 -0
  244. package/stack-template/app/ui-kit/src/hooks/useFieldArray.test.tsx +160 -0
  245. package/stack-template/app/ui-kit/src/hooks/useFieldArray.ts +85 -0
  246. package/stack-template/app/ui-kit/src/hooks/useFocusTrap.ts +67 -0
  247. package/stack-template/app/ui-kit/src/hooks/useForm.test.tsx +192 -0
  248. package/stack-template/app/ui-kit/src/hooks/useForm.ts +119 -0
  249. package/stack-template/app/ui-kit/src/hooks/useFullscreen.test.tsx +71 -0
  250. package/stack-template/app/ui-kit/src/hooks/useFullscreen.ts +68 -0
  251. package/stack-template/app/ui-kit/src/hooks/useHover.test.tsx +30 -0
  252. package/stack-template/app/ui-kit/src/hooks/useHover.ts +23 -0
  253. package/stack-template/app/ui-kit/src/hooks/useInView.test.tsx +70 -0
  254. package/stack-template/app/ui-kit/src/hooks/useInView.ts +55 -0
  255. package/stack-template/app/ui-kit/src/hooks/useInfiniteScroll.test.tsx +72 -0
  256. package/stack-template/app/ui-kit/src/hooks/useInfiniteScroll.ts +45 -0
  257. package/stack-template/app/ui-kit/src/hooks/useIsFirstRender.test.ts +30 -0
  258. package/stack-template/app/ui-kit/src/hooks/useIsFirstRender.ts +14 -0
  259. package/stack-template/app/ui-kit/src/hooks/useKeyPress.test.ts +45 -0
  260. package/stack-template/app/ui-kit/src/hooks/useKeyPress.ts +31 -0
  261. package/stack-template/app/ui-kit/src/hooks/useLocalStorage.test.ts +102 -0
  262. package/stack-template/app/ui-kit/src/hooks/useLocalStorage.ts +34 -0
  263. package/stack-template/app/ui-kit/src/hooks/useLockBodyScroll.test.ts +42 -0
  264. package/stack-template/app/ui-kit/src/hooks/useLockBodyScroll.ts +13 -0
  265. package/stack-template/app/ui-kit/src/hooks/useMeasure.test.tsx +57 -0
  266. package/stack-template/app/ui-kit/src/hooks/useMeasure.ts +32 -0
  267. package/stack-template/app/ui-kit/src/hooks/useMediaQuery.test.ts +73 -0
  268. package/stack-template/app/ui-kit/src/hooks/useMediaQuery.ts +20 -0
  269. package/stack-template/app/ui-kit/src/hooks/useMountEffect.test.ts +22 -0
  270. package/stack-template/app/ui-kit/src/hooks/useMountEffect.ts +10 -0
  271. package/stack-template/app/ui-kit/src/hooks/useOnlineStatus.test.ts +36 -0
  272. package/stack-template/app/ui-kit/src/hooks/useOnlineStatus.ts +21 -0
  273. package/stack-template/app/ui-kit/src/hooks/usePrevious.test.ts +35 -0
  274. package/stack-template/app/ui-kit/src/hooks/usePrevious.ts +13 -0
  275. package/stack-template/app/ui-kit/src/hooks/useScrollProgress.test.ts +59 -0
  276. package/stack-template/app/ui-kit/src/hooks/useScrollProgress.ts +31 -0
  277. package/stack-template/app/ui-kit/src/hooks/useSessionStorage.test.ts +80 -0
  278. package/stack-template/app/ui-kit/src/hooks/useSessionStorage.ts +34 -0
  279. package/stack-template/app/ui-kit/src/hooks/useThrottle.test.ts +61 -0
  280. package/stack-template/app/ui-kit/src/hooks/useThrottle.ts +30 -0
  281. package/stack-template/app/ui-kit/src/hooks/useTimeout.test.ts +95 -0
  282. package/stack-template/app/ui-kit/src/hooks/useTimeout.ts +38 -0
  283. package/stack-template/app/ui-kit/src/hooks/useTitle.test.ts +34 -0
  284. package/stack-template/app/ui-kit/src/hooks/useTitle.ts +24 -0
  285. package/stack-template/app/ui-kit/src/hooks/useToggle.test.ts +46 -0
  286. package/stack-template/app/ui-kit/src/hooks/useToggle.ts +16 -0
  287. package/stack-template/app/ui-kit/src/hooks/useUpdateEffect.test.ts +25 -0
  288. package/stack-template/app/ui-kit/src/hooks/useUpdateEffect.ts +18 -0
  289. package/stack-template/app/ui-kit/src/hooks/useWindowSize.test.ts +33 -0
  290. package/stack-template/app/ui-kit/src/hooks/useWindowSize.ts +23 -0
  291. package/stack-template/app/ui-kit/src/index.ts +218 -0
  292. package/stack-template/app/ui-kit/src/intro-showcase.stories.tsx +272 -0
  293. package/stack-template/app/ui-kit/src/intro.docs.mdx +247 -0
  294. package/stack-template/app/ui-kit/src/motion/motion-showcase.stories.tsx +234 -0
  295. package/stack-template/app/ui-kit/src/motion/motion.md +38 -0
  296. package/stack-template/app/ui-kit/src/provider/index.tsx +77 -0
  297. package/stack-template/app/ui-kit/src/provider/provider.stories.tsx +87 -0
  298. package/stack-template/app/ui-kit/src/provider/provider.test.tsx +121 -0
  299. package/stack-template/app/ui-kit/src/styles/base.css +171 -0
  300. package/stack-template/app/ui-kit/src/styles/dark-theme.test.ts +21 -0
  301. package/stack-template/app/ui-kit/src/styles/tailwind.css +220 -0
  302. package/stack-template/app/ui-kit/src/styles/themes/dark.css +71 -0
  303. package/stack-template/app/ui-kit/src/styles/tokens.css +133 -0
  304. package/stack-template/app/ui-kit/src/styles/ui-kit.css +10 -0
  305. package/stack-template/app/ui-kit/src/templates/auth.stories.tsx +425 -0
  306. package/stack-template/app/ui-kit/src/templates/crud.stories.tsx +416 -0
  307. package/stack-template/app/ui-kit/src/templates/dashboard.stories.tsx +504 -0
  308. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch1-deep-focus.tsx +96 -0
  309. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch2-living-docs.tsx +134 -0
  310. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch3-team-velocity.tsx +148 -0
  311. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch4-ship-your-app.tsx +100 -0
  312. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch5-future.tsx +67 -0
  313. package/stack-template/app/ui-kit/src/templates/experience/chapters/hero.tsx +434 -0
  314. package/stack-template/app/ui-kit/src/templates/experience/chapters/nav-footer.tsx +85 -0
  315. package/stack-template/app/ui-kit/src/templates/experience/hero.stories.tsx +27 -0
  316. package/stack-template/app/ui-kit/src/templates/experience/hero.test.tsx +108 -0
  317. package/stack-template/app/ui-kit/src/templates/experience/index.stories.tsx +51 -0
  318. package/stack-template/app/ui-kit/src/templates/experience/lib/ChapterShell.tsx +84 -0
  319. package/stack-template/app/ui-kit/src/templates/experience/lib/SideNav.tsx +173 -0
  320. package/stack-template/app/ui-kit/src/templates/experience/lib/chapter-shell.test.tsx +266 -0
  321. package/stack-template/app/ui-kit/src/templates/experience/lib/scroll-mood.tsx +143 -0
  322. package/stack-template/app/ui-kit/src/templates/experience/lib/starfield.test.tsx +31 -0
  323. package/stack-template/app/ui-kit/src/templates/experience/lib/starfield.tsx +190 -0
  324. package/stack-template/app/ui-kit/src/templates/experience/mood-engine.stories.tsx +114 -0
  325. package/stack-template/app/ui-kit/src/templates/experience/shell-nav.stories.tsx +113 -0
  326. package/stack-template/app/ui-kit/src/templates/kanban-project.stories.tsx +352 -0
  327. package/stack-template/app/ui-kit/src/templates/landing.stories.tsx +380 -0
  328. package/stack-template/app/ui-kit/src/templates/parallax-landing.stories.tsx +633 -0
  329. package/stack-template/app/ui-kit/src/templates/settings.stories.tsx +474 -0
  330. package/stack-template/app/ui-kit/src/ui/accordion/accordion.stories.tsx +91 -0
  331. package/stack-template/app/ui-kit/src/ui/accordion/accordion.test.tsx +99 -0
  332. package/stack-template/app/ui-kit/src/ui/accordion/index.tsx +107 -0
  333. package/stack-template/app/ui-kit/src/ui/affix/affix.stories.tsx +104 -0
  334. package/stack-template/app/ui-kit/src/ui/affix/affix.test.tsx +138 -0
  335. package/stack-template/app/ui-kit/src/ui/affix/index.tsx +89 -0
  336. package/stack-template/app/ui-kit/src/ui/alert/alert.stories.tsx +149 -0
  337. package/stack-template/app/ui-kit/src/ui/alert/alert.test.tsx +85 -0
  338. package/stack-template/app/ui-kit/src/ui/alert/index.tsx +118 -0
  339. package/stack-template/app/ui-kit/src/ui/anchor/anchor.stories.tsx +96 -0
  340. package/stack-template/app/ui-kit/src/ui/anchor/anchor.test.tsx +191 -0
  341. package/stack-template/app/ui-kit/src/ui/anchor/index.tsx +144 -0
  342. package/stack-template/app/ui-kit/src/ui/auto-complete/auto-complete.stories.tsx +67 -0
  343. package/stack-template/app/ui-kit/src/ui/auto-complete/auto-complete.test.tsx +94 -0
  344. package/stack-template/app/ui-kit/src/ui/auto-complete/index.tsx +54 -0
  345. package/stack-template/app/ui-kit/src/ui/avatar/avatar.stories.tsx +132 -0
  346. package/stack-template/app/ui-kit/src/ui/avatar/avatar.test.tsx +65 -0
  347. package/stack-template/app/ui-kit/src/ui/avatar/index.tsx +48 -0
  348. package/stack-template/app/ui-kit/src/ui/avatar-group/avatar-group.stories.tsx +113 -0
  349. package/stack-template/app/ui-kit/src/ui/avatar-group/avatar-group.test.tsx +71 -0
  350. package/stack-template/app/ui-kit/src/ui/avatar-group/index.tsx +66 -0
  351. package/stack-template/app/ui-kit/src/ui/backdrop/backdrop.stories.tsx +66 -0
  352. package/stack-template/app/ui-kit/src/ui/backdrop/backdrop.test.tsx +37 -0
  353. package/stack-template/app/ui-kit/src/ui/backdrop/index.tsx +29 -0
  354. package/stack-template/app/ui-kit/src/ui/badge/badge.stories.tsx +105 -0
  355. package/stack-template/app/ui-kit/src/ui/badge/badge.test.tsx +115 -0
  356. package/stack-template/app/ui-kit/src/ui/badge/index.tsx +154 -0
  357. package/stack-template/app/ui-kit/src/ui/blockui/blockui.stories.tsx +34 -0
  358. package/stack-template/app/ui-kit/src/ui/blockui/blockui.test.tsx +29 -0
  359. package/stack-template/app/ui-kit/src/ui/blockui/index.tsx +25 -0
  360. package/stack-template/app/ui-kit/src/ui/bottom-navigation/bottom-navigation.stories.tsx +70 -0
  361. package/stack-template/app/ui-kit/src/ui/bottom-navigation/bottom-navigation.test.tsx +68 -0
  362. package/stack-template/app/ui-kit/src/ui/bottom-navigation/index.tsx +82 -0
  363. package/stack-template/app/ui-kit/src/ui/branch-fill.test.tsx +245 -0
  364. package/stack-template/app/ui-kit/src/ui/breadcrumb/breadcrumb.stories.tsx +103 -0
  365. package/stack-template/app/ui-kit/src/ui/breadcrumb/breadcrumb.test.tsx +49 -0
  366. package/stack-template/app/ui-kit/src/ui/breadcrumb/index.tsx +37 -0
  367. package/stack-template/app/ui-kit/src/ui/busy-box/busy-box.stories.tsx +30 -0
  368. package/stack-template/app/ui-kit/src/ui/busy-box/busy-box.test.tsx +29 -0
  369. package/stack-template/app/ui-kit/src/ui/busy-box/index.tsx +25 -0
  370. package/stack-template/app/ui-kit/src/ui/button/button.stories.tsx +121 -0
  371. package/stack-template/app/ui-kit/src/ui/button/button.test.tsx +207 -0
  372. package/stack-template/app/ui-kit/src/ui/button/index.tsx +128 -0
  373. package/stack-template/app/ui-kit/src/ui/calendar/calendar.stories.tsx +100 -0
  374. package/stack-template/app/ui-kit/src/ui/calendar/calendar.test.tsx +92 -0
  375. package/stack-template/app/ui-kit/src/ui/calendar/index.tsx +163 -0
  376. package/stack-template/app/ui-kit/src/ui/card/card.stories.tsx +203 -0
  377. package/stack-template/app/ui-kit/src/ui/card/card.test.tsx +135 -0
  378. package/stack-template/app/ui-kit/src/ui/card/index.tsx +84 -0
  379. package/stack-template/app/ui-kit/src/ui/carousel/carousel.stories.tsx +533 -0
  380. package/stack-template/app/ui-kit/src/ui/carousel/carousel.test.tsx +148 -0
  381. package/stack-template/app/ui-kit/src/ui/carousel/index.tsx +195 -0
  382. package/stack-template/app/ui-kit/src/ui/cascade-select/cascade-select.stories.tsx +126 -0
  383. package/stack-template/app/ui-kit/src/ui/cascade-select/cascade-select.test.tsx +132 -0
  384. package/stack-template/app/ui-kit/src/ui/cascade-select/index.tsx +87 -0
  385. package/stack-template/app/ui-kit/src/ui/chart/chart-theme.test.tsx +79 -0
  386. package/stack-template/app/ui-kit/src/ui/chart/chart.stories.tsx +278 -0
  387. package/stack-template/app/ui-kit/src/ui/chart/chart.test.tsx +103 -0
  388. package/stack-template/app/ui-kit/src/ui/chart/index.tsx +172 -0
  389. package/stack-template/app/ui-kit/src/ui/checkbox/checkbox.stories.tsx +67 -0
  390. package/stack-template/app/ui-kit/src/ui/checkbox/checkbox.test.tsx +99 -0
  391. package/stack-template/app/ui-kit/src/ui/checkbox/index.tsx +52 -0
  392. package/stack-template/app/ui-kit/src/ui/chips/chips.stories.tsx +53 -0
  393. package/stack-template/app/ui-kit/src/ui/chips/chips.test.tsx +86 -0
  394. package/stack-template/app/ui-kit/src/ui/chips/index.tsx +44 -0
  395. package/stack-template/app/ui-kit/src/ui/collapse/collapse.stories.tsx +93 -0
  396. package/stack-template/app/ui-kit/src/ui/collapse/collapse.test.tsx +128 -0
  397. package/stack-template/app/ui-kit/src/ui/collapse/index.tsx +75 -0
  398. package/stack-template/app/ui-kit/src/ui/color-picker/color-picker.stories.tsx +48 -0
  399. package/stack-template/app/ui-kit/src/ui/color-picker/color-picker.test.tsx +68 -0
  400. package/stack-template/app/ui-kit/src/ui/color-picker/index.tsx +38 -0
  401. package/stack-template/app/ui-kit/src/ui/context-menu/context-menu.stories.tsx +73 -0
  402. package/stack-template/app/ui-kit/src/ui/context-menu/context-menu.test.tsx +93 -0
  403. package/stack-template/app/ui-kit/src/ui/context-menu/index.tsx +79 -0
  404. package/stack-template/app/ui-kit/src/ui/count-up/count-up.stories.tsx +80 -0
  405. package/stack-template/app/ui-kit/src/ui/count-up/count-up.test.tsx +121 -0
  406. package/stack-template/app/ui-kit/src/ui/count-up/index.tsx +70 -0
  407. package/stack-template/app/ui-kit/src/ui/date-picker/date-picker.stories.tsx +154 -0
  408. package/stack-template/app/ui-kit/src/ui/date-picker/date-picker.test.tsx +221 -0
  409. package/stack-template/app/ui-kit/src/ui/date-picker/index.tsx +287 -0
  410. package/stack-template/app/ui-kit/src/ui/date-picker/locale-constants.ts +90 -0
  411. package/stack-template/app/ui-kit/src/ui/date-picker/locale.tsx +15 -0
  412. package/stack-template/app/ui-kit/src/ui/deferred-content/deferred-content.stories.tsx +62 -0
  413. package/stack-template/app/ui-kit/src/ui/deferred-content/deferred-content.test.tsx +94 -0
  414. package/stack-template/app/ui-kit/src/ui/deferred-content/index.tsx +61 -0
  415. package/stack-template/app/ui-kit/src/ui/descriptions/descriptions.stories.tsx +114 -0
  416. package/stack-template/app/ui-kit/src/ui/descriptions/descriptions.test.tsx +75 -0
  417. package/stack-template/app/ui-kit/src/ui/descriptions/index.tsx +48 -0
  418. package/stack-template/app/ui-kit/src/ui/divider/divider.stories.tsx +66 -0
  419. package/stack-template/app/ui-kit/src/ui/divider/divider.test.tsx +83 -0
  420. package/stack-template/app/ui-kit/src/ui/divider/index.tsx +65 -0
  421. package/stack-template/app/ui-kit/src/ui/drag-drop/drag-drop.stories.tsx +145 -0
  422. package/stack-template/app/ui-kit/src/ui/drag-drop/drag-drop.test.tsx +352 -0
  423. package/stack-template/app/ui-kit/src/ui/drag-drop/index.tsx +456 -0
  424. package/stack-template/app/ui-kit/src/ui/drawer/drawer.stories.tsx +108 -0
  425. package/stack-template/app/ui-kit/src/ui/drawer/drawer.test.tsx +132 -0
  426. package/stack-template/app/ui-kit/src/ui/drawer/index.tsx +113 -0
  427. package/stack-template/app/ui-kit/src/ui/dropdown/dropdown.stories.tsx +61 -0
  428. package/stack-template/app/ui-kit/src/ui/dropdown/dropdown.test.tsx +101 -0
  429. package/stack-template/app/ui-kit/src/ui/dropdown/index.tsx +162 -0
  430. package/stack-template/app/ui-kit/src/ui/editor/EditorInner.tsx +93 -0
  431. package/stack-template/app/ui-kit/src/ui/editor/editor.stories.tsx +37 -0
  432. package/stack-template/app/ui-kit/src/ui/editor/editor.test.tsx +84 -0
  433. package/stack-template/app/ui-kit/src/ui/editor/index.tsx +58 -0
  434. package/stack-template/app/ui-kit/src/ui/empty-state/empty-state.stories.tsx +24 -0
  435. package/stack-template/app/ui-kit/src/ui/empty-state/empty-state.test.tsx +48 -0
  436. package/stack-template/app/ui-kit/src/ui/empty-state/index.tsx +22 -0
  437. package/stack-template/app/ui-kit/src/ui/experience3d/experience3d.stories.tsx +66 -0
  438. package/stack-template/app/ui-kit/src/ui/experience3d/experience3d.test.tsx +50 -0
  439. package/stack-template/app/ui-kit/src/ui/experience3d/index.tsx +457 -0
  440. package/stack-template/app/ui-kit/src/ui/field/field-array.stories.tsx +214 -0
  441. package/stack-template/app/ui-kit/src/ui/field/field.stories.tsx +158 -0
  442. package/stack-template/app/ui-kit/src/ui/field/field.test.tsx +68 -0
  443. package/stack-template/app/ui-kit/src/ui/field/index.tsx +48 -0
  444. package/stack-template/app/ui-kit/src/ui/fieldset/fieldset.stories.tsx +49 -0
  445. package/stack-template/app/ui-kit/src/ui/fieldset/fieldset.test.tsx +88 -0
  446. package/stack-template/app/ui-kit/src/ui/fieldset/index.tsx +62 -0
  447. package/stack-template/app/ui-kit/src/ui/flex/flex.stories.tsx +96 -0
  448. package/stack-template/app/ui-kit/src/ui/flex/flex.test.tsx +79 -0
  449. package/stack-template/app/ui-kit/src/ui/flex/index.tsx +45 -0
  450. package/stack-template/app/ui-kit/src/ui/float-button/float-button.stories.tsx +82 -0
  451. package/stack-template/app/ui-kit/src/ui/float-button/float-button.test.tsx +107 -0
  452. package/stack-template/app/ui-kit/src/ui/float-button/index.tsx +124 -0
  453. package/stack-template/app/ui-kit/src/ui/galleria/galleria.stories.tsx +78 -0
  454. package/stack-template/app/ui-kit/src/ui/galleria/galleria.test.tsx +67 -0
  455. package/stack-template/app/ui-kit/src/ui/galleria/index.tsx +47 -0
  456. package/stack-template/app/ui-kit/src/ui/grid/grid.stories.tsx +179 -0
  457. package/stack-template/app/ui-kit/src/ui/grid/grid.test.tsx +286 -0
  458. package/stack-template/app/ui-kit/src/ui/grid/index.tsx +104 -0
  459. package/stack-template/app/ui-kit/src/ui/icons/icons.stories.tsx +52 -0
  460. package/stack-template/app/ui-kit/src/ui/icons/icons.test.tsx +60 -0
  461. package/stack-template/app/ui-kit/src/ui/icons/index.tsx +294 -0
  462. package/stack-template/app/ui-kit/src/ui/image/image.stories.tsx +231 -0
  463. package/stack-template/app/ui-kit/src/ui/image/image.test.tsx +79 -0
  464. package/stack-template/app/ui-kit/src/ui/image/index.tsx +76 -0
  465. package/stack-template/app/ui-kit/src/ui/inplace/index.tsx +33 -0
  466. package/stack-template/app/ui-kit/src/ui/inplace/inplace.stories.tsx +75 -0
  467. package/stack-template/app/ui-kit/src/ui/inplace/inplace.test.tsx +58 -0
  468. package/stack-template/app/ui-kit/src/ui/input/index.tsx +133 -0
  469. package/stack-template/app/ui-kit/src/ui/input/input-search.stories.tsx +112 -0
  470. package/stack-template/app/ui-kit/src/ui/input/input-search.test.tsx +116 -0
  471. package/stack-template/app/ui-kit/src/ui/input/input-search.tsx +116 -0
  472. package/stack-template/app/ui-kit/src/ui/input/input.stories.tsx +176 -0
  473. package/stack-template/app/ui-kit/src/ui/input/input.test.tsx +106 -0
  474. package/stack-template/app/ui-kit/src/ui/input-mask/index.tsx +39 -0
  475. package/stack-template/app/ui-kit/src/ui/input-mask/input-mask.stories.tsx +46 -0
  476. package/stack-template/app/ui-kit/src/ui/input-mask/input-mask.test.tsx +57 -0
  477. package/stack-template/app/ui-kit/src/ui/input-number/index.tsx +125 -0
  478. package/stack-template/app/ui-kit/src/ui/input-number/input-number.stories.tsx +190 -0
  479. package/stack-template/app/ui-kit/src/ui/input-number/input-number.test.tsx +157 -0
  480. package/stack-template/app/ui-kit/src/ui/input-otp/index.tsx +57 -0
  481. package/stack-template/app/ui-kit/src/ui/input-otp/input-otp.stories.tsx +90 -0
  482. package/stack-template/app/ui-kit/src/ui/input-otp/input-otp.test.tsx +66 -0
  483. package/stack-template/app/ui-kit/src/ui/kanban/index.tsx +277 -0
  484. package/stack-template/app/ui-kit/src/ui/kanban/kanban.stories.tsx +219 -0
  485. package/stack-template/app/ui-kit/src/ui/kanban/kanban.test.tsx +234 -0
  486. package/stack-template/app/ui-kit/src/ui/knob/index.tsx +58 -0
  487. package/stack-template/app/ui-kit/src/ui/knob/knob.stories.tsx +49 -0
  488. package/stack-template/app/ui-kit/src/ui/knob/knob.test.tsx +42 -0
  489. package/stack-template/app/ui-kit/src/ui/layout/index.tsx +145 -0
  490. package/stack-template/app/ui-kit/src/ui/layout/layout.stories.tsx +158 -0
  491. package/stack-template/app/ui-kit/src/ui/layout/layout.test.tsx +154 -0
  492. package/stack-template/app/ui-kit/src/ui/link/index.tsx +61 -0
  493. package/stack-template/app/ui-kit/src/ui/link/link.stories.tsx +68 -0
  494. package/stack-template/app/ui-kit/src/ui/link/link.test.tsx +69 -0
  495. package/stack-template/app/ui-kit/src/ui/list/index.tsx +135 -0
  496. package/stack-template/app/ui-kit/src/ui/list/list.stories.tsx +194 -0
  497. package/stack-template/app/ui-kit/src/ui/list/list.test.tsx +164 -0
  498. package/stack-template/app/ui-kit/src/ui/listbox/index.tsx +27 -0
  499. package/stack-template/app/ui-kit/src/ui/listbox/listbox.stories.tsx +57 -0
  500. package/stack-template/app/ui-kit/src/ui/listbox/listbox.test.tsx +49 -0
  501. package/stack-template/app/ui-kit/src/ui/mega-menu/index.tsx +142 -0
  502. package/stack-template/app/ui-kit/src/ui/mega-menu/mega-menu.stories.tsx +137 -0
  503. package/stack-template/app/ui-kit/src/ui/mega-menu/mega-menu.test.tsx +130 -0
  504. package/stack-template/app/ui-kit/src/ui/mention/index.tsx +76 -0
  505. package/stack-template/app/ui-kit/src/ui/mention/mention.stories.tsx +44 -0
  506. package/stack-template/app/ui-kit/src/ui/mention/mention.test.tsx +87 -0
  507. package/stack-template/app/ui-kit/src/ui/menu/index.tsx +256 -0
  508. package/stack-template/app/ui-kit/src/ui/menu/menu.stories.tsx +124 -0
  509. package/stack-template/app/ui-kit/src/ui/menu/menu.test.tsx +251 -0
  510. package/stack-template/app/ui-kit/src/ui/menubar/index.tsx +42 -0
  511. package/stack-template/app/ui-kit/src/ui/menubar/menubar.stories.tsx +66 -0
  512. package/stack-template/app/ui-kit/src/ui/menubar/menubar.test.tsx +65 -0
  513. package/stack-template/app/ui-kit/src/ui/message/index.tsx +123 -0
  514. package/stack-template/app/ui-kit/src/ui/message/message.stories.tsx +104 -0
  515. package/stack-template/app/ui-kit/src/ui/message/message.test.tsx +109 -0
  516. package/stack-template/app/ui-kit/src/ui/modal/index.tsx +142 -0
  517. package/stack-template/app/ui-kit/src/ui/modal/modal.stories.tsx +128 -0
  518. package/stack-template/app/ui-kit/src/ui/modal/modal.test.tsx +166 -0
  519. package/stack-template/app/ui-kit/src/ui/notification/index.tsx +142 -0
  520. package/stack-template/app/ui-kit/src/ui/notification/notification.stories.tsx +155 -0
  521. package/stack-template/app/ui-kit/src/ui/notification/notification.test.tsx +83 -0
  522. package/stack-template/app/ui-kit/src/ui/order-list/index.tsx +38 -0
  523. package/stack-template/app/ui-kit/src/ui/order-list/order-list.stories.tsx +38 -0
  524. package/stack-template/app/ui-kit/src/ui/order-list/order-list.test.tsx +54 -0
  525. package/stack-template/app/ui-kit/src/ui/org-chart/index.tsx +138 -0
  526. package/stack-template/app/ui-kit/src/ui/org-chart/org-chart.stories.tsx +76 -0
  527. package/stack-template/app/ui-kit/src/ui/org-chart/org-chart.test.tsx +98 -0
  528. package/stack-template/app/ui-kit/src/ui/pagination/index.tsx +102 -0
  529. package/stack-template/app/ui-kit/src/ui/pagination/pagination.stories.tsx +103 -0
  530. package/stack-template/app/ui-kit/src/ui/pagination/pagination.test.tsx +112 -0
  531. package/stack-template/app/ui-kit/src/ui/panel-menu/index.tsx +59 -0
  532. package/stack-template/app/ui-kit/src/ui/panel-menu/panel-menu.stories.tsx +96 -0
  533. package/stack-template/app/ui-kit/src/ui/panel-menu/panel-menu.test.tsx +64 -0
  534. package/stack-template/app/ui-kit/src/ui/parallax/index.tsx +62 -0
  535. package/stack-template/app/ui-kit/src/ui/parallax/parallax.stories.tsx +115 -0
  536. package/stack-template/app/ui-kit/src/ui/parallax/parallax.test.tsx +148 -0
  537. package/stack-template/app/ui-kit/src/ui/password/index.tsx +67 -0
  538. package/stack-template/app/ui-kit/src/ui/password/password.stories.tsx +43 -0
  539. package/stack-template/app/ui-kit/src/ui/password/password.test.tsx +45 -0
  540. package/stack-template/app/ui-kit/src/ui/pick-list/index.tsx +103 -0
  541. package/stack-template/app/ui-kit/src/ui/pick-list/pick-list.stories.tsx +59 -0
  542. package/stack-template/app/ui-kit/src/ui/pick-list/pick-list.test.tsx +94 -0
  543. package/stack-template/app/ui-kit/src/ui/popconfirm/index.tsx +102 -0
  544. package/stack-template/app/ui-kit/src/ui/popconfirm/popconfirm.stories.tsx +73 -0
  545. package/stack-template/app/ui-kit/src/ui/popconfirm/popconfirm.test.tsx +127 -0
  546. package/stack-template/app/ui-kit/src/ui/popover/index.tsx +136 -0
  547. package/stack-template/app/ui-kit/src/ui/popover/popover.stories.tsx +114 -0
  548. package/stack-template/app/ui-kit/src/ui/popover/popover.test.tsx +172 -0
  549. package/stack-template/app/ui-kit/src/ui/progress/index.tsx +46 -0
  550. package/stack-template/app/ui-kit/src/ui/progress/progress.stories.tsx +57 -0
  551. package/stack-template/app/ui-kit/src/ui/progress/progress.test.tsx +90 -0
  552. package/stack-template/app/ui-kit/src/ui/qr-code/index.tsx +88 -0
  553. package/stack-template/app/ui-kit/src/ui/qr-code/qr-code.stories.tsx +109 -0
  554. package/stack-template/app/ui-kit/src/ui/qr-code/qr-code.test.tsx +155 -0
  555. package/stack-template/app/ui-kit/src/ui/qr-code/qrcode-core.ts +56 -0
  556. package/stack-template/app/ui-kit/src/ui/qr-code/qrcode-generator.vendor.ts +2300 -0
  557. package/stack-template/app/ui-kit/src/ui/radio/index.tsx +62 -0
  558. package/stack-template/app/ui-kit/src/ui/radio/radio.stories.tsx +94 -0
  559. package/stack-template/app/ui-kit/src/ui/radio/radio.test.tsx +83 -0
  560. package/stack-template/app/ui-kit/src/ui/rating/index.tsx +36 -0
  561. package/stack-template/app/ui-kit/src/ui/rating/rating.stories.tsx +42 -0
  562. package/stack-template/app/ui-kit/src/ui/rating/rating.test.tsx +45 -0
  563. package/stack-template/app/ui-kit/src/ui/result/index.tsx +72 -0
  564. package/stack-template/app/ui-kit/src/ui/result/result.stories.tsx +82 -0
  565. package/stack-template/app/ui-kit/src/ui/result/result.test.tsx +57 -0
  566. package/stack-template/app/ui-kit/src/ui/reveal/index.tsx +83 -0
  567. package/stack-template/app/ui-kit/src/ui/reveal/reveal.stories.tsx +91 -0
  568. package/stack-template/app/ui-kit/src/ui/reveal/reveal.test.tsx +148 -0
  569. package/stack-template/app/ui-kit/src/ui/schedule/index.tsx +104 -0
  570. package/stack-template/app/ui-kit/src/ui/schedule/schedule.fc.test.tsx +95 -0
  571. package/stack-template/app/ui-kit/src/ui/schedule/schedule.stories.tsx +61 -0
  572. package/stack-template/app/ui-kit/src/ui/schedule/schedule.test.tsx +41 -0
  573. package/stack-template/app/ui-kit/src/ui/scroll-page/index.tsx +46 -0
  574. package/stack-template/app/ui-kit/src/ui/scroll-page/scroll-page.stories.tsx +92 -0
  575. package/stack-template/app/ui-kit/src/ui/scroll-page/scroll-page.test.tsx +51 -0
  576. package/stack-template/app/ui-kit/src/ui/scroll-panel/index.tsx +16 -0
  577. package/stack-template/app/ui-kit/src/ui/scroll-panel/scroll-panel.stories.tsx +37 -0
  578. package/stack-template/app/ui-kit/src/ui/scroll-panel/scroll-panel.test.tsx +41 -0
  579. package/stack-template/app/ui-kit/src/ui/scrolltop/index.tsx +27 -0
  580. package/stack-template/app/ui-kit/src/ui/scrolltop/scrolltop.stories.tsx +41 -0
  581. package/stack-template/app/ui-kit/src/ui/scrolltop/scrolltop.test.tsx +37 -0
  582. package/stack-template/app/ui-kit/src/ui/segmented/index.tsx +47 -0
  583. package/stack-template/app/ui-kit/src/ui/segmented/segmented.stories.tsx +126 -0
  584. package/stack-template/app/ui-kit/src/ui/segmented/segmented.test.tsx +77 -0
  585. package/stack-template/app/ui-kit/src/ui/select/index.tsx +302 -0
  586. package/stack-template/app/ui-kit/src/ui/select/select.stories.tsx +268 -0
  587. package/stack-template/app/ui-kit/src/ui/select/select.test.tsx +226 -0
  588. package/stack-template/app/ui-kit/src/ui/sidebar/index.tsx +83 -0
  589. package/stack-template/app/ui-kit/src/ui/sidebar/sidebar.stories.tsx +71 -0
  590. package/stack-template/app/ui-kit/src/ui/sidebar/sidebar.test.tsx +101 -0
  591. package/stack-template/app/ui-kit/src/ui/skeleton/index.tsx +55 -0
  592. package/stack-template/app/ui-kit/src/ui/skeleton/skeleton.stories.tsx +110 -0
  593. package/stack-template/app/ui-kit/src/ui/skeleton/skeleton.test.tsx +74 -0
  594. package/stack-template/app/ui-kit/src/ui/slide-menu/index.tsx +103 -0
  595. package/stack-template/app/ui-kit/src/ui/slide-menu/slide-menu.stories.tsx +92 -0
  596. package/stack-template/app/ui-kit/src/ui/slide-menu/slide-menu.test.tsx +120 -0
  597. package/stack-template/app/ui-kit/src/ui/slider/index.tsx +90 -0
  598. package/stack-template/app/ui-kit/src/ui/slider/slider.stories.tsx +60 -0
  599. package/stack-template/app/ui-kit/src/ui/slider/slider.test.tsx +66 -0
  600. package/stack-template/app/ui-kit/src/ui/space/index.tsx +32 -0
  601. package/stack-template/app/ui-kit/src/ui/space/space.stories.tsx +66 -0
  602. package/stack-template/app/ui-kit/src/ui/space/space.test.tsx +56 -0
  603. package/stack-template/app/ui-kit/src/ui/speed-dial/index.tsx +32 -0
  604. package/stack-template/app/ui-kit/src/ui/speed-dial/speed-dial.stories.tsx +34 -0
  605. package/stack-template/app/ui-kit/src/ui/speed-dial/speed-dial.test.tsx +34 -0
  606. package/stack-template/app/ui-kit/src/ui/spinner/index.tsx +74 -0
  607. package/stack-template/app/ui-kit/src/ui/spinner/spinner.stories.tsx +64 -0
  608. package/stack-template/app/ui-kit/src/ui/spinner/spinner.test.tsx +66 -0
  609. package/stack-template/app/ui-kit/src/ui/split-button/index.tsx +155 -0
  610. package/stack-template/app/ui-kit/src/ui/split-button/split-button.stories.tsx +137 -0
  611. package/stack-template/app/ui-kit/src/ui/split-button/split-button.test.tsx +152 -0
  612. package/stack-template/app/ui-kit/src/ui/splitter/index.tsx +49 -0
  613. package/stack-template/app/ui-kit/src/ui/splitter/splitter.stories.tsx +24 -0
  614. package/stack-template/app/ui-kit/src/ui/splitter/splitter.test.tsx +21 -0
  615. package/stack-template/app/ui-kit/src/ui/statistic/index.tsx +28 -0
  616. package/stack-template/app/ui-kit/src/ui/statistic/statistic.stories.tsx +112 -0
  617. package/stack-template/app/ui-kit/src/ui/statistic/statistic.test.tsx +39 -0
  618. package/stack-template/app/ui-kit/src/ui/steps/index.tsx +50 -0
  619. package/stack-template/app/ui-kit/src/ui/steps/steps.stories.tsx +57 -0
  620. package/stack-template/app/ui-kit/src/ui/steps/steps.test.tsx +55 -0
  621. package/stack-template/app/ui-kit/src/ui/switch/index.tsx +87 -0
  622. package/stack-template/app/ui-kit/src/ui/switch/switch.stories.tsx +123 -0
  623. package/stack-template/app/ui-kit/src/ui/switch/switch.test.tsx +98 -0
  624. package/stack-template/app/ui-kit/src/ui/tab-menu/index.tsx +33 -0
  625. package/stack-template/app/ui-kit/src/ui/tab-menu/tab-menu.stories.tsx +49 -0
  626. package/stack-template/app/ui-kit/src/ui/tab-menu/tab-menu.test.tsx +50 -0
  627. package/stack-template/app/ui-kit/src/ui/table/index.tsx +690 -0
  628. package/stack-template/app/ui-kit/src/ui/table/table-advanced.stories.tsx +91 -0
  629. package/stack-template/app/ui-kit/src/ui/table/table-advanced.test.tsx +188 -0
  630. package/stack-template/app/ui-kit/src/ui/table/table-expandable.stories.tsx +91 -0
  631. package/stack-template/app/ui-kit/src/ui/table/table-expandable.test.tsx +143 -0
  632. package/stack-template/app/ui-kit/src/ui/table/table.stories.tsx +342 -0
  633. package/stack-template/app/ui-kit/src/ui/table/table.test.tsx +465 -0
  634. package/stack-template/app/ui-kit/src/ui/table/types.ts +173 -0
  635. package/stack-template/app/ui-kit/src/ui/tabs/index.tsx +118 -0
  636. package/stack-template/app/ui-kit/src/ui/tabs/tabs.stories.tsx +113 -0
  637. package/stack-template/app/ui-kit/src/ui/tabs/tabs.test.tsx +77 -0
  638. package/stack-template/app/ui-kit/src/ui/tag/index.tsx +68 -0
  639. package/stack-template/app/ui-kit/src/ui/tag/tag.stories.tsx +88 -0
  640. package/stack-template/app/ui-kit/src/ui/tag/tag.test.tsx +126 -0
  641. package/stack-template/app/ui-kit/src/ui/team/debt-board/debt-board.stories.tsx +52 -0
  642. package/stack-template/app/ui-kit/src/ui/team/debt-board/debt-board.test.tsx +72 -0
  643. package/stack-template/app/ui-kit/src/ui/team/debt-board/index.tsx +125 -0
  644. package/stack-template/app/ui-kit/src/ui/team/inbox-thread/inbox-thread.stories.tsx +70 -0
  645. package/stack-template/app/ui-kit/src/ui/team/inbox-thread/inbox-thread.test.tsx +56 -0
  646. package/stack-template/app/ui-kit/src/ui/team/inbox-thread/index.tsx +107 -0
  647. package/stack-template/app/ui-kit/src/ui/team/ping-feed/index.tsx +102 -0
  648. package/stack-template/app/ui-kit/src/ui/team/ping-feed/ping-feed.stories.tsx +57 -0
  649. package/stack-template/app/ui-kit/src/ui/team/ping-feed/ping-feed.test.tsx +60 -0
  650. package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/index.tsx +60 -0
  651. package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/stage-pipeline.stories.tsx +68 -0
  652. package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/stage-pipeline.test.tsx +50 -0
  653. package/stack-template/app/ui-kit/src/ui/team/team-dashboard/index.tsx +103 -0
  654. package/stack-template/app/ui-kit/src/ui/team/team-dashboard/team-dashboard.stories.tsx +72 -0
  655. package/stack-template/app/ui-kit/src/ui/team/team-dashboard/team-dashboard.test.tsx +72 -0
  656. package/stack-template/app/ui-kit/src/ui/time-picker/index.tsx +143 -0
  657. package/stack-template/app/ui-kit/src/ui/time-picker/time-picker.stories.tsx +90 -0
  658. package/stack-template/app/ui-kit/src/ui/time-picker/time-picker.test.tsx +64 -0
  659. package/stack-template/app/ui-kit/src/ui/timeline/index.tsx +91 -0
  660. package/stack-template/app/ui-kit/src/ui/timeline/timeline.stories.tsx +209 -0
  661. package/stack-template/app/ui-kit/src/ui/timeline/timeline.test.tsx +116 -0
  662. package/stack-template/app/ui-kit/src/ui/timesheet/index.tsx +277 -0
  663. package/stack-template/app/ui-kit/src/ui/timesheet/timesheet.stories.tsx +97 -0
  664. package/stack-template/app/ui-kit/src/ui/timesheet/timesheet.test.tsx +103 -0
  665. package/stack-template/app/ui-kit/src/ui/toggle-button/index.tsx +28 -0
  666. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.stories.tsx +85 -0
  667. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.test.tsx +97 -0
  668. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.tsx +81 -0
  669. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button.stories.tsx +46 -0
  670. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button.test.tsx +38 -0
  671. package/stack-template/app/ui-kit/src/ui/toolbar/index.tsx +18 -0
  672. package/stack-template/app/ui-kit/src/ui/toolbar/toolbar.stories.tsx +35 -0
  673. package/stack-template/app/ui-kit/src/ui/toolbar/toolbar.test.tsx +11 -0
  674. package/stack-template/app/ui-kit/src/ui/tooltip/index.tsx +61 -0
  675. package/stack-template/app/ui-kit/src/ui/tooltip/tooltip.stories.tsx +81 -0
  676. package/stack-template/app/ui-kit/src/ui/tooltip/tooltip.test.tsx +120 -0
  677. package/stack-template/app/ui-kit/src/ui/tour/index.tsx +210 -0
  678. package/stack-template/app/ui-kit/src/ui/tour/tour.stories.tsx +153 -0
  679. package/stack-template/app/ui-kit/src/ui/tour/tour.test.tsx +131 -0
  680. package/stack-template/app/ui-kit/src/ui/transition/index.tsx +377 -0
  681. package/stack-template/app/ui-kit/src/ui/transition/transition.stories.tsx +254 -0
  682. package/stack-template/app/ui-kit/src/ui/transition/transition.test.tsx +285 -0
  683. package/stack-template/app/ui-kit/src/ui/tree/index.tsx +68 -0
  684. package/stack-template/app/ui-kit/src/ui/tree/tree.stories.tsx +139 -0
  685. package/stack-template/app/ui-kit/src/ui/tree/tree.test.tsx +77 -0
  686. package/stack-template/app/ui-kit/src/ui/tree-select/index.tsx +251 -0
  687. package/stack-template/app/ui-kit/src/ui/tree-select/tree-select.stories.tsx +105 -0
  688. package/stack-template/app/ui-kit/src/ui/tree-select/tree-select.test.tsx +174 -0
  689. package/stack-template/app/ui-kit/src/ui/tree-table/index.tsx +229 -0
  690. package/stack-template/app/ui-kit/src/ui/tree-table/tree-table.stories.tsx +111 -0
  691. package/stack-template/app/ui-kit/src/ui/tree-table/tree-table.test.tsx +137 -0
  692. package/stack-template/app/ui-kit/src/ui/typography/index.tsx +124 -0
  693. package/stack-template/app/ui-kit/src/ui/typography/typography.stories.tsx +65 -0
  694. package/stack-template/app/ui-kit/src/ui/typography/typography.test.tsx +117 -0
  695. package/stack-template/app/ui-kit/src/ui/upload/index.tsx +39 -0
  696. package/stack-template/app/ui-kit/src/ui/upload/upload-core.tsx +204 -0
  697. package/stack-template/app/ui-kit/src/ui/upload/upload-dropzone.tsx +79 -0
  698. package/stack-template/app/ui-kit/src/ui/upload/upload.stories.tsx +67 -0
  699. package/stack-template/app/ui-kit/src/ui/upload/upload.test.tsx +204 -0
  700. package/stack-template/app/ui-kit/src/ui/virtual-scroll/index.tsx +86 -0
  701. package/stack-template/app/ui-kit/src/ui/virtual-scroll/virtual-scroll.stories.tsx +111 -0
  702. package/stack-template/app/ui-kit/src/ui/virtual-scroll/virtual-scroll.test.tsx +125 -0
  703. package/stack-template/app/ui-kit/src/ui/watermark/index.tsx +182 -0
  704. package/stack-template/app/ui-kit/src/ui/watermark/watermark.stories.tsx +96 -0
  705. package/stack-template/app/ui-kit/src/ui/watermark/watermark.test.tsx +120 -0
  706. package/stack-template/app/ui-kit/src/utils/array.test.ts +88 -0
  707. package/stack-template/app/ui-kit/src/utils/array.ts +51 -0
  708. package/stack-template/app/ui-kit/src/utils/dom.test.tsx +69 -0
  709. package/stack-template/app/ui-kit/src/utils/dom.ts +38 -0
  710. package/stack-template/app/ui-kit/src/utils/format.test.ts +63 -0
  711. package/stack-template/app/ui-kit/src/utils/format.ts +81 -0
  712. package/stack-template/app/ui-kit/tests/setup.ts +15 -0
  713. package/stack-template/app/ui-kit/tsconfig.json +18 -0
  714. package/stack-template/app/ui-kit/tsup.config.ts +37 -0
  715. package/stack-template/app/ui-kit/vercel.json +6 -0
  716. package/stack-template/app/ui-kit/vitest.config.ts +22 -0
  717. package/stack-template/contracts/auth/token-contract.md +119 -0
  718. package/stack-template/contracts/auth/users.json +35 -0
  719. package/stack-template/contracts/db/tasks-schema.sql +62 -0
  720. package/stack-template/contracts/events/fixtures/task.assigned.json +11 -0
  721. package/stack-template/contracts/events/fixtures/task.assignment_failed.json +11 -0
  722. package/stack-template/contracts/events/fixtures/task.created.json +12 -0
  723. package/stack-template/contracts/events/fixtures/task.deleted.json +10 -0
  724. package/stack-template/contracts/events/fixtures/task.updated.json +12 -0
  725. package/stack-template/contracts/events/task-events.md +80 -0
  726. package/stack-template/contracts/openapi/activity.yaml +196 -0
  727. package/stack-template/contracts/openapi/auth.yaml +310 -0
  728. package/stack-template/contracts/openapi/tasks.yaml +316 -0
  729. package/stack-template/contracts/openapi/users.yaml +345 -0
  730. package/stack-template/docs/adr/0001-mixed-stack.md +14 -0
  731. package/stack-template/docs/adr/0002-mf-rspack.md +14 -0
  732. package/stack-template/docs/adr/0003-contract-first.md +14 -0
  733. package/stack-template/docs/adr/0004-readonly-schema-tradeoff.md +14 -0
  734. package/stack-template/docs/adr/0005-fail-closed.md +14 -0
  735. package/stack-template/docs/adr/0006-fire-and-forget-events.md +14 -0
  736. package/stack-template/docs/adr/0007-fork-not-upgrade.md +14 -0
  737. package/stack-template/docs/adr/0008-kafka-outbox-saga.md +24 -0
  738. package/stack-template/docs/adr/0009-ui-kit-split.md +39 -0
  739. package/stack-template/docs/adr/README.md +15 -0
  740. package/stack-template/docs/ai/recipes.md +956 -0
  741. package/stack-template/docs/ai/table-Theming.md +25 -0
  742. package/stack-template/docs/ai/table-datadisplay-mz.md +20 -0
  743. package/stack-template/docs/ai/table-feedback.md +20 -0
  744. package/stack-template/docs/ai/table-forms.md +26 -0
  745. package/stack-template/docs/git-flow.md +70 -0
  746. package/stack-template/docs/parity-matrix.md +102 -0
  747. package/stack-template/docs/superpowers/contexts/auth-real/gap-answer.md +195 -0
  748. package/stack-template/docs/superpowers/contexts/auth-real/sf-1.md +21 -0
  749. package/stack-template/docs/superpowers/contexts/auth-real/sf-2.md +21 -0
  750. package/stack-template/docs/superpowers/contexts/auth-real/sf-3.md +17 -0
  751. package/stack-template/docs/superpowers/contexts/auth-real/sf-4.md +20 -0
  752. package/stack-template/docs/superpowers/contexts/auth-real/sf-5.md +21 -0
  753. package/stack-template/docs/superpowers/contexts/experience-design.md +85 -0
  754. package/stack-template/docs/superpowers/contexts/sf-1.md +39 -0
  755. package/stack-template/docs/superpowers/contexts/sf-2.md +42 -0
  756. package/stack-template/docs/superpowers/contexts/sf-3.md +42 -0
  757. package/stack-template/docs/superpowers/contexts/sf-4.md +26 -0
  758. package/stack-template/docs/superpowers/contexts/sf-5.md +36 -0
  759. package/stack-template/docs/superpowers/contexts/sf-6.md +36 -0
  760. package/stack-template/docs/superpowers/contexts/sf-7.md +35 -0
  761. package/stack-template/docs/superpowers/contexts/sf-cin-overview.md +21 -0
  762. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-1.md +46 -0
  763. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-2.md +44 -0
  764. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-3.md +47 -0
  765. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-4.md +44 -0
  766. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-5.md +36 -0
  767. package/stack-template/docs/superpowers/designs/direction-approved.md +11 -0
  768. package/stack-template/docs/superpowers/designs/ui-redesign/drafts/a-roulette-soundviz.html +353 -0
  769. package/stack-template/docs/superpowers/designs/ui-redesign/drafts/b-reference.html +347 -0
  770. package/stack-template/docs/superpowers/designs/ui-redesign/drafts/c-designer.html +375 -0
  771. package/stack-template/docs/superpowers/designs/ui-redesign/ds-demo.html +140 -0
  772. package/stack-template/docs/superpowers/designs/ui-redesign-direction.md +93 -0
  773. package/stack-template/docs/superpowers/improvements-log.md +158 -0
  774. package/stack-template/docs/superpowers/mindmaps/auth-real.wakii +115 -0
  775. package/stack-template/docs/superpowers/mindmaps/kafka-outbox-saga.wakii +110 -0
  776. package/stack-template/docs/superpowers/mindmaps/micro-boilerplate.wakii +171 -0
  777. package/stack-template/docs/superpowers/mindmaps/ui-redesign.wakii +116 -0
  778. package/stack-template/docs/superpowers/mindmaps/vu53-cinematic-experience.wakii +32 -0
  779. package/stack-template/docs/superpowers/plans/2026-10-12-sf-1-contracts-platform-plan.md +44 -0
  780. package/stack-template/docs/superpowers/plans/2026-10-12-sf-3-spring-svc-impact.md +69 -0
  781. package/stack-template/docs/superpowers/plans/2026-10-12-sf-3-spring-svc-plan.md +27 -0
  782. package/stack-template/docs/superpowers/plans/2026-10-12-sf-4-go-svc-plan.md +99 -0
  783. package/stack-template/docs/superpowers/plans/2026-10-12-sf-5-fe-shell-plan.md +64 -0
  784. package/stack-template/docs/superpowers/plans/2026-10-12-sf-6-fe-remotes-plan.md +83 -0
  785. package/stack-template/docs/superpowers/plans/2026-10-12-sf-7-convergence-plan.md +59 -0
  786. package/stack-template/docs/superpowers/plans/2026-10-12-sf2-node-svc-plan.md +19 -0
  787. package/stack-template/docs/superpowers/plans/2026-10-13-sf-1-kafka-foundation-plan.md +30 -0
  788. package/stack-template/docs/superpowers/plans/2026-10-13-sf-1-ui-redesign-plan.md +28 -0
  789. package/stack-template/docs/superpowers/plans/2026-10-13-sf-2-node-outbox-plan.md +46 -0
  790. package/stack-template/docs/superpowers/plans/2026-10-13-sf-3-go-consumer-plan.md +31 -0
  791. package/stack-template/docs/superpowers/plans/2026-10-13-sf-4-spring-tx-plan.md +96 -0
  792. package/stack-template/docs/superpowers/plans/2026-10-13-sf-5-convergence-plan.md +21 -0
  793. package/stack-template/docs/superpowers/plans/2026-10-14-sf-2-ui-redesign-plan.md +32 -0
  794. package/stack-template/docs/superpowers/plans/2026-10-14-sf-3-ui-redesign-plan.md +34 -0
  795. package/stack-template/docs/superpowers/plans/2026-10-14-sf-5-ui-redesign-plan.md +35 -0
  796. package/stack-template/docs/superpowers/plans/2026-10-17-auth-real-plan.md +112 -0
  797. package/stack-template/docs/superpowers/plans/2026-10-17-ui-kit-split-plan.md +18 -0
  798. package/stack-template/docs/superpowers/reviews/2026-10-18-data-display-coverage.md +52 -0
  799. package/stack-template/docs/superpowers/reviews/code-reviewer-sf-5-r1.md +65 -0
  800. package/stack-template/docs/superpowers/reviews/security-audit-sf-5-auth-real.md +39 -0
  801. package/stack-template/docs/superpowers/specs/2026-10-12-boilerplate-microservice-mfe.md +110 -0
  802. package/stack-template/docs/superpowers/specs/2026-10-12-sf-3-spring-svc-design.md +160 -0
  803. package/stack-template/docs/superpowers/specs/2026-10-12-sf-7-convergence-spec.md +114 -0
  804. package/stack-template/docs/superpowers/specs/2026-10-12-sf2-node-svc-spec.md +42 -0
  805. package/stack-template/docs/superpowers/specs/2026-10-13-kafka-outbox-saga.md +111 -0
  806. package/stack-template/docs/superpowers/specs/2026-10-13-ui-redesign.md +173 -0
  807. package/stack-template/docs/superpowers/specs/2026-10-14-sf-3-ui-redesign.md +46 -0
  808. package/stack-template/docs/superpowers/specs/2026-10-14-sf-5-ui-redesign.md +30 -0
  809. package/stack-template/docs/superpowers/specs/2026-10-17-antd-look-tokens.md +28 -0
  810. package/stack-template/docs/superpowers/specs/2026-10-17-auth-real-design.md +124 -0
  811. package/stack-template/docs/superpowers/specs/2026-10-17-tailwind-migration.md +32 -0
  812. package/stack-template/docs/superpowers/specs/2026-10-17-ui-kit-split.md +44 -0
  813. package/stack-template/docs/superpowers/specs/2026-10-18-0.3.0-release-notes.md +77 -0
  814. package/stack-template/docs/toolchain.md +28 -0
  815. package/stack-template/docs/wakii-playbook.md +172 -0
  816. package/stack-template/docs/walkthrough.md +204 -0
  817. package/stack-template/orca.yaml +146 -0
  818. package/stack-template/package.json +19 -0
  819. package/stack-template/platform/.env.example +72 -0
  820. package/stack-template/platform/conventions/01-dockerfile-pattern.md +78 -0
  821. package/stack-template/platform/conventions/02-healthcheck.md +26 -0
  822. package/stack-template/platform/conventions/03-logging.md +41 -0
  823. package/stack-template/platform/conventions/04-error-envelope.md +41 -0
  824. package/stack-template/platform/conventions/05-ports.md +38 -0
  825. package/stack-template/platform/conventions/06-configuration.md +25 -0
  826. package/stack-template/platform/conventions/07-cors.md +23 -0
  827. package/stack-template/platform/conventions/08-gateway-and-remotes.md +33 -0
  828. package/stack-template/platform/conventions/09-async-messaging.md +42 -0
  829. package/stack-template/platform/conventions/README.md +15 -0
  830. package/stack-template/platform/docker-compose.yml +255 -0
  831. package/stack-template/platform/gateway/nginx/nginx.conf +137 -0
  832. package/stack-template/platform/postgres/init/01-init.sh +55 -0
  833. package/stack-template/pnpm-lock.yaml +15992 -0
  834. package/stack-template/pnpm-workspace.yaml +24 -0
  835. package/stack-template/scripts/scaffold/scaffold.sh +110 -0
  836. package/stack-template/scripts/smoke/e2e.sh +305 -0
  837. package/stack-template/scripts/snapshot-stack-template.sh +84 -0
  838. package/stack-template/services/auth-svc/.dockerignore +5 -0
  839. package/stack-template/services/auth-svc/Dockerfile +32 -0
  840. package/stack-template/services/auth-svc/README.md +101 -0
  841. package/stack-template/services/auth-svc/drizzle/0000_init.sql +25 -0
  842. package/stack-template/services/auth-svc/drizzle/meta/0000_snapshot.json +190 -0
  843. package/stack-template/services/auth-svc/drizzle/meta/_journal.json +13 -0
  844. package/stack-template/services/auth-svc/drizzle.config.ts +10 -0
  845. package/stack-template/services/auth-svc/package.json +35 -0
  846. package/stack-template/services/auth-svc/pnpm-lock.yaml +2425 -0
  847. package/stack-template/services/auth-svc/src/app.test.ts +403 -0
  848. package/stack-template/services/auth-svc/src/app.ts +103 -0
  849. package/stack-template/services/auth-svc/src/auth-crypto.test.ts +32 -0
  850. package/stack-template/services/auth-svc/src/auth-crypto.ts +25 -0
  851. package/stack-template/services/auth-svc/src/db/client.ts +24 -0
  852. package/stack-template/services/auth-svc/src/db/migrate.ts +72 -0
  853. package/stack-template/services/auth-svc/src/db/schema.ts +39 -0
  854. package/stack-template/services/auth-svc/src/db/seed.ts +60 -0
  855. package/stack-template/services/auth-svc/src/env.test.ts +55 -0
  856. package/stack-template/services/auth-svc/src/env.ts +57 -0
  857. package/stack-template/services/auth-svc/src/logger.ts +31 -0
  858. package/stack-template/services/auth-svc/src/plugins/auth.ts +70 -0
  859. package/stack-template/services/auth-svc/src/repo.drizzle.integration.test.ts +182 -0
  860. package/stack-template/services/auth-svc/src/repo.drizzle.ts +144 -0
  861. package/stack-template/services/auth-svc/src/repo.test-support.ts +168 -0
  862. package/stack-template/services/auth-svc/src/repo.ts +60 -0
  863. package/stack-template/services/auth-svc/src/routes/auth.ts +193 -0
  864. package/stack-template/services/auth-svc/src/routes/health.ts +40 -0
  865. package/stack-template/services/auth-svc/src/server.ts +54 -0
  866. package/stack-template/services/auth-svc/tsconfig.json +20 -0
  867. package/stack-template/services/go-svc/.dockerignore +5 -0
  868. package/stack-template/services/go-svc/Dockerfile +19 -0
  869. package/stack-template/services/go-svc/README.md +93 -0
  870. package/stack-template/services/go-svc/cmd/server/main.go +105 -0
  871. package/stack-template/services/go-svc/go.mod +12 -0
  872. package/stack-template/services/go-svc/internal/api/auth.go +83 -0
  873. package/stack-template/services/go-svc/internal/api/auth_test.go +92 -0
  874. package/stack-template/services/go-svc/internal/api/envelope.go +61 -0
  875. package/stack-template/services/go-svc/internal/api/envelope_test.go +51 -0
  876. package/stack-template/services/go-svc/internal/api/fakes_test.go +105 -0
  877. package/stack-template/services/go-svc/internal/api/feed.go +98 -0
  878. package/stack-template/services/go-svc/internal/api/feed_test.go +118 -0
  879. package/stack-template/services/go-svc/internal/api/health.go +34 -0
  880. package/stack-template/services/go-svc/internal/api/health_test.go +46 -0
  881. package/stack-template/services/go-svc/internal/api/json.go +13 -0
  882. package/stack-template/services/go-svc/internal/api/middleware.go +82 -0
  883. package/stack-template/services/go-svc/internal/api/middleware_test.go +48 -0
  884. package/stack-template/services/go-svc/internal/api/openapi/activity.yaml +196 -0
  885. package/stack-template/services/go-svc/internal/api/openapi.go +29 -0
  886. package/stack-template/services/go-svc/internal/api/openapi_test.go +38 -0
  887. package/stack-template/services/go-svc/internal/api/router.go +86 -0
  888. package/stack-template/services/go-svc/internal/api/stats.go +63 -0
  889. package/stack-template/services/go-svc/internal/api/stats_test.go +83 -0
  890. package/stack-template/services/go-svc/internal/api/types.go +32 -0
  891. package/stack-template/services/go-svc/internal/apperr/apperr.go +9 -0
  892. package/stack-template/services/go-svc/internal/config/config.go +115 -0
  893. package/stack-template/services/go-svc/internal/config/config_test.go +92 -0
  894. package/stack-template/services/go-svc/internal/consumer/envelope.go +78 -0
  895. package/stack-template/services/go-svc/internal/consumer/envelope_test.go +154 -0
  896. package/stack-template/services/go-svc/internal/consumer/handler.go +91 -0
  897. package/stack-template/services/go-svc/internal/consumer/handler_test.go +136 -0
  898. package/stack-template/services/go-svc/internal/consumer/producer.go +117 -0
  899. package/stack-template/services/go-svc/internal/consumer/runner.go +194 -0
  900. package/stack-template/services/go-svc/internal/consumer/runner_test.go +351 -0
  901. package/stack-template/services/go-svc/internal/logging/logging.go +49 -0
  902. package/stack-template/services/go-svc/internal/model/model.go +37 -0
  903. package/stack-template/services/go-svc/internal/resolve/resolver.go +134 -0
  904. package/stack-template/services/go-svc/internal/resolve/resolver_test.go +82 -0
  905. package/stack-template/services/go-svc/internal/resolve/token.go +130 -0
  906. package/stack-template/services/go-svc/internal/resolve/token_test.go +151 -0
  907. package/stack-template/services/go-svc/internal/store/events.go +71 -0
  908. package/stack-template/services/go-svc/internal/store/migrate.go +90 -0
  909. package/stack-template/services/go-svc/internal/store/migrate_test.go +34 -0
  910. package/stack-template/services/go-svc/internal/store/migrations/0001_create_events.sql +20 -0
  911. package/stack-template/services/go-svc/internal/store/migrations/0002_widen_action_cascade.sql +14 -0
  912. package/stack-template/services/go-svc/internal/store/store.go +65 -0
  913. package/stack-template/services/go-svc/internal/store/tasks.go +109 -0
  914. package/stack-template/services/go-svc/internal/swagger/assets/LICENSE +202 -0
  915. package/stack-template/services/go-svc/internal/swagger/assets/NOTICE +2 -0
  916. package/stack-template/services/go-svc/internal/swagger/assets/favicon-16x16.png +0 -0
  917. package/stack-template/services/go-svc/internal/swagger/assets/favicon-32x32.png +0 -0
  918. package/stack-template/services/go-svc/internal/swagger/assets/swagger-ui-bundle.js +2 -0
  919. package/stack-template/services/go-svc/internal/swagger/assets/swagger-ui.css +3 -0
  920. package/stack-template/services/go-svc/internal/swagger/index.html +28 -0
  921. package/stack-template/services/go-svc/internal/swagger/swagger.go +38 -0
  922. package/stack-template/services/go-svc/test/integration/integration_test.go +523 -0
  923. package/stack-template/services/node-svc/.dockerignore +5 -0
  924. package/stack-template/services/node-svc/Dockerfile +27 -0
  925. package/stack-template/services/node-svc/README.md +155 -0
  926. package/stack-template/services/node-svc/drizzle/0000_init.sql +17 -0
  927. package/stack-template/services/node-svc/drizzle/0001_status-assignment-failed.sql +2 -0
  928. package/stack-template/services/node-svc/drizzle/0002_outbox-table.sql +7 -0
  929. package/stack-template/services/node-svc/drizzle/meta/0000_snapshot.json +136 -0
  930. package/stack-template/services/node-svc/drizzle/meta/0001_snapshot.json +136 -0
  931. package/stack-template/services/node-svc/drizzle/meta/0002_snapshot.json +180 -0
  932. package/stack-template/services/node-svc/drizzle/meta/_journal.json +27 -0
  933. package/stack-template/services/node-svc/drizzle.config.ts +10 -0
  934. package/stack-template/services/node-svc/package.json +39 -0
  935. package/stack-template/services/node-svc/pnpm-lock.yaml +2706 -0
  936. package/stack-template/services/node-svc/src/app.test.ts +611 -0
  937. package/stack-template/services/node-svc/src/app.ts +126 -0
  938. package/stack-template/services/node-svc/src/clients/spring.ts +53 -0
  939. package/stack-template/services/node-svc/src/compensation-consumer.test.ts +157 -0
  940. package/stack-template/services/node-svc/src/compensation-consumer.ts +170 -0
  941. package/stack-template/services/node-svc/src/db/client.ts +23 -0
  942. package/stack-template/services/node-svc/src/db/migrate.ts +63 -0
  943. package/stack-template/services/node-svc/src/db/schema-diff.test.ts +252 -0
  944. package/stack-template/services/node-svc/src/db/schema.ts +64 -0
  945. package/stack-template/services/node-svc/src/env.ts +52 -0
  946. package/stack-template/services/node-svc/src/logger.ts +18 -0
  947. package/stack-template/services/node-svc/src/outbox-relay.test.ts +141 -0
  948. package/stack-template/services/node-svc/src/outbox-relay.ts +182 -0
  949. package/stack-template/services/node-svc/src/plugins/auth.ts +76 -0
  950. package/stack-template/services/node-svc/src/repo.drizzle.test.ts +182 -0
  951. package/stack-template/services/node-svc/src/repo.drizzle.ts +158 -0
  952. package/stack-template/services/node-svc/src/repo.ts +73 -0
  953. package/stack-template/services/node-svc/src/routes/health.ts +42 -0
  954. package/stack-template/services/node-svc/src/routes/tasks.ts +287 -0
  955. package/stack-template/services/node-svc/src/server.ts +91 -0
  956. package/stack-template/services/node-svc/src/types/api.d.ts +391 -0
  957. package/stack-template/services/node-svc/src/types/log.ts +3 -0
  958. package/stack-template/services/node-svc/tsconfig.json +20 -0
  959. package/stack-template/services/spring-svc/.dockerignore +5 -0
  960. package/stack-template/services/spring-svc/.mvn/wrapper/maven-wrapper.properties +20 -0
  961. package/stack-template/services/spring-svc/Dockerfile +22 -0
  962. package/stack-template/services/spring-svc/README.md +121 -0
  963. package/stack-template/services/spring-svc/mvnw +332 -0
  964. package/stack-template/services/spring-svc/mvnw.cmd +206 -0
  965. package/stack-template/services/spring-svc/pom.xml +144 -0
  966. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/SpringSvcApplication.java +12 -0
  967. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/Team.java +64 -0
  968. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/TeamRepository.java +34 -0
  969. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/User.java +72 -0
  970. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/UserRepository.java +10 -0
  971. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/logging/LowercaseLevelJsonProvider.java +24 -0
  972. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/security/JwtAuthFilter.java +89 -0
  973. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/security/JwtVerifier.java +48 -0
  974. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/service/TeamService.java +84 -0
  975. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ApiError.java +15 -0
  976. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ApiException.java +37 -0
  977. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/DevCorsConfig.java +41 -0
  978. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ErrorEnvelope.java +27 -0
  979. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/GlobalExceptionHandler.java +90 -0
  980. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/HealthController.java +46 -0
  981. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ReadinessService.java +40 -0
  982. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/TeamController.java +79 -0
  983. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/UserController.java +187 -0
  984. package/stack-template/services/spring-svc/src/main/java/db/migration/V2__SeedUsers.java +66 -0
  985. package/stack-template/services/spring-svc/src/main/resources/application.yml +42 -0
  986. package/stack-template/services/spring-svc/src/main/resources/db/migration/V1__init.sql +24 -0
  987. package/stack-template/services/spring-svc/src/main/resources/logback-spring.xml +34 -0
  988. package/stack-template/services/spring-svc/src/main/resources/openapi/users.yaml +345 -0
  989. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/logging/LogShapeTest.java +39 -0
  990. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/security/JwtAuthFilterTest.java +106 -0
  991. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/seed/SeedMatchIntegrationTest.java +68 -0
  992. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/service/TeamServiceRollbackTest.java +122 -0
  993. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/DevCorsTest.java +45 -0
  994. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/HealthCheckTest.java +56 -0
  995. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/TeamApiTest.java +139 -0
  996. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/TestPingController.java +21 -0
  997. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/UserApiTest.java +182 -0
  998. package/stack-template/stack-manifest.json +285 -0
@@ -0,0 +1,204 @@
1
+ # Fresh-clone walkthrough — từ clone đến demo chạy được
2
+
3
+ Checklist cho người MỚI copy boilerplate. Mọi lệnh dưới đây là những gì đã chạy thật trong CI (evidence: `docs/superpowers/evidence/sf-5-convergence/test-run.txt` — convergence 10 services + e2e 2 chiều; các SF trước: `evidence/sf-*/`).
4
+
5
+ ## 0. Toolchain cần có
6
+
7
+ Đọc [toolchain.md](toolchain.md). Tóm tắt: Node 22 + pnpm 9 (corepack) + JDK 21 + Go 1.24 + bash/curl. Docker TÙY CHỌN (không có vẫn xong được — chọn đường A hoặc B bên dưới). LƯU Ý: saga demo (mục 4b) + DLQ cần Kafka → đường A (compose); đường B chỉ chạy happy path (`SMOKE_SAGA=0`).
8
+
9
+ ## 1. Clone + cài đặt
10
+
11
+ ```bash
12
+ git clone <repo> && cd <repo>
13
+ pnpm install --frozen-lockfile # FE workspace (app/*)
14
+ cd services/node-svc && pnpm install --frozen-lockfile --ignore-workspace && cd ../.. # node-svc standalone lockfile
15
+ cd services/auth-svc && pnpm install --frozen-lockfile --ignore-workspace && cd ../.. # auth-svc standalone lockfile
16
+ ```
17
+
18
+ ## 2. Postgres + seed
19
+
20
+ Cần Postgres 16 chạy sẵn với init script của platform (schemas + roles + readonly grants):
21
+
22
+ - **Có Docker (dễ nhất):** `cd platform && cp .env.example .env` (điền mật khẩu) → `docker compose up -d postgres` — init script `platform/postgres/init/01-init.sh` tự chạy lần đầu.
23
+ - **Không Docker:** cài/portable Postgres 16, `initdb` một data dir rồi chạy nội dung `platform/postgres/init/01-init.sh` tay (tạo db `boilerplate`, roles `node_svc`/`spring_svc`/`go_svc`/`go_readonly`/`auth_svc` với mật khẩu khớp .env, schemas + default privileges).
24
+
25
+ ## 3. Chọn đường chạy demo
26
+
27
+ ### Đường A — Compose (có Docker — khuyến nghị)
28
+
29
+ ```bash
30
+ cd platform
31
+ cp .env.example .env # điền JWT_SECRET (openssl rand -base64 48) + passwords
32
+ docker compose down -v # ⚠️ CHẠY 1 LẦN sau pull nếu máy có pgdata volume TỪ bản cũ:
33
+ # (1) Flyway V2 seed user svc-fail/svc-activity + (2) init script tạo
34
+ # schema `auth` + role `auth_svc` (auth-real SF-5) CHỈ chạy lúc volume
35
+ # MỚI — volume cũ thiếu → saga chết ở auth/validate, auth-svc chết ở
36
+ # DATABASE auth (healthcheck /readyz đỏ, gateway không lên được).
37
+ # ⚠️ `.env` tạo từ bản cũ: thêm `AUTH_SVC_DB_PASSWORD` (cp từ .env.example).
38
+ # Kafka KHÔNG có data volume — topics mất sau mỗi `down` → tạo tường minh
39
+ # TRƯỚC khi boot services (giống CI convergence.yml; tránh 2 race: go consumer
40
+ # kẹt empty-assignment khi subscribe trước topic + DLQ publish Unknown Topic):
41
+ docker compose up -d postgres kafka
42
+ until docker compose exec -T kafka /opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092 >/dev/null 2>&1; do sleep 2; done
43
+ for topic in task-events task-events.dlq; do
44
+ docker compose exec -T kafka /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 \
45
+ --create --if-not-exists --topic "$topic" --partitions 1 --replication-factor 1
46
+ done
47
+ docker compose up -d --build # health-gated chain tự đợi đúng thứ tự (10 services, kafka lazy-connect)
48
+ bash ../scripts/smoke/e2e.sh # từ platform/ — script ở repo root. PASS = 15 bước, 3 luồng:
49
+ # happy : login→task→feed QUA KAFKA (outbox → topic → go consumer)
50
+ # auth-real : register→refresh rotation→reuse→401→logout + RBAC (user DELETE 403, alice 204)
51
+ # saga : assign svc-fail → task assignment_failed + event gốc ở task-events.dlq
52
+ # Mở browser: http://localhost:8080/ → login alice@demo.local / demo-password
53
+ # (hoặc tự register account mới — tab Register, mục 4a)
54
+ ```
55
+
56
+ ### Đường B — Native (không Docker — từng service một)
57
+
58
+ ```bash
59
+ # 4 service BE — mỗi lệnh 1 terminal, env theo .env.example (placeholder dev):
60
+ cd services/auth-svc && JWT_SECRET=<dev-secret> PORT=8090 \
61
+ DATABASE_URL="postgres://auth_svc:<pw>@localhost:5432/boilerplate" \
62
+ USERS_FIXTURE_PATH=$(pwd)/../../contracts/auth/users.json \
63
+ AUTH_DEV_PASSWORD=demo-password pnpm dev
64
+
65
+ cd services/spring-svc && SPRING_DATASOURCE_URL="jdbc:postgresql://localhost:5432/boilerplate" \
66
+ SPRING_DATASOURCE_USERNAME=spring_svc SPRING_DATASOURCE_PASSWORD=<pw> \
67
+ JWT_SECRET=<dev-secret> SERVER_PORT=8081 USERS_FIXTURE_PATH=$(pwd)/../../contracts/auth/users.json \
68
+ ./mvnw spring-boot:run # Windows: ./mvnw.cmd
69
+
70
+ cd services/node-svc && JWT_SECRET=<dev-secret> PORT=3001 \
71
+ DATABASE_URL="postgres://node_svc:<pw>@localhost:5432/boilerplate" \
72
+ SPRING_SVC_URL=http://localhost:8081 GO_SVC_URL=http://localhost:8082 pnpm dev
73
+
74
+ cd services/go-svc && JWT_SECRET=<dev-secret> PORT=8082 \
75
+ DATABASE_URL="postgres://go_svc:<pw>@localhost:5432/boilerplate" \
76
+ DATABASE_READONLY_URL="postgres://<owner-user>:<owner-pw>@localhost:5432/boilerplate" \
77
+ SPRING_SVC_URL=http://localhost:8081 go run ./cmd/server
78
+
79
+ # FE (3 terminal):
80
+ cd app/shell && pnpm dev # :3000
81
+ cd app/remotes/tasks && pnpm dev # :4001
82
+ cd app/remotes/activity && pnpm dev # :4002
83
+ ```
84
+
85
+ Native mode KHÔNG có nginx gateway — FE gọi thẳng service port theo conventions/07 (CORS dev đã mở). Chain 3 service "qua một cổng" là đặc tính của compose mode (đường A) + CI e2e-smoke job.
86
+
87
+ ### Verify chain bằng smoke script (cả hai đường)
88
+
89
+ Script gọi qua prefix `/api/<svc>` (giống gateway routing — conventions/08):
90
+ - Đường A (từ repo root, không cd platform): `bash scripts/smoke/e2e.sh` (mặc định `GATEWAY_URL=http://localhost:8080`). Mặc định chạy **2 chiều** — happy + saga kèm DLQ assert (cần docker để exec `kafka-console-consumer` trong container kafka).
91
+ - Đường B (native, không Kafka): `SMOKE_SAGA=0 bash scripts/smoke/e2e.sh` — happy + auth-real (bỏ saga + DLQ). Không có gateway thật — chứng minh chain bằng cách gọi service trực tiếp, hoặc dựng proxy mapping `/api/*` (SF-7 dùng mini Node proxy cục bộ khi verify native — KHÔNG commit vì chỉ phục vụ verify).
92
+
93
+ ## 4. Browser walkthrough (human gate — KHÔNG trong CI)
94
+
95
+ Trên máy có stack sống (đường A hoặc B + FE dev servers). UI theo light **antd-look** (decision 2026-10-17 — spec `docs/superpowers/specs/2026-10-17-antd-look-tokens.md`): nền canvas `#f5f5f5`, khối trắng `#ffffff`, 1 accent `#1677ff`, badge pill chấm-màu; dark (palette direction B cũ) là theme phụ qua `UiKitProvider` (`data-bp-theme`).
96
+
97
+ 1. Mở `http://localhost:8080/` (đường A) hoặc `http://localhost:3000/` (đường B) → thấy **dashboard chào** với quick links Tasks/Activity + box **TÀI KHOẢN DEMO** (`alice@demo.local / demo-password`, `fail@demo.local`). Login → nav phải hiện user chip (avatar + email) + nút **Đăng xuất**.
98
+ 2. Nav → **Tasks** (item nav active gạch accent): form **Tạo task** (Tiêu đề + Mô tả) → task mới xuất hiện đầu danh sách, heading **"Danh sách (x/total)"** cập nhật. Thử tiếp:
99
+ - **Sửa inline**: nút *Sửa* trên card → input inline tiêu đề/mô tả → *Lưu* (PATCH thật) / *Huỷ*.
100
+ - **Đổi status**: select trên card (`Cần làm` / `Đang làm` / `Xong`) — lúc PATCH đang bay item hiện spinner + select khoá (per-item busy).
101
+ - **Lọc**: chip `Tất cả` / `Cần làm` / `Đang làm` / `Xong` → danh sách + "x/total" lọc theo `?status=`.
102
+ - **Tải thêm**: nếu total > số đã tải, nút *Tải thêm* cuối danh sách nạp trang kế (limit/offset thật), "x/total" tăng dần tới đủ.
103
+ - **Xoá**: nút *Xoá* → xác nhận inline ("Xoá task này?" → *Xác nhận xoá* / *Huỷ*) — xoá thật qua DELETE.
104
+ - Mỗi card hiển thị assignee (UUID rút gọn monospace, hover thấy đủ), "Chưa gán" nếu trống, + createdAt vi-VN.
105
+ 3. Nav → **Activity**: **stats cards** (Tổng task / Cần làm / Đang làm / Xong / Sự kiện 24h qua) + **feed timeline nhóm theo ngày** phản ánh mọi thao tác ở bước 2 qua Kafka (outbox → `task-events` → go consumer): badge "đã tạo / đã cập nhật / đã giao / đã xoá" từng màu, tên task, time vi-VN. Nút *Làm mới* load lại.
106
+ 4. **Remote-down fallback**: dừng 1 remote rồi reload shell — đường A: `docker stop boilerplate-remote-tasks-1`; đường B: Ctrl-C dev server `:4001`. Shell vẫn nguyên (nav + user chip), slot Tasks hiện fallback "Không tải được phần **tasks**…" + nút **Thử lại**; **Activity vẫn chạy bình thường**. Khôi phục: khởi động lại remote (`docker start` / chạy lại `pnpm dev`) rồi nút *Thử lại* tải lại remote; nếu nút chưa ăn (MF runtime giữ rejection cũ) thì **reload trang** — remote sống lại mount bình thường.
107
+
108
+ ### 4a. Auth thật — register / refresh / logout-all 2 tab (epic auth-real)
109
+
110
+ 1. **Register**: mở `http://localhost:8080/` → tab **Register** trên login screen → email mới + password (8–72 ký tự) + tên hiển thị → tạo xong là đăng nhập luôn (roles `["user"]`). Đăng xuất → đăng nhập lại bằng account vừa tạo ✓.
111
+ 2. **Refresh rotation (2 tab)**: đăng nhập cùng account ở 2 tab. Tab 1 đứng yên đến khi access token hết hạn (30m) — request kế tab 1 tự refresh (rotate) rồi retry, KHÔNG bị văng về login. (Nhạy hơn: `POST /api/auth/refresh` tay bằng refreshToken trong `localStorage['bp.rt']` — response trả cặp mới, token cũ không dùng lại được.)
112
+ 3. **Logout-all (chuẩn acceptance — 1 tab chết, 1 tab còn)**: tab 2 bấm **Đăng xuất** (chỉ revoke refresh của tab đó — tab 1 VẪN sống vì access token 30m còn hạn). Để chết HẾT tab: gọi logout-all (chưa có nút UI — dùng token của account). P2 security-audit SF-5: đừng dán token thẳng vào lệnh (rơi shell history) — dùng `read -rs`:
113
+ ```bash
114
+ read -rs TOKEN # dán access token rồi Enter (không echo)
115
+ curl -X POST http://localhost:8080/api/auth/logout-all -H "Authorization: Bearer $TOKEN"
116
+ unset TOKEN
117
+ ```
118
+ Quay lại tab 1, bấm bất kỳ thao tác gọi API kế tiếp → 401 → auto-refresh fail (token bị revoke-all) → về màn login. Đó là hành vi ĐÚNG (không cross-tab realtime — kiểm ở request kế).
119
+ 4. **RBAC demo**: login `bob@demo.local` / `demo-password` (roles `["user"]`) → tạo task → nút **Xoá** → bị chặn (403 FORBIDDEN — hiện thông báo lỗi, task còn nguyên). Login `alice@demo.local` (roles `["admin"]`) → xoá cùng task → thành công. e2e assert cùng chuỗi (bước 11–12).
120
+
121
+ ### 4b. Saga demo (story FI-76 — cần đường A, có Kafka)
122
+
123
+ 1. Trong **Tasks**, tạo task (vd `saga-demo`) rồi gán cho user fixture fail: **`fail@demo.local`** — UI hiển thị assignee ở chế độ read-only (UUID rút gọn), việc gán đi qua API: `PATCH /api/tasks/{id}` với `assigneeId=55555555-5555-4555-8555-555555555555` (swagger `:8080/api/tasks/docs` hoặc curl với Bearer token).
124
+ 2. Go consumer cố tình fail ×3 (simulate hook — assignee trùng svc-fail) → publish compensating event `task.assignment_failed` vào topic chung → node compensation consumer cập nhật status.
125
+ 3. Quan sát trên **Tasks**: task chuyển badge **"Gán thất bại"** (pill đỏ chấm đỏ — nhận diện rõ; task ở trạng thái này không còn select status — system-owned). Event gốc (task.assigned) nằm ở `task-events.dlq`:
126
+ ```bash
127
+ docker compose -f platform/docker-compose.yml --env-file platform/.env.example exec -T kafka \
128
+ /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 \
129
+ --topic task-events.dlq --from-beginning --timeout-ms 15000
130
+ # mỗi dòng = 1 DLQ message: {"schemaVersion":1,"originalEvent":"{...task.assigned...}","error":{"reason":...,"retries":3,...}}
131
+ ```
132
+ 4. **Recovery**: re-assign cho user hợp lệ (bob, id `22222222-2222-4222-8222-222222222222`) → saga chạy lại từ đầu (bob ≠ svc-fail, go handler xử lý thường). LƯU Ý: `assignment_failed` là system-owned — re-assign KHÔNG tự reset status (repo `update()` chỉ set field trong patch); muốn đưa task về luồng hiển thị bình thường, PATCH tường minh `{"assigneeId":"<bob-id>","status":"todo"}` (status writable 3 giá trị — `assignment_failed` PATCH cấm). Trên UI task có lại badge "Cần làm" + select status.
133
+
134
+ > ℹ️ BUG-1 standalone prod trắng trang (report VU-53, 2026-10-14) **ĐÃ FIX** (sf-5b): shared `eager:true` + entry `standalone` static + nginx alias `/remotes/<name>/` — standalone :4001/:4002 render đầy đủ ở build prod. Evidence: `docs/superpowers/evidence/sf-5b-ui-redesign-fix/` (browser walkthrough + phantom-grep trước/sau).
135
+
136
+ > ℹ️ Job `convergence/e2e-smoke` (GitHub Actions) mô tả chuỗi saga assert status + DLQ bằng `kafka-console-consumer` (không cần browser) — **hiện workflow ĐANG DISABLE (billing, xem CLAUDE.md)**; gate khi push là `.husky/pre-push` (chỉ FE checks, không chạy e2e). Cần verify saga thì chạy tay: `bash scripts/smoke/e2e.sh` (mục "Verify chain bằng smoke script" trên).
137
+
138
+ ### 4c. Storybook — design system sống (Templates + 129 titles)
139
+
140
+ UI của shell/remotes build từ `@wakii/ui-kit` — xem toàn bộ + thử template ghép sẵn:
141
+
142
+ ```bash
143
+ pnpm --filter @wakii/ui-kit storybook # → http://localhost:6006 (script tự stamp version)
144
+ ```
145
+
146
+ Số liệu thật (index Storybook 2026-10-18): **129 titles · 623 story exports**, trong đó
147
+ nhóm **Templates** — 6 template "trang thật" (controlled state sống, không phải mock render):
148
+
149
+ | Template | Story path (`?path=/story/…`) | Ghép từ |
150
+ |----------|-------------------------------|---------|
151
+ | Dashboard admin | `templates-dashboard--dashboard` | `Layout` (Sider+Header) + Row/Col + Card/Statistic + Table + Timeline + Chart |
152
+ | Kanban project | `templates-kanban-project--project-board` | `KanbanBoard` (4 cột + WIP limit) + Segmented/Input.Search/Select filter + `Timesheet` + `message` toast khi move |
153
+ | CRUD table | `templates-crud-table--full-demo` | `Table` (sort 3-state/selection/expandable/fixed header/summary) + `Drawer` form (useForm+zod) + `Popconfirm` + `message` |
154
+ | Auth | `templates-auth--sign-in` · `--sign-up` · `--split-layout` | `useForm` + zod + Field/Input/Button + `Layout` split |
155
+ | Landing | `templates-landing--landing-alive` | `Parallax` + `Reveal` + `CountUp`/`Statistic` + `Grid` |
156
+ | Settings | `templates-settings--settings` | `Tabs` + `Switch` + `Field` + live theme toggle |
157
+
158
+ Mẹo: toolbar Storybook có **toggle dark** (`data-bp-theme` trên body preview — mọi component
159
+ theo token nên cả index đổi theme 1 click). AI agents đọc [AGENTS.md](../AGENTS.md) +
160
+ [docs/ai/recipes.md](ai/recipes.md) — bản đồ khi-dùng + 12 recipe copy-chạy. Chi tiết
161
+ Templates: `app/ui-kit/README.md` § Templates.
162
+
163
+ ## 5. Copy/scaffold project mới
164
+
165
+ ```bash
166
+ bash scripts/scaffold/scaffold.sh my-project
167
+ cd my-project
168
+ pnpm install --no-frozen-lockfile # lần đầu non-frozen — xem SCAFFOLD.md
169
+ # rồi lặp lại mục 2-4 trong project mới
170
+ ```
171
+
172
+ Phát triển tiếp project mới theo story workflow (Wakii): xem [wakii-playbook.md](wakii-playbook.md) — decision tree story/single/fix + 4 archetype chia SF + gates.
173
+
174
+ ## 6. CI báo gì
175
+
176
+ | Workflow | Chạy khi | Bằng chứng |
177
+ |----------|---------|-----------|
178
+ | `contracts` | contracts/**, platform/** đổi | spectral + gitleaks + compose config + boot-smoke auth-svc + schemathesis FULL (auth.yaml v2) |
179
+ | `services-*` / `shell` / `remotes-*` | thư mục tương ứng đổi | build + test + docker build + boot-smoke (node/go có kafka boot-smoke) |
180
+ | `convergence` (SF-5, story FI-76) | mọi push | e2e 2 chiều trên compose 10 services (happy qua Kafka + saga → `assignment_failed` + DLQ assert) + copy-dir standalone + scaffold output build được |
181
+
182
+ ## 7. Hành trình team — app-fit 4 apps + tài liệu nội bộ (2026-10-18)
183
+
184
+ **App-fit**: 4 app FE đã migrate hết sang `@wakii/ui-kit` (tokens + components qua source):
185
+
186
+ | App | Đã fit |
187
+ |-----|--------|
188
+ | `app/shell` (MF host :3000) | layout + nav + tokens từ phiên trước |
189
+ | `app/remotes/tasks` (:4001) | `TaskForm`/`TaskItem` chuyển `useForm` + zod + `Field`/`Input`/`Textarea` (+`useFieldArray` sẵn trong kit), `TaskList` giữ contract (EmptyState ở page level) |
190
+ | `app/remotes/activity` (:4002) | `ActivityPage` + `StatTile` → `Card`/`Statistic` ui-kit |
191
+ | `app/admin` | dashboard layout `Grid`/`Card`/`Statistic` giữ stat-intent |
192
+
193
+ **Templates**: 6 trang mẫu ghép sẵn trong Storybook (bảng §4) — copy điểm khởi đầu cho
194
+ trang thật; recipes kèm tại [docs/ai/recipes.md](ai/recipes.md).
195
+
196
+ **Hướng tới 0.3.0**: megagate 32 commits (241416f..HEAD) đã gate xanh — release notes
197
+ draft soạn sẵn tại [`docs/superpowers/specs/2026-10-18-0.3.0-release-notes.md`](superpowers/specs/2026-10-18-0.3.0-release-notes.md) — merge PR là chốt release
198
+ (ui-kit consumed qua source nên "release" = điểm merge, xem CHANGELOG head).
199
+
200
+ **Tài liệu nội bộ team (local-only, gitignored — không vào PR)**: `docs/team/` chứa
201
+ [RULES.md](team/RULES.md) (hiến phần vận hành: vai trò, vòng làm việc, thang tin cậy
202
+ T1→T3, sở hữu file), `TEAM.md` (roster + standup + report log), `DECISIONS.md`
203
+ (tiền-duyệt), `inbox/` (thư peer-to-peer), `CHANNEL.md`. Bản tóm tắt in-repo cho
204
+ session mới: [CLAUDE.md](../CLAUDE.md) § "Team protocol".
@@ -0,0 +1,146 @@
1
+ # orca.yaml — descriptor MÁY ĐỌC cho AI agent (Claude Code / Orca agents / Codex…).
2
+ # ⚠️ Orca CLI KHÔNG consume file này — nó là bản đồ repo dạng structured cho agent
3
+ # parse khi onboard. Văn bản cho người/xét nghiệm: CLAUDE.md + docs/walkthrough.md.
4
+ # Quy ước: sửa file này CÙNG commit với mọi thay đổi nó mô tả (port, lệnh, path) —
5
+ # drift giữa descriptor và thực tế = lỗi onboarding agent (tương tự quy tắc 4 chỗ
6
+ # của port table — platform/conventions/05-ports.md).
7
+ name: architecture-overview
8
+ description: >
9
+ Boilerplate nội bộ copy-able (epic FI-62): mixed-stack services
10
+ (Node/Spring/Go) + Module Federation FE (Rspack), demo e2e task management
11
+ qua nginx gateway, Docker Compose + CI. Scaffold project mới:
12
+ bash scripts/scaffold/scaffold.sh <tên-mới>
13
+
14
+ stack:
15
+ node: ">=22"
16
+ pnpm: ">=9" # corepack enable — root packageManager pin 9.15.9
17
+ jdk: "21"
18
+ go: "1.24"
19
+ postgres: "16"
20
+ workspaces: pnpm workspace (root) NHƯNG node-svc + auth-svc có standalone lockfile (cài riêng, xem services.auth-svc.install)
21
+
22
+ # ── Contracts — SOURCE OF TRUTH. Sửa contract TRƯỚC, code theo sau. ──────────
23
+ contracts:
24
+ openapi: [contracts/openapi/tasks.yaml, contracts/openapi/users.yaml, contracts/openapi/activity.yaml, contracts/openapi/auth.yaml]
25
+ ddl_canonical: contracts/db/tasks-schema.sql
26
+ events_contract: contracts/events/task-events.md
27
+ event_fixtures: contracts/events/fixtures/ # golden envelope — node/go test cùng nguồn
28
+ auth_users_fixture: contracts/auth/users.json # id UUID CỐ ĐỊNH — không đổi id user cũ
29
+ lint: pnpm lint:contracts # spectral
30
+
31
+ services:
32
+ gateway:
33
+ type: nginx
34
+ port: 8080
35
+ path: platform/gateway
36
+ note: CỔNG DUY NHẤT browser/FE chạm vào — routing /api/<svc>/* + presence-check JWT (401)
37
+ node-svc:
38
+ path: services/node-svc
39
+ port: 3001
40
+ tech: Fastify + TypeScript + Drizzle
41
+ install: cd services/node-svc && pnpm install --frozen-lockfile --ignore-workspace
42
+ dev: pnpm dev # tsx watch
43
+ build: pnpm build # tsc
44
+ test: pnpm test # vitest run
45
+ healthz: [/healthz, /readyz]
46
+ owns: schema tasks — CRUD + outbox relay + compensation consumer (Kafka)
47
+ spring-svc:
48
+ path: services/spring-svc
49
+ port: 8081
50
+ tech: Spring Boot 3 + Flyway
51
+ run: ./mvnw spring-boot:run
52
+ test: ./mvnw test
53
+ owns: schema users + teams (@Transactional demo)
54
+ go-svc:
55
+ path: services/go-svc
56
+ port: 8082
57
+ tech: Go 1.24 + chi
58
+ run: go run ./cmd/server
59
+ test: go test ./...
60
+ healthz: [/healthz, /readyz]
61
+ owns: schema activity (tự migrate) — feed/stats + Kafka consumer (idempotent, retry ×3 → DLQ + saga)
62
+ note: đọc-ONLY schema tasks qua role go_readonly; snapshot openapi nhúng phải bit-identical contract (CI drift-guard)
63
+ auth-svc:
64
+ path: services/auth-svc
65
+ port: 8090
66
+ tech: Fastify + TypeScript + Drizzle (auth thật — epic auth-real VU-59)
67
+ install: cd services/auth-svc && pnpm install --frozen-lockfile --ignore-workspace
68
+ dev: pnpm dev # tsx watch
69
+ build: pnpm build # tsc
70
+ test: pnpm test # vitest run
71
+ healthz: [/healthz, /readyz]
72
+ owns: schema auth (users + refresh_tokens — seed users.json GIỮ UUID) — register/login/refresh rotation CAS/reuse-detect/logout; claims roles = RBAC source
73
+ note: iss JWT PINNED "auth-mock" (token-contract.md — giá trị lịch sử, KHÔNG đổi theo tên service)
74
+
75
+ app:
76
+ shared:
77
+ path: app/shared
78
+ scope: "@wakii/fe-shared"
79
+ role: LOGIC (api-client/token-storage/error-envelope/mf-bootstrap) — consumed QUA SOURCE, không build
80
+ read_locked: # cấm sửa ngoài story/epic được duyệt — versions + contracts đã test thật
81
+ - src/api-client.ts
82
+ - src/token-storage.ts
83
+ - src/error-envelope.ts
84
+ - src/mf-bootstrap.ts
85
+ - package.json#mfToolkit
86
+ ui-kit:
87
+ path: app/ui-kit
88
+ scope: "@wakii/ui-kit"
89
+ role: DESIGN SYSTEM (tokens + base css + primitives + Storybook 9 dev-only) — consumed QUA SOURCE; KHÔNG read-locked (đổi qua story thường, evidence = build-storybook) — ADR-0009
90
+ shell:
91
+ path: app/shell
92
+ port: 3000
93
+ role: MF host (Rspack) — nav + login + RemoteSlot (error boundary + retry)
94
+ commands: {dev: pnpm dev, build: pnpm build, test: pnpm test, typecheck: pnpm typecheck}
95
+ remotes:
96
+ tasks: {path: app/remotes/tasks, port: 4001, gateway: /remotes/tasks/}
97
+ activity: {path: app/remotes/activity, port: 4002, gateway: /remotes/activity/}
98
+ note: standalone dev vẫn tự mang tokens (import tokens trong entry — quyết định epic VU-53 #5)
99
+ pins: # catalog: (pnpm-workspace.yaml) + mfToolkit — NÂNG CẤP PHẢI RE-SPIKE (app/spike)
100
+ react: 19.3.0
101
+ react-dom: 19.3.0
102
+ rspack: 1.7.12
103
+ module-federation-enhanced: 0.21.6
104
+
105
+ run:
106
+ compose: # đường A — khuyến nghị, full saga + DLQ
107
+ prep: |
108
+ cd platform && cp -n .env.example .env # điền JWT_SECRET + passwords
109
+ docker compose --env-file .env up -d postgres kafka
110
+ # đợi kafka healthy rồi tạo topic TRƯỚC khi boot services (race empty-assignment):
111
+ for topic in task-events task-events.dlq; do
112
+ docker compose --env-file .env exec -T kafka /opt/kafka/bin/kafka-topics.sh \
113
+ --bootstrap-server localhost:9092 --create --if-not-exists --topic "$topic" \
114
+ --partitions 1 --replication-factor 1
115
+ done
116
+ docker compose --env-file .env up -d --build # 10 services, health-gated chain
117
+ verify: bash scripts/smoke/e2e.sh # 2 chiều — happy + saga + DLQ assert
118
+ url: http://localhost:8080
119
+ native: docs/walkthrough.md # đường B — từng service, SMOKE_SAGA=0 cho smoke
120
+ demo_login: {user: alice@demo.local, password: demo-password}
121
+ saga_fail_user: fail@demo.local # assign cho user này → go fail ×3 → assignment_failed → DLQ
122
+
123
+ test_all: # full suite local — PASS hết trước khi claim done
124
+ - pnpm --filter shell test && pnpm --filter shell typecheck
125
+ - pnpm --filter node-svc test
126
+ - pnpm --filter auth-svc test
127
+ - cd services/go-svc && go test ./...
128
+ - cd services/spring-svc && ./mvnw test
129
+
130
+ docs:
131
+ start_here: docs/walkthrough.md # fresh-clone → demo chạy được
132
+ conventions: platform/conventions/ # 01–09 — BẮT BUỘC, không đúng = review fail
133
+ adr: docs/adr/ # 0001–0009 — quyết định kiến trúc đã chốt
134
+ toolchain: docs/toolchain.md
135
+ ci: .github/workflows/ # 10 workflows (HIỆN DISABLE — xem gotchas) — bảng mô tả ở CLAUDE.md
136
+ evidence: docs/superpowers/evidence/ # test-run + screenshots theo story
137
+
138
+ gotchas:
139
+ - "CI GitHub Actions ĐANG DISABLE (billing, 2026-10) — gate khi push là .husky/pre-push (branch rule + FE checks theo path); workflows trong .github/ chỉ còn giá trị tham khảo khi bật lại"
140
+ - "Vitest test ranh giới ngày: TZ pin qua test.env trong vitest.config — môi trường dev +07 che bug, đừng bỏ pin"
141
+ - "node-svc + auth-svc: standalone lockfile — pnpm install PHẢI --ignore-workspace, chạy TRONG thư mục service, không phải workspace root"
142
+ - "fe-shared standalone: khai catalog: → cần mini workspace (sed catalog block từ root pnpm-workspace.yaml) — mẫu ở .github/workflows/convergence.yml step copy-dir"
143
+ - "pgdata volume từ bản cũ thiếu user svc-fail/svc-activity (Flyway V2) + role auth_svc/schema auth (init script chỉ chạy volume mới — auth-real SF-5) → docker compose down -v 1 lần rồi up lại; .env bản cũ thêm AUTH_SVC_DB_PASSWORD từ .env.example"
144
+ - "assignment_failed là system-owned: re-assign KHÔNG tự reset status — PATCH tường minh {assigneeId, status:'todo'} (status writable: todo/in_progress/done)"
145
+ - "Inter-service call QUA TÊN COMPOSE (http://node-svc:3001), không localhost; .env không bao giờ commit"
146
+ - "Sửa port = 4 chỗ cùng commit: conventions/05-ports.md + .env.example + docker-compose.yml + README"
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "__STACK_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "Boilerplate microservice + micro-frontend — template nội bộ copy-able (epic FI-62)",
6
+ "packageManager": "pnpm@9.15.9",
7
+ "engines": {
8
+ "node": ">=22",
9
+ "pnpm": ">=9"
10
+ },
11
+ "scripts": {
12
+ "lint:contracts": "spectral lint contracts/openapi/*.yaml",
13
+ "prepare": "test -e .git && husky || true"
14
+ },
15
+ "devDependencies": {
16
+ "@stoplight/spectral-cli": "^6.17.0",
17
+ "husky": "^9.1.0"
18
+ }
19
+ }
@@ -0,0 +1,72 @@
1
+ # ============================================================================
2
+ # Env inventory ĐẦY ĐỦ — nguồn sự duy nhất về cấu hình compose + services.
3
+ # Cách dùng: cp .env.example .env rồi điền giá trị thật. .env KHÔNG commit.
4
+ # Quy tắc: thêm env var mới = thêm vào đây cùng commit (platform/conventions/06).
5
+ # ============================================================================
6
+
7
+ # --- Shared ---
8
+ # Secret ký + verify JWT HS256 (contracts/auth/token-contract.md). BẮT BUỘC đổi khi dùng.
9
+ # Sinh: openssl rand -base64 48
10
+ JWT_SECRET=change-me-openssl-rand-base64-48
11
+
12
+ # Log level mọi service: debug | info | warn | error
13
+ LOG_LEVEL=info
14
+
15
+ # --- Ports (platform/conventions/05-ports.md) ---
16
+ # ⚠️ Các biến *_PORT chỉ đổi port side HOST (truy cập từ máy dev); port TRONG
17
+ # mạng compose cố định theo bảng — container port hardcode trong compose.
18
+ GATEWAY_PORT=8080
19
+ SHELL_PORT=3000
20
+ REMOTE_TASKS_PORT=4001
21
+ REMOTE_ACTIVITY_PORT=4002
22
+ NODE_SVC_PORT=3001
23
+ SPRING_SVC_PORT=8081
24
+ GO_SVC_PORT=8082
25
+ AUTH_PORT=8090
26
+ POSTGRES_PORT=5432
27
+
28
+ # --- Postgres ---
29
+ POSTGRES_USER=boilerplate
30
+ POSTGRES_PASSWORD=change-me-postgres
31
+ POSTGRES_DB=boilerplate
32
+
33
+ # Password per-service DB role (tạo bởi platform/postgres/init/01-init.sh)
34
+ NODE_SVC_DB_PASSWORD=change-me-node
35
+ SPRING_SVC_DB_PASSWORD=change-me-spring
36
+ GO_SVC_DB_PASSWORD=change-me-go
37
+ GO_READONLY_DB_PASSWORD=change-me-goreadonly
38
+ AUTH_SVC_DB_PASSWORD=change-me-auth
39
+
40
+ # Password service user `svc-activity` (fixture users.json) — go-svc login
41
+ # auth lấy service token cho resolver (conventions/09). BẮT BUỘC khớp
42
+ # AUTH_DEV_PASSWORD (auth-svc so password hash của seeded users — token-contract.md §5).
43
+ SVC_ACTIVITY_PASSWORD=demo-password
44
+
45
+ # --- Kafka (conventions/09, ADR-0008) ---
46
+ # Bootstrap servers. Trong mạng compose = tên service `kafka:9092` (9092 KHÔNG
47
+ # expose ra host). Native dev ngoài compose override thành localhost:9092.
48
+ KAFKA_BROKERS=kafka:9092
49
+
50
+ # --- URLs inter-service (trong mạng compose dùng tên service) ---
51
+ NODE_SVC_URL=http://node-svc:3001
52
+ SPRING_SVC_URL=http://spring-svc:8081
53
+ GO_SVC_URL=http://go-svc:8082
54
+ # KEY giữ AUTH_MOCK_URL (go-svc đọc theo tên env này — gap-answer ④ epic VU-59);
55
+ # VALUE trỏ auth-svc (đổi KEY = follow-up cụm iss-rename).
56
+ AUTH_MOCK_URL=http://auth-svc:8090
57
+ SHELL_URL=http://shell:3000
58
+ REMOTE_TASKS_URL=http://remote-tasks:4001
59
+ REMOTE_ACTIVITY_URL=http://remote-activity:4002
60
+
61
+ # --- FE (dev, ngoài compose) ---
62
+ # Origin được phép CORS khi chạy native dev (platform/conventions/07-cors.md)
63
+ CORS_DEV_ORIGIN=http://localhost:3000,http://localhost:4001,http://localhost:4002
64
+
65
+ # --- auth (rename AUTH_MOCK_* → AUTH_* hoàn tất SF-5 VU-64 — compose đã swap) ---
66
+ # Dev password cho SEEDED fixture users (users.json — token-contract.md §5).
67
+ # Default demo-password KHÔNG ĐỔI: e2e + svc-activity + seed cùng một nguồn.
68
+ AUTH_DEV_PASSWORD=demo-password
69
+ # TTL access token JWT (auth-svc — token-contract.md §1)
70
+ ACCESS_TOKEN_TTL=30m
71
+ # Đường dẫn users fixture trong container
72
+ USERS_FIXTURE_PATH=/app/users.json
@@ -0,0 +1,78 @@
1
+ # 01 — Dockerfile multi-stage pattern
2
+
3
+ Mọi service dùng **2 stage**: `deps` (cài dependency, cache được) → `runtime` (copy artifact + prod deps, image mỏng). Không chạy build tool trong runtime image.
4
+
5
+ ## Node (Fastify/TS — node-svc, auth-svc)
6
+
7
+ ```dockerfile
8
+ # deps stage
9
+ FROM node:22-alpine AS deps
10
+ WORKDIR /app
11
+ COPY package.json pnpm-lock.yaml ./
12
+ RUN corepack enable && pnpm install --frozen-lockfile
13
+
14
+ # runtime stage
15
+ FROM node:22-alpine AS runtime
16
+ WORKDIR /app
17
+ ENV NODE_ENV=production
18
+ COPY --from=deps /app/node_modules ./node_modules
19
+ COPY dist ./dist
20
+ USER node
21
+ EXPOSE 3001
22
+ CMD ["node", "dist/server.js"]
23
+ ```
24
+
25
+ ## Spring Boot (spring-svc)
26
+
27
+ ```dockerfile
28
+ # deps stage — mvnw tải dependency vào layer cache riêng
29
+ FROM eclipse-temurin:21-jdk-alpine AS deps
30
+ WORKDIR /app
31
+ COPY .mvn .mvn
32
+ COPY mvnw pom.xml ./
33
+ RUN ./mvnw -B dependency:go-offline
34
+
35
+ # build stage
36
+ FROM deps AS build
37
+ COPY src src
38
+ RUN ./mvnw -B package -DskipTests
39
+
40
+ # runtime stage — JRE-only, jar fat
41
+ FROM eclipse-temurin:21-jre-alpine AS runtime
42
+ WORKDIR /app
43
+ COPY --from=build /app/target/*.jar app.jar
44
+ USER 1001
45
+ EXPOSE 8081
46
+ ENTRYPOINT ["java", "-jar", "app.jar"]
47
+ ```
48
+
49
+ ## Go (go-svc)
50
+
51
+ ```dockerfile
52
+ # build stage
53
+ FROM golang:1.24-alpine AS build
54
+ WORKDIR /src
55
+ COPY go.mod go.sum ./
56
+ RUN go mod download
57
+ COPY . .
58
+ RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /out/go-svc ./cmd/server
59
+
60
+ # runtime stage — static binary trên distroless
61
+ FROM gcr.io/distroless/static-debian12:nonroot AS runtime
62
+ COPY --from=build /out/go-svc /go-svc
63
+ EXPOSE 8082
64
+ ENTRYPOINT ["/go-svc"]
65
+ ```
66
+
67
+ ## Quy tắc
68
+
69
+ 1. **Pin base image theo digest hoặc minor tag cụ thể** — không `:latest`. SF-7 rà lại lần cuối.
70
+ 2. Image chạy **non-root** (`USER node` / `USER 1001` / distroless nonroot).
71
+ 3. `EXPOSE` = port của service theo [05-ports.md](05-ports.md).
72
+ 4. Healthcheck KHÔNG khai trong Dockerfile — khai trong `platform/docker-compose.yml` (một nguồn duy nhất).
73
+ 5. Thứ tự `COPY` tối ưu cache: lockfile/manifest trước, source sau.
74
+ 6. CI boot-smoke build đúng Dockerfile này — nếu build local pass mà CI fail, check `.dockerignore` trước (node_modules/target/bin không được vào context).
75
+ 7. **Lockfile variant cho workspace member (SF-7 sync — học từ SF-2, improvements-log):** service là member của pnpm workspace nhưng compose build context = **thư mục con** → root `pnpm-lock.yaml` KHÔNG vào được context. Hai cách chuẩn:
76
+ - **Local standalone lockfile** (precedent node-svc, auth-svc): commit `pnpm-lock.yaml` trong thư mục service (sinh bằng `pnpm install --ignore-workspace`), Dockerfile `COPY package.json pnpm-lock.yaml` + `pnpm install --frozen-lockfile`.
77
+ - **Repo-root build context** (precedent shell/remotes): Dockerfile khai `context: ..` + `dockerfile: app/<app>/Dockerfile` để root workspace lockfile + `app/shared` vào được context.
78
+ Đừng trộn: COPY root lockfile trong context thư mục con = build fail lúc deps stage.
@@ -0,0 +1,26 @@
1
+ # 02 — Healthcheck: `/healthz` + `/readyz`
2
+
3
+ Mọi HTTP service expose 2 endpoint không-auth (gateway không chặn, service không verify JWT trên 2 path này):
4
+
5
+ | Endpoint | Ý nghĩa | Trả về khi ổn | Trả về khi chưa ổn |
6
+ |----------|---------|---------------|--------------------|
7
+ | `/healthz` | **Liveness** — process sống | `200 {"status":"ok"}` | process chết → không response |
8
+ | `/readyz` | **Readiness** — nhận traffic được (deps xong) | `200 {"status":"ok"}` | `503` error envelope |
9
+
10
+ ## Điều kiện ready per service
11
+
12
+ | Service | `/readyz` = 200 khi |
13
+ |---------|---------------------|
14
+ | node-svc | DB migration chạy xong + spring-svc reachable (kiểm lúc boot, không ping liên tục) |
15
+ | spring-svc | Flyway migration xong + DataSource healthy |
16
+ | go-svc | Migration schema `activity` xong + SELECT thử được schema `tasks` (readonly role) |
17
+ | auth-svc | migration schema auth + seed fixture xong (/readyz kiểm DB thật — rule 2) |
18
+
19
+ ## Quy tắc
20
+
21
+ 1. Body JSON: `{"status":"ok"}` — không thêm trường (CI boot-smoke grep đúng shape này).
22
+ 2. `/readyz` phải kiểm tra **thật** (query DB thật), không hardcode 200.
23
+ 3. Compose `healthcheck` khai ở `platform/docker-compose.yml` probe **`/readyz`** (health-gated — SF-7). Ngoại lệ có chủ đích: **go-svc KHÔNG có healthcheck trong compose** — runtime distroless không có shell/wget, Dockerfile read-only với convergence (SF-7); readiness của go-svc được chứng minh bằng `scripts/smoke/e2e.sh` poll `/api/activity/stats` (compose `depends_on` go-svc ở mức `service_started`). Gateway cũng KHÔNG có healthcheck (nginx proxy thuần, không route `/readyz` — probe sẽ 404).
24
+ 4. CI boot-smoke job: container up → curl `/healthz` → curl `/readyz` → cả hai 200 mới pass.
25
+ 5. Path mounting: service mount **prefix `/api/<svc>`** cho business routes; `/healthz` + `/readyz` nằm **ngoài prefix** (naked path, ví dụ node-svc serve `/healthz` chứ không phải `/api/tasks/healthz`). Xem [08-gateway-and-remotes.md](08-gateway-and-remotes.md).
26
+ 6. **Mirror rule (SF-7, học từ SF-4 — improvements-log finding schemathesis 404):** service expose `/healthz` + `/readyz` **cả hai dạng** — naked path (cho compose healthcheck + CI boot-smoke) VÀ mirror dưới prefix `/api/<svc>/healthz` + `/api/<svc>/readyz` (cho OpenAPI spec khai dưới `servers.url` + schemathesis contract test). Áp cho MỌI service mới; auth-svc là precedent mới nhất (auth-mock cũ đã decommission — epic auth-real SF-5). Service không expose mirror = contract test fail 404 khi chạy qua base-url có prefix.
@@ -0,0 +1,41 @@
1
+ # 03 — JSON log shape chung
2
+
3
+ Mọi service log JSON một dòng mỗi entry ra **stdout** (12-factor; compose/CI collect). Không log ra file.
4
+
5
+ ## Shape
6
+
7
+ ```json
8
+ {
9
+ "ts": "2026-10-12T05:00:00.123Z",
10
+ "level": "info",
11
+ "service": "node-svc",
12
+ "msg": "task created",
13
+ "requestId": "b1c2...",
14
+ "taskId": "9f0e...",
15
+ "durationMs": 12
16
+ }
17
+ ```
18
+
19
+ | Trường | Bắt buộc | Ghi chú |
20
+ |--------|----------|---------|
21
+ | `ts` | ✓ | ISO 8601 UTC, độ chính xác ms |
22
+ | `level` | ✓ | `debug` \| `info` \| `warn` \| `error` |
23
+ | `service` | ✓ | `node-svc` \| `spring-svc` \| `go-svc` \| `auth-svc` \| `gateway` |
24
+ | `msg` | ✓ | Câu ngắn, tiếng Anh, không nhạy cảm |
25
+ | `requestId` | khi xử lý request | Lấy từ header `X-Request-Id` (gateway sinh nếu thiếu) — trace xuyên gateway → service |
26
+ | còn lại | tuỳ | Case camelCase; KHÔNG log JWT/email/password toàn phần (mask email: `a***@demo.local`) |
27
+
28
+ ## Stack mapping
29
+
30
+ | Stack | Thư viện |
31
+ |-------|----------|
32
+ | node-svc | `pino` (mặc định JSON) |
33
+ | spring-svc | Logback `LogstashEncoder` (`net.logstash.logback`) |
34
+ | go-svc | `log/slog` JSON handler |
35
+ | auth-svc | `pino` |
36
+
37
+ ## Quy tắc
38
+
39
+ 1. **Fire-and-forget event push** (node-svc → go-svc): fail = log `level:"warn"`, msg chứa `event push failed`, KHÔNG raise error cho caller, KHÔNG retry (ADR SF-7).
40
+ 2. Unhandled error: `level:"error"` + stack trong trường `err` (string).
41
+ 3. Không dùng `console.log` trong service Node — mọi log đi qua logger có shape trên.
@@ -0,0 +1,41 @@
1
+ # 04 — Error envelope chung
2
+
3
+ Mọi HTTP response 4xx/5xx của mọi service dùng **một** shape — mirror trong `components.schemas.Error` của cả 4 OpenAPI specs (spectral rule `error-envelope-shape` warn nếu lệch).
4
+
5
+ ## Shape
6
+
7
+ ```json
8
+ {
9
+ "error": {
10
+ "code": "TASK_NOT_FOUND",
11
+ "message": "Task 9f0e... không tồn tại",
12
+ "requestId": "b1c2...",
13
+ "details": null
14
+ }
15
+ }
16
+ ```
17
+
18
+ | Trường | Bắt buộc | Ghi chú |
19
+ |--------|----------|---------|
20
+ | `error.code` | ✓ | `SCREAMING_SNAKE` — máy đọc được |
21
+ | `error.message` | ✓ | Người đọc được; không chứa secret |
22
+ | `error.requestId` | ✓ (nullable) | Echo `X-Request-Id` |
23
+ | `error.details` | ✗ | Dữ liệu bổ sung có cấu trúc (vd validation field errors) |
24
+
25
+ ## Code catalog tối thiểu
26
+
27
+ | Code | HTTP | Dùng khi |
28
+ |------|------|----------|
29
+ | `VALIDATION_ERROR` | 400 | Payload sai schema |
30
+ | `UNAUTHORIZED` | 401 | Thiếu/sai/hết hạn JWT (service tự verify) |
31
+ | `NOT_FOUND` | 404 | Resource không tồn tại |
32
+ | `CONFLICT` | 409 | Email đã tồn tại… |
33
+ | `UNPROCESSABLE` | 422 | Assignee không tồn tại (spring trả 404 khi node validate) |
34
+ | `DEPENDENCY_DOWN` | 503 | spring-svc down khi node validate user (fail-closed); go không đọc được schema tasks |
35
+ | `INTERNAL` | 500 | Unhandled — KHÔNG lộ stack trong message |
36
+
37
+ ## Quy tắc
38
+
39
+ 1. Fastify/spring/Go framework error mặc định (vd Fastify `FST_ERR_*`) phải được **map sang envelope** bằng error handler riêng.
40
+ 2. Gateway (nginx) 401 presence-check trả envelope tương tự (`{"error":{"code":"UNAUTHORIZED",...}}`) qua `default.conf` inline response.
41
+ 3. FE decode envelope bằng helper `decodeErrorEnvelope` trong `app/shared` — không tự parse message đáy.