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.
- package/README.md +66 -2
- package/dist/chunk-7XGW4UJ5.js +75 -0
- package/dist/chunk-AKPWS7FJ.js +76 -0
- package/dist/chunk-ELM6GGC5.js +50 -0
- package/dist/chunk-ON2WTGZH.js +77 -0
- package/dist/index.js +385 -0
- package/dist/manifest-2JVLRMDB.js +10 -0
- package/dist/manifest-O35TPW73.js +10 -0
- package/dist/manifest-TXTY67BF.js +10 -0
- package/dist/manifest-XWHR7Y3F.js +10 -0
- package/package.json +23 -4
- package/stack-template/.changeset/config.json +15 -0
- package/stack-template/.changeset/vu53-ui-redesign.md +11 -0
- package/stack-template/.claude/agents/be-dev.md +56 -0
- package/stack-template/.claude/agents/contracts-keeper.md +51 -0
- package/stack-template/.claude/agents/e2e-runner.md +61 -0
- package/stack-template/.claude/agents/fe-dev.md +53 -0
- package/stack-template/.claude/settings.json +77 -0
- package/stack-template/.claude/settings.local.json +9 -0
- package/stack-template/.claude/skills/add-service/SKILL.md +81 -0
- package/stack-template/.claude/skills/sync-contracts/SKILL.md +74 -0
- package/stack-template/.editorconfig +21 -0
- package/stack-template/.gitattributes +10 -0
- package/stack-template/.github/pull_request_template.md +26 -0
- package/stack-template/.github/workflow-templates/services-ci.yml.example +69 -0
- package/stack-template/.github/workflows/contracts.yml +133 -0
- package/stack-template/.github/workflows/convergence.yml +209 -0
- package/stack-template/.github/workflows/git-guard.yml +44 -0
- package/stack-template/.github/workflows/publish-uikit.yml +96 -0
- package/stack-template/.github/workflows/remotes-activity.yml +82 -0
- package/stack-template/.github/workflows/remotes-tasks.yml +82 -0
- package/stack-template/.github/workflows/services-auth-svc.yml +153 -0
- package/stack-template/.github/workflows/services-go-svc.yml +281 -0
- package/stack-template/.github/workflows/services-node-svc.yml +173 -0
- package/stack-template/.github/workflows/services-spring-svc.yml +132 -0
- package/stack-template/.github/workflows/shell.yml +78 -0
- package/stack-template/.github/workflows/ui-kit.yml +51 -0
- package/stack-template/.husky/commit-msg +14 -0
- package/stack-template/.husky/pre-push +51 -0
- package/stack-template/.spectral.yaml +17 -0
- package/stack-template/AGENTS.md +197 -0
- package/stack-template/CLAUDE.md +114 -0
- package/stack-template/README.md +172 -0
- package/stack-template/app/admin/index.html +12 -0
- package/stack-template/app/admin/package.json +40 -0
- package/stack-template/app/admin/scripts/verify-chart.mjs +49 -0
- package/stack-template/app/admin/src/App.test.tsx +70 -0
- package/stack-template/app/admin/src/App.tsx +33 -0
- package/stack-template/app/admin/src/data/users.ts +47 -0
- package/stack-template/app/admin/src/layout/AdminLayout.tsx +212 -0
- package/stack-template/app/admin/src/main.tsx +17 -0
- package/stack-template/app/admin/src/pages/ComponentsDemo.tsx +138 -0
- package/stack-template/app/admin/src/pages/Dashboard.tsx +182 -0
- package/stack-template/app/admin/src/pages/HooksDemo.tsx +153 -0
- package/stack-template/app/admin/src/pages/Settings.tsx +156 -0
- package/stack-template/app/admin/src/pages/UploadPage.tsx +34 -0
- package/stack-template/app/admin/src/pages/Users.test.tsx +66 -0
- package/stack-template/app/admin/src/pages/Users.tsx +245 -0
- package/stack-template/app/admin/src/styles.css +9 -0
- package/stack-template/app/admin/src/tests/setup.ts +15 -0
- package/stack-template/app/admin/tsconfig.json +18 -0
- package/stack-template/app/admin/vite.config.ts +11 -0
- package/stack-template/app/admin/vitest.config.ts +14 -0
- package/stack-template/app/create-wakii-app/README.md +71 -0
- package/stack-template/app/create-wakii-app/package.json +27 -0
- package/stack-template/app/create-wakii-app/scripts/publish-npm.sh +38 -0
- package/stack-template/app/create-wakii-app/src/index.ts +127 -0
- package/stack-template/app/create-wakii-app/src/options.test.ts +80 -0
- package/stack-template/app/create-wakii-app/src/options.ts +117 -0
- package/stack-template/app/create-wakii-app/src/scaffold.test.ts +143 -0
- package/stack-template/app/create-wakii-app/src/scaffold.ts +194 -0
- package/stack-template/app/create-wakii-app/tsconfig.json +17 -0
- package/stack-template/app/create-wakii-app/vitest.config.ts +9 -0
- package/stack-template/app/create-wakii-stack/package.json +27 -0
- package/stack-template/app/create-wakii-stack/src/manifest.ts +101 -0
- package/stack-template/app/create-wakii-stack/src/options.ts +106 -0
- package/stack-template/app/create-wakii-stack/src/scaffold.ts +315 -0
- package/stack-template/app/create-wakii-stack/tsconfig.json +17 -0
- package/stack-template/app/create-wakii-stack/vitest.config.ts +9 -0
- package/stack-template/app/remotes/activity/Dockerfile +36 -0
- package/stack-template/app/remotes/activity/README.md +59 -0
- package/stack-template/app/remotes/activity/index.html +11 -0
- package/stack-template/app/remotes/activity/nginx.conf +35 -0
- package/stack-template/app/remotes/activity/package.json +40 -0
- package/stack-template/app/remotes/activity/rspack.config.mjs +152 -0
- package/stack-template/app/remotes/activity/src/ActivityPage.tsx +139 -0
- package/stack-template/app/remotes/activity/src/api.ts +63 -0
- package/stack-template/app/remotes/activity/src/app.css +7 -0
- package/stack-template/app/remotes/activity/src/components/FeedItem.tsx +39 -0
- package/stack-template/app/remotes/activity/src/components/StatTile.tsx +24 -0
- package/stack-template/app/remotes/activity/src/components/Timeline.tsx +53 -0
- package/stack-template/app/remotes/activity/src/components/time.ts +30 -0
- package/stack-template/app/remotes/activity/src/env.d.ts +5 -0
- package/stack-template/app/remotes/activity/src/index.tsx +12 -0
- package/stack-template/app/remotes/activity/src/standalone.tsx +36 -0
- package/stack-template/app/remotes/activity/tests/ActivityPage.test.tsx +260 -0
- package/stack-template/app/remotes/activity/tests/api.test.ts +61 -0
- package/stack-template/app/remotes/activity/tests/setup.ts +1 -0
- package/stack-template/app/remotes/activity/tests/test-utils.tsx +16 -0
- package/stack-template/app/remotes/activity/tsconfig.json +26 -0
- package/stack-template/app/remotes/activity/vitest.config.ts +38 -0
- package/stack-template/app/remotes/tasks/Dockerfile +36 -0
- package/stack-template/app/remotes/tasks/README.md +59 -0
- package/stack-template/app/remotes/tasks/index.html +11 -0
- package/stack-template/app/remotes/tasks/nginx.conf +35 -0
- package/stack-template/app/remotes/tasks/package.json +41 -0
- package/stack-template/app/remotes/tasks/rspack.config.mjs +153 -0
- package/stack-template/app/remotes/tasks/src/TasksPage.tsx +284 -0
- package/stack-template/app/remotes/tasks/src/api.ts +109 -0
- package/stack-template/app/remotes/tasks/src/app.css +7 -0
- package/stack-template/app/remotes/tasks/src/components/StatusBadge.tsx +20 -0
- package/stack-template/app/remotes/tasks/src/components/StatusSelect.tsx +27 -0
- package/stack-template/app/remotes/tasks/src/components/TaskForm.tsx +74 -0
- package/stack-template/app/remotes/tasks/src/components/TaskItem.tsx +199 -0
- package/stack-template/app/remotes/tasks/src/components/TaskList.tsx +60 -0
- package/stack-template/app/remotes/tasks/src/components/status.ts +23 -0
- package/stack-template/app/remotes/tasks/src/env.d.ts +5 -0
- package/stack-template/app/remotes/tasks/src/index.tsx +12 -0
- package/stack-template/app/remotes/tasks/src/standalone.tsx +38 -0
- package/stack-template/app/remotes/tasks/tests/TasksPage.test.tsx +445 -0
- package/stack-template/app/remotes/tasks/tests/api.test.ts +159 -0
- package/stack-template/app/remotes/tasks/tests/setup.ts +1 -0
- package/stack-template/app/remotes/tasks/tests/test-utils.tsx +16 -0
- package/stack-template/app/remotes/tasks/tsconfig.json +26 -0
- package/stack-template/app/remotes/tasks/vitest.config.ts +34 -0
- package/stack-template/app/shared/README.md +21 -0
- package/stack-template/app/shared/package.json +37 -0
- package/stack-template/app/shared/src/api-client.ts +66 -0
- package/stack-template/app/shared/src/error-envelope.ts +38 -0
- package/stack-template/app/shared/src/index.ts +21 -0
- package/stack-template/app/shared/src/mf-bootstrap.ts +89 -0
- package/stack-template/app/shared/src/refresh-client.ts +170 -0
- package/stack-template/app/shared/src/token-storage.ts +57 -0
- package/stack-template/app/shell/Dockerfile +37 -0
- package/stack-template/app/shell/README.md +79 -0
- package/stack-template/app/shell/index.html +11 -0
- package/stack-template/app/shell/nginx.conf +23 -0
- package/stack-template/app/shell/package.json +43 -0
- package/stack-template/app/shell/rspack.config.mjs +147 -0
- package/stack-template/app/shell/src/App.tsx +57 -0
- package/stack-template/app/shell/src/api.ts +36 -0
- package/stack-template/app/shell/src/app.css +11 -0
- package/stack-template/app/shell/src/bootstrap.tsx +24 -0
- package/stack-template/app/shell/src/components/Layout.tsx +35 -0
- package/stack-template/app/shell/src/components/NavBar.tsx +118 -0
- package/stack-template/app/shell/src/components/RemoteSlot.tsx +82 -0
- package/stack-template/app/shell/src/components/RequireAuth.tsx +14 -0
- package/stack-template/app/shell/src/env.d.ts +7 -0
- package/stack-template/app/shell/src/index.tsx +3 -0
- package/stack-template/app/shell/src/pages/HomePage.tsx +70 -0
- package/stack-template/app/shell/src/pages/LoginPage.tsx +217 -0
- package/stack-template/app/shell/src/remote-urls.ts +18 -0
- package/stack-template/app/shell/tests/a11y.test.tsx +53 -0
- package/stack-template/app/shell/tests/api-timeout.test.ts +43 -0
- package/stack-template/app/shell/tests/integration.test.tsx +93 -0
- package/stack-template/app/shell/tests/login.test.tsx +227 -0
- package/stack-template/app/shell/tests/mf-retry.test.ts +76 -0
- package/stack-template/app/shell/tests/refresh-client.test.ts +301 -0
- package/stack-template/app/shell/tests/remote-slot.test.tsx +109 -0
- package/stack-template/app/shell/tests/remote-urls.test.ts +26 -0
- package/stack-template/app/shell/tests/setup.ts +15 -0
- package/stack-template/app/shell/tests/shell-chrome.test.tsx +126 -0
- package/stack-template/app/shell/tsconfig.json +26 -0
- package/stack-template/app/shell/vitest.config.ts +42 -0
- package/stack-template/app/spike/README.md +35 -0
- package/stack-template/app/spike/host/index.html +11 -0
- package/stack-template/app/spike/host/package.json +17 -0
- package/stack-template/app/spike/host/rspack.config.mjs +34 -0
- package/stack-template/app/spike/host/src/bootstrap.jsx +26 -0
- package/stack-template/app/spike/host/src/index.jsx +3 -0
- package/stack-template/app/spike/remote/package.json +17 -0
- package/stack-template/app/spike/remote/rspack.config.mjs +36 -0
- package/stack-template/app/spike/remote/src/Hello.jsx +7 -0
- package/stack-template/app/spike/remote/src/index.js +2 -0
- package/stack-template/app/spike/serve.mjs +31 -0
- package/stack-template/app/starter-templates/template-feats/extras/carousel/src/DemoCarousel.tsx +99 -0
- package/stack-template/app/starter-templates/template-feats/extras/chart/src/DemoChart.tsx +84 -0
- package/stack-template/app/starter-templates/template-feats/extras/editor/src/DemoEditor.tsx +110 -0
- package/stack-template/app/starter-templates/template-feats/extras/schedule/src/DemoSchedule.tsx +81 -0
- package/stack-template/app/starter-templates/template-feats/router/src/App.tsx +332 -0
- package/stack-template/app/starter-templates/template-feats/router/src/main.tsx +14 -0
- package/stack-template/app/starter-templates/vite-js/README.md +72 -0
- package/stack-template/app/starter-templates/vite-js/index.html +12 -0
- package/stack-template/app/starter-templates/vite-js/jsconfig.json +10 -0
- package/stack-template/app/starter-templates/vite-js/package.json +22 -0
- package/stack-template/app/starter-templates/vite-js/src/App.jsx +158 -0
- package/stack-template/app/starter-templates/vite-js/src/main.jsx +10 -0
- package/stack-template/app/starter-templates/vite-js/src/styles.css +15 -0
- package/stack-template/app/starter-templates/vite-js/src/theme.js +21 -0
- package/stack-template/app/starter-templates/vite-js/vite.config.mjs +8 -0
- package/stack-template/app/starter-templates/vite-ts/README.md +53 -0
- package/stack-template/app/starter-templates/vite-ts/index.html +12 -0
- package/stack-template/app/starter-templates/vite-ts/package.json +29 -0
- package/stack-template/app/starter-templates/vite-ts/src/App.tsx +181 -0
- package/stack-template/app/starter-templates/vite-ts/src/main.tsx +12 -0
- package/stack-template/app/starter-templates/vite-ts/src/styles.css +21 -0
- package/stack-template/app/starter-templates/vite-ts/src/theme.ts +16 -0
- package/stack-template/app/starter-templates/vite-ts/tsconfig.json +25 -0
- package/stack-template/app/starter-templates/vite-ts/tsconfig.node.json +11 -0
- package/stack-template/app/starter-templates/vite-ts/vite.config.ts +10 -0
- package/stack-template/app/ui-kit/.storybook/main.ts +29 -0
- package/stack-template/app/ui-kit/.storybook/manager-head.html +97 -0
- package/stack-template/app/ui-kit/.storybook/manager.ts +138 -0
- package/stack-template/app/ui-kit/.storybook/preview-head.html +57 -0
- package/stack-template/app/ui-kit/.storybook/preview.ts +62 -0
- package/stack-template/app/ui-kit/.storybook/tailwind-preview.css +3 -0
- package/stack-template/app/ui-kit/.storybook/test-runner.config.ts +20 -0
- package/stack-template/app/ui-kit/CHANGELOG.md +137 -0
- package/stack-template/app/ui-kit/LICENSE +21 -0
- package/stack-template/app/ui-kit/MIGRATION.md +84 -0
- package/stack-template/app/ui-kit/README.md +173 -0
- package/stack-template/app/ui-kit/RELEASE.md +77 -0
- package/stack-template/app/ui-kit/USAGE.md +380 -0
- package/stack-template/app/ui-kit/eslint.config.js +47 -0
- package/stack-template/app/ui-kit/package.json +166 -0
- package/stack-template/app/ui-kit/scripts/publish-github.sh +39 -0
- package/stack-template/app/ui-kit/scripts/publish-npm.sh +76 -0
- package/stack-template/app/ui-kit/scripts/stamp-build.cjs +13 -0
- package/stack-template/app/ui-kit/src/KitchenSink.stories.tsx +576 -0
- package/stack-template/app/ui-kit/src/Tokens.stories.tsx +193 -0
- package/stack-template/app/ui-kit/src/entries/carousel.ts +7 -0
- package/stack-template/app/ui-kit/src/entries/chart.ts +4 -0
- package/stack-template/app/ui-kit/src/entries/editor.ts +4 -0
- package/stack-template/app/ui-kit/src/entries/experience3d.ts +5 -0
- package/stack-template/app/ui-kit/src/entries/schedule.ts +5 -0
- package/stack-template/app/ui-kit/src/env.d.ts +3 -0
- package/stack-template/app/ui-kit/src/hooks/form.stories.tsx +80 -0
- package/stack-template/app/ui-kit/src/hooks/hooks-new.stories.tsx +392 -0
- package/stack-template/app/ui-kit/src/hooks/hooks.stories.tsx +167 -0
- package/stack-template/app/ui-kit/src/hooks/useClickAway.test.tsx +63 -0
- package/stack-template/app/ui-kit/src/hooks/useClickAway.ts +30 -0
- package/stack-template/app/ui-kit/src/hooks/useControllableState.test.ts +36 -0
- package/stack-template/app/ui-kit/src/hooks/useControllableState.ts +41 -0
- package/stack-template/app/ui-kit/src/hooks/useCopyToClipboard.test.ts +89 -0
- package/stack-template/app/ui-kit/src/hooks/useCopyToClipboard.ts +20 -0
- package/stack-template/app/ui-kit/src/hooks/useCountdown.test.ts +88 -0
- package/stack-template/app/ui-kit/src/hooks/useCountdown.ts +38 -0
- package/stack-template/app/ui-kit/src/hooks/useDebounce.test.ts +71 -0
- package/stack-template/app/ui-kit/src/hooks/useDebounce.ts +14 -0
- package/stack-template/app/ui-kit/src/hooks/useDefault.test.ts +37 -0
- package/stack-template/app/ui-kit/src/hooks/useDefault.ts +15 -0
- package/stack-template/app/ui-kit/src/hooks/useEventListener.test.ts +47 -0
- package/stack-template/app/ui-kit/src/hooks/useEventListener.ts +28 -0
- package/stack-template/app/ui-kit/src/hooks/useFieldArray.test.tsx +160 -0
- package/stack-template/app/ui-kit/src/hooks/useFieldArray.ts +85 -0
- package/stack-template/app/ui-kit/src/hooks/useFocusTrap.ts +67 -0
- package/stack-template/app/ui-kit/src/hooks/useForm.test.tsx +192 -0
- package/stack-template/app/ui-kit/src/hooks/useForm.ts +119 -0
- package/stack-template/app/ui-kit/src/hooks/useFullscreen.test.tsx +71 -0
- package/stack-template/app/ui-kit/src/hooks/useFullscreen.ts +68 -0
- package/stack-template/app/ui-kit/src/hooks/useHover.test.tsx +30 -0
- package/stack-template/app/ui-kit/src/hooks/useHover.ts +23 -0
- package/stack-template/app/ui-kit/src/hooks/useInView.test.tsx +70 -0
- package/stack-template/app/ui-kit/src/hooks/useInView.ts +55 -0
- package/stack-template/app/ui-kit/src/hooks/useInfiniteScroll.test.tsx +72 -0
- package/stack-template/app/ui-kit/src/hooks/useInfiniteScroll.ts +45 -0
- package/stack-template/app/ui-kit/src/hooks/useIsFirstRender.test.ts +30 -0
- package/stack-template/app/ui-kit/src/hooks/useIsFirstRender.ts +14 -0
- package/stack-template/app/ui-kit/src/hooks/useKeyPress.test.ts +45 -0
- package/stack-template/app/ui-kit/src/hooks/useKeyPress.ts +31 -0
- package/stack-template/app/ui-kit/src/hooks/useLocalStorage.test.ts +102 -0
- package/stack-template/app/ui-kit/src/hooks/useLocalStorage.ts +34 -0
- package/stack-template/app/ui-kit/src/hooks/useLockBodyScroll.test.ts +42 -0
- package/stack-template/app/ui-kit/src/hooks/useLockBodyScroll.ts +13 -0
- package/stack-template/app/ui-kit/src/hooks/useMeasure.test.tsx +57 -0
- package/stack-template/app/ui-kit/src/hooks/useMeasure.ts +32 -0
- package/stack-template/app/ui-kit/src/hooks/useMediaQuery.test.ts +73 -0
- package/stack-template/app/ui-kit/src/hooks/useMediaQuery.ts +20 -0
- package/stack-template/app/ui-kit/src/hooks/useMountEffect.test.ts +22 -0
- package/stack-template/app/ui-kit/src/hooks/useMountEffect.ts +10 -0
- package/stack-template/app/ui-kit/src/hooks/useOnlineStatus.test.ts +36 -0
- package/stack-template/app/ui-kit/src/hooks/useOnlineStatus.ts +21 -0
- package/stack-template/app/ui-kit/src/hooks/usePrevious.test.ts +35 -0
- package/stack-template/app/ui-kit/src/hooks/usePrevious.ts +13 -0
- package/stack-template/app/ui-kit/src/hooks/useScrollProgress.test.ts +59 -0
- package/stack-template/app/ui-kit/src/hooks/useScrollProgress.ts +31 -0
- package/stack-template/app/ui-kit/src/hooks/useSessionStorage.test.ts +80 -0
- package/stack-template/app/ui-kit/src/hooks/useSessionStorage.ts +34 -0
- package/stack-template/app/ui-kit/src/hooks/useThrottle.test.ts +61 -0
- package/stack-template/app/ui-kit/src/hooks/useThrottle.ts +30 -0
- package/stack-template/app/ui-kit/src/hooks/useTimeout.test.ts +95 -0
- package/stack-template/app/ui-kit/src/hooks/useTimeout.ts +38 -0
- package/stack-template/app/ui-kit/src/hooks/useTitle.test.ts +34 -0
- package/stack-template/app/ui-kit/src/hooks/useTitle.ts +24 -0
- package/stack-template/app/ui-kit/src/hooks/useToggle.test.ts +46 -0
- package/stack-template/app/ui-kit/src/hooks/useToggle.ts +16 -0
- package/stack-template/app/ui-kit/src/hooks/useUpdateEffect.test.ts +25 -0
- package/stack-template/app/ui-kit/src/hooks/useUpdateEffect.ts +18 -0
- package/stack-template/app/ui-kit/src/hooks/useWindowSize.test.ts +33 -0
- package/stack-template/app/ui-kit/src/hooks/useWindowSize.ts +23 -0
- package/stack-template/app/ui-kit/src/index.ts +218 -0
- package/stack-template/app/ui-kit/src/intro-showcase.stories.tsx +272 -0
- package/stack-template/app/ui-kit/src/intro.docs.mdx +247 -0
- package/stack-template/app/ui-kit/src/motion/motion-showcase.stories.tsx +234 -0
- package/stack-template/app/ui-kit/src/motion/motion.md +38 -0
- package/stack-template/app/ui-kit/src/provider/index.tsx +77 -0
- package/stack-template/app/ui-kit/src/provider/provider.stories.tsx +87 -0
- package/stack-template/app/ui-kit/src/provider/provider.test.tsx +121 -0
- package/stack-template/app/ui-kit/src/styles/base.css +171 -0
- package/stack-template/app/ui-kit/src/styles/dark-theme.test.ts +21 -0
- package/stack-template/app/ui-kit/src/styles/tailwind.css +220 -0
- package/stack-template/app/ui-kit/src/styles/themes/dark.css +71 -0
- package/stack-template/app/ui-kit/src/styles/tokens.css +133 -0
- package/stack-template/app/ui-kit/src/styles/ui-kit.css +10 -0
- package/stack-template/app/ui-kit/src/templates/auth.stories.tsx +425 -0
- package/stack-template/app/ui-kit/src/templates/crud.stories.tsx +416 -0
- package/stack-template/app/ui-kit/src/templates/dashboard.stories.tsx +504 -0
- package/stack-template/app/ui-kit/src/templates/experience/chapters/ch1-deep-focus.tsx +96 -0
- package/stack-template/app/ui-kit/src/templates/experience/chapters/ch2-living-docs.tsx +134 -0
- package/stack-template/app/ui-kit/src/templates/experience/chapters/ch3-team-velocity.tsx +148 -0
- package/stack-template/app/ui-kit/src/templates/experience/chapters/ch4-ship-your-app.tsx +100 -0
- package/stack-template/app/ui-kit/src/templates/experience/chapters/ch5-future.tsx +67 -0
- package/stack-template/app/ui-kit/src/templates/experience/chapters/hero.tsx +434 -0
- package/stack-template/app/ui-kit/src/templates/experience/chapters/nav-footer.tsx +85 -0
- package/stack-template/app/ui-kit/src/templates/experience/hero.stories.tsx +27 -0
- package/stack-template/app/ui-kit/src/templates/experience/hero.test.tsx +108 -0
- package/stack-template/app/ui-kit/src/templates/experience/index.stories.tsx +51 -0
- package/stack-template/app/ui-kit/src/templates/experience/lib/ChapterShell.tsx +84 -0
- package/stack-template/app/ui-kit/src/templates/experience/lib/SideNav.tsx +173 -0
- package/stack-template/app/ui-kit/src/templates/experience/lib/chapter-shell.test.tsx +266 -0
- package/stack-template/app/ui-kit/src/templates/experience/lib/scroll-mood.tsx +143 -0
- package/stack-template/app/ui-kit/src/templates/experience/lib/starfield.test.tsx +31 -0
- package/stack-template/app/ui-kit/src/templates/experience/lib/starfield.tsx +190 -0
- package/stack-template/app/ui-kit/src/templates/experience/mood-engine.stories.tsx +114 -0
- package/stack-template/app/ui-kit/src/templates/experience/shell-nav.stories.tsx +113 -0
- package/stack-template/app/ui-kit/src/templates/kanban-project.stories.tsx +352 -0
- package/stack-template/app/ui-kit/src/templates/landing.stories.tsx +380 -0
- package/stack-template/app/ui-kit/src/templates/parallax-landing.stories.tsx +633 -0
- package/stack-template/app/ui-kit/src/templates/settings.stories.tsx +474 -0
- package/stack-template/app/ui-kit/src/ui/accordion/accordion.stories.tsx +91 -0
- package/stack-template/app/ui-kit/src/ui/accordion/accordion.test.tsx +99 -0
- package/stack-template/app/ui-kit/src/ui/accordion/index.tsx +107 -0
- package/stack-template/app/ui-kit/src/ui/affix/affix.stories.tsx +104 -0
- package/stack-template/app/ui-kit/src/ui/affix/affix.test.tsx +138 -0
- package/stack-template/app/ui-kit/src/ui/affix/index.tsx +89 -0
- package/stack-template/app/ui-kit/src/ui/alert/alert.stories.tsx +149 -0
- package/stack-template/app/ui-kit/src/ui/alert/alert.test.tsx +85 -0
- package/stack-template/app/ui-kit/src/ui/alert/index.tsx +118 -0
- package/stack-template/app/ui-kit/src/ui/anchor/anchor.stories.tsx +96 -0
- package/stack-template/app/ui-kit/src/ui/anchor/anchor.test.tsx +191 -0
- package/stack-template/app/ui-kit/src/ui/anchor/index.tsx +144 -0
- package/stack-template/app/ui-kit/src/ui/auto-complete/auto-complete.stories.tsx +67 -0
- package/stack-template/app/ui-kit/src/ui/auto-complete/auto-complete.test.tsx +94 -0
- package/stack-template/app/ui-kit/src/ui/auto-complete/index.tsx +54 -0
- package/stack-template/app/ui-kit/src/ui/avatar/avatar.stories.tsx +132 -0
- package/stack-template/app/ui-kit/src/ui/avatar/avatar.test.tsx +65 -0
- package/stack-template/app/ui-kit/src/ui/avatar/index.tsx +48 -0
- package/stack-template/app/ui-kit/src/ui/avatar-group/avatar-group.stories.tsx +113 -0
- package/stack-template/app/ui-kit/src/ui/avatar-group/avatar-group.test.tsx +71 -0
- package/stack-template/app/ui-kit/src/ui/avatar-group/index.tsx +66 -0
- package/stack-template/app/ui-kit/src/ui/backdrop/backdrop.stories.tsx +66 -0
- package/stack-template/app/ui-kit/src/ui/backdrop/backdrop.test.tsx +37 -0
- package/stack-template/app/ui-kit/src/ui/backdrop/index.tsx +29 -0
- package/stack-template/app/ui-kit/src/ui/badge/badge.stories.tsx +105 -0
- package/stack-template/app/ui-kit/src/ui/badge/badge.test.tsx +115 -0
- package/stack-template/app/ui-kit/src/ui/badge/index.tsx +154 -0
- package/stack-template/app/ui-kit/src/ui/blockui/blockui.stories.tsx +34 -0
- package/stack-template/app/ui-kit/src/ui/blockui/blockui.test.tsx +29 -0
- package/stack-template/app/ui-kit/src/ui/blockui/index.tsx +25 -0
- package/stack-template/app/ui-kit/src/ui/bottom-navigation/bottom-navigation.stories.tsx +70 -0
- package/stack-template/app/ui-kit/src/ui/bottom-navigation/bottom-navigation.test.tsx +68 -0
- package/stack-template/app/ui-kit/src/ui/bottom-navigation/index.tsx +82 -0
- package/stack-template/app/ui-kit/src/ui/branch-fill.test.tsx +245 -0
- package/stack-template/app/ui-kit/src/ui/breadcrumb/breadcrumb.stories.tsx +103 -0
- package/stack-template/app/ui-kit/src/ui/breadcrumb/breadcrumb.test.tsx +49 -0
- package/stack-template/app/ui-kit/src/ui/breadcrumb/index.tsx +37 -0
- package/stack-template/app/ui-kit/src/ui/busy-box/busy-box.stories.tsx +30 -0
- package/stack-template/app/ui-kit/src/ui/busy-box/busy-box.test.tsx +29 -0
- package/stack-template/app/ui-kit/src/ui/busy-box/index.tsx +25 -0
- package/stack-template/app/ui-kit/src/ui/button/button.stories.tsx +121 -0
- package/stack-template/app/ui-kit/src/ui/button/button.test.tsx +207 -0
- package/stack-template/app/ui-kit/src/ui/button/index.tsx +128 -0
- package/stack-template/app/ui-kit/src/ui/calendar/calendar.stories.tsx +100 -0
- package/stack-template/app/ui-kit/src/ui/calendar/calendar.test.tsx +92 -0
- package/stack-template/app/ui-kit/src/ui/calendar/index.tsx +163 -0
- package/stack-template/app/ui-kit/src/ui/card/card.stories.tsx +203 -0
- package/stack-template/app/ui-kit/src/ui/card/card.test.tsx +135 -0
- package/stack-template/app/ui-kit/src/ui/card/index.tsx +84 -0
- package/stack-template/app/ui-kit/src/ui/carousel/carousel.stories.tsx +533 -0
- package/stack-template/app/ui-kit/src/ui/carousel/carousel.test.tsx +148 -0
- package/stack-template/app/ui-kit/src/ui/carousel/index.tsx +195 -0
- package/stack-template/app/ui-kit/src/ui/cascade-select/cascade-select.stories.tsx +126 -0
- package/stack-template/app/ui-kit/src/ui/cascade-select/cascade-select.test.tsx +132 -0
- package/stack-template/app/ui-kit/src/ui/cascade-select/index.tsx +87 -0
- package/stack-template/app/ui-kit/src/ui/chart/chart-theme.test.tsx +79 -0
- package/stack-template/app/ui-kit/src/ui/chart/chart.stories.tsx +278 -0
- package/stack-template/app/ui-kit/src/ui/chart/chart.test.tsx +103 -0
- package/stack-template/app/ui-kit/src/ui/chart/index.tsx +172 -0
- package/stack-template/app/ui-kit/src/ui/checkbox/checkbox.stories.tsx +67 -0
- package/stack-template/app/ui-kit/src/ui/checkbox/checkbox.test.tsx +99 -0
- package/stack-template/app/ui-kit/src/ui/checkbox/index.tsx +52 -0
- package/stack-template/app/ui-kit/src/ui/chips/chips.stories.tsx +53 -0
- package/stack-template/app/ui-kit/src/ui/chips/chips.test.tsx +86 -0
- package/stack-template/app/ui-kit/src/ui/chips/index.tsx +44 -0
- package/stack-template/app/ui-kit/src/ui/collapse/collapse.stories.tsx +93 -0
- package/stack-template/app/ui-kit/src/ui/collapse/collapse.test.tsx +128 -0
- package/stack-template/app/ui-kit/src/ui/collapse/index.tsx +75 -0
- package/stack-template/app/ui-kit/src/ui/color-picker/color-picker.stories.tsx +48 -0
- package/stack-template/app/ui-kit/src/ui/color-picker/color-picker.test.tsx +68 -0
- package/stack-template/app/ui-kit/src/ui/color-picker/index.tsx +38 -0
- package/stack-template/app/ui-kit/src/ui/context-menu/context-menu.stories.tsx +73 -0
- package/stack-template/app/ui-kit/src/ui/context-menu/context-menu.test.tsx +93 -0
- package/stack-template/app/ui-kit/src/ui/context-menu/index.tsx +79 -0
- package/stack-template/app/ui-kit/src/ui/count-up/count-up.stories.tsx +80 -0
- package/stack-template/app/ui-kit/src/ui/count-up/count-up.test.tsx +121 -0
- package/stack-template/app/ui-kit/src/ui/count-up/index.tsx +70 -0
- package/stack-template/app/ui-kit/src/ui/date-picker/date-picker.stories.tsx +154 -0
- package/stack-template/app/ui-kit/src/ui/date-picker/date-picker.test.tsx +221 -0
- package/stack-template/app/ui-kit/src/ui/date-picker/index.tsx +287 -0
- package/stack-template/app/ui-kit/src/ui/date-picker/locale-constants.ts +90 -0
- package/stack-template/app/ui-kit/src/ui/date-picker/locale.tsx +15 -0
- package/stack-template/app/ui-kit/src/ui/deferred-content/deferred-content.stories.tsx +62 -0
- package/stack-template/app/ui-kit/src/ui/deferred-content/deferred-content.test.tsx +94 -0
- package/stack-template/app/ui-kit/src/ui/deferred-content/index.tsx +61 -0
- package/stack-template/app/ui-kit/src/ui/descriptions/descriptions.stories.tsx +114 -0
- package/stack-template/app/ui-kit/src/ui/descriptions/descriptions.test.tsx +75 -0
- package/stack-template/app/ui-kit/src/ui/descriptions/index.tsx +48 -0
- package/stack-template/app/ui-kit/src/ui/divider/divider.stories.tsx +66 -0
- package/stack-template/app/ui-kit/src/ui/divider/divider.test.tsx +83 -0
- package/stack-template/app/ui-kit/src/ui/divider/index.tsx +65 -0
- package/stack-template/app/ui-kit/src/ui/drag-drop/drag-drop.stories.tsx +145 -0
- package/stack-template/app/ui-kit/src/ui/drag-drop/drag-drop.test.tsx +352 -0
- package/stack-template/app/ui-kit/src/ui/drag-drop/index.tsx +456 -0
- package/stack-template/app/ui-kit/src/ui/drawer/drawer.stories.tsx +108 -0
- package/stack-template/app/ui-kit/src/ui/drawer/drawer.test.tsx +132 -0
- package/stack-template/app/ui-kit/src/ui/drawer/index.tsx +113 -0
- package/stack-template/app/ui-kit/src/ui/dropdown/dropdown.stories.tsx +61 -0
- package/stack-template/app/ui-kit/src/ui/dropdown/dropdown.test.tsx +101 -0
- package/stack-template/app/ui-kit/src/ui/dropdown/index.tsx +162 -0
- package/stack-template/app/ui-kit/src/ui/editor/EditorInner.tsx +93 -0
- package/stack-template/app/ui-kit/src/ui/editor/editor.stories.tsx +37 -0
- package/stack-template/app/ui-kit/src/ui/editor/editor.test.tsx +84 -0
- package/stack-template/app/ui-kit/src/ui/editor/index.tsx +58 -0
- package/stack-template/app/ui-kit/src/ui/empty-state/empty-state.stories.tsx +24 -0
- package/stack-template/app/ui-kit/src/ui/empty-state/empty-state.test.tsx +48 -0
- package/stack-template/app/ui-kit/src/ui/empty-state/index.tsx +22 -0
- package/stack-template/app/ui-kit/src/ui/experience3d/experience3d.stories.tsx +66 -0
- package/stack-template/app/ui-kit/src/ui/experience3d/experience3d.test.tsx +50 -0
- package/stack-template/app/ui-kit/src/ui/experience3d/index.tsx +457 -0
- package/stack-template/app/ui-kit/src/ui/field/field-array.stories.tsx +214 -0
- package/stack-template/app/ui-kit/src/ui/field/field.stories.tsx +158 -0
- package/stack-template/app/ui-kit/src/ui/field/field.test.tsx +68 -0
- package/stack-template/app/ui-kit/src/ui/field/index.tsx +48 -0
- package/stack-template/app/ui-kit/src/ui/fieldset/fieldset.stories.tsx +49 -0
- package/stack-template/app/ui-kit/src/ui/fieldset/fieldset.test.tsx +88 -0
- package/stack-template/app/ui-kit/src/ui/fieldset/index.tsx +62 -0
- package/stack-template/app/ui-kit/src/ui/flex/flex.stories.tsx +96 -0
- package/stack-template/app/ui-kit/src/ui/flex/flex.test.tsx +79 -0
- package/stack-template/app/ui-kit/src/ui/flex/index.tsx +45 -0
- package/stack-template/app/ui-kit/src/ui/float-button/float-button.stories.tsx +82 -0
- package/stack-template/app/ui-kit/src/ui/float-button/float-button.test.tsx +107 -0
- package/stack-template/app/ui-kit/src/ui/float-button/index.tsx +124 -0
- package/stack-template/app/ui-kit/src/ui/galleria/galleria.stories.tsx +78 -0
- package/stack-template/app/ui-kit/src/ui/galleria/galleria.test.tsx +67 -0
- package/stack-template/app/ui-kit/src/ui/galleria/index.tsx +47 -0
- package/stack-template/app/ui-kit/src/ui/grid/grid.stories.tsx +179 -0
- package/stack-template/app/ui-kit/src/ui/grid/grid.test.tsx +286 -0
- package/stack-template/app/ui-kit/src/ui/grid/index.tsx +104 -0
- package/stack-template/app/ui-kit/src/ui/icons/icons.stories.tsx +52 -0
- package/stack-template/app/ui-kit/src/ui/icons/icons.test.tsx +60 -0
- package/stack-template/app/ui-kit/src/ui/icons/index.tsx +294 -0
- package/stack-template/app/ui-kit/src/ui/image/image.stories.tsx +231 -0
- package/stack-template/app/ui-kit/src/ui/image/image.test.tsx +79 -0
- package/stack-template/app/ui-kit/src/ui/image/index.tsx +76 -0
- package/stack-template/app/ui-kit/src/ui/inplace/index.tsx +33 -0
- package/stack-template/app/ui-kit/src/ui/inplace/inplace.stories.tsx +75 -0
- package/stack-template/app/ui-kit/src/ui/inplace/inplace.test.tsx +58 -0
- package/stack-template/app/ui-kit/src/ui/input/index.tsx +133 -0
- package/stack-template/app/ui-kit/src/ui/input/input-search.stories.tsx +112 -0
- package/stack-template/app/ui-kit/src/ui/input/input-search.test.tsx +116 -0
- package/stack-template/app/ui-kit/src/ui/input/input-search.tsx +116 -0
- package/stack-template/app/ui-kit/src/ui/input/input.stories.tsx +176 -0
- package/stack-template/app/ui-kit/src/ui/input/input.test.tsx +106 -0
- package/stack-template/app/ui-kit/src/ui/input-mask/index.tsx +39 -0
- package/stack-template/app/ui-kit/src/ui/input-mask/input-mask.stories.tsx +46 -0
- package/stack-template/app/ui-kit/src/ui/input-mask/input-mask.test.tsx +57 -0
- package/stack-template/app/ui-kit/src/ui/input-number/index.tsx +125 -0
- package/stack-template/app/ui-kit/src/ui/input-number/input-number.stories.tsx +190 -0
- package/stack-template/app/ui-kit/src/ui/input-number/input-number.test.tsx +157 -0
- package/stack-template/app/ui-kit/src/ui/input-otp/index.tsx +57 -0
- package/stack-template/app/ui-kit/src/ui/input-otp/input-otp.stories.tsx +90 -0
- package/stack-template/app/ui-kit/src/ui/input-otp/input-otp.test.tsx +66 -0
- package/stack-template/app/ui-kit/src/ui/kanban/index.tsx +277 -0
- package/stack-template/app/ui-kit/src/ui/kanban/kanban.stories.tsx +219 -0
- package/stack-template/app/ui-kit/src/ui/kanban/kanban.test.tsx +234 -0
- package/stack-template/app/ui-kit/src/ui/knob/index.tsx +58 -0
- package/stack-template/app/ui-kit/src/ui/knob/knob.stories.tsx +49 -0
- package/stack-template/app/ui-kit/src/ui/knob/knob.test.tsx +42 -0
- package/stack-template/app/ui-kit/src/ui/layout/index.tsx +145 -0
- package/stack-template/app/ui-kit/src/ui/layout/layout.stories.tsx +158 -0
- package/stack-template/app/ui-kit/src/ui/layout/layout.test.tsx +154 -0
- package/stack-template/app/ui-kit/src/ui/link/index.tsx +61 -0
- package/stack-template/app/ui-kit/src/ui/link/link.stories.tsx +68 -0
- package/stack-template/app/ui-kit/src/ui/link/link.test.tsx +69 -0
- package/stack-template/app/ui-kit/src/ui/list/index.tsx +135 -0
- package/stack-template/app/ui-kit/src/ui/list/list.stories.tsx +194 -0
- package/stack-template/app/ui-kit/src/ui/list/list.test.tsx +164 -0
- package/stack-template/app/ui-kit/src/ui/listbox/index.tsx +27 -0
- package/stack-template/app/ui-kit/src/ui/listbox/listbox.stories.tsx +57 -0
- package/stack-template/app/ui-kit/src/ui/listbox/listbox.test.tsx +49 -0
- package/stack-template/app/ui-kit/src/ui/mega-menu/index.tsx +142 -0
- package/stack-template/app/ui-kit/src/ui/mega-menu/mega-menu.stories.tsx +137 -0
- package/stack-template/app/ui-kit/src/ui/mega-menu/mega-menu.test.tsx +130 -0
- package/stack-template/app/ui-kit/src/ui/mention/index.tsx +76 -0
- package/stack-template/app/ui-kit/src/ui/mention/mention.stories.tsx +44 -0
- package/stack-template/app/ui-kit/src/ui/mention/mention.test.tsx +87 -0
- package/stack-template/app/ui-kit/src/ui/menu/index.tsx +256 -0
- package/stack-template/app/ui-kit/src/ui/menu/menu.stories.tsx +124 -0
- package/stack-template/app/ui-kit/src/ui/menu/menu.test.tsx +251 -0
- package/stack-template/app/ui-kit/src/ui/menubar/index.tsx +42 -0
- package/stack-template/app/ui-kit/src/ui/menubar/menubar.stories.tsx +66 -0
- package/stack-template/app/ui-kit/src/ui/menubar/menubar.test.tsx +65 -0
- package/stack-template/app/ui-kit/src/ui/message/index.tsx +123 -0
- package/stack-template/app/ui-kit/src/ui/message/message.stories.tsx +104 -0
- package/stack-template/app/ui-kit/src/ui/message/message.test.tsx +109 -0
- package/stack-template/app/ui-kit/src/ui/modal/index.tsx +142 -0
- package/stack-template/app/ui-kit/src/ui/modal/modal.stories.tsx +128 -0
- package/stack-template/app/ui-kit/src/ui/modal/modal.test.tsx +166 -0
- package/stack-template/app/ui-kit/src/ui/notification/index.tsx +142 -0
- package/stack-template/app/ui-kit/src/ui/notification/notification.stories.tsx +155 -0
- package/stack-template/app/ui-kit/src/ui/notification/notification.test.tsx +83 -0
- package/stack-template/app/ui-kit/src/ui/order-list/index.tsx +38 -0
- package/stack-template/app/ui-kit/src/ui/order-list/order-list.stories.tsx +38 -0
- package/stack-template/app/ui-kit/src/ui/order-list/order-list.test.tsx +54 -0
- package/stack-template/app/ui-kit/src/ui/org-chart/index.tsx +138 -0
- package/stack-template/app/ui-kit/src/ui/org-chart/org-chart.stories.tsx +76 -0
- package/stack-template/app/ui-kit/src/ui/org-chart/org-chart.test.tsx +98 -0
- package/stack-template/app/ui-kit/src/ui/pagination/index.tsx +102 -0
- package/stack-template/app/ui-kit/src/ui/pagination/pagination.stories.tsx +103 -0
- package/stack-template/app/ui-kit/src/ui/pagination/pagination.test.tsx +112 -0
- package/stack-template/app/ui-kit/src/ui/panel-menu/index.tsx +59 -0
- package/stack-template/app/ui-kit/src/ui/panel-menu/panel-menu.stories.tsx +96 -0
- package/stack-template/app/ui-kit/src/ui/panel-menu/panel-menu.test.tsx +64 -0
- package/stack-template/app/ui-kit/src/ui/parallax/index.tsx +62 -0
- package/stack-template/app/ui-kit/src/ui/parallax/parallax.stories.tsx +115 -0
- package/stack-template/app/ui-kit/src/ui/parallax/parallax.test.tsx +148 -0
- package/stack-template/app/ui-kit/src/ui/password/index.tsx +67 -0
- package/stack-template/app/ui-kit/src/ui/password/password.stories.tsx +43 -0
- package/stack-template/app/ui-kit/src/ui/password/password.test.tsx +45 -0
- package/stack-template/app/ui-kit/src/ui/pick-list/index.tsx +103 -0
- package/stack-template/app/ui-kit/src/ui/pick-list/pick-list.stories.tsx +59 -0
- package/stack-template/app/ui-kit/src/ui/pick-list/pick-list.test.tsx +94 -0
- package/stack-template/app/ui-kit/src/ui/popconfirm/index.tsx +102 -0
- package/stack-template/app/ui-kit/src/ui/popconfirm/popconfirm.stories.tsx +73 -0
- package/stack-template/app/ui-kit/src/ui/popconfirm/popconfirm.test.tsx +127 -0
- package/stack-template/app/ui-kit/src/ui/popover/index.tsx +136 -0
- package/stack-template/app/ui-kit/src/ui/popover/popover.stories.tsx +114 -0
- package/stack-template/app/ui-kit/src/ui/popover/popover.test.tsx +172 -0
- package/stack-template/app/ui-kit/src/ui/progress/index.tsx +46 -0
- package/stack-template/app/ui-kit/src/ui/progress/progress.stories.tsx +57 -0
- package/stack-template/app/ui-kit/src/ui/progress/progress.test.tsx +90 -0
- package/stack-template/app/ui-kit/src/ui/qr-code/index.tsx +88 -0
- package/stack-template/app/ui-kit/src/ui/qr-code/qr-code.stories.tsx +109 -0
- package/stack-template/app/ui-kit/src/ui/qr-code/qr-code.test.tsx +155 -0
- package/stack-template/app/ui-kit/src/ui/qr-code/qrcode-core.ts +56 -0
- package/stack-template/app/ui-kit/src/ui/qr-code/qrcode-generator.vendor.ts +2300 -0
- package/stack-template/app/ui-kit/src/ui/radio/index.tsx +62 -0
- package/stack-template/app/ui-kit/src/ui/radio/radio.stories.tsx +94 -0
- package/stack-template/app/ui-kit/src/ui/radio/radio.test.tsx +83 -0
- package/stack-template/app/ui-kit/src/ui/rating/index.tsx +36 -0
- package/stack-template/app/ui-kit/src/ui/rating/rating.stories.tsx +42 -0
- package/stack-template/app/ui-kit/src/ui/rating/rating.test.tsx +45 -0
- package/stack-template/app/ui-kit/src/ui/result/index.tsx +72 -0
- package/stack-template/app/ui-kit/src/ui/result/result.stories.tsx +82 -0
- package/stack-template/app/ui-kit/src/ui/result/result.test.tsx +57 -0
- package/stack-template/app/ui-kit/src/ui/reveal/index.tsx +83 -0
- package/stack-template/app/ui-kit/src/ui/reveal/reveal.stories.tsx +91 -0
- package/stack-template/app/ui-kit/src/ui/reveal/reveal.test.tsx +148 -0
- package/stack-template/app/ui-kit/src/ui/schedule/index.tsx +104 -0
- package/stack-template/app/ui-kit/src/ui/schedule/schedule.fc.test.tsx +95 -0
- package/stack-template/app/ui-kit/src/ui/schedule/schedule.stories.tsx +61 -0
- package/stack-template/app/ui-kit/src/ui/schedule/schedule.test.tsx +41 -0
- package/stack-template/app/ui-kit/src/ui/scroll-page/index.tsx +46 -0
- package/stack-template/app/ui-kit/src/ui/scroll-page/scroll-page.stories.tsx +92 -0
- package/stack-template/app/ui-kit/src/ui/scroll-page/scroll-page.test.tsx +51 -0
- package/stack-template/app/ui-kit/src/ui/scroll-panel/index.tsx +16 -0
- package/stack-template/app/ui-kit/src/ui/scroll-panel/scroll-panel.stories.tsx +37 -0
- package/stack-template/app/ui-kit/src/ui/scroll-panel/scroll-panel.test.tsx +41 -0
- package/stack-template/app/ui-kit/src/ui/scrolltop/index.tsx +27 -0
- package/stack-template/app/ui-kit/src/ui/scrolltop/scrolltop.stories.tsx +41 -0
- package/stack-template/app/ui-kit/src/ui/scrolltop/scrolltop.test.tsx +37 -0
- package/stack-template/app/ui-kit/src/ui/segmented/index.tsx +47 -0
- package/stack-template/app/ui-kit/src/ui/segmented/segmented.stories.tsx +126 -0
- package/stack-template/app/ui-kit/src/ui/segmented/segmented.test.tsx +77 -0
- package/stack-template/app/ui-kit/src/ui/select/index.tsx +302 -0
- package/stack-template/app/ui-kit/src/ui/select/select.stories.tsx +268 -0
- package/stack-template/app/ui-kit/src/ui/select/select.test.tsx +226 -0
- package/stack-template/app/ui-kit/src/ui/sidebar/index.tsx +83 -0
- package/stack-template/app/ui-kit/src/ui/sidebar/sidebar.stories.tsx +71 -0
- package/stack-template/app/ui-kit/src/ui/sidebar/sidebar.test.tsx +101 -0
- package/stack-template/app/ui-kit/src/ui/skeleton/index.tsx +55 -0
- package/stack-template/app/ui-kit/src/ui/skeleton/skeleton.stories.tsx +110 -0
- package/stack-template/app/ui-kit/src/ui/skeleton/skeleton.test.tsx +74 -0
- package/stack-template/app/ui-kit/src/ui/slide-menu/index.tsx +103 -0
- package/stack-template/app/ui-kit/src/ui/slide-menu/slide-menu.stories.tsx +92 -0
- package/stack-template/app/ui-kit/src/ui/slide-menu/slide-menu.test.tsx +120 -0
- package/stack-template/app/ui-kit/src/ui/slider/index.tsx +90 -0
- package/stack-template/app/ui-kit/src/ui/slider/slider.stories.tsx +60 -0
- package/stack-template/app/ui-kit/src/ui/slider/slider.test.tsx +66 -0
- package/stack-template/app/ui-kit/src/ui/space/index.tsx +32 -0
- package/stack-template/app/ui-kit/src/ui/space/space.stories.tsx +66 -0
- package/stack-template/app/ui-kit/src/ui/space/space.test.tsx +56 -0
- package/stack-template/app/ui-kit/src/ui/speed-dial/index.tsx +32 -0
- package/stack-template/app/ui-kit/src/ui/speed-dial/speed-dial.stories.tsx +34 -0
- package/stack-template/app/ui-kit/src/ui/speed-dial/speed-dial.test.tsx +34 -0
- package/stack-template/app/ui-kit/src/ui/spinner/index.tsx +74 -0
- package/stack-template/app/ui-kit/src/ui/spinner/spinner.stories.tsx +64 -0
- package/stack-template/app/ui-kit/src/ui/spinner/spinner.test.tsx +66 -0
- package/stack-template/app/ui-kit/src/ui/split-button/index.tsx +155 -0
- package/stack-template/app/ui-kit/src/ui/split-button/split-button.stories.tsx +137 -0
- package/stack-template/app/ui-kit/src/ui/split-button/split-button.test.tsx +152 -0
- package/stack-template/app/ui-kit/src/ui/splitter/index.tsx +49 -0
- package/stack-template/app/ui-kit/src/ui/splitter/splitter.stories.tsx +24 -0
- package/stack-template/app/ui-kit/src/ui/splitter/splitter.test.tsx +21 -0
- package/stack-template/app/ui-kit/src/ui/statistic/index.tsx +28 -0
- package/stack-template/app/ui-kit/src/ui/statistic/statistic.stories.tsx +112 -0
- package/stack-template/app/ui-kit/src/ui/statistic/statistic.test.tsx +39 -0
- package/stack-template/app/ui-kit/src/ui/steps/index.tsx +50 -0
- package/stack-template/app/ui-kit/src/ui/steps/steps.stories.tsx +57 -0
- package/stack-template/app/ui-kit/src/ui/steps/steps.test.tsx +55 -0
- package/stack-template/app/ui-kit/src/ui/switch/index.tsx +87 -0
- package/stack-template/app/ui-kit/src/ui/switch/switch.stories.tsx +123 -0
- package/stack-template/app/ui-kit/src/ui/switch/switch.test.tsx +98 -0
- package/stack-template/app/ui-kit/src/ui/tab-menu/index.tsx +33 -0
- package/stack-template/app/ui-kit/src/ui/tab-menu/tab-menu.stories.tsx +49 -0
- package/stack-template/app/ui-kit/src/ui/tab-menu/tab-menu.test.tsx +50 -0
- package/stack-template/app/ui-kit/src/ui/table/index.tsx +690 -0
- package/stack-template/app/ui-kit/src/ui/table/table-advanced.stories.tsx +91 -0
- package/stack-template/app/ui-kit/src/ui/table/table-advanced.test.tsx +188 -0
- package/stack-template/app/ui-kit/src/ui/table/table-expandable.stories.tsx +91 -0
- package/stack-template/app/ui-kit/src/ui/table/table-expandable.test.tsx +143 -0
- package/stack-template/app/ui-kit/src/ui/table/table.stories.tsx +342 -0
- package/stack-template/app/ui-kit/src/ui/table/table.test.tsx +465 -0
- package/stack-template/app/ui-kit/src/ui/table/types.ts +173 -0
- package/stack-template/app/ui-kit/src/ui/tabs/index.tsx +118 -0
- package/stack-template/app/ui-kit/src/ui/tabs/tabs.stories.tsx +113 -0
- package/stack-template/app/ui-kit/src/ui/tabs/tabs.test.tsx +77 -0
- package/stack-template/app/ui-kit/src/ui/tag/index.tsx +68 -0
- package/stack-template/app/ui-kit/src/ui/tag/tag.stories.tsx +88 -0
- package/stack-template/app/ui-kit/src/ui/tag/tag.test.tsx +126 -0
- package/stack-template/app/ui-kit/src/ui/team/debt-board/debt-board.stories.tsx +52 -0
- package/stack-template/app/ui-kit/src/ui/team/debt-board/debt-board.test.tsx +72 -0
- package/stack-template/app/ui-kit/src/ui/team/debt-board/index.tsx +125 -0
- package/stack-template/app/ui-kit/src/ui/team/inbox-thread/inbox-thread.stories.tsx +70 -0
- package/stack-template/app/ui-kit/src/ui/team/inbox-thread/inbox-thread.test.tsx +56 -0
- package/stack-template/app/ui-kit/src/ui/team/inbox-thread/index.tsx +107 -0
- package/stack-template/app/ui-kit/src/ui/team/ping-feed/index.tsx +102 -0
- package/stack-template/app/ui-kit/src/ui/team/ping-feed/ping-feed.stories.tsx +57 -0
- package/stack-template/app/ui-kit/src/ui/team/ping-feed/ping-feed.test.tsx +60 -0
- package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/index.tsx +60 -0
- package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/stage-pipeline.stories.tsx +68 -0
- package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/stage-pipeline.test.tsx +50 -0
- package/stack-template/app/ui-kit/src/ui/team/team-dashboard/index.tsx +103 -0
- package/stack-template/app/ui-kit/src/ui/team/team-dashboard/team-dashboard.stories.tsx +72 -0
- package/stack-template/app/ui-kit/src/ui/team/team-dashboard/team-dashboard.test.tsx +72 -0
- package/stack-template/app/ui-kit/src/ui/time-picker/index.tsx +143 -0
- package/stack-template/app/ui-kit/src/ui/time-picker/time-picker.stories.tsx +90 -0
- package/stack-template/app/ui-kit/src/ui/time-picker/time-picker.test.tsx +64 -0
- package/stack-template/app/ui-kit/src/ui/timeline/index.tsx +91 -0
- package/stack-template/app/ui-kit/src/ui/timeline/timeline.stories.tsx +209 -0
- package/stack-template/app/ui-kit/src/ui/timeline/timeline.test.tsx +116 -0
- package/stack-template/app/ui-kit/src/ui/timesheet/index.tsx +277 -0
- package/stack-template/app/ui-kit/src/ui/timesheet/timesheet.stories.tsx +97 -0
- package/stack-template/app/ui-kit/src/ui/timesheet/timesheet.test.tsx +103 -0
- package/stack-template/app/ui-kit/src/ui/toggle-button/index.tsx +28 -0
- package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.stories.tsx +85 -0
- package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.test.tsx +97 -0
- package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.tsx +81 -0
- package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button.stories.tsx +46 -0
- package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button.test.tsx +38 -0
- package/stack-template/app/ui-kit/src/ui/toolbar/index.tsx +18 -0
- package/stack-template/app/ui-kit/src/ui/toolbar/toolbar.stories.tsx +35 -0
- package/stack-template/app/ui-kit/src/ui/toolbar/toolbar.test.tsx +11 -0
- package/stack-template/app/ui-kit/src/ui/tooltip/index.tsx +61 -0
- package/stack-template/app/ui-kit/src/ui/tooltip/tooltip.stories.tsx +81 -0
- package/stack-template/app/ui-kit/src/ui/tooltip/tooltip.test.tsx +120 -0
- package/stack-template/app/ui-kit/src/ui/tour/index.tsx +210 -0
- package/stack-template/app/ui-kit/src/ui/tour/tour.stories.tsx +153 -0
- package/stack-template/app/ui-kit/src/ui/tour/tour.test.tsx +131 -0
- package/stack-template/app/ui-kit/src/ui/transition/index.tsx +377 -0
- package/stack-template/app/ui-kit/src/ui/transition/transition.stories.tsx +254 -0
- package/stack-template/app/ui-kit/src/ui/transition/transition.test.tsx +285 -0
- package/stack-template/app/ui-kit/src/ui/tree/index.tsx +68 -0
- package/stack-template/app/ui-kit/src/ui/tree/tree.stories.tsx +139 -0
- package/stack-template/app/ui-kit/src/ui/tree/tree.test.tsx +77 -0
- package/stack-template/app/ui-kit/src/ui/tree-select/index.tsx +251 -0
- package/stack-template/app/ui-kit/src/ui/tree-select/tree-select.stories.tsx +105 -0
- package/stack-template/app/ui-kit/src/ui/tree-select/tree-select.test.tsx +174 -0
- package/stack-template/app/ui-kit/src/ui/tree-table/index.tsx +229 -0
- package/stack-template/app/ui-kit/src/ui/tree-table/tree-table.stories.tsx +111 -0
- package/stack-template/app/ui-kit/src/ui/tree-table/tree-table.test.tsx +137 -0
- package/stack-template/app/ui-kit/src/ui/typography/index.tsx +124 -0
- package/stack-template/app/ui-kit/src/ui/typography/typography.stories.tsx +65 -0
- package/stack-template/app/ui-kit/src/ui/typography/typography.test.tsx +117 -0
- package/stack-template/app/ui-kit/src/ui/upload/index.tsx +39 -0
- package/stack-template/app/ui-kit/src/ui/upload/upload-core.tsx +204 -0
- package/stack-template/app/ui-kit/src/ui/upload/upload-dropzone.tsx +79 -0
- package/stack-template/app/ui-kit/src/ui/upload/upload.stories.tsx +67 -0
- package/stack-template/app/ui-kit/src/ui/upload/upload.test.tsx +204 -0
- package/stack-template/app/ui-kit/src/ui/virtual-scroll/index.tsx +86 -0
- package/stack-template/app/ui-kit/src/ui/virtual-scroll/virtual-scroll.stories.tsx +111 -0
- package/stack-template/app/ui-kit/src/ui/virtual-scroll/virtual-scroll.test.tsx +125 -0
- package/stack-template/app/ui-kit/src/ui/watermark/index.tsx +182 -0
- package/stack-template/app/ui-kit/src/ui/watermark/watermark.stories.tsx +96 -0
- package/stack-template/app/ui-kit/src/ui/watermark/watermark.test.tsx +120 -0
- package/stack-template/app/ui-kit/src/utils/array.test.ts +88 -0
- package/stack-template/app/ui-kit/src/utils/array.ts +51 -0
- package/stack-template/app/ui-kit/src/utils/dom.test.tsx +69 -0
- package/stack-template/app/ui-kit/src/utils/dom.ts +38 -0
- package/stack-template/app/ui-kit/src/utils/format.test.ts +63 -0
- package/stack-template/app/ui-kit/src/utils/format.ts +81 -0
- package/stack-template/app/ui-kit/tests/setup.ts +15 -0
- package/stack-template/app/ui-kit/tsconfig.json +18 -0
- package/stack-template/app/ui-kit/tsup.config.ts +37 -0
- package/stack-template/app/ui-kit/vercel.json +6 -0
- package/stack-template/app/ui-kit/vitest.config.ts +22 -0
- package/stack-template/contracts/auth/token-contract.md +119 -0
- package/stack-template/contracts/auth/users.json +35 -0
- package/stack-template/contracts/db/tasks-schema.sql +62 -0
- package/stack-template/contracts/events/fixtures/task.assigned.json +11 -0
- package/stack-template/contracts/events/fixtures/task.assignment_failed.json +11 -0
- package/stack-template/contracts/events/fixtures/task.created.json +12 -0
- package/stack-template/contracts/events/fixtures/task.deleted.json +10 -0
- package/stack-template/contracts/events/fixtures/task.updated.json +12 -0
- package/stack-template/contracts/events/task-events.md +80 -0
- package/stack-template/contracts/openapi/activity.yaml +196 -0
- package/stack-template/contracts/openapi/auth.yaml +310 -0
- package/stack-template/contracts/openapi/tasks.yaml +316 -0
- package/stack-template/contracts/openapi/users.yaml +345 -0
- package/stack-template/docs/adr/0001-mixed-stack.md +14 -0
- package/stack-template/docs/adr/0002-mf-rspack.md +14 -0
- package/stack-template/docs/adr/0003-contract-first.md +14 -0
- package/stack-template/docs/adr/0004-readonly-schema-tradeoff.md +14 -0
- package/stack-template/docs/adr/0005-fail-closed.md +14 -0
- package/stack-template/docs/adr/0006-fire-and-forget-events.md +14 -0
- package/stack-template/docs/adr/0007-fork-not-upgrade.md +14 -0
- package/stack-template/docs/adr/0008-kafka-outbox-saga.md +24 -0
- package/stack-template/docs/adr/0009-ui-kit-split.md +39 -0
- package/stack-template/docs/adr/README.md +15 -0
- package/stack-template/docs/ai/recipes.md +956 -0
- package/stack-template/docs/ai/table-Theming.md +25 -0
- package/stack-template/docs/ai/table-datadisplay-mz.md +20 -0
- package/stack-template/docs/ai/table-feedback.md +20 -0
- package/stack-template/docs/ai/table-forms.md +26 -0
- package/stack-template/docs/git-flow.md +70 -0
- package/stack-template/docs/parity-matrix.md +102 -0
- package/stack-template/docs/superpowers/contexts/auth-real/gap-answer.md +195 -0
- package/stack-template/docs/superpowers/contexts/auth-real/sf-1.md +21 -0
- package/stack-template/docs/superpowers/contexts/auth-real/sf-2.md +21 -0
- package/stack-template/docs/superpowers/contexts/auth-real/sf-3.md +17 -0
- package/stack-template/docs/superpowers/contexts/auth-real/sf-4.md +20 -0
- package/stack-template/docs/superpowers/contexts/auth-real/sf-5.md +21 -0
- package/stack-template/docs/superpowers/contexts/experience-design.md +85 -0
- package/stack-template/docs/superpowers/contexts/sf-1.md +39 -0
- package/stack-template/docs/superpowers/contexts/sf-2.md +42 -0
- package/stack-template/docs/superpowers/contexts/sf-3.md +42 -0
- package/stack-template/docs/superpowers/contexts/sf-4.md +26 -0
- package/stack-template/docs/superpowers/contexts/sf-5.md +36 -0
- package/stack-template/docs/superpowers/contexts/sf-6.md +36 -0
- package/stack-template/docs/superpowers/contexts/sf-7.md +35 -0
- package/stack-template/docs/superpowers/contexts/sf-cin-overview.md +21 -0
- package/stack-template/docs/superpowers/contexts/ui-redesign/sf-1.md +46 -0
- package/stack-template/docs/superpowers/contexts/ui-redesign/sf-2.md +44 -0
- package/stack-template/docs/superpowers/contexts/ui-redesign/sf-3.md +47 -0
- package/stack-template/docs/superpowers/contexts/ui-redesign/sf-4.md +44 -0
- package/stack-template/docs/superpowers/contexts/ui-redesign/sf-5.md +36 -0
- package/stack-template/docs/superpowers/designs/direction-approved.md +11 -0
- package/stack-template/docs/superpowers/designs/ui-redesign/drafts/a-roulette-soundviz.html +353 -0
- package/stack-template/docs/superpowers/designs/ui-redesign/drafts/b-reference.html +347 -0
- package/stack-template/docs/superpowers/designs/ui-redesign/drafts/c-designer.html +375 -0
- package/stack-template/docs/superpowers/designs/ui-redesign/ds-demo.html +140 -0
- package/stack-template/docs/superpowers/designs/ui-redesign-direction.md +93 -0
- package/stack-template/docs/superpowers/improvements-log.md +158 -0
- package/stack-template/docs/superpowers/mindmaps/auth-real.wakii +115 -0
- package/stack-template/docs/superpowers/mindmaps/kafka-outbox-saga.wakii +110 -0
- package/stack-template/docs/superpowers/mindmaps/micro-boilerplate.wakii +171 -0
- package/stack-template/docs/superpowers/mindmaps/ui-redesign.wakii +116 -0
- package/stack-template/docs/superpowers/mindmaps/vu53-cinematic-experience.wakii +32 -0
- package/stack-template/docs/superpowers/plans/2026-10-12-sf-1-contracts-platform-plan.md +44 -0
- package/stack-template/docs/superpowers/plans/2026-10-12-sf-3-spring-svc-impact.md +69 -0
- package/stack-template/docs/superpowers/plans/2026-10-12-sf-3-spring-svc-plan.md +27 -0
- package/stack-template/docs/superpowers/plans/2026-10-12-sf-4-go-svc-plan.md +99 -0
- package/stack-template/docs/superpowers/plans/2026-10-12-sf-5-fe-shell-plan.md +64 -0
- package/stack-template/docs/superpowers/plans/2026-10-12-sf-6-fe-remotes-plan.md +83 -0
- package/stack-template/docs/superpowers/plans/2026-10-12-sf-7-convergence-plan.md +59 -0
- package/stack-template/docs/superpowers/plans/2026-10-12-sf2-node-svc-plan.md +19 -0
- package/stack-template/docs/superpowers/plans/2026-10-13-sf-1-kafka-foundation-plan.md +30 -0
- package/stack-template/docs/superpowers/plans/2026-10-13-sf-1-ui-redesign-plan.md +28 -0
- package/stack-template/docs/superpowers/plans/2026-10-13-sf-2-node-outbox-plan.md +46 -0
- package/stack-template/docs/superpowers/plans/2026-10-13-sf-3-go-consumer-plan.md +31 -0
- package/stack-template/docs/superpowers/plans/2026-10-13-sf-4-spring-tx-plan.md +96 -0
- package/stack-template/docs/superpowers/plans/2026-10-13-sf-5-convergence-plan.md +21 -0
- package/stack-template/docs/superpowers/plans/2026-10-14-sf-2-ui-redesign-plan.md +32 -0
- package/stack-template/docs/superpowers/plans/2026-10-14-sf-3-ui-redesign-plan.md +34 -0
- package/stack-template/docs/superpowers/plans/2026-10-14-sf-5-ui-redesign-plan.md +35 -0
- package/stack-template/docs/superpowers/plans/2026-10-17-auth-real-plan.md +112 -0
- package/stack-template/docs/superpowers/plans/2026-10-17-ui-kit-split-plan.md +18 -0
- package/stack-template/docs/superpowers/reviews/2026-10-18-data-display-coverage.md +52 -0
- package/stack-template/docs/superpowers/reviews/code-reviewer-sf-5-r1.md +65 -0
- package/stack-template/docs/superpowers/reviews/security-audit-sf-5-auth-real.md +39 -0
- package/stack-template/docs/superpowers/specs/2026-10-12-boilerplate-microservice-mfe.md +110 -0
- package/stack-template/docs/superpowers/specs/2026-10-12-sf-3-spring-svc-design.md +160 -0
- package/stack-template/docs/superpowers/specs/2026-10-12-sf-7-convergence-spec.md +114 -0
- package/stack-template/docs/superpowers/specs/2026-10-12-sf2-node-svc-spec.md +42 -0
- package/stack-template/docs/superpowers/specs/2026-10-13-kafka-outbox-saga.md +111 -0
- package/stack-template/docs/superpowers/specs/2026-10-13-ui-redesign.md +173 -0
- package/stack-template/docs/superpowers/specs/2026-10-14-sf-3-ui-redesign.md +46 -0
- package/stack-template/docs/superpowers/specs/2026-10-14-sf-5-ui-redesign.md +30 -0
- package/stack-template/docs/superpowers/specs/2026-10-17-antd-look-tokens.md +28 -0
- package/stack-template/docs/superpowers/specs/2026-10-17-auth-real-design.md +124 -0
- package/stack-template/docs/superpowers/specs/2026-10-17-tailwind-migration.md +32 -0
- package/stack-template/docs/superpowers/specs/2026-10-17-ui-kit-split.md +44 -0
- package/stack-template/docs/superpowers/specs/2026-10-18-0.3.0-release-notes.md +77 -0
- package/stack-template/docs/toolchain.md +28 -0
- package/stack-template/docs/wakii-playbook.md +172 -0
- package/stack-template/docs/walkthrough.md +204 -0
- package/stack-template/orca.yaml +146 -0
- package/stack-template/package.json +19 -0
- package/stack-template/platform/.env.example +72 -0
- package/stack-template/platform/conventions/01-dockerfile-pattern.md +78 -0
- package/stack-template/platform/conventions/02-healthcheck.md +26 -0
- package/stack-template/platform/conventions/03-logging.md +41 -0
- package/stack-template/platform/conventions/04-error-envelope.md +41 -0
- package/stack-template/platform/conventions/05-ports.md +38 -0
- package/stack-template/platform/conventions/06-configuration.md +25 -0
- package/stack-template/platform/conventions/07-cors.md +23 -0
- package/stack-template/platform/conventions/08-gateway-and-remotes.md +33 -0
- package/stack-template/platform/conventions/09-async-messaging.md +42 -0
- package/stack-template/platform/conventions/README.md +15 -0
- package/stack-template/platform/docker-compose.yml +255 -0
- package/stack-template/platform/gateway/nginx/nginx.conf +137 -0
- package/stack-template/platform/postgres/init/01-init.sh +55 -0
- package/stack-template/pnpm-lock.yaml +15992 -0
- package/stack-template/pnpm-workspace.yaml +24 -0
- package/stack-template/scripts/scaffold/scaffold.sh +110 -0
- package/stack-template/scripts/smoke/e2e.sh +305 -0
- package/stack-template/scripts/snapshot-stack-template.sh +84 -0
- package/stack-template/services/auth-svc/.dockerignore +5 -0
- package/stack-template/services/auth-svc/Dockerfile +32 -0
- package/stack-template/services/auth-svc/README.md +101 -0
- package/stack-template/services/auth-svc/drizzle/0000_init.sql +25 -0
- package/stack-template/services/auth-svc/drizzle/meta/0000_snapshot.json +190 -0
- package/stack-template/services/auth-svc/drizzle/meta/_journal.json +13 -0
- package/stack-template/services/auth-svc/drizzle.config.ts +10 -0
- package/stack-template/services/auth-svc/package.json +35 -0
- package/stack-template/services/auth-svc/pnpm-lock.yaml +2425 -0
- package/stack-template/services/auth-svc/src/app.test.ts +403 -0
- package/stack-template/services/auth-svc/src/app.ts +103 -0
- package/stack-template/services/auth-svc/src/auth-crypto.test.ts +32 -0
- package/stack-template/services/auth-svc/src/auth-crypto.ts +25 -0
- package/stack-template/services/auth-svc/src/db/client.ts +24 -0
- package/stack-template/services/auth-svc/src/db/migrate.ts +72 -0
- package/stack-template/services/auth-svc/src/db/schema.ts +39 -0
- package/stack-template/services/auth-svc/src/db/seed.ts +60 -0
- package/stack-template/services/auth-svc/src/env.test.ts +55 -0
- package/stack-template/services/auth-svc/src/env.ts +57 -0
- package/stack-template/services/auth-svc/src/logger.ts +31 -0
- package/stack-template/services/auth-svc/src/plugins/auth.ts +70 -0
- package/stack-template/services/auth-svc/src/repo.drizzle.integration.test.ts +182 -0
- package/stack-template/services/auth-svc/src/repo.drizzle.ts +144 -0
- package/stack-template/services/auth-svc/src/repo.test-support.ts +168 -0
- package/stack-template/services/auth-svc/src/repo.ts +60 -0
- package/stack-template/services/auth-svc/src/routes/auth.ts +193 -0
- package/stack-template/services/auth-svc/src/routes/health.ts +40 -0
- package/stack-template/services/auth-svc/src/server.ts +54 -0
- package/stack-template/services/auth-svc/tsconfig.json +20 -0
- package/stack-template/services/go-svc/.dockerignore +5 -0
- package/stack-template/services/go-svc/Dockerfile +19 -0
- package/stack-template/services/go-svc/README.md +93 -0
- package/stack-template/services/go-svc/cmd/server/main.go +105 -0
- package/stack-template/services/go-svc/go.mod +12 -0
- package/stack-template/services/go-svc/internal/api/auth.go +83 -0
- package/stack-template/services/go-svc/internal/api/auth_test.go +92 -0
- package/stack-template/services/go-svc/internal/api/envelope.go +61 -0
- package/stack-template/services/go-svc/internal/api/envelope_test.go +51 -0
- package/stack-template/services/go-svc/internal/api/fakes_test.go +105 -0
- package/stack-template/services/go-svc/internal/api/feed.go +98 -0
- package/stack-template/services/go-svc/internal/api/feed_test.go +118 -0
- package/stack-template/services/go-svc/internal/api/health.go +34 -0
- package/stack-template/services/go-svc/internal/api/health_test.go +46 -0
- package/stack-template/services/go-svc/internal/api/json.go +13 -0
- package/stack-template/services/go-svc/internal/api/middleware.go +82 -0
- package/stack-template/services/go-svc/internal/api/middleware_test.go +48 -0
- package/stack-template/services/go-svc/internal/api/openapi/activity.yaml +196 -0
- package/stack-template/services/go-svc/internal/api/openapi.go +29 -0
- package/stack-template/services/go-svc/internal/api/openapi_test.go +38 -0
- package/stack-template/services/go-svc/internal/api/router.go +86 -0
- package/stack-template/services/go-svc/internal/api/stats.go +63 -0
- package/stack-template/services/go-svc/internal/api/stats_test.go +83 -0
- package/stack-template/services/go-svc/internal/api/types.go +32 -0
- package/stack-template/services/go-svc/internal/apperr/apperr.go +9 -0
- package/stack-template/services/go-svc/internal/config/config.go +115 -0
- package/stack-template/services/go-svc/internal/config/config_test.go +92 -0
- package/stack-template/services/go-svc/internal/consumer/envelope.go +78 -0
- package/stack-template/services/go-svc/internal/consumer/envelope_test.go +154 -0
- package/stack-template/services/go-svc/internal/consumer/handler.go +91 -0
- package/stack-template/services/go-svc/internal/consumer/handler_test.go +136 -0
- package/stack-template/services/go-svc/internal/consumer/producer.go +117 -0
- package/stack-template/services/go-svc/internal/consumer/runner.go +194 -0
- package/stack-template/services/go-svc/internal/consumer/runner_test.go +351 -0
- package/stack-template/services/go-svc/internal/logging/logging.go +49 -0
- package/stack-template/services/go-svc/internal/model/model.go +37 -0
- package/stack-template/services/go-svc/internal/resolve/resolver.go +134 -0
- package/stack-template/services/go-svc/internal/resolve/resolver_test.go +82 -0
- package/stack-template/services/go-svc/internal/resolve/token.go +130 -0
- package/stack-template/services/go-svc/internal/resolve/token_test.go +151 -0
- package/stack-template/services/go-svc/internal/store/events.go +71 -0
- package/stack-template/services/go-svc/internal/store/migrate.go +90 -0
- package/stack-template/services/go-svc/internal/store/migrate_test.go +34 -0
- package/stack-template/services/go-svc/internal/store/migrations/0001_create_events.sql +20 -0
- package/stack-template/services/go-svc/internal/store/migrations/0002_widen_action_cascade.sql +14 -0
- package/stack-template/services/go-svc/internal/store/store.go +65 -0
- package/stack-template/services/go-svc/internal/store/tasks.go +109 -0
- package/stack-template/services/go-svc/internal/swagger/assets/LICENSE +202 -0
- package/stack-template/services/go-svc/internal/swagger/assets/NOTICE +2 -0
- package/stack-template/services/go-svc/internal/swagger/assets/favicon-16x16.png +0 -0
- package/stack-template/services/go-svc/internal/swagger/assets/favicon-32x32.png +0 -0
- package/stack-template/services/go-svc/internal/swagger/assets/swagger-ui-bundle.js +2 -0
- package/stack-template/services/go-svc/internal/swagger/assets/swagger-ui.css +3 -0
- package/stack-template/services/go-svc/internal/swagger/index.html +28 -0
- package/stack-template/services/go-svc/internal/swagger/swagger.go +38 -0
- package/stack-template/services/go-svc/test/integration/integration_test.go +523 -0
- package/stack-template/services/node-svc/.dockerignore +5 -0
- package/stack-template/services/node-svc/Dockerfile +27 -0
- package/stack-template/services/node-svc/README.md +155 -0
- package/stack-template/services/node-svc/drizzle/0000_init.sql +17 -0
- package/stack-template/services/node-svc/drizzle/0001_status-assignment-failed.sql +2 -0
- package/stack-template/services/node-svc/drizzle/0002_outbox-table.sql +7 -0
- package/stack-template/services/node-svc/drizzle/meta/0000_snapshot.json +136 -0
- package/stack-template/services/node-svc/drizzle/meta/0001_snapshot.json +136 -0
- package/stack-template/services/node-svc/drizzle/meta/0002_snapshot.json +180 -0
- package/stack-template/services/node-svc/drizzle/meta/_journal.json +27 -0
- package/stack-template/services/node-svc/drizzle.config.ts +10 -0
- package/stack-template/services/node-svc/package.json +39 -0
- package/stack-template/services/node-svc/pnpm-lock.yaml +2706 -0
- package/stack-template/services/node-svc/src/app.test.ts +611 -0
- package/stack-template/services/node-svc/src/app.ts +126 -0
- package/stack-template/services/node-svc/src/clients/spring.ts +53 -0
- package/stack-template/services/node-svc/src/compensation-consumer.test.ts +157 -0
- package/stack-template/services/node-svc/src/compensation-consumer.ts +170 -0
- package/stack-template/services/node-svc/src/db/client.ts +23 -0
- package/stack-template/services/node-svc/src/db/migrate.ts +63 -0
- package/stack-template/services/node-svc/src/db/schema-diff.test.ts +252 -0
- package/stack-template/services/node-svc/src/db/schema.ts +64 -0
- package/stack-template/services/node-svc/src/env.ts +52 -0
- package/stack-template/services/node-svc/src/logger.ts +18 -0
- package/stack-template/services/node-svc/src/outbox-relay.test.ts +141 -0
- package/stack-template/services/node-svc/src/outbox-relay.ts +182 -0
- package/stack-template/services/node-svc/src/plugins/auth.ts +76 -0
- package/stack-template/services/node-svc/src/repo.drizzle.test.ts +182 -0
- package/stack-template/services/node-svc/src/repo.drizzle.ts +158 -0
- package/stack-template/services/node-svc/src/repo.ts +73 -0
- package/stack-template/services/node-svc/src/routes/health.ts +42 -0
- package/stack-template/services/node-svc/src/routes/tasks.ts +287 -0
- package/stack-template/services/node-svc/src/server.ts +91 -0
- package/stack-template/services/node-svc/src/types/api.d.ts +391 -0
- package/stack-template/services/node-svc/src/types/log.ts +3 -0
- package/stack-template/services/node-svc/tsconfig.json +20 -0
- package/stack-template/services/spring-svc/.dockerignore +5 -0
- package/stack-template/services/spring-svc/.mvn/wrapper/maven-wrapper.properties +20 -0
- package/stack-template/services/spring-svc/Dockerfile +22 -0
- package/stack-template/services/spring-svc/README.md +121 -0
- package/stack-template/services/spring-svc/mvnw +332 -0
- package/stack-template/services/spring-svc/mvnw.cmd +206 -0
- package/stack-template/services/spring-svc/pom.xml +144 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/SpringSvcApplication.java +12 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/Team.java +64 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/TeamRepository.java +34 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/User.java +72 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/UserRepository.java +10 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/logging/LowercaseLevelJsonProvider.java +24 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/security/JwtAuthFilter.java +89 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/security/JwtVerifier.java +48 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/service/TeamService.java +84 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ApiError.java +15 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ApiException.java +37 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/DevCorsConfig.java +41 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ErrorEnvelope.java +27 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/GlobalExceptionHandler.java +90 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/HealthController.java +46 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ReadinessService.java +40 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/TeamController.java +79 -0
- package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/UserController.java +187 -0
- package/stack-template/services/spring-svc/src/main/java/db/migration/V2__SeedUsers.java +66 -0
- package/stack-template/services/spring-svc/src/main/resources/application.yml +42 -0
- package/stack-template/services/spring-svc/src/main/resources/db/migration/V1__init.sql +24 -0
- package/stack-template/services/spring-svc/src/main/resources/logback-spring.xml +34 -0
- package/stack-template/services/spring-svc/src/main/resources/openapi/users.yaml +345 -0
- package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/logging/LogShapeTest.java +39 -0
- package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/security/JwtAuthFilterTest.java +106 -0
- package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/seed/SeedMatchIntegrationTest.java +68 -0
- package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/service/TeamServiceRollbackTest.java +122 -0
- package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/DevCorsTest.java +45 -0
- package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/HealthCheckTest.java +56 -0
- package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/TeamApiTest.java +139 -0
- package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/TestPingController.java +21 -0
- package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/UserApiTest.java +182 -0
- package/stack-template/stack-manifest.json +285 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Theming & Hooks — when to use
|
|
2
|
+
|
|
3
|
+
Group: theming-hooks (worker F). Source of truth: `app/ui-kit/src/provider/` + `app/ui-kit/src/hooks/`.
|
|
4
|
+
Merge target: AGENTS.md (coordinator-owned — do not edit AGENTS.md directly).
|
|
5
|
+
|
|
6
|
+
| Component | Use when | Power props/combo |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| `UiKitProvider` | Scope a theme subtree — dark mode or runtime token overrides with zero re-render | `theme`: `'dark'` or object `{ accent, accentHi, canvas, s1/s2/s3, ink/ink2/ink3, line, done/doing/fail }` (13 keys → CSS vars cascade to descendants) · `accent`/`accentHover` shorthand for one-line brand swap · wrap app root or a single panel |
|
|
9
|
+
| `useForm` | Form state + zod validation with a minimal RHF-style API | `schema` (zod = source of truth) · `mode`: `'onSubmit' \| 'onBlur' \| 'onChange'` · errors land on `errors.field`, auto-focus first `[name]` invalid · combo: `Field` + `Input` + `Button` |
|
|
10
|
+
| `useClickAway` | Close on outside interaction — dropdown, popover, menu | returned `ref` attaches to the "inside" element · handler via ref (no re-bind) · combo: `Dropdown`/`Menu`/custom popover |
|
|
11
|
+
| `useFocusTrap` | Lock Tab focus inside a dialog; restore focus to trigger on close | `(ref, active)` — focuses first focusable (or container), cycles Tab, restores on deactivate · combo: `Modal`/`Drawer` (built in) or any custom `role="dialog"` |
|
|
12
|
+
| `useCopyToClipboard` | Copy-to-clipboard with user feedback | returned `[copiedText, copy]` — `copy(text)` → boolean success · combo: `Button` + "Copied!" flash, input copy affordance |
|
|
13
|
+
| `useCountdown` | Ticking countdown — OTP resend, cooldown lock | `initialSeconds` (+ `intervalMs`) → `{ remaining, restart, … }` · combo: `Button` disabled while counting |
|
|
14
|
+
| `useDebounce` | Delayed value — search-as-you-type, expensive derivations | `delayMs` (default 500) · combo: `Input` search → `Table`/`List` filter, API calls |
|
|
15
|
+
| `useThrottle` | Rate-limited value — scroll/resize/infinite-scroll handlers | `intervalMs` (default 500) · combo: `useWindowSize` consumers, scroll triggers |
|
|
16
|
+
| `useTimeout` | Component-safe timeout effect | `callback` + `delayMs` → `{ start, clear, … }` · combo: toast auto-dismiss, tooltip delays |
|
|
17
|
+
| `useToggle` | Boolean on/off state | `initialValue` → `[value, toggle]` · combo: `Collapse` custom triggers, sidebar collapsed, any show/hide |
|
|
18
|
+
| `useDefault` | State that falls back to a default when value is undefined | `defaultValue` · combo: controlled/uncontrolled bridge, form field fallbacks |
|
|
19
|
+
| `usePrevious` | Value from the previous render | single arg · combo: change detection in effects, transition diffs |
|
|
20
|
+
| `useHover` | Hover state without CSS — JS-driven visuals | returned `ref` · combo: drag handles, canvas-like interactions CSS can't express |
|
|
21
|
+
| `useKeyPress` | Reactive "is key pressed" + optional callback | `targetKey` (`'Escape'`, `'Enter'`…) + `onPress` · combo: ESC-close handlers (dialogs have it built in), shortcut hints |
|
|
22
|
+
| `useLockBodyScroll` | Prevent background scroll while open | `locked` (default true) · combo: `Modal`/`Drawer` (built in), fullscreen previews |
|
|
23
|
+
| `useMediaQuery` | Reactive matchMedia boolean, updates in real time | `query` (e.g. `'(min-width: 768px)'`) · combo: responsive JS behavior, `prefers-reduced-motion` branches |
|
|
24
|
+
| `useWindowSize` | Live viewport width/height | no args · combo: virtualized lists, breakpoint-adjacent JS logic |
|
|
25
|
+
| `useLocalStorage` / `useSessionStorage` | Persistent (tab) / session state without effect boilerplate | `key` + `initialValue` · combo: theme preference, drafts, wizard step memory |
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Data Display m–z — when to use
|
|
2
|
+
|
|
3
|
+
> Group G slice (components `m`→`z`). Merged into `AGENTS.md` "Data Display" section by the coordinator.
|
|
4
|
+
> APIs verified against source during the full-case-matrix audit (stories 56→59, tests 95→110 in this group).
|
|
5
|
+
|
|
6
|
+
| Component | Use when | Power props / combo |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| `Schedule` | Month calendar (FullCalendar dayGrid) for date-driven events — sprints, deadlines, bookings | `events` + `onEventClick` · `fallback` node for missing peer-dep `@fullcalendar/*` · heavy: subpath `@wakii/ui-kit/schedule` · wrap in `Card` |
|
|
9
|
+
| `Segmented` | Compact single-choice switcher with no panels — view period, density, sort mode | `options` + controlled `value`/`onChange` · swap for `Tabs` when you don't need content panels · toolbar/filter-bar headers |
|
|
10
|
+
| `Skeleton` | Loading placeholder mirroring the real layout before data lands | `variant` (text/row/card/circle/button) + `count` · stack `circle`+`text`+`row` to compose a card · prefer `Table loading` for grids · `classNames` slots (`wrapper`/`bone`) |
|
|
11
|
+
| `Statistic` | Big-number KPI readout — title + value + prefix/suffix | `value` + `prefix`/`suffix` · `valueStyle` to color by status · tabular-nums built in · `Card` dashboards |
|
|
12
|
+
| `Steps` | Horizontal wizard progress header (done/current/waiting) | `current` (prop-driven, no internal state) · `aria-current="step"` built in · `Button` next/back beneath it (recipe 4) |
|
|
13
|
+
| `Table` | Data grid — sort/filter/paginate/select for CRUD backbones | `columns` (`sortable`/`filterable`/`render`/`align`) · recipe 2 CRUD · `virtual` for 5k+ rows · `selectionMode` bulk actions · `globalFilter` · `classNames` slots (`wrapper`/`header`/`row`/`cell`) |
|
|
14
|
+
| `Tabs` | Switch between content panels in place — settings, detail views | `items` + controlled `activeKey`/`onChange` · settings pages (recipe 9) · swap for `Segmented` when panels aren't needed · `classNames` slots (`wrapper`/`tablist`/`tab`/`panel`) |
|
|
15
|
+
| `Tag` | Tiny label chip — statuses, metadata; `Tag.Checkable` for filter chips | `closable`+`onClose` (consumer removes) · Checkable: `checked`+`onChange` · `Table` status cells · `Checkable` chip groups in filter bars |
|
|
16
|
+
| `Timeline` | Vertical activity feed — dot + text + time per entry | `items` (per-item `color` dot, `label` time) · `Card` body feeds · audit/history panels (recipe 6) |
|
|
17
|
+
| `Tree` | Expand/collapse hierarchy — file trees, category nav | `data` + `defaultExpandedKeys` · uncontrolled expand state · side navigation panels · use `TreeSelect` when a value must be picked |
|
|
18
|
+
| `TreeSelect` | Pick one leaf from a hierarchy — searchable `Parent / Child` path | `treeData` + `searchable` (label or path match) · `clearable` in filter bars · leaf-only selection · `ariaLabel` required — wrap in `Field` |
|
|
19
|
+
|
|
20
|
+
> Note: `Pagination` also falls in the m–z range but is **not** part of group G's slice — needs an owner before merging.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Feedback & Overlay — when to use (group H)
|
|
2
|
+
|
|
3
|
+
Source: `app/ui-kit/src/ui/*` real props. 14 components. Merge target: `AGENTS.md` section "Feedback & Overlay — khi nào dùng".
|
|
4
|
+
|
|
5
|
+
| Component | Use when | Power props/combo |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| `Alert` | Inline status banner that stays in the page flow (not transient) — filled by default, `outlined` for the tinted look | `type` (`success\|info\|warning\|error`) · `variant="outlined"` · `description` detail line · `closable`+`onClose` dismissible · `classNames` slots (antd v5) |
|
|
8
|
+
| `BlockUI` | Lock a region in place while it is busy — scrim + centered label over the wrapped content | `blocked` toggle · `message` label on the scrim · wrap `Table`/`Card` during fetch · pair with `Spinner` outside the lock |
|
|
9
|
+
| `ContextMenu` | Right-click menu on a region — positioned at the pointer | `items` (key `'---'` = divider, `danger`/`disabled` per item) · `onItemClick` switch by key · arrow-key nav + ESC + outside-click built-in |
|
|
10
|
+
| `Drawer` | Side panel for detail/form without leaving the page (portal, focus trap, scroll lock) | `open`+`onClose` (ESC, mask click, × wired) · `width` (default 378 antd) · `footer` action row · `classNames` slots |
|
|
11
|
+
| `Dropdown` | Button-triggered action menu — role=menu with full keyboard nav | `items` + `onItemClick` · `trigger` = `Button` · `'---'` divider · `danger`/`disabled` per item · ArrowUp/Down/Home/End built-in |
|
|
12
|
+
| `Message` | Transient global toast — static API, 3s auto-dismiss, no React state needed | `message.success\|info\|warning\|error(content)` · `classNames` slots (wrapper/icon/content) |
|
|
13
|
+
| `Modal` | Blocking confirm/dialog on top of the page (portal, focus trap, scroll lock) | `open` + `onOk`/`onCancel` (ESC + mask + × all cancel) · `danger` red OK · `confirmLoading` locks both buttons · `okText`/`cancelText` · `classNames` slots |
|
|
14
|
+
| `Notification` | Rich toast with title + description — static API, 4.5s, manual × close | `notification.success(title, description?)` · `classNames` slots (wrapper/title/content) |
|
|
15
|
+
| `Popconfirm` | Confirm bubble anchored to a trigger (delete guard) — ESC = cancel, role=dialog | `open` (controlled) + `onConfirm`/`onCancel` · `danger` red icon/OK · `title` + `description` · `okText`/`cancelText` |
|
|
16
|
+
| `Progress` | Line progress bar with % readout — values clamped to 0–100 | `percent` · `status="exception\|success"` recolors bar (red/green) · `showInfo={false}` hides % |
|
|
17
|
+
| `Result` | Full-area status page — icon + color + default title per status | `status` (`success\|error\|info\|warning\|404\|500`) · `title`/`subTitle` override · `extra` action buttons |
|
|
18
|
+
| `Skeleton` | Loading placeholder bones with shimmer wave | `variant` (`text\|row\|card\|circle\|button`) · `count` repeats a bone · compose circle+text+row for a loading card · `classNames` slots (wrapper/bone) |
|
|
19
|
+
| `Spinner` | Inline busy indicator — 3 variants, label is the required accessible name | `label` (REQUIRED aria-label) · `variant` (`ring\|dots\|bars`) · `size` sm/md/lg · `color` (`inverse` on dark surfaces) |
|
|
20
|
+
| `Tooltip` | Hover/focus hint bubble (top/bottom) — portal-free, wraps the trigger in place | `title` (bubble content) · `placement="top\|bottom"` · `aria-describedby` auto-wired · ESC dismisses |
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Forms — when to use (group E)
|
|
2
|
+
|
|
3
|
+
Source: `app/ui-kit/src/ui/*` real props. 20 components. Merge target: `AGENTS.md` section "Forms — khi nào dùng".
|
|
4
|
+
|
|
5
|
+
| Component | Use when | Power props/combo |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| `AutoComplete` | Free-text input with type-to-filter suggestions (search-as-type) | `suggestions` · `onChange` raw text + `onSelect` picked value · empty `suggestions` → dropdown never opens · `Field` wrap |
|
|
8
|
+
| `Calendar` | Month grid for inline date browsing/picking (no trigger field) | `value` + `onChange` controlled day · `locale="vi"\|"en"` · `range` + `onDayHover` (drives DatePicker) · `bare` inside panels |
|
|
9
|
+
| `CascadeSelect` | Hierarchical pick (region → city → ward) through expanding panel columns | `options` nested `children` define levels · `value` is a path array `["hn","bd"]` · keyboard ↑↓/Enter/Esc built into the trigger |
|
|
10
|
+
| `Checkbox` | Single on/off decision with a visible label | `checked` + `onChange(bool)` · `disabled` · inside `Field` — prefer `Switch` for instant-apply settings |
|
|
11
|
+
| `Chips` | Multi-value tag input — Enter adds, × removes, Backspace pops the last | `value: string[]` + `onChange` · `placeholder` hint · `disabled` hides input + remove buttons · duplicates ignored |
|
|
12
|
+
| `ColorPicker` | Color choice: swatch + preset grid + native picker + hex field | `presets` curated palette (`[]` = native + hex only) · `value` hex · `onChange` fires from preset/native/hex alike |
|
|
13
|
+
| `DatePicker` | Date pick through a trigger + calendar panel | `range` + `showTime` + `locale` vi/en · `value: Date \| [Date, Date]` · `now` injectable for tests · `prefix` icon · footer "Today"/OK |
|
|
14
|
+
| `Inplace` | Click-to-edit inline value (read mode → edit form → close) | `display` + `children` (the edit form) · `onClose` after closing · pair `Input`/`Textarea` inside |
|
|
15
|
+
| `InputMask` | Constrained format typing — `9`=digit, `a`=letter, `*`=alnum, others literal | `mask` · `placeholder` showing the format · `ariaLabel` for accessible name · typing past an invalid char just stops |
|
|
16
|
+
| `InputNumber` | Numeric input with vertical stepper + ↑↓ + min/max clamp | `min`/`max`/`step` · `invalid` red border · blur snaps the display to the clamp · `value` is read at mount (uncontrolled internal) |
|
|
17
|
+
| `InputOTP` | N single-char cells with auto-advance + multi-cell paste | `length` · `value`/`onChange` as one joined string · `ariaLabel` per cell ("code 1…") · digits only · Backspace walks back |
|
|
18
|
+
| `Mention` | Textarea with @-triggered mention list | `suggestions` filtered by the text after @ · ↑↓ + Enter/Esc keyboard pick · picks insert `"@Name "` · `value`/`onChange` is the full text |
|
|
19
|
+
| `Password` | Password field with show/hide toggle (+ optional strength meter) | `showStrength` meter with --st-* colors · `ariaLabel` · `value`/`onChange` · wraps `Input` |
|
|
20
|
+
| `PickList` | Two-column transfer (source ⇄ target) | `source`/`target` + `onChange(source, target)` · multi-pick then chevron move · each listbox keyboard-navigable (↑↓ + Enter/Space) · `aria-multiselectable` |
|
|
21
|
+
| `Radio`/`RadioGroup` | Single choice among a few always-visible options | `RadioGroup options` + `value` · per-option `disabled` · standalone `Radio` for one-offs · prefer `Select` when options are many |
|
|
22
|
+
| `Slider` | Numeric pick on a track — single value or a range | `range: [lo, hi]` + `onRangeChange` · `step` snapping · keyboard ←↓/→↑ clamped · `ariaLabel` required (`role="slider"`) |
|
|
23
|
+
| `Switch` | Instant on/off setting toggle | `checked` + `onChange` · `size="small"` for dense rows · inside `Field`/settings `Tabs` · `role="switch"` + `aria-checked` built-in |
|
|
24
|
+
| `TimePicker` | HH:mm pick via stepper panel (+ "Now" shortcut) | `value` Date keeps its date-part on change, string `"HH:mm"` emits epoch-day · `locale` vi/en · `now` injectable for tests · pairs with `DatePicker` `showTime` |
|
|
25
|
+
| `ToggleButton` | Button with a pressed state (on/off action) | `checked` exposed as `aria-pressed` · `disabled` · clusters of toggles (filters/view switches) · unchecked = default variant look |
|
|
26
|
+
| `TreeSelect` | Pick a LEAF from a hierarchy, with search + clear | `treeData` nested `children` (parents are headers, not pickable) · `searchable` filters by label/path · `clearable` × resets · trigger shows the `"A / B"` path |
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Git flow — architecture-overview
|
|
2
|
+
|
|
3
|
+
Quy ước nhánh + merge cho repo boilerplate. Mục tiêu: `main` luôn xanh CI + deployable,
|
|
4
|
+
mọi thay đổi đi qua PR để có evidence + review trail (CI chạy trên PR trước khi vào main).
|
|
5
|
+
|
|
6
|
+
## Nhánh
|
|
7
|
+
|
|
8
|
+
| Loại | Tên | Từ | Vào |
|
|
9
|
+
|---|---|---|---|
|
|
10
|
+
| Story (epic/SF) | `__STACK_ORG__/story-<slug>` hoặc `__STACK_ORG__/sf-N-<slug>` | `main` | PR → `main` |
|
|
11
|
+
| Fix | `__STACK_ORG__/fix-<slug>` | `main` | PR → `main` |
|
|
12
|
+
| Docs/chore nhỏ | `__STACK_ORG__/docs-<slug>` / `__STACK_ORG__/chore-<slug>` | `main` | PR → `main` |
|
|
13
|
+
|
|
14
|
+
Quy tắc:
|
|
15
|
+
|
|
16
|
+
1. **Nhánh mới luôn từ `main` mới nhất** (`git fetch origin && git checkout -b <tên> origin/main`) — tránh mâu thuẫn với các merge đang lơ lửng.
|
|
17
|
+
2. **Không push thẳng `main`.** Từ 2026-10-17: thay đổi vào main qua PR (CI gates chạy trên PR). Ngoại lệ thực tế khẩn (CI infra chết) — merge trực tiếp + nêu rõ trong commit message.
|
|
18
|
+
3. **Một nhánh = một chủ đề.** Rename/chore lớn (vd `frontend/ → app/`) là commit riêng, không trộn với feature.
|
|
19
|
+
4. Worktree song song (Orca/Claude sessions): mỗi session một nhánh riêng; **đọc `git log` nhánh TRƯỚC khi commit** — branch có thể đã được session khác đẩy tiến.
|
|
20
|
+
|
|
21
|
+
## PR
|
|
22
|
+
|
|
23
|
+
- Mở bằng `gh pr create` — template tự áp dụng (`.github/pull_request_template.md`).
|
|
24
|
+
- **CI phải xanh trên PR trước merge** (convergence chạy mọi push; các workflow khác theo paths).
|
|
25
|
+
- **Merge = `--no-ff`**, message theo convention: `merge(<loại>): <tóm tắt>` + ghi rõ nguồn
|
|
26
|
+
(vd `merge(feat): ui-kit — tách design system + Storybook 9 (ADR-0009)`).
|
|
27
|
+
- Sau merge: xoá nhánh remote (`git push origin --delete <nhánh>`) + local khi không còn dùng.
|
|
28
|
+
- Self-merge cho phép với docs/chore nhỏ; feature/fix đụng runtime cần ≥1 approve (reviewer
|
|
29
|
+
là agent `code-reviewer` hoặc người).
|
|
30
|
+
|
|
31
|
+
## Commit message
|
|
32
|
+
|
|
33
|
+
- Convention: `<type>(<scope>): <mô tả>` — type: `feat|fix|refactor|docs|test|chore|merge`.
|
|
34
|
+
- Body ghi **root cause + evidence** khi là fix (mẫu: `fix(ci): convergence...` — nêu run ID,
|
|
35
|
+
local repro); ghi **verified gì** khi là refactor/feat (số test, build PASS).
|
|
36
|
+
- Đổi behavior + story workflow → chụp evidence vào `docs/superpowers/evidence/`.
|
|
37
|
+
|
|
38
|
+
## Rule được ENFORCE (husky pre-push + commit-msg)
|
|
39
|
+
|
|
40
|
+
⚠️ 2026-10-17: GitHub Actions DISABLE (billing) → **hooks là lớp chính**. `.husky/pre-push`
|
|
41
|
+
chặn push vi phạm 2 rule sau + chạy FE checks (typecheck/vitest/build) cho package bị đổi:
|
|
42
|
+
|
|
43
|
+
1. **Branch name**: `__STACK_ORG__/<story|sf|fix|docs|chore|feat>-<slug-kebab>`
|
|
44
|
+
(vd `__STACK_ORG__/fix-gosvc-recent-events`, `__STACK_ORG__/sf-5-ui-redesign-conv`)
|
|
45
|
+
2. **Commit message**: `<type>(<scope>): <mô tả>` với type ∈
|
|
46
|
+
`feat|fix|refactor|docs|test|chore|style|perf|build|ci|revert`
|
|
47
|
+
(merge commits "Merge pull request #N" được ngoại lệ)
|
|
48
|
+
|
|
49
|
+
pre-push CHẠY THÊM FE checks (typecheck/vitest/build-storybook) cho package có file đổi
|
|
50
|
+
(so với origin/main) — thay thế lớp CI shell/remotes/ui-kit đã tắt.
|
|
51
|
+
|
|
52
|
+
Feedback sớm ngay tại máy — **husky** tự cài khi `pnpm install` (root `prepare` script
|
|
53
|
+
chạy `husky`, guard `test -d .git` để không chết trong docker/CI không có .git):
|
|
54
|
+
|
|
55
|
+
- `.husky/commit-msg` — validate conventional commit TRƯỚC khi commit tạo (mirror
|
|
56
|
+
git-guard; merge commits được ngoại lệ; thoát khẩn `git commit --no-verify` — CI vẫn chặn)
|
|
57
|
+
- CI `git-guard` vẫn là lớp enforce cuối cùng (hook chỉ là feedback sớm, ai tắt hook
|
|
58
|
+
cũng không qua nổi PR)
|
|
59
|
+
|
|
60
|
+
Worktree (Orca/Claude session): `pnpm install` trong worktree cũng chạy root `prepare`
|
|
61
|
+
→ husky tự active theo worktree đó. Bỏ qua khẩn: `git push --no-verify` (tự chịu trách
|
|
62
|
+
nhiệm — KHÔNG có lớp CI phía sau cho đến khi billing được khôi phục).
|
|
63
|
+
|
|
64
|
+
## Checklist nhanh trước merge
|
|
65
|
+
|
|
66
|
+
- [ ] Suite local xanh (xem bảng lệnh trong CLAUDE.md — `test_all:` của orca.yaml)
|
|
67
|
+
- [ ] CI xanh trên nhánh/PR (kể cả `convergence`)
|
|
68
|
+
- [ ] Không đụng READ-LOCKED (`app/shared/src/*.ts` logic + `mfToolkit`) nếu chưa có epic duyệt
|
|
69
|
+
- [ ] Đụng contract → sync đủ bề mặt (xem agent `contracts-keeper`)
|
|
70
|
+
- [ ] Descriptor đồng bộ (CLAUDE.md / orca.yaml / agents) nếu đổi cấu trúc, port, lệnh
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Parity matrix — benchmark → ui-kit
|
|
2
|
+
|
|
3
|
+
Bảng đối chiếu component/benchmark gốc ↔ bản token hoá trong `app/ui-kit`.
|
|
4
|
+
"Đủ dùng" = đủ surface chính của benchmark, không đuổi 100% API. Cập nhật mỗi
|
|
5
|
+
batch ship (cột "Mức" ý kiến review, không phải cam kết API).
|
|
6
|
+
|
|
7
|
+
| Component | Benchmark | Mức | Ghi chú parity |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| Button | antd | đủ dùng | variant `type` + `htmlType` tách (type của antd = htmlType), size, danger, loading |
|
|
10
|
+
| Input / Textarea | antd | đủ dùng | h-8, status error = prop `invalid`, prefix/suffix affix, allowClear, size small/middle/large |
|
|
11
|
+
| InputNumber | PrimeReact | đủ dùng | stepper icon XẶP DỌC trong mép phải, keyboard ↑↓, clamp min/max |
|
|
12
|
+
| Select / MultiSelect | PrimeReact | đủ dùng | filterable, multiple chips + select-all, option groups, loading, showClear |
|
|
13
|
+
| AutoComplete / CascadeSelect | PrimeReact | đủ dùng | cùng ngôn ngữ Select |
|
|
14
|
+
| DatePicker / TimePicker | antd | đủ dùng | range + showTime, locale vi/en, TimePicker stepper Giờ/Phút |
|
|
15
|
+
| Calendar | PrimeReact ô vuông → ngôn ngữ nút chung | đủ dùng | states theo pagination: outline thường / accent selected / ring today / adjacent disabled; locale vi/en + range |
|
|
16
|
+
| Table (DataTable) | PrimeReact | đủ dùng | client-side data grid + filter + Skeleton shimmer |
|
|
17
|
+
| List | antd | đủ dùng | items + renderItem, loading→Skeleton, empty→EmptyState, pagination client |
|
|
18
|
+
| Pagination | antd | đủ dùng | item vuông 32 outline, active accent đặc + fontWeightStrong, SVG chevron, ellipsis `···` jump ±5 |
|
|
19
|
+
| Alert | antd | đủ dùng | **filled mặc định** (WCAG AA), `variant="outlined"` giữ look cũ |
|
|
20
|
+
| Menu (đa cấp) | antd | đủ dùng | vertical/horizontal, submenu ∞ cấp, auto-open selectedKey, animate grid-rows, a11y menu/menuitem |
|
|
21
|
+
| Menubar / ContextMenu / PanelMenu / TabMenu / SplitButton | PrimeReact | đủ dùng | họ menu navigation; ContextMenu right-click + separator |
|
|
22
|
+
| Sidebar | antd Layout.Sider | đủ dùng | collapsible 200↔80 icon-only, brand/footer slot, `MenuCompactContext` |
|
|
23
|
+
| Dropdown / Toolbar / SpeedDial / Splitter | PrimeReact | đủ dùng | navigation phụ |
|
|
24
|
+
| Tabs | antd/PrimeReact | đủ dùng | ARIA tabs pattern |
|
|
25
|
+
| Upload / UploadDropzone | antd | đủ dùng | hidden input + beforeUpload guard, drag-drop, danh sách file |
|
|
26
|
+
| Field | antd Form.Item (lite) | đủ dùng | label + error(role=alert)/hint, id `aria-describedby` suy từ htmlFor |
|
|
27
|
+
| useForm | React Hook Form (lite) + zod | đủ dùng | values/errors/touched, mode onSubmit/onBlur/onChange, focus-first-invalid; zod peer-dep |
|
|
28
|
+
| Icon | primeicons 7.0.0 | đủ dùng | 48 icon path data gốc, viewBox 24, fill currentColor, tree-shake import thẳng |
|
|
29
|
+
| Modal / Drawer / Notification / Message / Popconfirm | antd | đủ dùng | feedback family; Message static API `message.success()` |
|
|
30
|
+
| Tooltip | antd | đủ dùng | placement top/bottom, trigger hover + focus |
|
|
31
|
+
| Progress / Statistic / Result / Steps / Space / Divider / Descriptions / Collapse / Card / Breadcrumb / Image / Tag / Badge / Avatar | antd | đủ dùng | display family; Result 404/500, AvatarGroup max "+N" |
|
|
32
|
+
| Carousel | PrimeReact API + Swiper engine | đủ dùng | peer-dep swiper qua subpath `@wakii/ui-kit/carousel`; nút nav direct slide API (v14-safe) |
|
|
33
|
+
| Chart | Chart.js | đủ dùng | subpath `@wakii/ui-kit/chart` |
|
|
34
|
+
| Schedule | FullCalendar | đủ dùng | subpath `@wakii/ui-kit/schedule`; peer optional (fallback khi chưa cài) |
|
|
35
|
+
| Editor | Tiptap | đủ dùng | subpath `@wakii/ui-kit/editor` |
|
|
36
|
+
| TreeSelect | antd TreeSelect (lite) | đủ dùng | data cây đệ quy, chỉ chọn leaf, trigger hiện đường dẫn |
|
|
37
|
+
| AvatarGroup | antd Avatar.Group | đủ dùng | stack overlap `-ml-2` + ring, max → pill "+N" tooltip |
|
|
38
|
+
| Hooks ×16 | usehooks.com | đủ dùng | useDebounce/useThrottle/useToggle/useLocalStorage/useSessionStorage/useMediaQuery/useWindowSize/useHover/useClickAway/useKeyPress/useTimeout/useCountdown/useCopyToClipboard/usePrevious/useDefault/useLockBodyScroll |
|
|
39
|
+
| Skeleton / Spinner / BusyBox / EmptyState / BlockUI / ScrollTop / Segmented / Knob / Inplace / Rating / Slider / Switch / Checkbox / Radio / ToggleButton / Password / InputMask / InputOTP / Mention / Galleria / Timeline / OrderList / PickList / ColorPicker / Knob | PrimeReact | đủ dùng | Tier 1–4 (xem story từng comp) |
|
|
40
|
+
| Typography | antd | đủ dùng | Title level 1–5, Text type, code/keyboard/copyable; metrics antd |
|
|
41
|
+
|
|
42
|
+
## Gap vs antd + MUI + PrimeReact — kế hoạch OCD-completion (2026-10-18)
|
|
43
|
+
|
|
44
|
+
Đối chiếu catalog 3 thư viện chuẩn; "đủ dùng" ở bảng trên nghĩa là surface CHÍNH, chưa phải
|
|
45
|
+
toàn bộ case. Danh sách dưới = còn thiếu thật, xếp theo giá trị usage thực tế:
|
|
46
|
+
|
|
47
|
+
### P0 — dùng gần như mọi app (làm trước)
|
|
48
|
+
|
|
49
|
+
| Thiếu | Benchmark | Ghi chú |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `Grid` (Row/Col) + `Flex` | antd Grid/Flex, MUI Grid/Stack | layout primitive nền tảng — hiện chỉ có `Space`; responsive span/gutter |
|
|
52
|
+
| `Popover` | antd Popover, MUI Popover, PrimeReact OverlayPanel | panel neo trigger nội dung tự do — Tooltip chỉ text, Popconfirm chỉ confirm |
|
|
53
|
+
| `Input.Search` | antd | variant input + nút search bên phải; filter-bar dùng liên tục |
|
|
54
|
+
| `Link` | MUI Link, antd Typography.Link | typography hiện KHÔNG có Link (đã verify grep) |
|
|
55
|
+
| `Affix` | antd | sticky wrapper cho toolbar/filter-bar |
|
|
56
|
+
| `Table` expandable rows | antd Table | row mở rộng chi tiết — CRUD hay dùng (đã verify chưa có) |
|
|
57
|
+
|
|
58
|
+
### P1 — app thật hay cần
|
|
59
|
+
|
|
60
|
+
| Thiếu | Benchmark | Ghi chú |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `Timesheet` | KHÔNG có sẵn ở antd/MUI/Prime (phải tự ghép DataGrid) | **user yêu cầu 2026-10-18** — domain composite: grid tuần × task, cell giờ InputNumber, tổng hàng/cột/grand, weekend shading, locale vi/en, week nav · làm được = hơn cả 3 benchmark |
|
|
63
|
+
| `DragDrop` + `KanbanBoard` | antd/MUI KHÔNG có (tự ghép dnd-kit) · PrimeReact chỉ DragDrop thô | **user yêu cầu 2026-10-18** — primitives Draggable/DropZone native 0-deps (desktop) + keyboard-move a11y · KanbanBoard composite (columns/cards/onCardMove/WIP-limit/renderCard) · touch = hạn chế đã ghi (hướng nâng cấp: peer-dep dnd-kit nếu app cần) |
|
|
64
|
+
| `Parallax` + `Reveal` + `CountUp` | KHÔNG component nào của 3 benchmark có (phải tự viết / react-spring) | **user yêu cầu 2026-10-18** — họ motion-effects 0-deps: Parallax scroll-linked transform (rAF) · Reveal enter-on-scroll (IntersectionObserver + keyframes sẵn) · CountUp số đếm animate · tôn trọng prefers-reduced-motion · differentiator "làm hơn đối thủ" |
|
|
65
|
+
| `Anchor` | antd | scroll-spy nav cho trang docs/long-form |
|
|
66
|
+
| `QRCode` | antd | link thanh toán / chia sẻ (bối cảnh VN dùng nhiều) |
|
|
67
|
+
| `Watermark` | antd | chống copy nội dung nhạy cảm |
|
|
68
|
+
| `Tour` | antd | onboarding sản phẩm; kết hợp `useFocusTrap` |
|
|
69
|
+
| `ToggleButtonGroup` | MUI | cluster `ToggleButton` hiện chỉ đơn lẻ |
|
|
70
|
+
| `VirtualScroller` | PrimeReact | `Table virtual` đã có — standalone cho List dài |
|
|
71
|
+
|
|
72
|
+
### P2 — niche, chỉ làm khi có app tiêu thụ
|
|
73
|
+
|
|
74
|
+
`Dock` (PrimeReact) · `MegaMenu` (PrimeReact) · `OrganizationChart` · `TreeTable` ·
|
|
75
|
+
`Terminal` · `Fieldset/Panel` (Card phủ phần lớn) · `DeferredContent` · motion primitives
|
|
76
|
+
(`<Fade>/<Zoom>` wrapper — keyframes đã có trong tokens).
|
|
77
|
+
|
|
78
|
+
### P2-CHUẨN-HÓA 2026-10-18 (user: "vẫn chưa đủ") — full-catalog diff, sóng xây mới
|
|
79
|
+
|
|
80
|
+
| Thiếu | Benchmark | Giá trị | Owner |
|
|
81
|
+
|---|---|---|---|
|
|
82
|
+
| `Layout` (Header/Content/Footer/Sider wiring) | antd Layout | CAO — app shell thật | W7 |
|
|
83
|
+
| `Form.List` (Field.Array dynamic add/remove) | antd Form.List | CAO — form động | W6 |
|
|
84
|
+
| `TreeTable` | PrimeReact | medium — cây dữ liệu bảng | D |
|
|
85
|
+
| `OrgChart` + `TriStateCheckbox` | PrimeReact | medium + nhỏ | V2 |
|
|
86
|
+
| `MegaMenu` + `SlideMenu` | PrimeReact | medium — nav advanced | W9 |
|
|
87
|
+
| `Fade/Zoom/Collapse` transitions + `Backdrop` | MUI transitions | medium — motion composable | W8 |
|
|
88
|
+
| `BottomNavigation` + `FloatButton` + `Fieldset` + `Terminal` + `DeferredContent` | MUI/antd/PrimeReact | nhỏ — mobile/utility | V1 (sau taxonomy) |
|
|
89
|
+
|
|
90
|
+
### Case-coverage OCD (song song component mới)
|
|
91
|
+
|
|
92
|
+
Mỗi component hiện có: đối chiếu trang docs antd/MUI/PrimeReact tương ứng, liệt kê
|
|
93
|
+
case/variant còn thiếu (vd Button `block`? Table `expandable`; Modal `centered`?) rồi bổ
|
|
94
|
+
sung stories EN + tests hành vi. Nguồn chân lý: docs của benchmark, KHÔNG đoán.
|
|
95
|
+
|
|
96
|
+
## Nguyên tắc token (áp cho mọi hàng)
|
|
97
|
+
|
|
98
|
+
1. **Màu**: chỉ token `--c-*`/`--ink*`/`--line*`/`--accent`/`--st-*` — không hex cứng trong component.
|
|
99
|
+
2. **Radius**: `rounded-lg` (8) cho control vuông; `rounded-pill` cho pill; một radius mỗi khối.
|
|
100
|
+
3. **Ngôn ngữ nút thống nhất** (2026-10-17): thường = transparent + `hover:bg-s3`; active/selected = `bg-accent text-white font-medium`; disabled = `text-ink3/ink4` + `cursor-not-allowed` không hover.
|
|
101
|
+
4. **Motion**: CSS thuần + motion tokens (`--motion-*`, `--ease-*`); animation height qua `grid-template-rows 0fr↔1fr`.
|
|
102
|
+
5. **Z-index**: scale token `--z-*` (dropdown < popover < modal < toast < tooltip) — không số cứng.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Gap-answer — 8 mục đổi shared files (epic auth-real VU-59)
|
|
2
|
+
|
|
3
|
+
> Soạn bởi SF-1 (VU-60) theo context pack `sf-1.md` mục "Gap-answer doc (8 mục)".
|
|
4
|
+
> Trạng thái: **PROPOSAL — chờ coordinator APPROVED-reply trên epic VU-59** trước khi
|
|
5
|
+
> SF thực thi. SF-1 KHÔNG commit compose/nginx/init/workspace (boundary).
|
|
6
|
+
> Mỗi mục ghi: file đích · giá trị HIỆN TẠI (đọc từ main 2026-10-17) → GIÁ TRỊ ĐÍCH ·
|
|
7
|
+
> SF thực thi · lý do. Tất cả anchor đã grep-verify trên tree SF-1.
|
|
8
|
+
|
|
9
|
+
## ① Compose entry `auth-mock` → `auth-svc`
|
|
10
|
+
|
|
11
|
+
**File:** `platform/docker-compose.yml` (block `auth-mock:` — dòng 75–94 hiện tại)
|
|
12
|
+
|
|
13
|
+
Đổi key service `auth-mock:` → `auth-svc:` + nội dung entry:
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
auth-svc:
|
|
17
|
+
build: ../services/auth-svc # ← đổi từ ./auth-mock (service mới ở services/)
|
|
18
|
+
environment:
|
|
19
|
+
PORT: 8090 # container port CỐ ĐỊNH (conventions/05) — giữ nguyên surface :8090
|
|
20
|
+
DATABASE_URL: postgres://auth_svc:${AUTH_SVC_DB_PASSWORD:?set in .env}@postgres:5432/${POSTGRES_DB:?set in .env}
|
|
21
|
+
JWT_SECRET: ${JWT_SECRET:?set in .env}
|
|
22
|
+
ACCESS_TOKEN_TTL: ${ACCESS_TOKEN_TTL:-30m} # token-contract.md §1
|
|
23
|
+
AUTH_DEV_PASSWORD: ${AUTH_DEV_PASSWORD:-demo-password} # decision #10
|
|
24
|
+
USERS_FIXTURE_PATH: /app/users.json
|
|
25
|
+
CORS_DEV_ORIGIN: ${CORS_DEV_ORIGIN:-}
|
|
26
|
+
LOG_LEVEL: ${LOG_LEVEL:-info}
|
|
27
|
+
volumes:
|
|
28
|
+
- ../contracts/auth/users.json:/app/users.json:ro # ← mục ⑤
|
|
29
|
+
ports:
|
|
30
|
+
- "${AUTH_PORT:-8090}:8090" # ← mục ⑦
|
|
31
|
+
depends_on:
|
|
32
|
+
postgres:
|
|
33
|
+
condition: service_healthy
|
|
34
|
+
healthcheck:
|
|
35
|
+
# wget /readyz (KHÔNG /healthz như auth-mock cũ) — readyz auth-svc kiểm DB
|
|
36
|
+
# thật (spec v2: "không hardcode 200") → service_healthy = đã migrate+seed.
|
|
37
|
+
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8090/readyz"]
|
|
38
|
+
interval: 5s
|
|
39
|
+
timeout: 3s
|
|
40
|
+
retries: 12
|
|
41
|
+
start_period: 20s # chờ migration + seed fixture lúc boot
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**SF thực thi:** SF-5 (decommission — xoá entry `auth-mock` + `platform/auth-mock/` cùng commit).
|
|
45
|
+
**Lý do:** giữ surface `:8090 /api/auth/*` (decision #2) — gateway/port-table/FE-flow không đổi.
|
|
46
|
+
|
|
47
|
+
## ② Key `gateway.depends_on.auth-mock` → `auth-svc`
|
|
48
|
+
|
|
49
|
+
**File:** `platform/docker-compose.yml` (dòng 102–104 hiện tại)
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
depends_on:
|
|
53
|
+
auth-svc: # ← đổi từ auth-mock
|
|
54
|
+
condition: service_healthy
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**SF thực thi:** SF-5 (cùng commit với ① — cùng file).
|
|
58
|
+
**Lý do:** gateway gate trên service_healthy; healthcheck auth-svc dùng `/readyz` (kiểm DB)
|
|
59
|
+
→ gateway chỉ nhận traffic khi auth-svc đã migrate + seed xong.
|
|
60
|
+
|
|
61
|
+
## ③ nginx upstream `auth-mock:8090` → `auth-svc:8090`
|
|
62
|
+
|
|
63
|
+
**File:** `platform/gateway/nginx/nginx.conf` (dòng 100–102 hiện tại)
|
|
64
|
+
|
|
65
|
+
```nginx
|
|
66
|
+
# ---------- API: auth → auth-svc (MỞ — entry login + register + swagger) ----------
|
|
67
|
+
location /api/auth {
|
|
68
|
+
set $up http://auth-svc:8090; # ← đổi từ http://auth-mock:8090
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**SF thực thi:** SF-5.
|
|
72
|
+
**Lý do:** pass-through giữ nguyên (conventions/08); chỉ hostname upstream đổi theo tên
|
|
73
|
+
service compose mới. Route rules + presence-check `/api/tasks|/api/users|/api/activity`
|
|
74
|
+
KHÔNG đổi.
|
|
75
|
+
|
|
76
|
+
## ④ go-svc env `AUTH_MOCK_URL` — đổi VALUE, giữ KEY
|
|
77
|
+
|
|
78
|
+
**File:** `platform/docker-compose.yml` (entry `go-svc`, dòng 186 hiện tại)
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
AUTH_MOCK_URL: http://auth-svc:8090 # ← chỉ đổi VALUE từ http://auth-mock:8090
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**File kèm:** `platform/.env.example` (dòng 53 hiện tại: `AUTH_MOCK_URL=http://auth-mock:8090`)
|
|
85
|
+
— cùng swap VALUE → `http://auth-svc:8090` trong cùng commit SF-5 (compose dùng literal nên
|
|
86
|
+
không phụ thuộc dòng này, nhưng native-dev consumer đọc `.env` sẽ trỏ host chết sau
|
|
87
|
+
decommission nếu quên; **KEY `AUTH_MOCK_URL` giữ nguyên** — go-svc đọc theo tên env này).
|
|
88
|
+
|
|
89
|
+
**SF thực thi:** SF-5.
|
|
90
|
+
**Lý do:** KEY giữ nguyên `AUTH_MOCK_URL` — go-svc đọc env này ở
|
|
91
|
+
`services/go-svc/internal/config/config.go:42` (`getenv("AUTH_MOCK_URL")`); đổi key =
|
|
92
|
+
sửa code go-svc (ngoài phạm vi gap-answer, không SF nào được brief sửa go-svc trừ
|
|
93
|
+
verify-code). Value-only swap = zero code change, zero risk cho go-svc.
|
|
94
|
+
**⚠️ Note cho follow-up:** `config.go:67` hardcode default `http://auth-mock:8090` khi
|
|
95
|
+
env unset — compose + CI luôn set env nên không lộ runtime; default stale này gom vào
|
|
96
|
+
follow-up "đổi tên auth-mock" cùng cụm iss-rename (spec decision #7).
|
|
97
|
+
|
|
98
|
+
## ⑤ Volume mount `users.json` cho auth-svc
|
|
99
|
+
|
|
100
|
+
**File:** `platform/docker-compose.yml` — đã embed trong entry ở mục ①; tách riêng để
|
|
101
|
+
review rõ:
|
|
102
|
+
|
|
103
|
+
```yaml
|
|
104
|
+
volumes:
|
|
105
|
+
- ../contracts/auth/users.json:/app/users.json:ro
|
|
106
|
+
environment:
|
|
107
|
+
USERS_FIXTURE_PATH: /app/users.json
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**SF thực thi:** SF-5 (đi kèm ①).
|
|
111
|
+
**Lý do:** auth-svc seed idempotent từ fixture GIỮ UUID (`ON CONFLICT (id) DO NOTHING`,
|
|
112
|
+
token-contract.md §5) — mount trực tiếp từ `contracts/` như auth-mock cũ: sửa fixture
|
|
113
|
+
không cần rebuild image. `GET /users` serve từ DB (schema `auth`), KHÔNG đọc fixture
|
|
114
|
+
mỗi request.
|
|
115
|
+
|
|
116
|
+
## ⑥ Init script + role `auth_svc` / schema `auth` / `AUTH_SVC_DB_PASSWORD`
|
|
117
|
+
|
|
118
|
+
**File 1:** `platform/postgres/init/01-init.sh` — thêm block sau block role go_readonly:
|
|
119
|
+
|
|
120
|
+
```sql
|
|
121
|
+
CREATE SCHEMA IF NOT EXISTS auth;
|
|
122
|
+
CREATE ROLE auth_svc LOGIN PASSWORD '${AUTH_SVC_DB_PASSWORD}';
|
|
123
|
+
GRANT USAGE, CREATE ON SCHEMA auth TO auth_svc;
|
|
124
|
+
ALTER ROLE auth_svc SET search_path = auth;
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**File 2:** `platform/docker-compose.yml` — entry `postgres.environment` thêm 1 dòng
|
|
128
|
+
(cạnh GO_READONLY_DB_PASSWORD, dòng 35 hiện tại):
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
AUTH_SVC_DB_PASSWORD: ${AUTH_SVC_DB_PASSWORD:?set in .env}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**File 3:** `platform/.env.example` — thêm 1 dòng vào block Postgres:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
AUTH_SVC_DB_PASSWORD=change-me-auth
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**SF thực thi:** SF-5 (cả 3 file; `.env.example` SF-5 đồng bộ cùng commit theo plan Task 5).
|
|
141
|
+
**Lý do:** auth-svc owns schema `auth` riêng (decision #3 — pattern per-service schema +
|
|
142
|
+
LOGIN role như 3 service cũ); init chỉ chạy trên volume MỚI → **gotcha: volume postgres cũ
|
|
143
|
+
phải `docker compose down -v` 1 lần** (epic acceptance #6 — gotcha vào orca.yaml +
|
|
144
|
+
walkthrough ở SF-5 docs sync).
|
|
145
|
+
|
|
146
|
+
## ⑦ `.env` renames (phần compose-side)
|
|
147
|
+
|
|
148
|
+
**Đã xong bởi SF-1** (commit này): `platform/.env.example` — `AUTH_MOCK_PORT=8090` →
|
|
149
|
+
`AUTH_PORT=8090`; `AUTH_MOCK_DEV_PASSWORD=demo-password` → `AUTH_DEV_PASSWORD=demo-password`
|
|
150
|
+
(+ comment nguồn chung e2e/svc-activity/seed); **+ `ACCESS_TOKEN_TTL=30m`**.
|
|
151
|
+
|
|
152
|
+
**Phần compose-side — SF-5 thực thi** (cùng commit ①):
|
|
153
|
+
|
|
154
|
+
| Vị trí trong compose (hiện tại) | Đổi thành |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `ports: - "${AUTH_MOCK_PORT:-8090}:8090"` (dòng 88) | `"${AUTH_PORT:-8090}:8090"` |
|
|
157
|
+
| `AUTH_MOCK_DEV_PASSWORD: ${AUTH_MOCK_DEV_PASSWORD:-demo-password}` (dòng 81) | `AUTH_DEV_PASSWORD: ${AUTH_DEV_PASSWORD:-demo-password}` (decision #10 — default `demo-password` KHÔNG đổi) |
|
|
158
|
+
| comment dòng 78/90 nhắc `${AUTH_MOCK_PORT}` | nhắc `${AUTH_PORT}` |
|
|
159
|
+
|
|
160
|
+
**Lý do:** decision #10 — `${AUTH_DEV_PASSWORD:-demo-password}` (KHÔNG `change-me-*`):
|
|
161
|
+
e2e + go-svc svc-activity + seed cùng một nguồn, acceptance epic #3 phụ thuộc.
|
|
162
|
+
`SVC_ACTIVITY_PASSWORD=demo-password` trong `.env.example` KHÔNG đổi (đã khớp nguồn chung).
|
|
163
|
+
|
|
164
|
+
## ⑧ `pnpm-workspace.yaml` + `services/auth-svc`
|
|
165
|
+
|
|
166
|
+
**File:** `pnpm-workspace.yaml` — thêm 1 dòng vào block `packages:`, cạnh
|
|
167
|
+
`- "services/node-svc"` (dòng cuối block hiện tại):
|
|
168
|
+
|
|
169
|
+
```yaml
|
|
170
|
+
# auth-svc (SF-2 epic VU-59 điền impl) — standalone lockfile như node-svc
|
|
171
|
+
- "services/auth-svc"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**SF thực thi:** SF-2 (plan Task 2 — Files: Modify `pnpm-workspace.yaml`; SF-2 là SF duy
|
|
175
|
+
nhất đụng file này trong tier 1 → an toàn song song).
|
|
176
|
+
**Lý do:** auth-svc là workspace member (mirror node-svc); install bằng
|
|
177
|
+
`pnpm install --frozen-lockfile --ignore-workspace` trong thư mục service đến khi vào
|
|
178
|
+
workspace chính thức (gotcha CLAUDE.md).
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Tóm tắt ma trận thực thi
|
|
183
|
+
|
|
184
|
+
| Mục | File | SF thực thi |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| ① compose entry | `platform/docker-compose.yml` | SF-5 |
|
|
187
|
+
| ② depends_on key | `platform/docker-compose.yml` | SF-5 |
|
|
188
|
+
| ③ nginx upstream | `platform/gateway/nginx/nginx.conf` | SF-5 |
|
|
189
|
+
| ④ go-svc env value | `platform/docker-compose.yml` + `.env.example:53` | SF-5 |
|
|
190
|
+
| ⑤ users.json mount | `platform/docker-compose.yml` | SF-5 |
|
|
191
|
+
| ⑥ init + role + env password | `platform/postgres/init/01-init.sh` + compose + `.env.example` | SF-5 |
|
|
192
|
+
| ⑦ .env renames | `.env.example` (SF-1 **đã xong**) + compose refs (SF-5) | SF-1 ✓ / SF-5 |
|
|
193
|
+
| ⑧ workspace line | `pnpm-workspace.yaml` | SF-2 |
|
|
194
|
+
|
|
195
|
+
Không mục nào cho 2 SF đụng cùng 1 shared file trong 1 tier (ràng buộc plan rev2).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# SF-1 Context Pack — Contracts + hiệp ước + gap-answer
|
|
2
|
+
> Đọc file này THAY VÌ tự tổng hợp. Epic spec: docs/superpowers/specs/2026-10-17-auth-real-design.md (rev2) · Plan Task 1: docs/superpowers/plans/2026-10-17-auth-real-plan.md · Bracket: docs/superpowers/mindmaps/auth-real.wakii · Linear: VU-60.
|
|
3
|
+
|
|
4
|
+
## Spec slice (chỉ phần SF-1 chịu trách nhiệm)
|
|
5
|
+
1. `contracts/openapi/auth.yaml` v2: schemas `RegisterRequest{email, password(8-72), displayName}`, `TokenPair{accessToken, refreshToken}`, `RefreshRequest`; paths `POST /register|/login|/refresh|/logout|/logout-all`; response login/register = `{user: UserRef, accessToken, refreshToken}` (DROP tokenType/expiresIn — decision #8); **giữ `GET /users`**; **xoá `/.well-known/openid-configuration`** + disclaimer header.
|
|
6
|
+
2. `contracts/auth/token-contract.md` v2: access TTL 30m; refresh opaque 256-bit, lưu sha256 hash, TTL 7d; rotation CAS atomic (`UPDATE ... WHERE id=$old AND revoked_at IS NULL RETURNING` — 0 rows = reuse); **reuse → revoke TẤT CẢ token user + 401 (strict)**; `iss` **PINNED "auth-mock"** (3 service + CI hardcode — đổi là follow-up riêng); `localStorage['bp.rt']` rationale (accepted-for-demo, httpOnly = upgrade path); RS256/JWKS = path OIDC.
|
|
7
|
+
3. `platform/.env.example`: +`AUTH_DEV_PASSWORD` default **`${AUTH_DEV_PASSWORD:-demo-password}`** (KHÔNG change-me-* — e2e/svc-activity/seed cùng nguồn), +`ACCESS_TOKEN_TTL=30m`, rename `AUTH_MOCK_PORT`→`AUTH_PORT`, `AUTH_MOCK_DEV_PASSWORD`→`AUTH_DEV_PASSWORD`.
|
|
8
|
+
4. `.github/workflows/contracts.yml`: schemathesis scope HẸP — chỉ paths auth-mock đang implement (paths mới sẽ 404 → job đỏ oan). Exclude register|refresh|logout đến SF-5.
|
|
9
|
+
5. **Gap-answer doc (8 mục, KHÔNG commit compose/nginx/init)**: ① compose entry auth-mock→auth-svc (:8090, healthcheck wget /readyz) ② key `gateway.depends_on.auth-mock`→`auth-svc` ③ nginx upstream auth-mock:8090→auth-svc:8090 ④ go-svc env `AUTH_MOCK_URL` value→`http://auth-svc:8090` ⑤ users.json volume mount cho auth-svc ⑥ init 01-init.sh + role `auth_svc`/schema `auth`/`AUTH_SVC_DB_PASSWORD` ⑦ .env renames (mục 3) ⑧ `pnpm-workspace.yaml` +`services/auth-svc`. FLAG coordinator duyệt — SF-5 thực thi.
|
|
10
|
+
|
|
11
|
+
## Touch map (SF-1 sở hữu)
|
|
12
|
+
`contracts/openapi/auth.yaml` · `contracts/auth/token-contract.md` · `platform/.env.example` · `.github/workflows/contracts.yml` (chỉ schemathesis scope) · gap-answer doc `docs/superpowers/contexts/auth-real/gap-answer.md`.
|
|
13
|
+
READ-ONLY: compose, nginx, init, pnpm-workspace (SF-5/SF-2 thực thi theo gap-answer đã duyệt).
|
|
14
|
+
|
|
15
|
+
## ACCEPTANCE (user-visible)
|
|
16
|
+
- `pnpm lint:contracts` xanh; CI `contracts` xanh với schemathesis SCOPED (không 404).
|
|
17
|
+
- token-contract.md v2 đọc được thành hiệp ước đầy đủ: TTLs, rotation CAS, reuse strict, iss pinned, bp.rt rationale — không còn câu nào nói TTL 8h / không refresh.
|
|
18
|
+
- Gap-answer 8 mục materialize thành file, coordinator comment APPROVED trên epic.
|
|
19
|
+
|
|
20
|
+
## Boundary (KHÔNG làm)
|
|
21
|
+
KHÔNG code runtime auth-svc (SF-2); KHÔNG commit compose/nginx/init/workspace (SF-5/SF-2 theo gap-answer); KHÔNG đụng node/go/spring verify code; KHÔNG đổi users.json (chỉ đọc để ghi contract).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# SF-2 Context Pack — auth-svc: schema + seed + 5 endpoints
|
|
2
|
+
> Epic spec: docs/superpowers/specs/2026-10-17-auth-real-design.md (rev2) · Plan Task 2: docs/superpowers/plans/2026-10-17-auth-real-plan.md · Bracket: docs/superpowers/mindmaps/auth-real.wakii · Linear: VU-61. Depends on: SF-1 (contracts đã merge — code theo auth.yaml v2 ĐÚNG rev đó).
|
|
3
|
+
|
|
4
|
+
## Spec slice
|
|
5
|
+
1. Service `services/auth-svc/` mirror node-svc: Fastify+TS+Drizzle, env/logger/JWT plugin (**verify issuer literal "auth-mock"** — PINNED), envelope handler (HttpError.statusCode, pino cast — improvements-log 2026-10-12), `/healthz`+`/readyz` naked+prefix. `pnpm-workspace.yaml` +`services/auth-svc` (1 dòng — shared file duy nhất SF-2 đụng, không ai khác đụng trong tier).
|
|
6
|
+
2. Migration 0000: 2 bảng theo spec §Kiến trúc (`roles text[] NOT NULL DEFAULT '{"user"}'`). Seed từ `contracts/auth/users.json`: giữ UUID/displayName/roles, `password_hash=argon2id(AUTH_DEV_PASSWORD)`, idempotent `ON CONFLICT (id) DO NOTHING`.
|
|
7
|
+
3. 5 endpoints: register (argon2id; email lowercase; 409 UNIQUE; password 8-72), login (sign HS256 TTL ACCESS_TOKEN_TTL iss "auth-mock" + refresh `crypto.randomBytes(32)`), refresh (**CAS rotation**: `UPDATE auth.refresh_tokens SET revoked_at=now(), replaced_by=$new WHERE id=$old AND revoked_at IS NULL RETURNING *` — 0 rows → reuse-detect: revoke tất cả user + 401), logout (204 idempotent), logout-all (Bearer sub). Envelope conventions/04; KHÔNG log password/refresh.
|
|
8
|
+
4. `.github/workflows/services-auth-svc.yml` mới từ `.github/workflow-templates/services-ci.yml.example` (path filter + permissions contents:read).
|
|
9
|
+
5. Local verify KHÔNG dùng compose (entry auth-svc chưa commit — SF-5 mới commit): postgres local tạo schema auth thủ công → `pnpm --filter auth-svc test` (unit + integration) → `docker build` → curl chuỗi health + register→login→refresh→reuse→401.
|
|
10
|
+
|
|
11
|
+
## Touch map (SF-2 sở hữu)
|
|
12
|
+
`services/auth-svc/**` (toàn bộ) · `.github/workflows/services-auth-svc.yml` (mới) · 1 dòng `pnpm-workspace.yaml` + lockfile.
|
|
13
|
+
READ-ONLY: `contracts/**` (SF-1), compose/nginx/init (SF-5), node/go/spring.
|
|
14
|
+
|
|
15
|
+
## ACCEPTANCE (user-visible)
|
|
16
|
+
- curl register→login→refresh→refresh-lại-token-cũ (401 + mọi refresh token của user chết)→logout (204, idempotent)→logout-all — chạy được đầu-cuối trên auth-svc boot local.
|
|
17
|
+
- 5 user fixture login được bằng AUTH_DEV_PASSWORD (alice roles admin, bob user — claims đúng từ seed).
|
|
18
|
+
- Workflow services-auth-svc.yml xanh trên nhánh (build + test + docker build + boot-smoke).
|
|
19
|
+
|
|
20
|
+
## Boundary (KHÔNG làm)
|
|
21
|
+
KHÔNG đụng node/go/spring/FE (SF-3/SF-4); KHÔNG commit compose/nginx/init (SF-5); KHÔNG đổi iss; KHÔNG đụng auth-mock (còn sống đến SF-5); RBAC (SF-3).
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# SF-3 Context Pack — node-svc RBAC: DELETE admin-only
|
|
2
|
+
> Epic spec: docs/superpowers/specs/2026-10-17-auth-real-design.md · Plan Task 3: docs/superpowers/plans/2026-10-17-auth-real-plan.md · Bracket: docs/superpowers/mindmaps/auth-real.wakii · Linear: VU-62. Depends on: SF-1 (contracts; kỹ thuật có thể đứng độc lập — roles claim đã có trong token hiện tại). Tier Standard (SF nhỏ).
|
|
3
|
+
|
|
4
|
+
## Spec slice
|
|
5
|
+
1. `services/node-svc/src/plugins/auth.ts`: xác nhận request.user mang `roles` (decode từ claims — đã có).
|
|
6
|
+
2. `services/node-svc/src/routes/tasks.ts`: preHandler DELETE `/tasks/:id` — reject 403 envelope `{code:"FORBIDDEN"}` khi `!user.roles?.includes('admin')` (message: 'Chỉ admin được xoá task').
|
|
7
|
+
3. Tests (RED trước): DELETE token roles `["user"]` → 403 envelope; alice admin → 200; missing roles → 403.
|
|
8
|
+
|
|
9
|
+
## Touch map (SF-3 sở hữu)
|
|
10
|
+
`services/node-svc/src/plugins/auth.ts` · `services/node-svc/src/routes/tasks.ts` · `services/node-svc/src/app.test.ts`.
|
|
11
|
+
READ-ONLY: mọi thứ khác.
|
|
12
|
+
|
|
13
|
+
## ACCEPTANCE (user-visible)
|
|
14
|
+
- Bob (roles user) thử xoá task qua API → 403 envelope rõ ràng; Alice (admin) xoá → 200. (e2e user-visible assert ở SF-5.)
|
|
15
|
+
|
|
16
|
+
## Boundary (KHÔNG làm)
|
|
17
|
+
KHÔNG đụng auth-svc (SF-2), FE (SF-4), e2e.sh (SF-5 thêm assert RBAC), PATCH/POST tasks (chỉ DELETE).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# SF-4 Context Pack — FE refresh-client + LoginPage register
|
|
2
|
+
> Epic spec: docs/superpowers/specs/2026-10-17-auth-real-design.md · Plan Task 4: docs/superpowers/plans/2026-10-17-auth-real-plan.md · Bracket: docs/superpowers/mindmaps/auth-real.wakii · Linear: VU-63. Depends on: SF-1 (auth.yaml v2 — response shape `{user, accessToken, refreshToken}`, DROP tokenType/expiresIn).
|
|
3
|
+
|
|
4
|
+
## Spec slice
|
|
5
|
+
1. `app/shared/src/refresh-client.ts` (FILE MỚI + export qua index.ts — token-storage.ts READ-LOCKED không đụng): `login/register/withRefresh/logout`. Access → tokenStorage (API có sẵn: setToken/clearToken); refresh → `localStorage['bp.rt']` (rationale pin token-contract v2). 401 → refresh single-flight (promise lock) đúng 1 lần → retry; refresh fail → clear 2 key + throw Unauthorized.
|
|
6
|
+
2. `app/shell/src/pages/LoginPage.tsx`: tab Login/Register (response v2 shape — LoginPage hiện đọc tokenType/expiresIn phải bỏ); lỗi 401/409 theo messages contract. **Tailwind v4 đã trên main (PR #13) — UI mới theo pattern Tailwind hiện hành, KHÔNG css-scoped cũ.**
|
|
7
|
+
3. `app/shell/src/api.ts`: login/register đi qua wrapper.
|
|
8
|
+
4. Tests (mock fetch): login/register lưu cặp đúng key; 401 → refresh đúng 1 lần → retry OK; refresh 401 → clear + Unauthorized; logout revoke + clear. Coverage gate 90/90/80/90 giữ; a11y suite (tab/form mới) giữ.
|
|
9
|
+
|
|
10
|
+
## Touch map (SF-4 sở hữu)
|
|
11
|
+
`app/shared/src/refresh-client.ts` (mới) · `app/shared/src/index.ts` (export) · `app/shell/src/pages/LoginPage.tsx` · `app/shell/src/api.ts` · `app/shell/tests/*`.
|
|
12
|
+
READ-ONLY: `app/shared/src/{api-client,token-storage,error-envelope,mf-bootstrap}.ts` (READ-LOCKED), `app/ui-kit/**` (consume primitives), remotes.
|
|
13
|
+
|
|
14
|
+
## ACCEPTANCE (user-visible)
|
|
15
|
+
- User đăng ký tài khoản mới từ UI → login → thấy nav user chip.
|
|
16
|
+
- Access token hết hạn (giả lập TTL ngắn/mock) → request kế tiếp tự refresh — UI KHÔNG thấy 401.
|
|
17
|
+
- Logout → 2 key sạch, về login.
|
|
18
|
+
|
|
19
|
+
## Boundary (KHÔNG làm)
|
|
20
|
+
KHÔNG sửa READ-LOCKED; KHÔNG đụng remotes tasks/activity (chỉ shell); KHÔNG làm cross-tab sync (SF-5 human walkthrough); KHÔNG đụng auth-svc/node (SF-2/SF-3).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# SF-5 Context Pack — Convergence + decommission + CI swap + docs
|
|
2
|
+
> Epic spec: docs/superpowers/specs/2026-10-17-auth-real-design.md · Plan Task 5: docs/superpowers/plans/2026-10-17-auth-real-plan.md · Bracket: docs/superpowers/mindmaps/auth-real.wakii · Linear: VU-64. Depends on: SF-2 + SF-3 + SF-4 (đã merge về dest).
|
|
3
|
+
|
|
4
|
+
## Spec slice
|
|
5
|
+
1. **Thực thi gap-answer 8 mục** (SF-1 soạn, coordinator APPROVED — đọc `docs/superpowers/contexts/auth-real/gap-answer.md` + epic comment): compose entry auth-mock→auth-svc (+depends_on key) · nginx upstream · go-svc env value `http://auth-svc:8090` · users.json mount · init role auth_svc · .env renames · workspace line (đã có từ SF-2).
|
|
6
|
+
2. **Xoá `platform/auth-mock/`** (thư mục + mọi tham chiếu sống).
|
|
7
|
+
3. **CI swap**: `contracts.yml` boot auth-svc + nới schemathesis full paths (bỏ scope SF-1); `services-go-svc.yml` + `services-spring-svc.yml` boot auth-svc. Node workflow không đổi (iss pinned). **Acceptance: TOÀN BỘ CI main xanh sau merge.**
|
|
8
|
+
4. **e2e.sh mở rộng** (bảo toàn: exit N = fail bước N, marker `SAGA_TASK_ID=`, SMOKE_SAGA=0 exit 0): +register `smoke-<ts>@demo.local` → refresh → reuse old → 401 → logout; +RBAC: register user roles ["user"] DELETE task → 403, alice → 200.
|
|
9
|
+
5. **Docs sync CÙNG commit**: walkthrough (+register/refresh + gotcha `down -v` 1 lần — volume cũ thiếu role auth_svc + sync số bước PASS), CLAUDE.md (auth-mock → auth-svc), orca.yaml (services entry + gotcha + test_all), README, toolchain, grep `auth-mock` = rỗng trên docs/CLAUDE.md/orca.yaml/README/.env.example/.github (token-contract/users.json $comment giữ note lịch sử).
|
|
10
|
+
6. **Security pass + human walkthrough 2 tab** (register→login→tab 2→logout-all→tab 1 chết ở request kế tiếp) — evidence `docs/superpowers/evidence/auth-real/`.
|
|
11
|
+
|
|
12
|
+
## Touch map (SF-5 sở hữu)
|
|
13
|
+
compose · nginx · init · 3 CI workflows · e2e.sh · platform/auth-mock/ (xoá) · docs toàn bộ liên quan.
|
|
14
|
+
READ-ONLY: services/auth-svc, node, go, spring, app/** (code SF trước — bug thấy được = REPORT coordinator, KHÔNG fix — SF hội tụ).
|
|
15
|
+
|
|
16
|
+
## ACCEPTANCE (user-visible)
|
|
17
|
+
- Fresh clone + `down -v` → compose up → login alice bằng UI mới → saga demo fail@demo.local VẪN chạy (badge Gán thất bại) → bob tạo task, xoá bị chặn 403, alice xoá được.
|
|
18
|
+
- e2e mở rộng PASS; toàn CI main xanh; auth-mock không còn tồn tại trong repo.
|
|
19
|
+
|
|
20
|
+
## Boundary (KHÔNG làm)
|
|
21
|
+
KHÔNG fix bug miền service/FE (report); KHÔNG đổi contracts (rev2 là final); KHÔNG đụng Linear state epic (coordinator).
|